summaryrefslogtreecommitdiff
path: root/packet.go
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2014-05-13 02:31:37 +0000
committerYawning Angel <yawning@schwanenlied.me>2014-05-13 02:31:37 +0000
commit9bfdd77f722807a611d6910bbef45084360064a1 (patch)
tree1cbc9c840bad373368ada0f8322e29ea6b24adf8 /packet.go
parent51a8dd5a86eeca744e0add680b1f4796c4babe2b (diff)
Add preliminary support for packet length obfuscation.
The same algorithm as ScrambleSuit is used, except: * SipHash-2-4 in OFB mode is used to create the distribution. * The system CSPRNG is used when sampling the distribution. This fixes most of #3, all that remains is generating and sending a persistent distribution on the server side to the client.
Diffstat (limited to 'packet.go')
-rw-r--r--packet.go24
1 files changed, 21 insertions, 3 deletions
diff --git a/packet.go b/packet.go
index afccc47..7bf4a6c 100644
--- a/packet.go
+++ b/packet.go
@@ -79,12 +79,25 @@ func makePacket(pkt []byte, pktType uint8, data []byte, padLen uint16) int {
pkt[0] = pktType
binary.BigEndian.PutUint16(pkt[1:], uint16(len(data)))
- copy(pkt[3:], data[:])
+ if len(data) > 0 {
+ copy(pkt[3:], data[:])
+ }
copy(pkt[3+len(data):], zeroPadBytes[:padLen])
return pktLen
}
+func (c *Obfs4Conn) makeAndEncryptPacket(pktType uint8, data []byte, padLen uint16) (int, []byte, error) {
+ var pkt [framing.MaximumFramePayloadLength]byte
+
+ // Wrap the payload in a packet.
+ n := makePacket(pkt[:], pktType, data[:], padLen)
+
+ // Encode the packet in an AEAD frame.
+ n, frame, err := c.encoder.Encode(pkt[:n])
+ return n, frame, err
+}
+
func (c *Obfs4Conn) decodePacket(pkt []byte) error {
if len(pkt) < packetOverhead {
return InvalidPacketLengthError(len(pkt))
@@ -99,8 +112,13 @@ func (c *Obfs4Conn) decodePacket(pkt []byte) error {
payload := pkt[3 : 3+payloadLen]
switch pktType {
case packetTypePayload:
- // packetTypePayload
- c.receiveDecodedBuffer.Write(payload)
+ if len(payload) > 0 {
+ c.receiveDecodedBuffer.Write(payload)
+ }
+ case packetTypePrngSeed:
+ if len(payload) == distSeedLength {
+ c.probDist.reset(payload)
+ }
default:
// Ignore unrecognised packet types.
}