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