Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/eap.py: 82%

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

194 statements  

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> 

5 

6""" 

7Extensible Authentication Protocol (EAP) 

8""" 

9 

10 

11import struct 

12 

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 

45 

46# 

47# EAPOL 

48# 

49 

50######################################################################### 

51# 

52# EAPOL protocol version 

53# IEEE Std 802.1X-2010 - Section 11.3.1 

54######################################################################### 

55# 

56 

57eapol_versions = { 

58 0x1: "802.1X-2001", 

59 0x2: "802.1X-2004", 

60 0x3: "802.1X-2010", 

61} 

62 

63######################################################################### 

64# 

65# EAPOL Packet Types 

66# IEEE Std 802.1X-2010 - Table 11.3 

67######################################################################### 

68# 

69 

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} 

81 

82 

83class EAPOL(Packet): 

84 """ 

85 EAPOL - IEEE Std 802.1X-2010 

86 """ 

87 

88 name = "EAPOL" 

89 fields_desc = [ 

90 ByteEnumField("version", 1, eapol_versions), 

91 ByteEnumField("type", 0, eapol_types), 

92 LenField("len", None, "H") 

93 ] 

94 

95 EAP_PACKET = 0 

96 START = 1 

97 LOGOFF = 2 

98 KEY = 3 

99 ASF = 4 

100 

101 def extract_padding(self, s): 

102 tmp_len = self.len 

103 return s[:tmp_len], s[tmp_len:] 

104 

105 def hashret(self): 

106 return chb(self.type) + self.payload.hashret() 

107 

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 

114 

115 def mysummary(self): 

116 return self.sprintf("EAPOL %EAPOL.type%") 

117 

118 

119# 

120# EAP 

121# 

122 

123 

124######################################################################### 

125# 

126# EAP methods types 

127# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4 

128######################################################################### 

129# 

130 

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} 

191 

192 

193######################################################################### 

194# 

195# EAP codes 

196# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1 

197######################################################################### 

198# 

199 

200eap_codes = { 

201 1: "Request", 

202 2: "Response", 

203 3: "Success", 

204 4: "Failure", 

205 5: "Initiate", 

206 6: "Finish" 

207} 

208 

209 

210class EAP(Packet): 

211 """ 

212 RFC 3748 - Extensible Authentication Protocol (EAP) 

213 """ 

214 

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 ] 

235 

236 ######################################################################### 

237 # 

238 # EAP codes 

239 # http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1 

240 ######################################################################### 

241 # 

242 

243 REQUEST = 1 

244 RESPONSE = 2 

245 SUCCESS = 3 

246 FAILURE = 4 

247 INITIATE = 5 

248 FINISH = 6 

249 

250 registered_methods = {} 

251 

252 @classmethod 

253 def register_variant(cls): 

254 cls.registered_methods[cls.type.default] = cls 

255 

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 

264 

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 

276 

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) 

286 

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 

293 

294 def guess_payload_class(self, _): 

295 return Padding 

296 

297 

298class EAP_MD5(EAP): 

299 """ 

300 RFC 3748 - "Extensible Authentication Protocol (EAP)" 

301 """ 

302 

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 ] 

315 

316 

317class EAP_TLS(EAP): 

318 """ 

319 RFC 5216 - "The EAP-TLS Authentication Protocol" 

320 """ 

321 

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 ] 

337 

338 

339class EAP_TTLS(EAP): 

340 """ 

341 RFC 5281 - "Extensible Authentication Protocol Tunneled Transport Layer 

342 Security Authenticated Protocol Version 0 (EAP-TTLSv0)" 

343 """ 

344 

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 ] 

361 

362 

363class EAP_PEAP(EAP): 

364 """ 

365 draft-josefsson-pppext-eap-tls-eap-05.txt - "Protected EAP Protocol (PEAP)" 

366 """ 

367 

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 ] 

384 

385 

386class EAP_FAST(EAP): 

387 """ 

388 RFC 4851 - "The Flexible Authentication via Secure Tunneling 

389 Extensible Authentication Protocol Method (EAP-FAST)" 

390 """ 

391 

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 ] 

408 

409 

410class LEAP(EAP): 

411 """ 

412 Cisco LEAP (Lightweight EAP) 

413 https://freeradius.org/rfc/leap.txt 

414 """ 

415 

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 ] 

429 

430 

431############################################################################# 

432# IEEE 802.1X-2010 - EAPOL-Key 

433############################################################################# 

434 

435# sect 11.9 of 802.1X-2010 

436# AND sect 12.7.2 of 802.11-2016 

437 

438 

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 ] 

476 

477 def extract_padding(self, s): 

478 return s[:self.key_length], s[self.key_length:] 

479 

480 def hashret(self): 

481 return struct.pack("!B", self.type) + self.payload.hashret() 

482 

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 

488 

489 def guess_key_number(self): 

490 """ 

491 Determines 4-way handshake key number 

492 

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.has_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 

506 

507 

508############################################################################# 

509# IEEE 802.1X-2010 - MACsec Key Agreement (MKA) protocol 

510############################################################################# 

511 

512######################################################################### 

513# 

514# IEEE 802.1X-2010 standard 

515# Section 11.11.1 

516######################################################################### 

517# 

518 

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} 

529 

530 

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} 

539 

540 

541class MACsecSCI(Packet): 

542 """ 

