Skip to content

Commit

Permalink
Merge tests and tweaks with existing EAPOL_KEY class
Browse files Browse the repository at this point in the history
Added EAPOL-Key layer according to IEEE 802.11-2016 standard. Layer
includes helper function for guessing 4-way handshake key number.
  • Loading branch information
TheMadProphet authored and gpotter2 committed Feb 4, 2024
1 parent 280d596 commit 6d785f9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 8 deletions.
32 changes: 27 additions & 5 deletions scapy/layers/eap.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ class LEAP(EAP):

class EAPOL_KEY(Packet):
name = "EAPOL_KEY"
deprecated_fields = {
"key": ("key_data", "2.6.0"),
"len": ("key_length", "2.6.0"),
}
fields_desc = [
ByteEnumField("key_descriptor_type", 1, {1: "RC4", 2: "RSN"}),
# Key Information
Expand All @@ -458,20 +462,20 @@ class EAPOL_KEY(Packet):
3: "AES-128-CMAC+AES-128",
}),
#
LenField("len", None, "H"),
LenField("key_length", None, "H"),
LongField("key_replay_counter", 0),
XStrFixedLenField("key_nonce", "", 32),
XStrFixedLenField("key_iv", "", 16),
XStrFixedLenField("key_rsc", "", 8),
XStrFixedLenField("key_id", "", 8),
XStrFixedLenField("key_mic", "", 16), # XXX size can be 24
LenField("key_length", None, "H"),
XStrLenField("key", "",
length_from=lambda pkt: pkt.key_length)
FieldLenField("key_data_length", None, length_of="key_data"),
XStrLenField("key_data", "",
length_from=lambda pkt: pkt.key_data_length)
]

def extract_padding(self, s):
return s[:self.len], s[self.len:]
return s[:self.key_length], s[self.key_length:]

def hashret(self):
return struct.pack("!B", self.type) + self.payload.hashret()
Expand All @@ -482,6 +486,24 @@ def answers(self, other):
return 1
return 0

def guess_key_number(self):
"""
Determines 4-way handshake key number
:return: key number (1-4), or 0 if it cannot be determined
"""
if self.key_type == 1:
if self.key_ack == 1:
if self.key_mic == 0:
return 1
if self.install == 1:
return 3
else:
if self.secure == 0:
return 2
return 4
return 0


#############################################################################
# IEEE 802.1X-2010 - MACsec Key Agreement (MKA) protocol
Expand Down
84 changes: 81 additions & 3 deletions test/scapy/layers/eap.uts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,87 @@ assert wifi[EAPOL].key_ack == 1
assert wifi[EAPOL].key_type == 1
assert wifi[EAPOL].key_descriptor_type_version == 2
assert wifi[EAPOL].key_replay_counter == 4
assert wifi[EAPOL].key_mic == b"\x00" * 16
assert wifi[EAPOL].key_length == 22
assert len(wifi[EAPOL].key) == 22
assert wifi[EAPOL].has_key_mic == 0
assert wifi[EAPOL].key_data_length == 22
assert len(wifi[EAPOL].key_data) == 22

= EAPOL-Key - Key 1 - Dissection (1)
s = b'\x02\x03\x00\x75\x02\x00\x8a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x12\x6a\xce\x64\xc1\xa6\x44\xd2\x7b\x84\xe0\x39\x26\x3b\x63\x3b\xc3\x74\xe3\x29\x9d\x7d\x45\xe1\xc4\x25\x44\x05\x48\x05\xbf\xe5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\xdd\x14\x00\x0f\xac\x04\x05\xb1\xb6\x8b\x5a\x91\xfc\x04\x06\x83\x84\x06\xe8\xd1\x5f\xdb'
eapol = EAPOL(s)
assert(eapol.version == 2)
assert(eapol.type == 3)
assert(eapol.len == 117)
assert(eapol.haslayer(EAPOL_KEY))
eapol_key = eapol[EAPOL_KEY]
assert(eapol_key.key_descriptor_type == 2)
assert(eapol_key.key_descriptor_type_version == 2)
assert(eapol_key.key_type == 1)
assert(eapol_key.key_length == 16)
assert(eapol_key.install == 0)
assert(eapol_key.key_ack == 1)
assert(eapol_key.key_mic == b"\x00" * 16)
assert(eapol_key.secure == 0)
assert(eapol_key.key_data_length == 22)
assert(eapol_key.guess_key_number() == 0)

