github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/mixnet/circuit.go (about)

     1  // Copyright (c) 2016, Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mixnet
    16  
    17  import (
    18  	"crypto/rand"
    19  	"encoding/binary"
    20  	"errors"
    21  	"io"
    22  
    23  	"golang.org/x/crypto/nacl/box"
    24  
    25  	"github.com/jlmucb/cloudproxy/go/tao"
    26  )
    27  
    28  // A circuit carries cells
    29  type Circuit struct {
    30  	conn    *Conn
    31  	id      uint64
    32  	cells   chan []byte
    33  	errs    chan error
    34  	next    *Circuit
    35  	entry   bool
    36  	exit    bool
    37  	forward bool
    38  
    39  	peerKey    *[32]byte
    40  	publicKey  *[32]byte
    41  	privateKey *[32]byte
    42  	sharedKey  *[32]byte
    43  }
    44  
    45  // A circuit now encrypts for the exit circuit. The key is assumed to be available
    46  // through "peerKey", and publicKey and privateKey are the keys are local keys
    47  // used to perform diffiehellman with peerKey. The keys are optional.
    48  func NewCircuit(conn *Conn, id uint64, entry, exit, forward bool) *Circuit {
    49  	return &Circuit{
    50  		conn:    conn,
    51  		id:      id,
    52  		cells:   make(chan []byte, 2),
    53  		errs:    make(chan error, 2),
    54  		entry:   entry,
    55  		exit:    exit,
    56  		forward: forward,
    57  	}
    58  }
    59  
    60  func (c *Circuit) SetKeys(peerKey, publicKey, privateKey *[32]byte) {
    61  	var sharedKey [32]byte
    62  	box.Precompute(&sharedKey, peerKey, privateKey)
    63  	c.peerKey = peerKey
    64  	c.publicKey = publicKey
    65  	c.privateKey = privateKey
    66  	c.sharedKey = &sharedKey
    67  }
    68  
    69  func (c *Circuit) Encrypt(msg []byte) []byte {
    70  	var nonce [24]byte
    71  	rand.Read(nonce[:])
    72  	boxed := box.SealAfterPrecomputation(nil, msg, &nonce, c.sharedKey)
    73  	boxed = append(nonce[:], boxed...)
    74  	return boxed
    75  }
    76  
    77  func (c *Circuit) Decrypt(boxed []byte) ([]byte, bool) {
    78  	var nonce [24]byte
    79  	copy(nonce[:], boxed[:24])
    80  	return box.OpenAfterPrecomputation(nil, boxed[24:], &nonce, c.sharedKey)
    81  }
    82  
    83  func (c *Circuit) Write(msg []byte) (int, error) {
    84  	// No need to multiplex writes
    85  	return c.conn.Write(msg)
    86  }
    87  
    88  func (c *Circuit) BufferCell(cell []byte, err error) {
    89  	c.cells <- cell
    90  	c.errs <- err
    91  }
    92  
    93  func (c *Circuit) Read(msg []byte) (int, error) {
    94  	cell, ok1 := <-c.cells
    95  	err, ok2 := <-c.errs
    96  	if !ok1 || !ok2 {
    97  		return 0, io.EOF
    98  	} else if err != nil {
    99  		return 0, err
   100  	}
   101  	n := copy(msg, cell)
   102  	return n, nil
   103  }
   104  
   105  func (c *Circuit) Close() error {
   106  	close(c.cells)
   107  	return nil
   108  }
   109  
   110  func breakMessages(msg []byte, res chan []byte) {
   111  	body := make([]byte, BODY_SIZE)
   112  	binary.LittleEndian.PutUint64(body, uint64(len(msg)))
   113  	bytes := copy(body[LEN_SIZE:], msg)
   114  	res <- body
   115  	for bytes < len(msg) {
   116  		body := make([]byte, BODY_SIZE)
   117  		bytes += copy(body, msg[bytes:])
   118  		res <- body
   119  	}
   120  	close(res)
   121  }
   122  
   123  // SendMessage divides a message into cells and sends each cell over the network
   124  // connection. A message is signaled to the receiver by the first byte of the
   125  // first cell. The next few bytes encode the total number of bytes in the
   126  // message.
   127  func (c *Circuit) SendMessage(msg []byte) error {
   128  	cell := make([]byte, CellBytes)
   129  	binary.LittleEndian.PutUint64(cell[ID:], c.id)
   130  	cell[TYPE] = msgCell
   131  
   132  	bodies := make(chan []byte)
   133  
   134  	go breakMessages(msg, bodies)
   135  	for {
   136  		body, ok := <-bodies
   137  		if !ok {
   138  			break
   139  		}
   140  		boxed := c.Encrypt(body)
   141  		copy(cell[BODY:], boxed)
   142  		if _, err := c.Write(cell); err != nil {
   143  			return err
   144  		}
   145  	}
   146  	return nil
   147  }
   148  
   149  // SendDirective serializes and pads a directive to the length of a cell and
   150  // sends it to the peer. A directive is signaled to the receiver by the first
   151  // byte of the cell. The next few bytes encode the length of of the serialized
   152  // protocol buffer. If the buffer doesn't fit in a cell, then throw an error.
   153  func (c *Circuit) SendDirective(d *Directive) (int, error) {
   154  	cell, err := marshalDirective(c.id, d)
   155  	if err != nil {
   156  		return 0, err
   157  	}
   158  	return c.Write(cell)
   159  }
   160  
   161  // ReceiveMessage reads message cells from the router and assembles them into
   162  // a messsage.
   163  func (c *Circuit) ReceiveMessage() ([]byte, error) {
   164  	// Receive cells from router.
   165  	cell := make([]byte, CellBytes)
   166  	n, err := c.Read(cell)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	if cell[TYPE] == dirCell {
   172  		var d Directive
   173  		if err = unmarshalDirective(cell, &d); err != nil {
   174  			return nil, err
   175  		}
   176  		if *d.Type == DirectiveType_ERROR {
   177  			return nil, errors.New("router error: " + (*d.Error))
   178  		}
   179  		return nil, errCellType
   180  	} else if cell[TYPE] != msgCell {
   181  		return nil, errCellType
   182  	}
   183  
   184  	boxed := cell[BODY:n]
   185  	if len(boxed) > 0 {
   186  		body, ok := c.Decrypt(boxed)
   187  		if !ok {
   188  			return nil, errors.New("Misauthenticated ciphertext")
   189  		}
   190  
   191  		msgBytes := binary.LittleEndian.Uint64(body)
   192  		if msgBytes > MaxMsgBytes {
   193  			return nil, errMsgLength
   194  		}
   195  
   196  		msg := make([]byte, msgBytes)
   197  		bytes := copy(msg, body[LEN_SIZE:])
   198  
   199  		for uint64(bytes) < msgBytes {
   200  			tao.ZeroBytes(cell)
   201  			n, err = c.Read(cell)
   202  			if err != nil {
   203  				return nil, err
   204  			} else if cell[TYPE] != msgCell {
   205  				return nil, errCellType
   206  			}
   207  			boxed := cell[BODY:n]
   208  			body, ok := c.Decrypt(boxed)
   209  			if !ok {
   210  				return nil, errors.New("Misauthenticated ciphertext")
   211  			}
   212  			bytes += copy(msg[bytes:], body)
   213  		}
   214  		return msg, nil
   215  	} else {
   216  		return nil, nil
   217  	}
   218  }
   219  
   220  // ReceiveDirective awaits a reply from the peer and returns the directive
   221  // received, e.g. in response to RouterContext.HandleProxy(). If the directive
   222  // type is ERROR, return an error.
   223  func (c *Circuit) ReceiveDirective(d *Directive) error {
   224  	cell := make([]byte, CellBytes)
   225  	_, err := c.Read(cell)
   226  	if err != nil {
   227  		return err
   228  	}
   229  
   230  	err = unmarshalDirective(cell, d)
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	if *d.Type == DirectiveType_ERROR {
   236  		return errors.New("router error: " + (*d.Error))
   237  	}
   238  	return nil
   239  }