Esempio n. 1
0
// Encode a packet
func Encode(pkt *Packet) (*bufpool.Buffer, error) {
	var (
		p      *bufpool.Buffer
		hdrLen int
		err    error
	)

	if pkt == nil {
		return bufpool.New().SetLen(2), nil
	}

	buf := byteBufferPool.Get().(*bytes.Buffer)
	buf.WriteByte(0)
	buf.WriteByte(0)

	if !pkt.header.IsZero() {
		if !pkt.header.IsBinary() {
			err = pkt.header.writeTo(buf)
			if err != nil {
				buf.Reset()
				byteBufferPool.Put(buf)
				return nil, err
			}
			hdrLen = buf.Len() - 2
			if hdrLen < 7 {
				buf.Reset()
				byteBufferPool.Put(buf)
				return nil, ErrInvalidPacket
			}
		} else {
			hdrLen = len(pkt.header.Bytes)
			if hdrLen >= 7 {
				buf.Reset()
				byteBufferPool.Put(buf)
				return nil, ErrInvalidPacket
			}
			buf.Write(pkt.header.Bytes)
		}
	}

	if pkt.body.Len() > 0 {
		pkt.body.WriteTo(buf)
	}

	p = bufpool.New()
	p.Set(buf.Bytes())
	binary.BigEndian.PutUint16(p.RawBytes(), uint16(hdrLen))

	buf.Reset()
	byteBufferPool.Put(buf)

	return p, nil
}
Esempio n. 2
0
func (mod *module) forwardMessage(e *e3x.Endpoint, x *e3x.Exchange, msg []byte, pipe *e3x.Pipe, reason error) error {
	var (
		token = cipherset.ExtractToken(msg)
		ex    = mod.lookupToken(token)
	)

	// not a bridged message
	if ex == nil {
		return nil
	}

	// handle bridged message
	dst := ex.ActivePipe()
	if dst == pipe {
		return nil
	}

	buf := bufpool.New().Set(msg)
	_, err := dst.Write(buf)
	buf.Free()
	if err != nil {
		mod.log.To(ex.RemoteHashname()).Printf("\x1B[35mFWD %x %s error=%s\x1B[0m", token, dst.RemoteAddr(), err)
		return nil
	} else {
		mod.log.To(ex.RemoteHashname()).Printf("\x1B[35mFWD %x %s\x1B[0m", token, dst.RemoteAddr())
		return e3x.ErrStopPropagation
	}
}
Esempio n. 3
0
func (c *connection) Write(b []byte) (int, error) {
	c.mtx.RLock()
	closed := c.closed
	c.mtx.RUnlock()

	if closed {
		return 0, io.EOF
	}

	if len(b) > 2 && b[0] == 0 && b[1] == 1 {
		return len(b), c.sendHandshake(b)
	}

	pipe := c.ex.ActivePipe()
	if pipe == nil {
		// drop
		return len(b), nil
	}

	buf := bufpool.New().Set(b)
	n, err := pipe.Write(buf)
	buf.Free()

	return n, err
}
Esempio n. 4
0
func (s *state) EncryptMessage(in []byte) ([]byte, error) {
	var (
		out       = bufpool.New().SetLen(lenKey + lenNonce + len(in) + box.Overhead + lenAuth)
		raw       = out.RawBytes()
		agreedKey [lenKey]byte
		ctLen     int
	)

	if !s.CanEncryptMessage() {
		panic("unable to encrypt message")
	}

	// copy public senderLineKey
	copy(raw[:lenKey], (*s.localLineKey.pub)[:])

	// copy the nonce
	copy(raw[lenKey:lenKey+lenNonce], s.nonce[:lenNonce])

	// make the agreedKey
	box.Precompute(&agreedKey, s.remoteKey.pub, s.localLineKey.prv)

	// encrypt p
	ctLen = len(box.SealAfterPrecomputation(raw[lenKey+lenNonce:lenKey+lenNonce], in, s.nonce, &agreedKey))

	// Sign message
	s.sign(raw[lenKey+lenNonce+ctLen:], s.nonce[:lenNonce], raw[:lenKey+lenNonce+ctLen])

	out.SetLen(lenKey + lenNonce + ctLen + lenAuth)

	return out.Get(nil), nil
}
Esempio n. 5
0
func New(body []byte) *Packet {
	pkt := pktPool.Get().(*Packet)

	if len(body) > 0 {
		pkt.body = bufpool.New().Set(body)
	}

	return pkt
}
Esempio n. 6
0
func (s *state) EncryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	var (
		outer   *lob.Packet
		inner   *bufpool.Buffer
		body    *bufpool.Buffer
		bodyRaw []byte
		nonce   [lenNonce]byte
		ctLen   int
		err     error
	)

	if !s.CanEncryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	// encode inner packet
	inner, err = lob.Encode(pkt)
	if err != nil {
		return nil, err
	}

	// make nonce
	copy(nonce[:], s.pktNoncePrefix[:])
	nonceSuffix := atomic.AddUint64(&s.pktNonceSuffix, 1)
	binary.BigEndian.PutUint64(nonce[16:], nonceSuffix)

	// alloc enough space
	body = bufpool.New().SetLen(lenToken + lenNonce + inner.Len() + box.Overhead)
	bodyRaw = body.RawBytes()

	// copy token
	copy(bodyRaw[:lenToken], s.remoteToken[:])

	// copy nonce
	copy(bodyRaw[lenToken:lenToken+lenNonce], nonce[:])

	// encrypt inner packet
	ctLen = len(box.SealAfterPrecomputation(
		bodyRaw[lenToken+lenNonce:lenToken+lenNonce], inner.RawBytes(), &nonce, s.lineEncryptionKey))
	body.SetLen(lenToken + lenNonce + ctLen)

	outer = lob.New(body.RawBytes())
	inner.Free()
	body.Free()

	return outer, nil
}
Esempio n. 7
0
func (c *HalfPipe) PushMessage(p []byte) {
	c.mtx.Lock()

	if c.closed {
		c.mtx.Unlock()
		return
	}

	c.readQueue = append(c.readQueue, bufpool.New().Set(p))

	c.cndRead.Signal()
	c.mtx.Unlock()
}
Esempio n. 8
0
func (mod *module) handle_peer(ch *e3x.Channel) {
	defer ch.Kill()

	log := mod.log.From(ch.RemoteHashname()).To(mod.e.LocalHashname())

	// MUST allow router role
	if mod.config.DisableRouter {
		log.Println("drop: router disabled")
		return
	}

	pkt, err := ch.ReadPacket()
	if err != nil {
		log.Printf("drop: failed to read packet: %s", err)
		return
	}

	peerStr, ok := pkt.Header().GetString("peer")
	if !ok {
		log.Printf("drop: no peer in packet")
		return
	}
	peer := hashname.H(peerStr)

	// MUST have link to either endpoint
	if mod.e.GetExchange(ch.RemoteHashname()) == nil && mod.e.GetExchange(peer) == nil {
		log.Printf("drop: no link to either peer")
		return
	}

	// MUST pass firewall
	if mod.config.AllowPeer != nil && !mod.config.AllowPeer(ch.RemoteHashname(), peer) {
		log.Printf("drop: blocked by firewall")
		return
	}

	ex := mod.e.GetExchange(peer)
	if ex == nil {
		log.Printf("drop: no exchange to target")
		// resolve?
		return
	}

	token := cipherset.ExtractToken(pkt.Body(nil))
	if token != cipherset.ZeroToken {
		// add bridge back to requester
		mod.RouteToken(token, ch.Exchange())
	}

	mod.connect(ex, bufpool.New().Set(pkt.Body(nil)))
}
Esempio n. 9
0
// Decode a packet
func Decode(p *bufpool.Buffer) (*Packet, error) {
	var (
		length int
		head   []byte
		body   []byte
		bytes  = p.RawBytes()
	)

	if len(bytes) < 2 {
		return nil, ErrInvalidPacket
	}

	length = int(binary.BigEndian.Uint16(bytes))
	if length+2 > len(bytes) {
		return nil, ErrInvalidPacket
	}

	head = bytes[2 : 2+length]
	if len(head) == 0 {
		head = nil
	}

	pkt := pktPool.Get().(*Packet)

	body = bytes[2+length:]
	if len(body) > 0 {
		pkt.body = bufpool.New().Set(body)
	}

	if len(head) >= 7 {
		err := parseHeader(pkt.Header(), head)
		if err != nil {
			pkt.Free()
			return nil, ErrInvalidPacket
		}
	} else if len(head) > 0 {
		pkt.Header().Bytes = append(make([]byte, 0, len(head)), head...)
	}

	return pkt, nil
}
Esempio n. 10
0
func (t *transport) Write(p []byte, dst dgram.Addr) (int, error) {
	a, ok := dst.(*inprocAddr)
	if !ok || a == nil {
		return 0, transports.ErrInvalidAddr
	}

	mtx.RLock()
	dstT := pipes[a.id]
	mtx.RUnlock()

	if dstT == nil {
		return 0, nil // drop
	}

	buf := bufpool.New().Set(p)

	func() {
		defer func() { recover() }()
		dstT.c <- packet{t.laddr, buf}
	}()

	return len(p), nil
}
Esempio n. 11
0
func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	if !s.CanDecryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	if !pkt.Header().IsZero() || pkt.BodyLen() < 16+4+4 {
		return nil, cipherset.ErrInvalidPacket
	}

	var (
		nonce    [16]byte
		bodyRaw  []byte
		innerRaw []byte
		innerLen = pkt.BodyLen() - (16 + 4 + 4)
		body     = bufpool.New()
		inner    = bufpool.New().SetLen(innerLen)
	)

	pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0])
	bodyRaw = body.RawBytes()
	innerRaw = inner.RawBytes()

	// compare token
	if !bytes.Equal(bodyRaw[:16], (*s.localToken)[:]) {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}

	// copy nonce
	copy(nonce[:], bodyRaw[16:16+4])

	{ // verify hmac
		mac := bodyRaw[16+4+innerLen:]

		macKey := append(s.lineDecryptionKey, nonce[:4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(bodyRaw[16+4 : 16+4+innerLen])
		if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 {
			inner.Free()
			body.Free()
			return nil, cipherset.ErrInvalidPacket
		}
	}

	{ // decrypt inner
		aesBlock, err := aes.NewCipher(s.lineDecryptionKey)
		if err != nil {
			inner.Free()
			body.Free()
			return nil, err
		}

		aes := Cipher.NewCTR(aesBlock, nonce[:])
		if aes == nil {
			inner.Free()
			body.Free()
			return nil, cipherset.ErrInvalidPacket
		}

		aes.XORKeyStream(innerRaw, bodyRaw[16+4:16+4+innerLen])
	}

	innerPkt, err := lob.Decode(inner)
	if err != nil {
		inner.Free()
		body.Free()
		return nil, err
	}

	inner.Free()
	body.Free()

	return innerPkt, nil
}
Esempio n. 12
0
func (s *state) EncryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	var (
		outer   *lob.Packet
		inner   *bufpool.Buffer
		body    *bufpool.Buffer
		bodyRaw []byte
		nonce   [16]byte
		ctLen   int
		err     error
	)

	if !s.CanEncryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	// encode inner packet
	inner, err = lob.Encode(pkt)
	if err != nil {
		return nil, err
	}

	ctLen = inner.Len()

	// make nonce
	_, err = io.ReadFull(rand.Reader, nonce[:4])
	if err != nil {
		return nil, err
	}

	// alloc enough space
	body = bufpool.New().SetLen(16 + 4 + ctLen + 4)
	bodyRaw = body.RawBytes()

	// copy token
	copy(bodyRaw[:16], (*s.remoteToken)[:])

	// copy nonce
	copy(bodyRaw[16:16+4], nonce[:])

	{ // encrypt inner
		aesBlock, err := aes.NewCipher(s.lineEncryptionKey)
		if err != nil {
			return nil, err
		}

		aes := Cipher.NewCTR(aesBlock, nonce[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aes.XORKeyStream(bodyRaw[16+4:16+4+ctLen], inner.RawBytes())
	}

	{ // compute HMAC
		macKey := append(s.lineEncryptionKey, bodyRaw[16:16+4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(bodyRaw[16+4 : 16+4+ctLen])
		sum := h.Sum(nil)
		copy(bodyRaw[16+4+ctLen:], fold(sum, 4))
	}

	outer = lob.New(body.RawBytes())
	inner.Free()
	body.Free()

	return outer, nil
}
Esempio n. 13
0
func (s *state) EncryptMessage(in []byte) ([]byte, error) {
	var (
		ctLen = len(in)
		out   = bufpool.New().SetLen(21 + 4 + ctLen + 4)
		raw   = out.RawBytes()
	)

	if !s.CanEncryptMessage() {
		panic("unable to encrypt message")
	}

	// copy public senderLineKey
	copy(raw[:21], s.localLineKey.Public())

	// copy the nonce
	_, err := io.ReadFull(rand.Reader, raw[21:21+4])
	if err != nil {
		return nil, err
	}

	{ // encrypt inner
		shared := ecdh.ComputeShared(
			secp160r1.P160(),
			s.remoteKey.pub.x, s.remoteKey.pub.y,
			s.localLineKey.prv.d)
		if shared == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aharedSum := sha256.Sum256(shared)
		aesKey := fold(aharedSum[:], 16)
		if aesKey == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aesBlock, err := aes.NewCipher(aesKey)
		if err != nil {
			return nil, err
		}

		var aesIv [16]byte
		copy(aesIv[:], raw[21:21+4])

		aes := Cipher.NewCTR(aesBlock, aesIv[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aes.XORKeyStream(raw[21+4:21+4+ctLen], in)
	}

	{ // compute HMAC
		macKey := ecdh.ComputeShared(secp160r1.P160(),
			s.remoteKey.pub.x, s.remoteKey.pub.y, s.localKey.prv.d)
		macKey = append(macKey, raw[21:21+4]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(raw[:21+4+ctLen])
		sum := h.Sum(nil)
		copy(raw[21+4+ctLen:], fold(sum, 4))
	}

	out.SetLen(21 + 4 + ctLen + 4)

	return out.Get(nil), nil
}
Esempio n. 14
0
func (c *cipher) DecryptHandshake(localKey cipherset.Key, p []byte) (cipherset.Handshake, error) {
	if len(p) < 21+4+4 {
		return nil, cipherset.ErrInvalidMessage
	}

	var (
		ctLen             = len(p) - (21 + 4 + 4)
		out               = bufpool.New()
		cs1aLocalKey, _   = localKey.(*key)
		remoteKey         *key
		remoteLineKey     *key
		hshake            *handshake
		remoteLineKeyData = p[:21]
		iv                = p[21 : 21+4]
		ciphertext        = p[21+4 : 21+4+ctLen]
		mac               = p[21+4+ctLen:]
	)

	if cs1aLocalKey == nil {
		return nil, cipherset.ErrInvalidState
	}

	{ // decrypt inner
		ephemX, ephemY := eccp.Unmarshal(secp160r1.P160(), remoteLineKeyData)
		if ephemX == nil || ephemY == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		shared := ecdh.ComputeShared(secp160r1.P160(), ephemX, ephemY, cs1aLocalKey.prv.d)
		if shared == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aharedSum := sha256.Sum256(shared)
		aesKey := fold(aharedSum[:], 16)
		if aesKey == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		aesBlock, err := aes.NewCipher(aesKey)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		var aesIv [16]byte
		copy(aesIv[:], iv)

		aes := Cipher.NewCTR(aesBlock, aesIv[:])
		if aes == nil {
			return nil, cipherset.ErrInvalidMessage
		}

		out.SetLen(ctLen)
		aes.XORKeyStream(out.RawBytes(), ciphertext)
		remoteLineKey = &key{}
		remoteLineKey.pub.x, remoteLineKey.pub.y = ephemX, ephemY
	}

	{ // decode inner
		inner, err := lob.Decode(out)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		at, hasAt := inner.Header().GetUint32("at")
		if !hasAt {
			return nil, cipherset.ErrInvalidMessage
		}

		delete(inner.Header().Extra, "at")

		parts, err := cipherset.PartsFromHeader(inner.Header())
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		if inner.BodyLen() != 21 {
			return nil, cipherset.ErrInvalidMessage
		}

		remoteKey = &key{}
		remoteKey.pub.x, remoteKey.pub.y = eccp.Unmarshal(secp160r1.P160(), inner.Body(nil))
		if !remoteKey.CanEncrypt() {
			return nil, cipherset.ErrInvalidMessage
		}

		hshake = &handshake{}
		hshake.at = at
		hshake.key = remoteKey
		hshake.lineKey = remoteLineKey
		hshake.parts = parts
	}

	{ // verify mac
		var nonce [16]byte
		copy(nonce[:], iv)

		macKey := ecdh.ComputeShared(secp160r1.P160(),
			remoteKey.pub.x, remoteKey.pub.y, cs1aLocalKey.prv.d)
		macKey = append(macKey, nonce[:]...)

		h := hmac.New(sha256.New, macKey)
		h.Write(p[:21+4+ctLen])
		if subtle.ConstantTimeCompare(mac, fold(h.Sum(nil), 4)) != 1 {
			return nil, cipherset.ErrInvalidMessage
		}
	}

	return hshake, nil
}
Esempio n. 15
0
func (e *Endpoint) accept(conn net.Conn) {
	var (
		token cipherset.Token
		msg   = bufpool.New()
		err   error
		n     int
	)
	n, err = conn.Read(msg.RawBytes()[:1500])
	if err != nil {
		msg.Free()
		conn.Close()
		return
	}
	msg.SetLen(n)

	// msg is either a handshake or a channel packet
	// when msg is a handshake decrypt it and pass it to the associated exchange
	// when msg is a channel packet lookup the exchange and pass it the msg
	// always associate the conn with the exchange

	if msg.Len() < 2 {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation {
			conn.Close()
		}
		msg.Free()
		return // to short
	}

	token = cipherset.ExtractToken(msg.RawBytes())
	e.mtx.Lock()
	exchange := e.tokens[token]
	e.mtx.Unlock()

	if exchange != nil {
		exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange)))
		return
	}

	if raw := msg.RawBytes(); len(raw) < 3 || raw[0] != 0 || raw[1] != 1 {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation {
			conn.Close()
		}
		msg.Free()
		return // to short
	}

	localIdent, err := e.LocalIdentity()
	if err != nil {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation {
			conn.Close()
		}
		e.traceDroppedPacket(msg.Get(nil), conn, err.Error())
		msg.Free()
		return // drop
	}

	// handle handshakes
	e.mtx.Lock()
	defer e.mtx.Unlock()

	var (
		csid = msg.RawBytes()[2]
		key  = e.keys[csid]
	)
	if key == nil {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, nil) != ErrStopPropagation {
			conn.Close()
		}
		msg.Free()
		return // no key for csid
	}

	handshake, err := cipherset.DecryptHandshake(csid, key, msg.RawBytes()[3:])
	if err != nil {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation {
			conn.Close()
		}
		e.traceDroppedPacket(msg.Get(nil), conn, err.Error())
		msg.Free()
		return // drop
	}

	hn, err := hashname.FromKeyAndIntermediates(csid,
		handshake.PublicKey().Public(), handshake.Parts())
	if err != nil {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation {
			conn.Close()
		}
		e.traceDroppedPacket(msg.Get(nil), conn, err.Error())
		msg.Free()
		return // drop
	}

	exchange = e.hashnames[hn]
	if exchange != nil {
		oldLocalToken := exchange.LocalToken()
		oldRemoteToken := exchange.RemoteToken()
		exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange)))
		newLocalToken := exchange.LocalToken()
		newRemoteToken := exchange.RemoteToken()

		if oldLocalToken != newLocalToken {
			delete(e.tokens, oldLocalToken)
			e.tokens[newLocalToken] = exchange
		}

		if oldRemoteToken != newRemoteToken {
			delete(e.tokens, oldRemoteToken)
			e.tokens[newRemoteToken] = exchange
		}

		return
	}

	exchange, err = newExchange(localIdent, nil, handshake, e.log, registerEndpoint(e))
	if err != nil {
		if e.endpointHooks.DropPacket(msg.Get(nil), conn, err) != ErrStopPropagation {
			conn.Close()
		}
		e.traceDroppedPacket(msg.Get(nil), conn, err.Error())
		msg.Free()
		return // drop
	}

	e.hashnames[hn] = exchange
	e.tokens[exchange.LocalToken()] = exchange
	e.tokens[exchange.RemoteToken()] = exchange
	exchange.state = ExchangeDialing
	exchange.received(newMessage(msg, newPipe(e.transport, conn, nil, exchange)))
}
Esempio n. 16
0
func (c *cipher) DecryptHandshake(localKey cipherset.Key, p []byte) (cipherset.Handshake, error) {
	if len(p) < lenKey+lenNonce+lenAuth {
		return nil, cipherset.ErrInvalidMessage
	}

	var (
		ctLen           = len(p) - (lenKey + lenNonce + lenAuth)
		out             = bufpool.New()
		handshake       = &handshake{}
		cs3aLocalKey, _ = localKey.(*key)
		at              uint32
		hasAt           bool
		mac             [lenAuth]byte
		nonce           [lenNonce]byte
		macKey          [lenKey]byte
		agreedKey       [lenKey]byte
		remoteKey       [lenKey]byte
		remoteLineKey   [lenKey]byte
		ciphertext      []byte
		ok              bool
	)

	if cs3aLocalKey == nil {
		return nil, cipherset.ErrInvalidState
	}

	copy(remoteLineKey[:], p[:lenKey])
	copy(nonce[:], p[lenKey:lenKey+lenNonce])
	copy(mac[:], p[lenKey+lenNonce+ctLen:])
	ciphertext = p[lenKey+lenNonce : lenKey+lenNonce+ctLen]

	// make agreedKey
	box.Precompute(&agreedKey, &remoteLineKey, cs3aLocalKey.prv)

	// decode BODY
	outBuf, ok := box.OpenAfterPrecomputation(out.RawBytes(), ciphertext, &nonce, &agreedKey)
	if !ok {
		return nil, cipherset.ErrInvalidMessage
	}
	out.SetLen(len(outBuf))

	{ // decode inner
		inner, err := lob.Decode(out)
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		at, hasAt = inner.Header().GetUint32("at")
		if !hasAt {
			return nil, cipherset.ErrInvalidMessage
		}

		delete(inner.Header().Extra, "at")

		parts, err := cipherset.PartsFromHeader(inner.Header())
		if err != nil {
			return nil, cipherset.ErrInvalidMessage
		}

		if inner.BodyLen() != lenKey {
			return nil, cipherset.ErrInvalidMessage
		}
		inner.Body(remoteKey[:0])

		handshake.at = at
		handshake.key = makeKey(nil, &remoteKey)
		handshake.lineKey = makeKey(nil, &remoteLineKey)
		handshake.parts = parts
	}

	{ // make macKey
		box.Precompute(&macKey, &remoteKey, cs3aLocalKey.prv)

		var (
			sha = sha256.New()
		)

		sha.Write(p[lenKey : lenKey+lenNonce])
		sha.Write(macKey[:])
		sha.Sum(macKey[:0])
	}

	if !poly1305.Verify(&mac, p[:lenKey+lenNonce+ctLen], &macKey) {
		return nil, cipherset.ErrInvalidMessage
	}

	return handshake, nil
}
Esempio n. 17
0
func (mod *module) handle_connect(ch *e3x.Channel) {
	defer ch.Kill()

	var (
		from        hashname.H
		localIdent  *e3x.Identity
		remoteIdent *e3x.Identity
		handshake   cipherset.Handshake
		innerData   = bufpool.New()
		err         error
	)

	localIdent, err = mod.e.LocalIdentity()
	if err != nil {
		return
	}

	pkt, err := ch.ReadPacket()
	if err != nil {
		return
	}

	pkt.Body(innerData.SetLen(pkt.BodyLen()).RawBytes()[:0])

	inner, err := lob.Decode(innerData)
	if err != nil {
		return
	}

	innerHdr := inner.Header()
	if innerHdr.IsBinary() && len(innerHdr.Bytes) == 1 {
		// handshake
		var (
			csid = innerHdr.Bytes[0]
			key  = localIdent.Keys()[csid]
		)
		if key == nil {
			return
		}

		handshake, err = cipherset.DecryptHandshake(csid, key, inner.Body(nil))
		if err != nil {
			return
		}

		from, err = hashname.FromIntermediates(handshake.Parts())
		if err != nil {
			return
		}

		remoteIdent, err = e3x.NewIdentity(cipherset.Keys{
			handshake.CSID(): handshake.PublicKey(),
		}, handshake.Parts(), nil)
		if err != nil {
			return
		}

	} else {
		// key packet

		var parts = make(cipherset.Parts)
		var csid uint8
		for key, value := range inner.Header().Extra {
			if len(key) != 2 {
				continue
			}

			keyData, err := hex.DecodeString(key)
			if err != nil {
				continue
			}

			partCSID := keyData[0]
			switch v := value.(type) {
			case bool:
				csid = partCSID
			case string:
				parts[partCSID] = v
			}
		}

		hn, err := hashname.FromKeyAndIntermediates(csid, inner.Body(nil), parts)
		if err != nil {
			return
		}

		from = hn

		pubKey, err := cipherset.DecodeKeyBytes(csid, inner.Body(nil), nil)
		if err != nil {
			return
		}

		remoteIdent, err = e3x.NewIdentity(cipherset.Keys{csid: pubKey}, parts, nil)
		if err != nil {
			return
		}
	}

	if from == "" {
		return
	}

	if mod.config.AllowConnect != nil && !mod.config.AllowConnect(from, ch.RemoteHashname()) {
		return
	}

	x, err := mod.e.CreateExchange(remoteIdent)
	if err != nil {
		return
	}

	// when the BODY contains a handshake
	if handshake != nil {
		routerExchange := ch.Exchange()
		routerAddr := &peerAddr{
			router: routerExchange.RemoteHashname(),
		}

		conn := newConnection(x.RemoteHashname(), routerAddr, routerExchange, func() {
			mod.unregisterConnection(routerExchange, x.LocalToken())
		})

		pipe, added := x.AddPipeConnection(conn, nil)
		if added {
			mod.registerConnection(routerExchange, x.LocalToken(), conn)
		}

		resp, ok := x.ApplyHandshake(handshake, pipe)
		if !ok {
			return
		}

		if resp != nil {
			err = mod.peerVia(ch.Exchange(), from, resp)
			if err != nil {
				return
			}
		}
	}

	// when the BODY contains a key packet
	if handshake == nil {
		pkt, err := x.GenerateHandshake()
		if err != nil {
			return
		}

		err = mod.peerVia(ch.Exchange(), from, pkt)
		if err != nil {
			return
		}
	}

	// Notify on-exchange callbacks
	mod.getIntroduction(from).resolve(x, nil)
}
Esempio n. 18
0
func (s *state) DecryptPacket(pkt *lob.Packet) (*lob.Packet, error) {
	s.mtx.RLock()
	defer s.mtx.RUnlock()

	if !s.CanDecryptPacket() {
		return nil, cipherset.ErrInvalidState
	}
	if pkt == nil {
		return nil, nil
	}

	if !pkt.Header().IsZero() || pkt.BodyLen() < lenToken+lenNonce {
		return nil, cipherset.ErrInvalidPacket
	}

	var (
		nonce    [lenNonce]byte
		bodyRaw  []byte
		innerRaw []byte
		innerPkt *lob.Packet
		body     = bufpool.New()
		inner    = bufpool.New()
		ok       bool
	)

	pkt.Body(body.SetLen(pkt.BodyLen()).RawBytes()[:0])
	bodyRaw = body.RawBytes()
	innerRaw = inner.RawBytes()

	// compare token
	if !bytes.Equal(bodyRaw[:lenToken], (*s.localToken)[:]) {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}

	// copy nonce
	copy(nonce[:], bodyRaw[lenToken:lenToken+lenNonce])

	// decrypt inner packet
	innerRaw, ok = box.OpenAfterPrecomputation(
		innerRaw[:0], bodyRaw[lenToken+lenNonce:], &nonce, s.lineDecryptionKey)
	if !ok {
		inner.Free()
		body.Free()
		return nil, cipherset.ErrInvalidPacket
	}
	inner.SetLen(len(innerRaw))

	innerPkt, err := lob.Decode(inner)
	if err != nil {
		inner.Free()
		body.Free()
		return nil, err
	}

	inner.Free()
	body.Free()

	return innerPkt, nil
}