Navigation Menu

Skip to content

Commit

Permalink
Add TLS layer serialization; bugfixes for layer memory reuse
Browse files Browse the repository at this point in the history
  • Loading branch information
jensenhwa authored and gconnell committed Aug 25, 2020
1 parent f6e4e27 commit d46e8eb
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -33,6 +33,7 @@ Jesse Ward <jesse@jesseward.com>
Kane Mathers <kane@kanemathers.name>
Jose Selvi <jselvi@pentester.es>
Yerden Zhumabekov <yerden.zhumabekov@gmail.com>
Jensen Hwa <jensenhwa@gmail.com>

-----------------------------------------------
FORKED FROM github.com/akrennmair/gopcap
Expand Down
1 change: 1 addition & 0 deletions layers/ip6.go
Expand Up @@ -512,6 +512,7 @@ func (i *IPv6HopByHop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback)
if err != nil {
return err
}
i.Options = i.Options[:0]
offset := 2
for offset < i.ActualLength {
opt, err := decodeIPv6HeaderTLVOption(data[offset:], df)
Expand Down
1 change: 1 addition & 0 deletions layers/tcp.go
Expand Up @@ -256,6 +256,7 @@ func (tcp *TCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
} else {
tcp.Options = tcp.Options[:0]
}
tcp.Padding = tcp.Padding[:0]
if tcp.DataOffset < 5 {
return fmt.Errorf("Invalid TCP data offset %d < 5", tcp.DataOffset)
}
Expand Down
65 changes: 65 additions & 0 deletions layers/tls.go
Expand Up @@ -135,6 +135,7 @@ func (t *TLS) decodeTLSRecords(data []byte, df gopacket.DecodeFeedback) error {

// since there are no further layers, the baselayer's content is
// pointing to this layer
// TODO: Consider removing this
t.BaseLayer = BaseLayer{Contents: data[:len(data)]}

var h TLSRecordHeader
Expand Down Expand Up @@ -206,3 +207,67 @@ func (t *TLS) NextLayerType() gopacket.LayerType {
func (t *TLS) Payload() []byte {
return nil
}

// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
func (t *TLS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
if !opts.FixLengths {
return errors.New("serialization of packets without fixing lengths has not been implemented yet")
}
totalLength := 0
for range t.ChangeCipherSpec {
totalLength += 5 + 1 // length of header + record
}
for range t.Handshake {
totalLength += 5
}
for _, record := range t.AppData {
totalLength += 5 + len(record.Payload)
}
for _, record := range t.Alert {
if len(record.EncryptedMsg) == 0 {
totalLength += 5 + 2
} else {
totalLength += 5 + len(record.EncryptedMsg)
}
}
data, err := b.PrependBytes(totalLength)
if err != nil {
return err
}
off := 0
for _, record := range t.ChangeCipherSpec {
off = encodeHeader(record.TLSRecordHeader, data, off)
data[off] = byte(record.Message)
off++
}
for _, record := range t.Handshake {
off = encodeHeader(record.TLSRecordHeader, data, off)
// TODO
}
for _, record := range t.AppData {
off = encodeHeader(record.TLSRecordHeader, data, off)
copy(data[off:], record.Payload)
off += len(record.Payload)
}
for _, record := range t.Alert {
off = encodeHeader(record.TLSRecordHeader, data, off)
if len(record.EncryptedMsg) == 0 {
data[off] = byte(record.Level)
data[off+1] = byte(record.Description)
off += 2
} else {
copy(data[off:], record.EncryptedMsg)
off += len(record.EncryptedMsg)
}
}
return nil
}

func encodeHeader(header TLSRecordHeader, data []byte, offset int) int {
data[offset] = byte(header.ContentType)
binary.BigEndian.PutUint16(data[offset+1:], uint16(header.Version))
binary.BigEndian.PutUint16(data[offset+3:], header.Length)

return offset + 5
}
52 changes: 50 additions & 2 deletions layers/tls_test.go
Expand Up @@ -245,9 +245,9 @@ func TestParseTLSClientHello(t *testing.T) {
}
}

func testTLSClientHelloDecodeFromBytes(t *testing.T) {
func TestTLSClientHelloDecodeFromBytes(t *testing.T) {
var got TLS
want := testClientKeyExchangeDecoded
want := *testClientKeyExchangeDecoded

if err := got.DecodeFromBytes(testClientKeyExchange, gopacket.NilDecodeFeedback); err != nil {
t.Errorf("TLS DecodeFromBytes first decode failed:\ngot:\n%#v\n\nwant:\n%#v\n\n", got, want)
Expand Down Expand Up @@ -300,6 +300,30 @@ func TestParseTLSAppData(t *testing.T) {
}
}

func TestSerializeTLSAppData(t *testing.T) {
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{FixLengths: true}
err := gopacket.SerializeLayers(buf, opts, testDoubleAppDataDecoded)
if err != nil {
t.Fatal(err)
}

p2 := gopacket.NewPacket(buf.Bytes(), LayerTypeTLS, testTLSDecodeOptions)
if p2.ErrorLayer() != nil {
t.Error("Failed to decode packet:", p2.ErrorLayer().Error())
}
checkLayers(p2, []gopacket.LayerType{LayerTypeTLS}, t)

if got, ok := p2.Layer(LayerTypeTLS).(*TLS); ok {
want := testDoubleAppDataDecoded
if !reflect.DeepEqual(got, want) {
t.Errorf("Reconstructed TLSAppData packet processing failed:\ngot:\n%#v\n\nwant:\n%#v\n\n", got, want)
}
} else {
t.Error("No TLS layer type found in reconstructed packet")
}
}

func TestParseTLSMalformed(t *testing.T) {
p := gopacket.NewPacket(testMalformed, LayerTypeTLS, testTLSDecodeOptions)
if p.ErrorLayer() == nil {
Expand Down Expand Up @@ -341,3 +365,27 @@ func TestParseTLSAlertEncrypted(t *testing.T) {
t.Error("No TLS layer type found in packet")
}
}

func TestSerializeTLSAlertEncrypted(t *testing.T) {
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{FixLengths: true}
err := gopacket.SerializeLayers(buf, opts, testAlertEncryptedDecoded)
if err != nil {
t.Fatal(err)
}

p2 := gopacket.NewPacket(buf.Bytes(), LayerTypeTLS, testTLSDecodeOptions)
if p2.ErrorLayer() != nil {
t.Error("Failed to decode packet:", p2.ErrorLayer().Error())
}
checkLayers(p2, []gopacket.LayerType{LayerTypeTLS}, t)

if got, ok := p2.Layer(LayerTypeTLS).(*TLS); ok {
want := testAlertEncryptedDecoded
if !reflect.DeepEqual(got, want) {
t.Errorf("Reconstructed TLSAlertEncrypted packet processing failed:\ngot:\n%#v\n\nwant:\n%#v\n\n", got, want)
}
} else {
t.Error("No TLS layer type found in reconstructed packet")
}
}

0 comments on commit d46e8eb

Please sign in to comment.