blob: 5a155d455a23790be0c47537cee8493df8d52019 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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 // TODO: Consider removing this
139 t.BaseLayer = BaseLayer{Contents: data[:len(data)]}
140
141 var h TLSRecordHeader
142 h.ContentType = TLSType(data[0])
143 h.Version = TLSVersion(binary.BigEndian.Uint16(data[1:3]))
144 h.Length = binary.BigEndian.Uint16(data[3:5])
145
146 if h.ContentType.String() == "Unknown" {
147 return errors.New("Unknown TLS record type")
148 }
149
150 hl := 5 // header length
151 tl := hl + int(h.Length)
152 if len(data) < tl {
153 df.SetTruncated()
154 return errors.New("TLS packet length mismatch")
155 }
156
157 switch h.ContentType {
158 default:
159 return errors.New("Unknown TLS record type")
160 case TLSChangeCipherSpec:
161 var r TLSChangeCipherSpecRecord
162 e := r.decodeFromBytes(h, data[hl:tl], df)
163 if e != nil {
164 return e
165 }
166 t.ChangeCipherSpec = append(t.ChangeCipherSpec, r)
167 case TLSAlert:
168 var r TLSAlertRecord
169 e := r.decodeFromBytes(h, data[hl:tl], df)
170 if e != nil {
171 return e
172 }
173 t.Alert = append(t.Alert, r)
174 case TLSHandshake:
175 var r TLSHandshakeRecord
176 e := r.decodeFromBytes(h, data[hl:tl], df)
177 if e != nil {
178 return e
179 }
180 t.Handshake = append(t.Handshake, r)
181 case TLSApplicationData:
182 var r TLSAppDataRecord
183 e := r.decodeFromBytes(h, data[hl:tl], df)
184 if e != nil {
185 return e
186 }
187 t.AppData = append(t.AppData, r)
188 }
189
190 if len(data) == tl {
191 return nil
192 }
193 return t.decodeTLSRecords(data[tl:len(data)], df)
194}
195
196// CanDecode implements gopacket.DecodingLayer.
197func (t *TLS) CanDecode() gopacket.LayerClass {
198 return LayerTypeTLS
199}
200
201// NextLayerType implements gopacket.DecodingLayer.
202func (t *TLS) NextLayerType() gopacket.LayerType {
203 return gopacket.LayerTypeZero
204}
205
206// Payload returns nil, since TLS encrypted payload is inside TLSAppDataRecord
207func (t *TLS) Payload() []byte {
208 return nil
209}
210
211// SerializeTo writes the serialized form of this layer into the
212// SerializationBuffer, implementing gopacket.SerializableLayer.
213func (t *TLS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
214 totalLength := 0
215 for _, record := range t.ChangeCipherSpec {
216 if opts.FixLengths {
217 record.Length = 1
218 }
219 totalLength += 5 + 1 // length of header + record
220 }
221 for range t.Handshake {
222 totalLength += 5
223 // TODO
224 }
225 for _, record := range t.AppData {
226 if opts.FixLengths {
227 record.Length = uint16(len(record.Payload))
228 }
229 totalLength += 5 + len(record.Payload)
230 }
231 for _, record := range t.Alert {
232 if len(record.EncryptedMsg) == 0 {
233 if opts.FixLengths {
234 record.Length = 2
235 }
236 totalLength += 5 + 2
237 } else {
238 if opts.FixLengths {
239 record.Length = uint16(len(record.EncryptedMsg))
240 }
241 totalLength += 5 + len(record.EncryptedMsg)
242 }
243 }
244 data, err := b.PrependBytes(totalLength)
245 if err != nil {
246 return err
247 }
248 off := 0
249 for _, record := range t.ChangeCipherSpec {
250 off = encodeHeader(record.TLSRecordHeader, data, off)
251 data[off] = byte(record.Message)
252 off++
253 }
254 for _, record := range t.Handshake {
255 off = encodeHeader(record.TLSRecordHeader, data, off)
256 // TODO
257 }
258 for _, record := range t.AppData {
259 off = encodeHeader(record.TLSRecordHeader, data, off)
260 copy(data[off:], record.Payload)
261 off += len(record.Payload)
262 }
263 for _, record := range t.Alert {
264 off = encodeHeader(record.TLSRecordHeader, data, off)
265 if len(record.EncryptedMsg) == 0 {
266 data[off] = byte(record.Level)
267 data[off+1] = byte(record.Description)
268 off += 2
269 } else {
270 copy(data[off:], record.EncryptedMsg)
271 off += len(record.EncryptedMsg)
272 }
273 }
274 return nil
275}
276
277func encodeHeader(header TLSRecordHeader, data []byte, offset int) int {
278 data[offset] = byte(header.ContentType)
279 binary.BigEndian.PutUint16(data[offset+1:], uint16(header.Version))
280 binary.BigEndian.PutUint16(data[offset+3:], header.Length)
281
282 return offset + 5
283}