543 Secure Channel Identifier. 

544 """ 

545 

546 ######################################################################### 

547 # 

548 # IEEE 802.1AE-2006 standard 

549 # Section 9.9 

550 ######################################################################### 

551 # 

552 

553 name = "SCI" 

554 fields_desc = [ 

555 SourceMACField("system_identifier"), 

556 ShortField("port_identifier", 0) 

557 ] 

558 

559 def extract_padding(self, s): 

560 return "", s 

561 

562 

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 """ 

569 

570 MACSEC_DEFAULT_ICV_LEN = 16 

571 EAPOL_MKA_DEFAULT_KEY_WRAP_LEN = 24 

572 

573 @classmethod 

574 def dispatch_hook(cls, _pkt=None, *args, **kargs): 

575 """ 

576 Returns the right parameter set class. 

577 """ 

578 

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) 

583 

584 return cls 

585 

586 

587class MKABasicParamSet(Packet): 

588 """ 

589 Basic Parameter Set (802.1X-2010, section 11.11). 

590 """ 

591 

592 ######################################################################### 

593 # 

594 # IEEE 802.1X-2010 standard 

595 # Section 11.11 

596 ######################################################################### 

597 # 

598 

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 ] 

621 

622 def extract_padding(self, s): 

623 return "", s 

624 

625 

626class MKAPeerListTuple(Packet): 

627 """ 

628 Live / Potential Peer List parameter sets tuples (802.1X-2010, section 11.11). # noqa: E501 

629 """ 

630 

631 name = "Peer List Tuple" 

632 fields_desc = [ 

633 XStrFixedLenField("member_id", "", length=12), 

634 XStrFixedLenField("message_number", "", length=4), 

635 ] 

636 

637 

638class MKALivePeerListParamSet(MKAParamSet): 

639 """ 

640 Live Peer List parameter sets (802.1X-2010, section 11.11). 

641 """ 

642 

643 ######################################################################### 

644 # 

645 # IEEE 802.1X-2010 standard 

646 # Section 11.11 

647 ######################################################################### 

648 # 

649 

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 ] 

664 

665 

666class MKAPotentialPeerListParamSet(MKAParamSet): 

667 """ 

668 Potential Peer List parameter sets (802.1X-2010, section 11.11). 

669 """ 

670 

671 ######################################################################### 

672 # 

673 # IEEE 802.1X-2010 standard 

674 # Section 11.11 

675 ######################################################################### 

676 # 

677 

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 ] 

692 

693 

694class MKASAKUseParamSet(MKAParamSet): 

695 """ 

696 SAK Use Parameter Set (802.1X-2010, section 11.11). 

697 """ 

698 

699 ######################################################################### 

700 # 

701 # IEEE 802.1X-2010 standard 

702 # Section 11.11 

703 ######################################################################### 

704 # 

705 

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 ] 

727 

728 

729class MKADistributedSAKParamSet(MKAParamSet): 

730 """ 

731 Distributed SAK parameter set (802.1X-2010, section 11.11). 

732 """ 

733 

734 ######################################################################### 

735 # 

736 # IEEE 802.1X-2010 standard 

737 # Section 11.11 

738 ######################################################################### 

739 # 

740 

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 ] 

759 

760 

761class MKADistributedCAKParamSet(MKAParamSet): 

762 """ 

763 Distributed CAK Parameter Set (802.1X-2010, section 11.11). 

764 """ 

765 

766 ######################################################################### 

767 # 

768 # IEEE 802.1X-2010 standard 

769 # Section 11.11 

770 ######################################################################### 

771 # 

772 

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 ] 

792 

793 

794class MKAICVSet(MKAParamSet): 

795 """ 

796 ICV (802.1X-2010, section 11.11). 

797 """ 

798 

799 ######################################################################### 

800 # 

801 # IEEE 802.1X-2010 standard 

802 # Section 11.11 

803 ######################################################################### 

804 # 

805 

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 ] 

820 

821 

822class MKAParamSetPacketListField(PacketListField): 

823 """ 

824 PacketListField that handles the parameter sets. 

825 """ 

826 

827 PARAM_SET_LEN_MASK = 0b0000111111111111 

828 

829 def m2i(self, pkt, m): 

830 return MKAParamSet(m) 

831 

832 def getfield(self, pkt, s): 

833 lst = [] 

834 remain = s 

835 

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) 

843 

844 return remain, lst 

845 

846 

847class MKAPDU(Packet): 

848 """ 

849 MACsec Key Agreement Protocol Data Unit. 

850 """ 

851 

852 ######################################################################### 

853 # 

854 # IEEE 802.1X-2010 standard 

855 # Section 11.11 

856 ######################################################################### 

857 # 

858 

859 name = "MKPDU" 

860 fields_desc = [ 

861 PacketField("basic_param_set", "", MKABasicParamSet), 

862 MKAParamSetPacketListField("parameter_sets", [], MKAParamSet), 

863 ] 

864 

865 def extract_padding(self, s): 

866 return "", s 

867 

868 

869# Bind EAPOL types 

870bind_layers(EAPOL, EAP, type=0) 

871bind_layers(EAPOL, EAPOL_KEY, type=3) 

872bind_layers(EAPOL, MKAPDU, type=5) 

873 

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)