Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scapy/layers/eap.py: 79%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Philippe Biondi <phil@secdev.org>
6"""
7Extensible Authentication Protocol (EAP)
8"""
11import struct
13from scapy.fields import (
14 BitEnumField,
15 BitField,
16 ByteEnumField,
17 ByteField,
18 ConditionalField,
19 FieldLenField,
20 FieldListField,
21 IntField,
22 LenField,
23 LongField,
24 PacketField,
25 PacketListField,
26 PadField,
27 ShortField,
28 StrLenField,
29 XByteField,
30 XIntField,
31 XStrField,
32 XStrFixedLenField,
33 XStrLenField,
34)
35from scapy.packet import (
36 Packet,
37 Padding,
38 bind_bottom_up,
39 bind_layers,
40 bind_top_down,
41)
42from scapy.layers.l2 import SourceMACField, Ether, CookedLinux, GRE, SNAP
43from scapy.config import conf
44from scapy.compat import orb, chb
46#
47# EAPOL
48#
50#########################################################################
51#
52# EAPOL protocol version
53# IEEE Std 802.1X-2010 - Section 11.3.1
54#########################################################################
55#
57eapol_versions = {
58 0x1: "802.1X-2001",
59 0x2: "802.1X-2004",
60 0x3: "802.1X-2010",
61}
63#########################################################################
64#
65# EAPOL Packet Types
66# IEEE Std 802.1X-2010 - Table 11.3
67#########################################################################
68#
70eapol_types = {
71 0x0: "EAP-Packet", # "EAPOL-EAP" in 801.1X-2010
72 0x1: "EAPOL-Start",
73 0x2: "EAPOL-Logoff",
74 0x3: "EAPOL-Key",
75 0x4: "EAPOL-Encapsulated-ASF-Alert",
76 0x5: "EAPOL-MKA",
77 0x6: "EAPOL-Announcement (Generic)",
78 0x7: "EAPOL-Announcement (Specific)",
79 0x8: "EAPOL-Announcement-Req"
80}
83class EAPOL(Packet):
84 """
85 EAPOL - IEEE Std 802.1X-2010
86 """
88 name = "EAPOL"
89 fields_desc = [
90 ByteEnumField("version", 1, eapol_versions),
91 ByteEnumField("type", 0, eapol_types),
92 LenField("len", None, "H")
93 ]
95 EAP_PACKET = 0
96 START = 1
97 LOGOFF = 2
98 KEY = 3
99 ASF = 4
101 def extract_padding(self, s):
102 tmp_len = self.len
103 return s[:tmp_len], s[tmp_len:]
105 def hashret(self):
106 return chb(self.type) + self.payload.hashret()
108 def answers(self, other):
109 if isinstance(other, EAPOL):
110 if ((self.type == self.EAP_PACKET) and
111 (other.type == self.EAP_PACKET)):
112 return self.payload.answers(other.payload)
113 return 0
115 def mysummary(self):
116 return self.sprintf("EAPOL %EAPOL.type%")
119#
120# EAP
121#
124#########################################################################
125#
126# EAP methods types
127# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4
128#########################################################################
129#
131eap_types = {
132 0: "Reserved",
133 1: "Identity",
134 2: "Notification",
135 3: "Legacy Nak",
136 4: "MD5-Challenge",
137 5: "One-Time Password (OTP)",
138 6: "Generic Token Card (GTC)",
139 7: "Allocated - RFC3748",
140 8: "Allocated - RFC3748",
141 9: "RSA Public Key Authentication",
142 10: "DSS Unilateral",
143 11: "KEA",
144 12: "KEA-VALIDATE",
145 13: "EAP-TLS",
146 14: "Defender Token (AXENT)",
147 15: "RSA Security SecurID EAP",
148 16: "Arcot Systems EAP",
149 17: "EAP-Cisco Wireless",
150 18: "GSM Subscriber Identity Modules (EAP-SIM)",
151 19: "SRP-SHA1",
152 20: "Unassigned",
153 21: "EAP-TTLS",
154 22: "Remote Access Service",
155 23: "EAP-AKA Authentication",
156 24: "EAP-3Com Wireless",
157 25: "PEAP",
158 26: "MS-EAP-Authentication",
159 27: "Mutual Authentication w/Key Exchange (MAKE)",
160 28: "CRYPTOCard",
161 29: "EAP-MSCHAP-V2",
162 30: "DynamID",
163 31: "Rob EAP",
164 32: "Protected One-Time Password",
165 33: "MS-Authentication-TLV",
166 34: "SentriNET",
167 35: "EAP-Actiontec Wireless",
168 36: "Cogent Systems Biometrics Authentication EAP",
169 37: "AirFortress EAP",
170 38: "EAP-HTTP Digest",
171 39: "SecureSuite EAP",
172 40: "DeviceConnect EAP",
173 41: "EAP-SPEKE",
174 42: "EAP-MOBAC",
175 43: "EAP-FAST",
176 44: "ZoneLabs EAP (ZLXEAP)",
177 45: "EAP-Link",
178 46: "EAP-PAX",
179 47: "EAP-PSK",
180 48: "EAP-SAKE",
181 49: "EAP-IKEv2",
182 50: "EAP-AKA",
183 51: "EAP-GPSK",
184 52: "EAP-pwd",
185 53: "EAP-EKE Version 1",
186 54: "EAP Method Type for PT-EAP",
187 55: "TEAP",
188 254: "Reserved for the Expanded Type",
189 255: "Experimental",
190}
193#########################################################################
194#
195# EAP codes
196# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1
197#########################################################################
198#
200eap_codes = {
201 1: "Request",
202 2: "Response",
203 3: "Success",
204 4: "Failure",
205 5: "Initiate",
206 6: "Finish"
207}
210class EAP(Packet):
211 """
212 RFC 3748 - Extensible Authentication Protocol (EAP)
213 """
215 name = "EAP"
216 fields_desc = [
217 ByteEnumField("code", 4, eap_codes),
218 ByteField("id", 0),
219 ShortField("len", None),
220 ConditionalField(ByteEnumField("type", 0, eap_types),
221 lambda pkt:pkt.code not in [
222 EAP.SUCCESS, EAP.FAILURE]),
223 ConditionalField(
224 FieldListField("desired_auth_types", [],
225 ByteEnumField("auth_type", 0, eap_types),
226 length_from=lambda pkt: pkt.len - 4),
227 lambda pkt:pkt.code == EAP.RESPONSE and pkt.type == 3),
228 ConditionalField(
229 StrLenField("identity", '', length_from=lambda pkt: pkt.len - 5),
230 lambda pkt: pkt.code == EAP.RESPONSE and hasattr(pkt, 'type') and pkt.type == 1), # noqa: E501
231 ConditionalField(
232 StrLenField("message", '', length_from=lambda pkt: pkt.len - 5),
233 lambda pkt: pkt.code == EAP.REQUEST and hasattr(pkt, 'type') and pkt.type == 1) # noqa: E501
234 ]
236 #########################################################################
237 #
238 # EAP codes
239 # http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1
240 #########################################################################
241 #
243 REQUEST = 1
244 RESPONSE = 2
245 SUCCESS = 3
246 FAILURE = 4
247 INITIATE = 5
248 FINISH = 6
250 registered_methods = {}
252 @classmethod
253 def register_variant(cls):
254 cls.registered_methods[cls.type.default] = cls
256 @classmethod
257 def dispatch_hook(cls, _pkt=None, *args, **kargs):
258 if _pkt:
259 c = orb(_pkt[0])
260 if c in [1, 2] and len(_pkt) >= 5:
261 t = orb(_pkt[4])
262 return cls.registered_methods.get(t, cls)
263 return cls
265 def answers(self, other):
266 if isinstance(other, EAP):
267 if self.code == self.REQUEST:
268 return 0
269 elif self.code == self.RESPONSE:
270 if ((other.code == self.REQUEST) and
271 (other.type == self.type)):
272 return 1
273 elif other.code == self.RESPONSE:
274 return 1
275 return 0
277 def mysummary(self):
278 summary_str = "EAP %{eap_class}.code% %{eap_class}.type%".format(
279 eap_class=self.__class__.__name__
280 )
281 if self.type == 1 and self.code == EAP.RESPONSE:
282 summary_str += " %{eap_class}.identity%".format(
283 eap_class=self.__class__.__name__
284 )
285 return self.sprintf(summary_str)
287 def post_build(self, p, pay):
288 if self.len is None:
289 tmp_len = len(p) + len(pay)
290 tmp_p = p[:2] + chb((tmp_len >> 8) & 0xff) + chb(tmp_len & 0xff)
291 p = tmp_p + p[4:]
292 return p + pay
294 def guess_payload_class(self, _):
295 return Padding
298class EAP_MD5(EAP):
299 """
300 RFC 3748 - "Extensible Authentication Protocol (EAP)"
301 """
303 name = "EAP-MD5"
304 match_subclass = True
305 fields_desc = [
306 ByteEnumField("code", 1, eap_codes),
307 ByteField("id", 0),
308 FieldLenField("len", None, fmt="H", length_of="optional_name",
309 adjust=lambda p, x: x + 6 + (p.value_size or 0)),
310 ByteEnumField("type", 4, eap_types),
311 FieldLenField("value_size", None, fmt="B", length_of="value"),
312 XStrLenField("value", '', length_from=lambda p: p.value_size),
313 XStrLenField("optional_name", '', length_from=lambda p: 0 if p.len is None or p.value_size is None else (p.len - p.value_size - 6)) # noqa: E501
314 ]
317class EAP_TLS(EAP):
318 """
319 RFC 5216 - "The EAP-TLS Authentication Protocol"
320 """
322 name = "EAP-TLS"
323 match_subclass = True
324 fields_desc = [
325 ByteEnumField("code", 1, eap_codes),
326 ByteField("id", 0),
327 FieldLenField("len", None, fmt="H", length_of="tls_data",
328 adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),
329 ByteEnumField("type", 13, eap_types),
330 BitField('L', 0, 1),
331 BitField('M', 0, 1),
332 BitField('S', 0, 1),
333 BitField('reserved', 0, 5),
334 ConditionalField(IntField('tls_message_len', 0), lambda pkt: pkt.L == 1), # noqa: E501
335 XStrLenField('tls_data', '', length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L)) # noqa: E501
336 ]
339class EAP_TTLS(EAP):
340 """
341 RFC 5281 - "Extensible Authentication Protocol Tunneled Transport Layer
342 Security Authenticated Protocol Version 0 (EAP-TTLSv0)"
343 """
345 name = "EAP-TTLS"
346 match_subclass = True
347 fields_desc = [
348 ByteEnumField("code", 1, eap_codes),
349 ByteField("id", 0),
350 FieldLenField("len", None, fmt="H", length_of="data",
351 adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),
352 ByteEnumField("type", 21, eap_types),
353 BitField("L", 0, 1),
354 BitField("M", 0, 1),
355 BitField("S", 0, 1),
356 BitField("reserved", 0, 2),
357 BitField("version", 0, 3),
358 ConditionalField(IntField("message_len", 0), lambda pkt: pkt.L == 1),
359 XStrLenField("data", "", length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L)) # noqa: E501
360 ]
363class EAP_PEAP(EAP):
364 """
365 draft-josefsson-pppext-eap-tls-eap-05.txt - "Protected EAP Protocol (PEAP)"
366 """
368 name = "PEAP"
369 match_subclass = True
370 fields_desc = [
371 ByteEnumField("code", 1, eap_codes),
372 ByteField("id", 0),
373 FieldLenField("len", None, fmt="H", length_of="tls_data",
374 adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),
375 ByteEnumField("type", 25, eap_types),
376 BitField("L", 0, 1),
377 BitField("M", 0, 1),
378 BitField("S", 0, 1),
379 BitField("reserved", 0, 3),
380 BitField("version", 1, 2),
381 ConditionalField(IntField("tls_message_len", 0), lambda pkt: pkt.L == 1), # noqa: E501
382 XStrLenField("tls_data", "", length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L)) # noqa: E501
383 ]
386class EAP_FAST(EAP):
387 """
388 RFC 4851 - "The Flexible Authentication via Secure Tunneling
389 Extensible Authentication Protocol Method (EAP-FAST)"
390 """
392 name = "EAP-FAST"
393 match_subclass = True
394 fields_desc = [
395 ByteEnumField("code", 1, eap_codes),
396 ByteField("id", 0),
397 FieldLenField("len", None, fmt="H", length_of="data",
398 adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),
399 ByteEnumField("type", 43, eap_types),
400 BitField('L', 0, 1),
401 BitField('M', 0, 1),
402 BitField('S', 0, 1),
403 BitField('reserved', 0, 2),
404 BitField('version', 0, 3),
405 ConditionalField(IntField('message_len', 0), lambda pkt: pkt.L == 1),
406 XStrLenField('data', '', length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L)) # noqa: E501
407 ]
410class LEAP(EAP):
411 """
412 Cisco LEAP (Lightweight EAP)
413 https://freeradius.org/rfc/leap.txt
414 """
416 name = "Cisco LEAP"
417 match_subclass = True
418 fields_desc = [
419 ByteEnumField("code", 1, eap_codes),
420 ByteField("id", 0),
421 ShortField("len", None),
422 ByteEnumField("type", 17, eap_types),
423 ByteField('version', 1),
424 XByteField('unused', 0),
425 FieldLenField("count", None, "challenge_response", "B", adjust=lambda p, x: len(p.challenge_response)), # noqa: E501
426 XStrLenField("challenge_response", "", length_from=lambda p: 0 or p.count), # noqa: E501
427 StrLenField("username", "", length_from=lambda p: p.len - (8 + (0 or p.count))) # noqa: E501
428 ]
431#############################################################################
432# IEEE 802.1X-2010 - EAPOL-Key
433#############################################################################
435# sect 11.9 of 802.1X-2010
436# AND sect 12.7.2 of 802.11-2016
439class EAPOL_KEY(Packet):
440 name = "EAPOL_KEY"
441 deprecated_fields = {
442 "key": ("key_data", "2.6.0"),
443 "len": ("key_length", "2.6.0"),
444 }
445 fields_desc = [
446 ByteEnumField("key_descriptor_type", 1, {1: "RC4", 2: "RSN"}),
447 # Key Information
448 BitField("res2", 0, 2),
449 BitField("smk_message", 0, 1),
450 BitField("encrypted_key_data", 0, 1),
451 BitField("request", 0, 1),
452 BitField("error", 0, 1),
453 BitField("secure", 0, 1),
454 BitField("has_key_mic", 1, 1),
455 BitField("key_ack", 0, 1),
456 BitField("install", 0, 1),
457 BitField("res", 0, 2),
458 BitEnumField("key_type", 0, 1, {0: "Group/SMK", 1: "Pairwise"}),
459 BitEnumField("key_descriptor_type_version", 0, 3, {
460 1: "HMAC-MD5+ARC4",
461 2: "HMAC-SHA1-128+AES-128",
462 3: "AES-128-CMAC+AES-128",
463 }),
464 #
465 LenField("key_length", None, "H"),
466 LongField("key_replay_counter", 0),
467 XStrFixedLenField("key_nonce", "", 32),
468 XStrFixedLenField("key_iv", "", 16),
469 XStrFixedLenField("key_rsc", "", 8),
470 XStrFixedLenField("key_id", "", 8),
471 XStrFixedLenField("key_mic", "", 16), # XXX size can be 24
472 FieldLenField("key_data_length", None, length_of="key_data"),
473 XStrLenField("key_data", "",
474 length_from=lambda pkt: pkt.key_data_length)
475 ]
477 def extract_padding(self, s):
478 return s[:self.key_length], s[self.key_length:]
480 def hashret(self):
481 return struct.pack("!B", self.type) + self.payload.hashret()
483 def answers(self, other):
484 if isinstance(other, EAPOL_KEY) and \
485 other.descriptor_type == self.descriptor_type:
486 return 1
487 return 0
489 def guess_key_number(self):
490 """
491 Determines 4-way handshake key number
493 :return: key number (1-4), or 0 if it cannot be determined
494 """
495 if self.key_type == 1:
496 if self.key_ack == 1:
497 if self.key_mic == 0:
498 return 1
499 if self.install == 1:
500 return 3
501 else:
502 if self.secure == 0:
503 return 2
504 return 4
505 return 0
508#############################################################################
509# IEEE 802.1X-2010 - MACsec Key Agreement (MKA) protocol
510#############################################################################
512#########################################################################
513#
514# IEEE 802.1X-2010 standard
515# Section 11.11.1
516#########################################################################
517#
519_parameter_set_types = {
520 1: "Live Peer List",
521 2: "Potential Peer List",
522 3: "MACsec SAK Use",
523 4: "Distributed SAK",
524 5: "Distributed CAK",
525 6: "KMD",
526 7: "Announcement",
527 255: "ICV Indicator"
528}
531# Used by MKAParamSet::dispatch_hook() to instantiate the appropriate class
532_param_set_cls = {
533 1: "MKALivePeerListParamSet",
534 2: "MKAPotentialPeerListParamSet",
535 3: "MKASAKUseParamSet",
536 4: "MKADistributedSAKParamSet",
537 255: "MKAICVSet",
538}
541class MACsecSCI(Packet):
542 """
543 Secure Channel Identifier.
544 """
546 #########################################################################
547 #
548 # IEEE 802.1AE-2006 standard
549 # Section 9.9
550 #########################################################################
551 #
553 name = "SCI"
554 fields_desc = [
555 SourceMACField("system_identifier"),
556 ShortField("port_identifier", 0)
557 ]
559 def extract_padding(self, s):
560 return "", s
563class MKAParamSet(Packet):
564 """
565 Class from which every parameter set class inherits (except
566 MKABasicParamSet, which has no "Parameter set type" field, and must
567 come first in the list of parameter sets).
568 """
570 MACSEC_DEFAULT_ICV_LEN = 16
571 EAPOL_MKA_DEFAULT_KEY_WRAP_LEN = 24
573 @classmethod
574 def dispatch_hook(cls, _pkt=None, *args, **kargs):
575 """
576 Returns the right parameter set class.
577 """
579 cls = conf.raw_layer
580 if _pkt is not None:
581 ptype = orb(_pkt[0])
582 return globals().get(_param_set_cls.get(ptype), conf.raw_layer)
584 return cls
587class MKABasicParamSet(Packet):
588 """
589 Basic Parameter Set (802.1X-2010, section 11.11).
590 """
592 #########################################################################
593 #
594 # IEEE 802.1X-2010 standard
595 # Section 11.11
596 #########################################################################
597 #
599 name = "Basic Parameter Set"
600 fields_desc = [
601 ByteField("mka_version_id", 0),
602 ByteField("key_server_priority", 0),
603 BitField("key_server", 0, 1),
604 BitField("macsec_desired", 0, 1),
605 BitField("macsec_capability", 0, 2),
606 BitField("param_set_body_len", 0, 12),
607 PacketField("SCI", MACsecSCI(), MACsecSCI),
608 XStrFixedLenField("actor_member_id", "", length=12),
609 XIntField("actor_message_number", 0),
610 XIntField("algorithm_agility", 0),
611 PadField(
612 XStrLenField(
613 "cak_name",
614 "",
615 length_from=lambda pkt: (pkt.param_set_body_len - 28)
616 ),
617 4,
618 padwith=b"\x00"
619 )
620 ]
622 def extract_padding(self, s):
623 return "", s
626class MKAPeerListTuple(Packet):
627 """
628 Live / Potential Peer List parameter sets tuples (802.1X-2010, section 11.11). # noqa: E501
629 """
631 name = "Peer List Tuple"
632 fields_desc = [
633 XStrFixedLenField("member_id", "", length=12),
634 XStrFixedLenField("message_number", "", length=4),
635 ]
638class MKALivePeerListParamSet(MKAParamSet):
639 """
640 Live Peer List parameter sets (802.1X-2010, section 11.11).
641 """
643 #########################################################################
644 #
645 # IEEE 802.1X-2010 standard
646 # Section 11.11
647 #########################################################################
648 #
650 name = "Live Peer List Parameter Set"
651 fields_desc = [
652 PadField(
653 ByteEnumField(
654 "param_set_type",
655 1,
656 _parameter_set_types
657 ),
658 2,
659 padwith=b"\x00"
660 ),
661 ShortField("param_set_body_len", 0),
662 PacketListField("member_id_message_num", [], MKAPeerListTuple)
663 ]
666class MKAPotentialPeerListParamSet(MKAParamSet):
667 """
668 Potential Peer List parameter sets (802.1X-2010, section 11.11).
669 """
671 #########################################################################
672 #
673 # IEEE 802.1X-2010 standard
674 # Section 11.11
675 #########################################################################
676 #
678 name = "Potential Peer List Parameter Set"
679 fields_desc = [
680 PadField(
681 ByteEnumField(
682 "param_set_type",
683 2,
684 _parameter_set_types
685 ),
686 2,
687 padwith=b"\x00"
688 ),
689 ShortField("param_set_body_len", 0),
690 PacketListField("member_id_message_num", [], MKAPeerListTuple)
691 ]
694class MKASAKUseParamSet(MKAParamSet):
695 """
696 SAK Use Parameter Set (802.1X-2010, section 11.11).
697 """
699 #########################################################################
700 #
701 # IEEE 802.1X-2010 standard
702 # Section 11.11
703 #########################################################################
704 #
706 name = "SAK Use Parameter Set"
707 fields_desc = [
708 ByteEnumField("param_set_type", 3, _parameter_set_types),
709 BitField("latest_key_an", 0, 2),
710 BitField("latest_key_tx", 0, 1),
711 BitField("latest_key_rx", 0, 1),
712 BitField("old_key_an", 0, 2),
713 BitField("old_key_tx", 0, 1),
714 BitField("old_key_rx", 0, 1),
715 BitField("plain_tx", 0, 1),
716 BitField("plain_rx", 0, 1),
717 BitField("X", 0, 1),
718 BitField("delay_protect", 0, 1),
719 BitField("param_set_body_len", 0, 12),
720 XStrFixedLenField("latest_key_key_server_member_id", "", length=12),
721 XStrFixedLenField("latest_key_key_number", "", length=4),
722 XStrFixedLenField("latest_key_lowest_acceptable_pn", "", length=4),
723 XStrFixedLenField("old_key_key_server_member_id", "", length=12),
724 XStrFixedLenField("old_key_key_number", "", length=4),
725 XStrFixedLenField("old_key_lowest_acceptable_pn", "", length=4)
726 ]
729class MKADistributedSAKParamSet(MKAParamSet):
730 """
731 Distributed SAK parameter set (802.1X-2010, section 11.11).
732 """
734 #########################################################################
735 #
736 # IEEE 802.1X-2010 standard
737 # Section 11.11
738 #########################################################################
739 #
741 name = "Distributed SAK parameter set"
742 fields_desc = [
743 ByteEnumField("param_set_type", 4, _parameter_set_types),
744 BitField("distributed_an", 0, 2),
745 BitField("confidentiality_offset", 0, 2),
746 BitField("unused", 0, 4),
747 ShortField("param_set_body_len", 0),
748 XStrFixedLenField("key_number", "", length=4),
749 ConditionalField(
750 XStrFixedLenField("macsec_cipher_suite", "", length=8),
751 lambda pkt: pkt.param_set_body_len > 28
752 ),
753 XStrFixedLenField(
754 "sak_aes_key_wrap",
755 "",
756 length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN
757 )
758 ]
761class MKADistributedCAKParamSet(MKAParamSet):
762 """
763 Distributed CAK Parameter Set (802.1X-2010, section 11.11).
764 """
766 #########################################################################
767 #
768 # IEEE 802.1X-2010 standard
769 # Section 11.11
770 #########################################################################
771 #
773 name = "Distributed CAK parameter set"
774 fields_desc = [
775 PadField(
776 ByteEnumField(
777 "param_set_type",
778 5,
779 _parameter_set_types
780 ),
781 2,
782 padwith=b"\x00"
783 ),
784 ShortField("param_set_body_len", 0),
785 XStrFixedLenField(
786 "cak_aes_key_wrap",
787 "",
788 length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN
789 ),
790 XStrField("cak_key_name", "")
791 ]
794class MKAICVSet(MKAParamSet):
795 """
796 ICV (802.1X-2010, section 11.11).
797 """
799 #########################################################################
800 #
801 # IEEE 802.1X-2010 standard
802 # Section 11.11
803 #########################################################################
804 #
806 name = "ICV"
807 fields_desc = [
808 PadField(
809 ByteEnumField(
810 "param_set_type",
811 255,
812 _parameter_set_types
813 ),
814 2,
815 padwith=b"\x00"
816 ),
817 ShortField("param_set_body_len", 0),
818 XStrFixedLenField("icv", "", length=MKAParamSet.MACSEC_DEFAULT_ICV_LEN)
819 ]
822class MKAParamSetPacketListField(PacketListField):
823 """
824 PacketListField that handles the parameter sets.
825 """
827 PARAM_SET_LEN_MASK = 0b0000111111111111
829 def m2i(self, pkt, m):
830 return MKAParamSet(m)
832 def getfield(self, pkt, s):
833 lst = []
834 remain = s
836 while remain:
837 len_bytes = struct.unpack("!H", remain[2:4])[0]
838 param_set_len = self.__class__.PARAM_SET_LEN_MASK & len_bytes
839 current = remain[:4 + param_set_len]
840 remain = remain[4 + param_set_len:]
841 current_packet = self.m2i(pkt, current)
842 lst.append(current_packet)
844 return remain, lst
847class MKAPDU(Packet):
848 """
849 MACsec Key Agreement Protocol Data Unit.
850 """
852 #########################################################################
853 #
854 # IEEE 802.1X-2010 standard
855 # Section 11.11
856 #########################################################################
857 #
859 name = "MKPDU"
860 fields_desc = [
861 PacketField("basic_param_set", "", MKABasicParamSet),
862 MKAParamSetPacketListField("parameter_sets", [], MKAParamSet),
863 ]
865 def extract_padding(self, s):
866 return "", s
869# Bind EAPOL types
870bind_layers(EAPOL, EAP, type=0)
871bind_layers(EAPOL, EAPOL_KEY, type=3)
872bind_layers(EAPOL, MKAPDU, type=5)
874bind_bottom_up(Ether, EAPOL, type=0x888e)
875# the reserved IEEE Std 802.1X PAE address
876bind_top_down(Ether, EAPOL, dst='01:80:c2:00:00:03', type=0x888e)
877bind_layers(CookedLinux, EAPOL, proto=0x888e)
878bind_layers(SNAP, EAPOL, code=0x888e)
879bind_layers(GRE, EAPOL, proto=0x888e)