func (c *Channel) traceReceivedPacket(pkt *lob.Packet) { if tracer.Enabled { tracer.Emit("channel.rcv.packet", tracer.Info{ "channel_id": c.TID, "packet_id": pkt.TID, "packet": tracer.Info{ "header": pkt.Header(), "body": base64.StdEncoding.EncodeToString(pkt.Body(nil)), }, }) } }
func TestPingPong(t *testing.T) { // t.Parallel() logs.ResetLogger() withTwoEndpoints(t, func(A, B *Endpoint) { var ( assert = assert.New(t) c *Channel ident *Identity pkt *lob.Packet err error ) go func() { c, err := A.Listen("ping", false).AcceptChannel() c.SetDeadline(time.Now().Add(10 * time.Second)) if assert.NoError(err) && assert.NotNil(c) { defer c.Close() pkt, err = c.ReadPacket() if assert.NoError(err) && assert.NotNil(pkt) { assert.Equal("ping", string(pkt.Body(nil))) err = c.WritePacket(lob.New([]byte("pong"))) assert.NoError(err) } } }() ident, err = A.LocalIdentity() assert.NoError(err) c, err = B.Open(ident, "ping", false) assert.NoError(err) if assert.NotNil(c) { defer c.Close() c.SetDeadline(time.Now().Add(10 * time.Second)) err = c.WritePacket(lob.New([]byte("ping"))) assert.NoError(err) pkt, err = c.ReadPacket() if assert.NoError(err) && assert.NotNil(pkt) { assert.Equal("pong", string(pkt.Body(nil))) } } }) }
func (c *Channel) traceDroppedPacket(pkt *lob.Packet, reason string) { if tracer.Enabled { info := tracer.Info{ "channel_id": c.TID, "packet_id": pkt.TID, "reason": reason, } if pkt != nil { info["packet"] = tracer.Info{ "header": pkt.Header(), "body": base64.StdEncoding.EncodeToString(pkt.Body(nil)), } } tracer.Emit("channel.rcv.packet", info) } }
func (c *Channel) traceWrite(pkt *lob.Packet, p *Pipe) { if tracer.Enabled { info := tracer.Info{ "channel_id": c.TID, } if p != nil { info["path"] = p.RemoteAddr().String() } if pkt != nil { info["packet_id"] = pkt.TID info["packet"] = tracer.Info{ "header": pkt.Header(), "body": base64.StdEncoding.EncodeToString(pkt.Body(nil)), } } tracer.Emit("channel.write", info) } }
func (c *Channel) traceWriteError(pkt *lob.Packet, p *Pipe, reason error) error { if tracer.Enabled { info := tracer.Info{ "channel_id": c.TID, "reason": reason.Error(), } if p != nil { info["path"] = p.RemoteAddr().String() } if pkt != nil { info["packet_id"] = pkt.TID info["packet"] = tracer.Info{ "header": pkt.Header(), "body": base64.StdEncoding.EncodeToString(pkt.Body(nil)), } } tracer.Emit("channel.write.error", info) } return reason }
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 *cipherTestSuite) TestPacketEncryption() { var ( assert = s.Assertions c = s.cipher ) var ( ka cipherset.Key kb cipherset.Key sa cipherset.State sb cipherset.State ha cipherset.Handshake hb cipherset.Handshake pkt *lob.Packet box []byte err error ok bool ) ka, err = c.GenerateKey() assert.NoError(err) kb, err = c.GenerateKey() assert.NoError(err) sa, err = c.NewState(ka) assert.NoError(err) sb, err = c.NewState(kb) assert.NoError(err) err = sa.SetRemoteKey(kb) assert.NoError(err) box, err = sa.EncryptHandshake(1, nil) assert.NoError(err) hb, err = c.DecryptHandshake(kb, box) assert.NoError(err) ok = sb.ApplyHandshake(hb) assert.True(ok) box, err = sb.EncryptHandshake(1, nil) assert.NoError(err) ha, err = c.DecryptHandshake(ka, box) assert.NoError(err) ok = sa.ApplyHandshake(ha) assert.True(ok) pkt = lob.New([]byte("Hello world!")) pkt.Header().SetInt("foo", 0xbeaf) pkt, err = sa.EncryptPacket(pkt) assert.NoError(err) assert.NotNil(pkt) assert.Nil(pkt.Header().Bytes) assert.True(pkt.Header().IsZero()) assert.NotEmpty(pkt.Body) pkt, err = sb.DecryptPacket(pkt) assert.NoError(err) assert.NotNil(pkt) assert.Nil(pkt.Header().Bytes) assert.Equal(&lob.Header{Extra: map[string]interface{}{"foo": 0xbeaf}}, pkt.Header()) assert.Equal([]byte("Hello world!"), pkt.Body(nil)) pkt = lob.New([]byte("Bye world!")) pkt.Header().SetInt("bar", 0xdead) pkt, err = sb.EncryptPacket(pkt) assert.NoError(err) assert.NotNil(pkt) assert.Nil(pkt.Header().Bytes) assert.True(pkt.Header().IsZero()) assert.NotEmpty(pkt.Body) pkt, err = sa.DecryptPacket(pkt) assert.NoError(err) assert.NotNil(pkt) assert.Nil(pkt.Header().Bytes) assert.Equal(&lob.Header{Extra: map[string]interface{}{"bar": 0xdead}}, pkt.Header()) assert.Equal([]byte("Bye world!"), pkt.Body(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 }