Naveen Sampath | 04696f7 | 2022-06-13 15:19:14 +0530 | [diff] [blame^] | 1 | // 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 | |
| 7 | package layers |
| 8 | |
| 9 | import ( |
| 10 | "encoding/binary" |
| 11 | "fmt" |
| 12 | "github.com/google/gopacket" |
| 13 | ) |
| 14 | |
| 15 | // EAPOL defines an EAP over LAN (802.1x) layer. |
| 16 | type EAPOL struct { |
| 17 | BaseLayer |
| 18 | Version uint8 |
| 19 | Type EAPOLType |
| 20 | Length uint16 |
| 21 | } |
| 22 | |
| 23 | // LayerType returns LayerTypeEAPOL. |
| 24 | func (e *EAPOL) LayerType() gopacket.LayerType { return LayerTypeEAPOL } |
| 25 | |
| 26 | // DecodeFromBytes decodes the given bytes into this layer. |
| 27 | func (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 |
| 41 | func (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. |
| 50 | func (e *EAPOL) CanDecode() gopacket.LayerClass { |
| 51 | return LayerTypeEAPOL |
| 52 | } |
| 53 | |
| 54 | // NextLayerType returns the layer type contained by this DecodingLayer. |
| 55 | func (e *EAPOL) NextLayerType() gopacket.LayerType { |
| 56 | return e.Type.LayerType() |
| 57 | } |
| 58 | |
| 59 | func 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 |
| 66 | type EAPOLKeyDescriptorType uint8 |
| 67 | |
| 68 | // Enumeration of EAPOLKeyDescriptorType |
| 69 | const ( |
| 70 | EAPOLKeyDescriptorTypeRC4 EAPOLKeyDescriptorType = 1 |
| 71 | EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2 |
| 72 | EAPOLKeyDescriptorTypeWPA EAPOLKeyDescriptorType = 254 |
| 73 | ) |
| 74 | |
| 75 | func (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) |
| 91 | type EAPOLKeyDescriptorVersion uint8 |
| 92 | |
| 93 | // Enumeration of EAPOLKeyDescriptorVersion |
| 94 | const ( |
| 95 | EAPOLKeyDescriptorVersionOther EAPOLKeyDescriptorVersion = 0 |
| 96 | EAPOLKeyDescriptorVersionRC4HMACMD5 EAPOLKeyDescriptorVersion = 1 |
| 97 | EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2 |
| 98 | EAPOLKeyDescriptorVersionAES128CMAC EAPOLKeyDescriptorVersion = 3 |
| 99 | ) |
| 100 | |
| 101 | func (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. |
| 118 | type EAPOLKeyType uint8 |
| 119 | |
| 120 | // Enumeration of EAPOLKeyType |
| 121 | const ( |
| 122 | EAPOLKeyTypeGroupSMK EAPOLKeyType = 0 |
| 123 | EAPOLKeyTypePairwise EAPOLKeyType = 1 |
| 124 | ) |
| 125 | |
| 126 | func (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 |
| 138 | type 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. |
| 164 | func (ek *EAPOLKey) LayerType() gopacket.LayerType { |
| 165 | return LayerTypeEAPOLKey |
| 166 | } |
| 167 | |
| 168 | // CanDecode returns the set of layer types that this DecodingLayer can decode. |
| 169 | func (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. |
| 175 | func (ek *EAPOLKey) NextLayerType() gopacket.LayerType { |
| 176 | if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 { |
| 177 | return LayerTypeDot11InformationElement |
| 178 | } |
| 179 | return gopacket.LayerTypePayload |
| 180 | } |
| 181 | |
| 182 | const eapolKeyFrameLen = 95 |
| 183 | |
| 184 | // DecodeFromBytes decodes the given bytes into this layer. |
| 185 | func (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. |
| 244 | func (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 | |
| 299 | func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error { |
| 300 | ek := &EAPOLKey{} |
| 301 | return decodingLayerDecoder(ek, data, p) |
| 302 | } |