blob: 902598a2069118666fc1c134a45ae398a065458c [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// Copyright 2012 Google, Inc. 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 "fmt"
12 "github.com/google/gopacket"
13)
14
15// EAPOL defines an EAP over LAN (802.1x) layer.
16type EAPOL struct {
17 BaseLayer
18 Version uint8
19 Type EAPOLType
20 Length uint16
21}
22
23// LayerType returns LayerTypeEAPOL.
24func (e *EAPOL) LayerType() gopacket.LayerType { return LayerTypeEAPOL }
25
26// DecodeFromBytes decodes the given bytes into this layer.
27func (e *EAPOL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
28 if len(data) < 4 {
29 df.SetTruncated()
30 return fmt.Errorf("EAPOL length %d too short", len(data))
31 }
32 e.Version = data[0]
33 e.Type = EAPOLType(data[1])
34 e.Length = binary.BigEndian.Uint16(data[2:4])
35 e.BaseLayer = BaseLayer{data[:4], data[4:]}
36 return nil
37}
38
39// SerializeTo writes the serialized form of this layer into the
40// SerializationBuffer, implementing gopacket.SerializableLayer
41func (e *EAPOL) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
42 bytes, _ := b.PrependBytes(4)
43 bytes[0] = e.Version
44 bytes[1] = byte(e.Type)
45 binary.BigEndian.PutUint16(bytes[2:], e.Length)
46 return nil
47}
48
49// CanDecode returns the set of layer types that this DecodingLayer can decode.
50func (e *EAPOL) CanDecode() gopacket.LayerClass {
51 return LayerTypeEAPOL
52}
53
54// NextLayerType returns the layer type contained by this DecodingLayer.
55func (e *EAPOL) NextLayerType() gopacket.LayerType {
56 return e.Type.LayerType()
57}
58
59func decodeEAPOL(data []byte, p gopacket.PacketBuilder) error {
60 e := &EAPOL{}
61 return decodingLayerDecoder(e, data, p)
62}
63
64// EAPOLKeyDescriptorType is an enumeration of key descriptor types
65// as specified by 802.1x in the EAPOL-Key frame
66type EAPOLKeyDescriptorType uint8
67
68// Enumeration of EAPOLKeyDescriptorType
69const (
70 EAPOLKeyDescriptorTypeRC4 EAPOLKeyDescriptorType = 1
71 EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2
72 EAPOLKeyDescriptorTypeWPA EAPOLKeyDescriptorType = 254
73)
74
75func (kdt EAPOLKeyDescriptorType) String() string {
76 switch kdt {
77 case EAPOLKeyDescriptorTypeRC4:
78 return "RC4"
79 case EAPOLKeyDescriptorTypeDot11:
80 return "802.11"
81 case EAPOLKeyDescriptorTypeWPA:
82 return "WPA"
83 default:
84 return fmt.Sprintf("unknown descriptor type %d", kdt)
85 }
86}
87
88// EAPOLKeyDescriptorVersion is an enumeration of versions specifying the
89// encryption algorithm for the key data and the authentication for the
90// message integrity code (MIC)
91type EAPOLKeyDescriptorVersion uint8
92
93// Enumeration of EAPOLKeyDescriptorVersion
94const (
95 EAPOLKeyDescriptorVersionOther EAPOLKeyDescriptorVersion = 0
96 EAPOLKeyDescriptorVersionRC4HMACMD5 EAPOLKeyDescriptorVersion = 1
97 EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2
98 EAPOLKeyDescriptorVersionAES128CMAC EAPOLKeyDescriptorVersion = 3
99)
100
101func (v EAPOLKeyDescriptorVersion) String() string {
102 switch v {
103 case EAPOLKeyDescriptorVersionOther:
104 return "Other"
105 case EAPOLKeyDescriptorVersionRC4HMACMD5:
106 return "RC4-HMAC-MD5"
107 case EAPOLKeyDescriptorVersionAESHMACSHA1:
108 return "AES-HMAC-SHA1-128"
109 case EAPOLKeyDescriptorVersionAES128CMAC:
110 return "AES-128-CMAC"
111 default:
112 return fmt.Sprintf("unknown version %d", v)
113 }
114}
115
116// EAPOLKeyType is an enumeration of key derivation types describing
117// the purpose of the keys being derived.
118type EAPOLKeyType uint8
119
120// Enumeration of EAPOLKeyType
121const (
122 EAPOLKeyTypeGroupSMK EAPOLKeyType = 0
123 EAPOLKeyTypePairwise EAPOLKeyType = 1
124)
125
126func (kt EAPOLKeyType) String() string {
127 switch kt {
128 case EAPOLKeyTypeGroupSMK:
129 return "Group/SMK"
130 case EAPOLKeyTypePairwise:
131 return "Pairwise"
132 default:
133 return fmt.Sprintf("unknown key type %d", kt)
134 }
135}
136
137// EAPOLKey defines an EAPOL-Key frame for 802.1x authentication
138type EAPOLKey struct {
139 BaseLayer
140 KeyDescriptorType EAPOLKeyDescriptorType
141 KeyDescriptorVersion EAPOLKeyDescriptorVersion
142 KeyType EAPOLKeyType
143 KeyIndex uint8
144 Install bool
145 KeyACK bool
146 KeyMIC bool
147 Secure bool
148 MICError bool
149 Request bool
150 HasEncryptedKeyData bool
151 SMKMessage bool
152 KeyLength uint16
153 ReplayCounter uint64
154 Nonce []byte
155 IV []byte
156 RSC uint64
157 ID uint64
158 MIC []byte
159 KeyDataLength uint16
160 EncryptedKeyData []byte
161}
162
163// LayerType returns LayerTypeEAPOLKey.
164func (ek *EAPOLKey) LayerType() gopacket.LayerType {
165 return LayerTypeEAPOLKey
166}
167
168// CanDecode returns the set of layer types that this DecodingLayer can decode.
169func (ek *EAPOLKey) CanDecode() gopacket.LayerType {
170 return LayerTypeEAPOLKey
171}
172
173// NextLayerType returns layers.LayerTypeDot11InformationElement if the key
174// data exists and is unencrypted, otherwise it does not expect a next layer.
175func (ek *EAPOLKey) NextLayerType() gopacket.LayerType {
176 if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 {
177 return LayerTypeDot11InformationElement
178 }
179 return gopacket.LayerTypePayload
180}
181
182const eapolKeyFrameLen = 95
183
184// DecodeFromBytes decodes the given bytes into this layer.
185func (ek *EAPOLKey) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
186 if len(data) < eapolKeyFrameLen {
187 df.SetTruncated()
188 return fmt.Errorf("EAPOLKey length %v too short, %v required",
189 len(data), eapolKeyFrameLen)
190 }
191
192 ek.KeyDescriptorType = EAPOLKeyDescriptorType(data[0])
193
194 info := binary.BigEndian.Uint16(data[1:3])
195 ek.KeyDescriptorVersion = EAPOLKeyDescriptorVersion(info & 0x0007)
196 ek.KeyType = EAPOLKeyType((info & 0x0008) >> 3)
197 ek.KeyIndex = uint8((info & 0x0030) >> 4)
198 ek.Install = (info & 0x0040) != 0
199 ek.KeyACK = (info & 0x0080) != 0
200 ek.KeyMIC = (info & 0x0100) != 0
201 ek.Secure = (info & 0x0200) != 0
202 ek.MICError = (info & 0x0400) != 0
203 ek.Request = (info & 0x0800) != 0
204 ek.HasEncryptedKeyData = (info & 0x1000) != 0
205 ek.SMKMessage = (info & 0x2000) != 0
206
207 ek.KeyLength = binary.BigEndian.Uint16(data[3:5])
208 ek.ReplayCounter = binary.BigEndian.Uint64(data[5:13])
209
210 ek.Nonce = data[13:45]
211 ek.IV = data[45:61]
212 ek.RSC = binary.BigEndian.Uint64(data[61:69])
213 ek.ID = binary.BigEndian.Uint64(data[69:77])
214 ek.MIC = data[77:93]
215
216 ek.KeyDataLength = binary.BigEndian.Uint16(data[93:95])
217
218 totalLength := eapolKeyFrameLen + int(ek.KeyDataLength)
219 if len(data) < totalLength {
220 df.SetTruncated()
221 return fmt.Errorf("EAPOLKey data length %d too short, %d required",
222 len(data)-eapolKeyFrameLen, ek.KeyDataLength)
223 }
224
225 if ek.HasEncryptedKeyData {
226 ek.EncryptedKeyData = data[eapolKeyFrameLen:totalLength]
227 ek.BaseLayer = BaseLayer{
228 Contents: data[:totalLength],
229 Payload: data[totalLength:],
230 }
231 } else {
232 ek.BaseLayer = BaseLayer{
233 Contents: data[:eapolKeyFrameLen],
234 Payload: data[eapolKeyFrameLen:],
235 }
236 }
237
238 return nil
239}
240
241// SerializeTo writes the serialized form of this layer into the
242// SerializationBuffer, implementing gopacket.SerializableLayer.
243// See the docs for gopacket.SerializableLayer for more info.
244func (ek *EAPOLKey) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
245 buf, err := b.PrependBytes(eapolKeyFrameLen + len(ek.EncryptedKeyData))
246 if err != nil {
247 return err
248 }
249
250 buf[0] = byte(ek.KeyDescriptorType)
251
252 var info uint16
253 info |= uint16(ek.KeyDescriptorVersion)
254 info |= uint16(ek.KeyType) << 3
255 info |= uint16(ek.KeyIndex) << 4
256 if ek.Install {
257 info |= 0x0040
258 }
259 if ek.KeyACK {
260 info |= 0x0080
261 }
262 if ek.KeyMIC {
263 info |= 0x0100
264 }
265 if ek.Secure {
266 info |= 0x0200
267 }
268 if ek.MICError {
269 info |= 0x0400
270 }
271 if ek.Request {
272 info |= 0x0800
273 }
274 if ek.HasEncryptedKeyData {
275 info |= 0x1000
276 }
277 if ek.SMKMessage {
278 info |= 0x2000
279 }
280 binary.BigEndian.PutUint16(buf[1:3], info)
281
282 binary.BigEndian.PutUint16(buf[3:5], ek.KeyLength)
283 binary.BigEndian.PutUint64(buf[5:13], ek.ReplayCounter)
284
285 copy(buf[13:45], ek.Nonce)
286 copy(buf[45:61], ek.IV)
287 binary.BigEndian.PutUint64(buf[61:69], ek.RSC)
288 binary.BigEndian.PutUint64(buf[69:77], ek.ID)
289 copy(buf[77:93], ek.MIC)
290
291 binary.BigEndian.PutUint16(buf[93:95], ek.KeyDataLength)
292 if len(ek.EncryptedKeyData) > 0 {
293 copy(buf[95:95+len(ek.EncryptedKeyData)], ek.EncryptedKeyData)
294 }
295
296 return nil
297}
298
299func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error {
300 ek := &EAPOLKey{}
301 return decodingLayerDecoder(ek, data, p)
302}