= EAPOL_KEY - Key 2 - Dissection (2)
s = b'\x02\x03\x00\x75\x02\x01\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x60\x5e\x85\xa7\x9c\xfa\xfd\xb0\xea\xa0\x50\x68\x3f\x97\xbe\x1b\x66\xde\xf7\xbc\x65\x20\x57\x31\x68\x71\xc2\x73\xc5\xae\x47\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91\x89\xcd\xf1\x88\x54\x8e\x73\xcd\x37\xd5\x78\x52\x66\x05\x88\x00\x16\x30\x14\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\x28\x00'
eapol = EAPOL(s)
assert(eapol.version == 2)
assert(eapol.type == 3)
assert(eapol.len == 117)
assert(eapol.haslayer(EAPOL_KEY))
eapol_key = eapol[EAPOL_KEY]
assert(eapol_key.key_descriptor_type == 2)
assert(eapol_key.key_descriptor_type_version == 2)
assert(eapol_key.key_type == 1)
assert(eapol_key.key_length == 16)
assert(eapol_key.install == 0)
assert(eapol_key.key_ack == 0)
assert(eapol_key.has_key_mic == 1)
assert(eapol_key.secure == 0)
assert(eapol_key.key_data_length == 22)
assert(eapol_key.guess_key_number() == 2)

= EAPOL_KEY - Key 3 - Dissection (3)
s = b'\x02\x03\x00\x97\x02\x13\xca\x00\x10\x00\x00\x00\x00\x00\x00\x00\x01\x12\x6a\xce\x64\xc1\xa6\x44\xd2\x7b\x84\xe0\x39\x26\x3b\x63\x3b\xc3\x74\xe3\x29\x9d\x7d\x45\xe1\xc4\x25\x44\x05\x48\x05\xbf\xe5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x1f\x1e\x80\xe7\x6c\xbf\x4a\x5c\xe9\xce\x84\x6d\x20\x7f\x7d\x00\x38\x10\xcc\x53\x66\x65\x5f\x7f\xf5\xd5\x5a\xf8\xc3\x87\x69\x85\xde\x7d\x96\xaa\xfd\x2b\x93\x48\x9f\x6c\xdf\x5f\x9c\x26\x2b\xe1\xad\x21\xeb\xce\x62\xc9\x4d\x88\x97\x1f\xd7\x5e\x23\xf6\x96\xf6\xc0\xe0\x1e\xf3\x52\x85\xe2\xf2\xcc'
eapol = EAPOL(s)
assert(eapol.version == 2)
assert(eapol.type == 3)
assert(eapol.len == 151)
assert(eapol.haslayer(EAPOL_KEY))
eapol_key = eapol[EAPOL_KEY]
assert(eapol_key.key_descriptor_type == 2)
assert(eapol_key.key_descriptor_type_version == 2)
assert(eapol_key.key_type == 1)
assert(eapol_key.key_length == 16)
assert(eapol_key.install == 1)
assert(eapol_key.key_ack == 1)
assert(eapol_key.has_key_mic == 1)
assert(eapol_key.secure == 1)
assert(eapol_key.key_data_length == 56)
assert(eapol_key.guess_key_number() == 3)

= EAPOL_KEY - Key 4 - Dissection (4)
s = b'\x02\x03\x00\x5f\x02\x03\x0a\x00\x10\x00\x00\x00\x00\x00\x00\x00\x01\x60\x5e\x85\xa7\x9c\xfa\xfd\xb0\xea\xa0\x50\x68\x3f\x97\xbe\x1b\x66\xde\xf7\xbc\x65\x20\x57\x31\x68\x71\xc2\x73\xc5\xae\x47\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x95\xe1\x76\xeb\x6b\xba\xc1\x6e\x06\x16\xb4\x14\x94\xd6\x0a\x00\x00'
eapol = EAPOL(s)
assert(eapol.version == 2)
assert(eapol.type == 3)
assert(eapol.len == 95)
assert(eapol.haslayer(EAPOL_KEY))
eapol_key = eapol[EAPOL_KEY]
assert(eapol_key.key_descriptor_type == 2)
assert(eapol_key.key_descriptor_type_version == 2)
assert(eapol_key.key_type == 1)
assert(eapol_key.key_length == 16)
assert(eapol_key.install == 0)
assert(eapol_key.key_ack == 0)
assert(eapol_key.has_key_mic == 1)
assert(eapol_key.secure == 1)
assert(eapol_key.key_data_length == 0)
assert(eapol_key.key_data == b'')
assert(eapol_key.guess_key_number() == 4)


############
############
Expand Down

0 comments on commit 6d785f9

Please sign in to comment.