Beispiel #1
0
// The connection is lazily established, letting data be included in the handshake.
// A subsequent Read() or Write() may fail establishing a connection.
func Dial(addr *net.UDPAddr) (c *CurveCPConn, err error) {
	c = new(CurveCPConn)
	c.client = new(curveCPClient)

	c.ephPublicKey, c.ephPrivateKey, err = box.GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}

	// TODO: fetch server and client long-term keys
	var sPublicKey [32]byte
	var cPrivateKey [32]byte

	box.Precompute(&c.client.sharedHelloKey, &sPublicKey, c.ephPrivateKey)
	box.Precompute(&c.client.sharedVouchKey, &sPublicKey, &cPrivateKey)

	nonceInt, err := rand.Int(rand.Reader, big.NewInt(1<<48)) // start incrementing at random [0,2^48)
	if err != nil {
		return nil, err
	}
	c.nonce = nonceInt.Int64()

	c.conn, err = net.DialUDP("udp", nil, addr)
	if err != nil {
		return nil, err
	}

	c.sendHello()
	deadline := 1000 // TODO: add to connection struct
	connectionTimeout := time.NewTimer(min(deadline, 60*time.Second))

	cookies := make(chan bool)
	go c.cookieReceiver(cookies)

	for {
		select {
		case <-cookies:
			break
		case <-time.After(time.Second): // repeat Hello; TODO: fuzz + backoff
			c.sendHello()
		case <-connectionTimeout.C:
			return nil, ConnectionTimeoutError
		}
	}

	go c.clientReactor()

	return c, nil
}
Beispiel #2
0
func newConn(sock *net.UDPConn, peerIdentity, publicKey, privateKey []byte, domain string) *conn {
	if len(peerIdentity) != 32 || len(publicKey) != 32 || len(privateKey) != 32 {
		panic("wrong key size")
	}
	c := &conn{
		domain: domain,

		packetIn: make(chan packet),
		sock:     sock,

		readRequest:  make(chan []byte),
		writeRequest: make(chan []byte),
		ioResult:     make(chan opResult),

		toSend:   list.New(),
		sendFree: list.New(),

		received: ringbuf.New(recvBufferSize),
	}
	// Key setup.
	copy(c.peerIdentity[:], peerIdentity)
	var pub, priv [32]byte
	copy(pub[:], publicKey)
	copy(priv[:], privateKey)
	box.Precompute(&c.sharedKey, &pub, &priv)

	// Send blocks
	for i := 0; i < numSendBlocks; i++ {
		c.sendFree.PushBack(new(block))
	}

	go c.pump()
	return c
}
Beispiel #3
0
func FormSessionKey(remotePublicKey, localPrivateKey *[32]byte, secretKey []byte) *[32]byte {
	var sharedKey [32]byte
	box.Precompute(&sharedKey, remotePublicKey, localPrivateKey)
	sharedKeySlice := sharedKey[:]
	sharedKeySlice = append(sharedKeySlice, secretKey...)
	sessionKey := sha256.Sum256(sharedKeySlice)
	return &sessionKey
}
Beispiel #4
0
func (c *CurveCPConn) cookieReceiver(ch chan bool) {
	for {
		var buff [1400]byte

		bytesRead, err := c.conn.Read(buff[:])
		if err != nil {
			// TODO: debug
			continue
		}

		if bytesRead != cookiePacketLength {
			debug(-1, -1, packetDiscard, 'd', unknownPkt)
			continue
		}

		if !bytes.HasPrefix(buff[:], cookiePkt.magic) {
			debug()
			continue
		}

		var text [128]byte
		var nonce [24]byte
		var sEphPublicKey [32]byte

		copy(nonce, cookiePkt.noncePrefix)
		copy(nonce[8:], packet[40:56])
		_, ok := box.OpenAfterPrecomputation(text, packet[56:], &nonce, &c.client.sharedHelloKey)
		if ok == false {
			debug(-1, -1, packetDiscard, 'd', unknownPkt)
			continue
		}

		copy(sEphPublicKey, text[0:32])
		box.Precompute(&c.sharedKey, &sEphPublicKey, &c.ephPrivateKey)
		copy(c.client.serverCookie, text[32:])

		ch <- true
		break
	}
}