// 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) peerVia(router *e3x.Exchange, to hashname.H, body *bufpool.Buffer) error { ch, err := router.Open("peer", false) if err != nil { return err } defer ch.Kill() pkt := lob.New(body.RawBytes()) pkt.Header().SetString("peer", string(to)) ch.WritePacket(pkt) return nil }
func (mod *module) connect(ex *e3x.Exchange, inner *bufpool.Buffer) error { ch, err := ex.Open("connect", false) if err != nil { return err } defer ch.Kill() err = ch.WritePacket(lob.New(inner.RawBytes())) if err != nil { return err } return 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 (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) 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 }