1// Copyright 2018 The GoPacket Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree.
6
7package layers
8
9import (
10	"encoding/binary"
11	"errors"
12
13	"github.com/google/gopacket"
14)
15
16// TLSType defines the type of data after the TLS Record
17type TLSType uint8
18
19// TLSType known values.
20const (
21	TLSChangeCipherSpec TLSType = 20
22	TLSAlert            TLSType = 21
23	TLSHandshake        TLSType = 22
24	TLSApplicationData  TLSType = 23
25	TLSUnknown          TLSType = 255
26)
27
28// String shows the register type nicely formatted
29func (tt TLSType) String() string {
30	switch tt {
31	default:
32		return "Unknown"
33	case TLSChangeCipherSpec:
34		return "Change Cipher Spec"
35	case TLSAlert:
36		return "Alert"
37	case TLSHandshake:
38		return "Handshake"
39	case TLSApplicationData:
40		return "Application Data"
41	}
42}
43
44// TLSVersion represents the TLS version in numeric format
45type TLSVersion uint16
46
47// Strings shows the TLS version nicely formatted
48func (tv TLSVersion) String() string {
49	switch tv {
50	default:
51		return "Unknown"
52	case 0x0200:
53		return "SSL 2.0"
54	case 0x0300:
55		return "SSL 3.0"
56	case 0x0301:
57		return "TLS 1.0"
58	case 0x0302:
59		return "TLS 1.1"
60	case 0x0303:
61		return "TLS 1.2"
62	case 0x0304:
63		return "TLS 1.3"
64	}
65}
66
67// TLS is specified in RFC 5246
68//
69//  TLS Record Protocol
70//  0  1  2  3  4  5  6  7  8
71//  +--+--+--+--+--+--+--+--+
72//  |     Content Type      |
73//  +--+--+--+--+--+--+--+--+
74//  |    Version (major)    |
75//  +--+--+--+--+--+--+--+--+
76//  |    Version (minor)    |
77//  +--+--+--+--+--+--+--+--+
78//  |        Length         |
79//  +--+--+--+--+--+--+--+--+
80//  |        Length         |
81//  +--+--+--+--+--+--+--+--+
82
83// TLS is actually a slide of TLSrecord structures
84type TLS struct {
85	BaseLayer
86
87	// TLS Records
88	ChangeCipherSpec []TLSChangeCipherSpecRecord
89	Handshake        []TLSHandshakeRecord
90	AppData          []TLSAppDataRecord
91	Alert            []TLSAlertRecord
92}
93
94// TLSRecordHeader contains all the information that each TLS Record types should have
95type TLSRecordHeader struct {
96	ContentType TLSType
97	Version     TLSVersion
98	Length      uint16
99}
100
101// LayerType returns gopacket.LayerTypeTLS.
102func (t *TLS) LayerType() gopacket.LayerType { return LayerTypeTLS }
103
104// decodeTLS decodes the byte slice into a TLS type. It also
105// setups the application Layer in PacketBuilder.
106func decodeTLS(data []byte, p gopacket.PacketBuilder) error {
107	t := &TLS{}
108	err := t.DecodeFromBytes(data, p)
109	if err != nil {
110		return err
111	}
112	p.AddLayer(t)
113	p.SetApplicationLayer(t)
114	return nil
115}
116
117// DecodeFromBytes decodes the slice into the TLS struct.
118func (t *TLS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
119	t.BaseLayer.Contents = data
120	t.BaseLayer.Payload = nil
121
122	t.ChangeCipherSpec = t.ChangeCipherSpec[:0]
123	t.Handshake = t.Handshake[:0]
124	t.AppData = t.AppData[:0]
125	t.Alert = t.Alert[:0]
126
127	return t.decodeTLSRecords(data, df)
128}
129
130func (t *TLS) decodeTLSRecords(data []byte, df gopacket.DecodeFeedback) error {
131	if len(data) < 5 {
132		df.SetTruncated()
133		return errors.New("TLS record too short")
134	}
135
136	// since there are no further layers, the baselayer's content is
137	// pointing to this layer
138	t.BaseLayer = BaseLayer{Contents: data[:len(data)]}
139
140	var h TLSRecordHeader
141	h.ContentType = TLSType(data[0])
142	h.Version = TLSVersion(binary.BigEndian.Uint16(data[1:3]))
143	h.Length = binary.BigEndian.Uint16(data[3:5])
144
145	if h.ContentType.String() == "Unknown" {
146		return errors.New("Unknown TLS record type")
147	}
148
149	hl := 5 // header length
150	tl := hl + int(h.Length)
151	if len(data) < tl {
152		df.SetTruncated()
153		return errors.New("TLS packet length mismatch")
154	}
155
156	switch h.ContentType {
157	default:
158		return errors.New("Unknown TLS record type")
159	case TLSChangeCipherSpec:
160		var r TLSChangeCipherSpecRecord
161		e := r.decodeFromBytes(h, data[hl:tl], df)
162		if e != nil {
163			return e
164		}
165		t.ChangeCipherSpec = append(t.ChangeCipherSpec, r)
166	case TLSAlert:
167		var r TLSAlertRecord
168		e := r.decodeFromBytes(h, data[hl:tl], df)
169		if e != nil {
170			return e
171		}
172		t.Alert = append(t.Alert, r)
173	case TLSHandshake:
174		var r TLSHandshakeRecord
175		e := r.decodeFromBytes(h, data[hl:tl], df)
176		if e != nil {
177			return e
178		}
179		t.Handshake = append(t.Handshake, r)
180	case TLSApplicationData:
181		var r TLSAppDataRecord
182		e := r.decodeFromBytes(h, data[hl:tl], df)
183		if e != nil {
184			return e
185		}
186		t.AppData = append(t.AppData, r)
187	}
188
189	if len(data) == tl {
190		return nil
191	}
192	return t.decodeTLSRecords(data[tl:len(data)], df)
193}
194
195// CanDecode implements gopacket.DecodingLayer.
196func (t *TLS) CanDecode() gopacket.LayerClass {
197	return LayerTypeTLS
198}
199
200// NextLayerType implements gopacket.DecodingLayer.
201func (t *TLS) NextLayerType() gopacket.LayerType {
202	return gopacket.LayerTypeZero
203}
204
205// Payload returns nil, since TLS encrypted payload is inside TLSAppDataRecord
206func (t *TLS) Payload() []byte {
207	return nil
208}
209