예제 #1
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)
}
예제 #2
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
}
예제 #3
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
}
예제 #4
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
}
예제 #5
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
}