// 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 }
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 } }
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 }
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 }
func New(body []byte) *Packet { pkt := pktPool.Get().(*Packet) if len(body) > 0 { pkt.body = bufpool.New().Set(body) } return pkt }
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 }
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() }
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))) }
// 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 }
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 }
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 }
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 }
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 }
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 }
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))) }
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 }
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) }
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 }