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) 2017 Maxence Tury 5 6""" 7TLS handshake extensions. 8""" 9 10 11import os 12import struct 13 14from scapy.fields import ( 15 ByteEnumField, 16 ByteField, 17 EnumField, 18 FieldLenField, 19 FieldListField, 20 IntField, 21 MayEnd, 22 PacketField, 23 PacketListField, 24 ShortEnumField, 25 ShortField, 26 StrFixedLenField, 27 StrLenField, 28 XStrLenField, 29) 30from scapy.packet import Packet, Raw, Padding 31from scapy.layers.x509 import X509_Extensions 32from scapy.layers.tls.basefields import _tls_version 33from scapy.layers.tls.keyexchange import (SigAndHashAlgsLenField, 34 SigAndHashAlgsField, _tls_hash_sig) 35from scapy.layers.tls.session import _GenericTLSSessionInheritance 36from scapy.layers.tls.crypto.groups import _tls_named_groups 37from scapy.layers.tls.crypto.suites import _tls_cipher_suites 38from scapy.themes import AnsiColorTheme 39from scapy.compat import raw 40from scapy.config import conf 41 42 43# Because ServerHello and HelloRetryRequest have the same 44# msg_type, the only way to distinguish these message is by 45# checking the random_bytes. If the random_bytes are equal to 46# SHA256('HelloRetryRequest') then we know this is a 47# HelloRetryRequest and the TLS_Ext_KeyShare must be parsed as 48# TLS_Ext_KeyShare_HRR and not as TLS_Ext_KeyShare_SH 49 50# from cryptography.hazmat.backends import default_backend 51# from cryptography.hazmat.primitives import hashes 52# digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) 53# digest.update(b"HelloRetryRequest") 54# _tls_hello_retry_magic = digest.finalize() 55 56_tls_hello_retry_magic = ( 57 b'\xcf!\xadt\xe5\x9aa\x11\xbe\x1d\x8c\x02\x1ee\xb8\x91\xc2\xa2\x11' 58 b'\x16z\xbb\x8c^\x07\x9e\t\xe2\xc8\xa83\x9c' 59) 60 61 62_tls_ext = {0: "server_name", # RFC 4366 63 1: "max_fragment_length", # RFC 4366 64 2: "client_certificate_url", # RFC 4366 65 3: "trusted_ca_keys", # RFC 4366 66 4: "truncated_hmac", # RFC 4366 67 5: "status_request", # RFC 4366 68 6: "user_mapping", # RFC 4681 69 7: "client_authz", # RFC 5878 70 8: "server_authz", # RFC 5878 71 9: "cert_type", # RFC 6091 72 # 10: "elliptic_curves", # RFC 4492 73 10: "supported_groups", 74 11: "ec_point_formats", # RFC 4492 75 13: "signature_algorithms", # RFC 5246 76 0x0f: "heartbeat", # RFC 6520 77 0x10: "alpn", # RFC 7301 78 0x12: "signed_certificate_timestamp", # RFC 6962 79 0x13: "client_certificate_type", # RFC 7250 80 0x14: "server_certificate_type", # RFC 7250 81 0x15: "padding", # RFC 7685 82 0x16: "encrypt_then_mac", # RFC 7366 83 0x17: "extended_master_secret", # RFC 7627 84 0x1c: "record_size_limit", # RFC 8449 85 0x23: "session_ticket", # RFC 5077 86 0x29: "pre_shared_key", 87 0x2a: "early_data_indication", 88 0x2b: "supported_versions", 89 0x2c: "cookie", 90 0x2d: "psk_key_exchange_modes", 91 0x2f: "certificate_authorities", 92 0x30: "oid_filters", 93 0x31: "post_handshake_auth", 94 0x32: "signature_algorithms_cert", 95 0x33: "key_share", 96 0x3374: "next_protocol_negotiation", 97 # RFC-draft-agl-tls-nextprotoneg-03 98 0xff01: "renegotiation_info", # RFC 5746 99 0xffce: "encrypted_server_name" 100 } 101 102 103class TLS_Ext_Unknown(_GenericTLSSessionInheritance): 104 """ 105 We put this here rather than in extensions.py in order to avoid 106 circular imports... 107 """ 108 name = "TLS Extension - Scapy Unknown" 109 fields_desc = [ShortEnumField("type", None, _tls_ext), 110 FieldLenField("len", None, fmt="!H", length_of="val"), 111 StrLenField("val", "", 112 length_from=lambda pkt: pkt.len)] 113 114 def post_build(self, p, pay): 115 if self.len is None: 116 tmp_len = len(p) - 4 117 p = p[:2] + struct.pack("!H", tmp_len) + p[4:] 118 return p + pay 119 120 121############################################################################### 122# ClientHello/ServerHello extensions # 123############################################################################### 124 125# We provide these extensions mostly for packet manipulation purposes. 126# For now, most of them are not considered by our automaton. 127 128class TLS_Ext_PrettyPacketList(TLS_Ext_Unknown): 129 """ 130 Dummy extension used for server_name/ALPN/NPN for a lighter representation: 131 the final field is showed as a 1-line list rather than as lots of packets. 132 XXX Define a new condition for packet lists in Packet._show_or_dump? 133 """ 134 135 def _show_or_dump(self, dump=False, indent=3, 136 lvl="", label_lvl="", first_call=True): 137 """ Reproduced from packet.py """ 138 ct = AnsiColorTheme() if dump else conf.color_theme 139 s = "%s%s %s %s \n" % (label_lvl, ct.punct("###["), 140 ct.layer_name(self.name), ct.punct("]###")) 141 for f in self.fields_desc[:-1]: 142 ncol = ct.field_name 143 vcol = ct.field_value 144 fvalue = self.getfieldval(f.name) 145 begn = "%s %-10s%s " % (label_lvl + lvl, ncol(f.name), 146 ct.punct("="),) 147 reprval = f.i2repr(self, fvalue) 148 if isinstance(reprval, str): 149 reprval = reprval.replace("\n", "\n" + " " * (len(label_lvl) + 150 len(lvl) + 151 len(f.name) + 152 4)) 153 s += "%s%s\n" % (begn, vcol(reprval)) 154 f = self.fields_desc[-1] 155 ncol = ct.field_name 156 vcol = ct.field_value 157 fvalue = self.getfieldval(f.name) 158 begn = "%s %-10s%s " % (label_lvl + lvl, ncol(f.name), ct.punct("="),) 159 reprval = f.i2repr(self, fvalue) 160 if isinstance(reprval, str): 161 reprval = reprval.replace("\n", "\n" + " " * (len(label_lvl) + 162 len(lvl) + 163 len(f.name) + 164 4)) 165 s += "%s%s\n" % (begn, vcol(reprval)) 166 if self.payload: 167 s += self.payload._show_or_dump(dump=dump, indent=indent, 168 lvl=lvl + (" " * indent * self.show_indent), # noqa: E501 169 label_lvl=label_lvl, first_call=False) # noqa: E501 170 171 if first_call and not dump: 172 print(s) 173 else: 174 return s 175 176 177_tls_server_name_types = {0: "host_name"} 178 179 180class ServerName(Packet): 181 name = "HostName" 182 fields_desc = [ByteEnumField("nametype", 0, _tls_server_name_types), 183 FieldLenField("namelen", None, length_of="servername"), 184 StrLenField("servername", "", 185 length_from=lambda pkt: pkt.namelen)] 186 187 def guess_payload_class(self, p): 188 return Padding 189 190 191class ServerListField(PacketListField): 192 def i2repr(self, pkt, x): 193 res = [p.servername for p in x] 194 return "[%s]" % ", ".join(repr(x) for x in res) 195 196 197class ServerLenField(FieldLenField): 198 """ 199 There is no length when there are no servernames (as in a ServerHello). 200 """ 201 202 def addfield(self, pkt, s, val): 203 if not val: 204 if not pkt.servernames: 205 return s 206 return super(ServerLenField, self).addfield(pkt, s, val) 207 208 209class TLS_Ext_ServerName(TLS_Ext_PrettyPacketList): # RFC 4366 210 name = "TLS Extension - Server Name" 211 fields_desc = [ShortEnumField("type", 0, _tls_ext), 212 MayEnd(FieldLenField("len", None, length_of="servernames", 213 adjust=lambda pkt, x: x + 2)), 214 ServerLenField("servernameslen", None, 215 length_of="servernames"), 216 ServerListField("servernames", [], ServerName, 217 length_from=lambda pkt: pkt.servernameslen)] 218 219 220class TLS_Ext_EncryptedServerName(TLS_Ext_PrettyPacketList): 221 name = "TLS Extension - Encrypted Server Name" 222 fields_desc = [ShortEnumField("type", 0xffce, _tls_ext), 223 MayEnd(ShortField("len", None)), 224 EnumField("cipher", None, _tls_cipher_suites), 225 ShortEnumField("key_exchange_group", None, 226 _tls_named_groups), 227 FieldLenField("key_exchange_len", None, 228 length_of="key_exchange", fmt="H"), 229 XStrLenField("key_exchange", "", 230 length_from=lambda pkt: pkt.key_exchange_len), 231 FieldLenField("record_digest_len", 232 None, length_of="record_digest"), 233 XStrLenField("record_digest", "", 234 length_from=lambda pkt: pkt.record_digest_len), 235 FieldLenField("encrypted_sni_len", None, 236 length_of="encrypted_sni", fmt="H"), 237 XStrLenField("encrypted_sni", "", 238 length_from=lambda pkt: pkt.encrypted_sni_len)] 239 240 241class TLS_Ext_MaxFragLen(TLS_Ext_Unknown): # RFC 4366 242 name = "TLS Extension - Max Fragment Length" 243 fields_desc = [ShortEnumField("type", 1, _tls_ext), 244 MayEnd(ShortField("len", None)), 245 ByteEnumField("maxfraglen", 4, {1: "2^9", 246 2: "2^10", 247 3: "2^11", 248 4: "2^12"})] 249 250 251class TLS_Ext_ClientCertURL(TLS_Ext_Unknown): # RFC 4366 252 name = "TLS Extension - Client Certificate URL" 253 fields_desc = [ShortEnumField("type", 2, _tls_ext), 254 MayEnd(ShortField("len", None))] 255 256 257_tls_trusted_authority_types = {0: "pre_agreed", 258 1: "key_sha1_hash", 259 2: "x509_name", 260 3: "cert_sha1_hash"} 261 262 263class TAPreAgreed(Packet): 264 name = "Trusted authority - pre_agreed" 265 fields_desc = [ByteEnumField("idtype", 0, _tls_trusted_authority_types)] 266 267 def guess_payload_class(self, p): 268 return Padding 269 270 271class TAKeySHA1Hash(Packet): 272 name = "Trusted authority - key_sha1_hash" 273 fields_desc = [ByteEnumField("idtype", 1, _tls_trusted_authority_types), 274 StrFixedLenField("id", None, 20)] 275 276 def guess_payload_class(self, p): 277 return Padding 278 279 280class TAX509Name(Packet): 281 """ 282 XXX Section 3.4 of RFC 4366. Implement a more specific DNField 283 rather than current StrLenField. 284 """ 285 name = "Trusted authority - x509_name" 286 fields_desc = [ByteEnumField("idtype", 2, _tls_trusted_authority_types), 287 FieldLenField("dnlen", None, length_of="dn"), 288 StrLenField("dn", "", length_from=lambda pkt: pkt.dnlen)] 289 290 def guess_payload_class(self, p): 291 return Padding 292 293 294class TACertSHA1Hash(Packet): 295 name = "Trusted authority - cert_sha1_hash" 296 fields_desc = [ByteEnumField("idtype", 3, _tls_trusted_authority_types), 297 StrFixedLenField("id", None, 20)] 298 299 def guess_payload_class(self, p): 300 return Padding 301 302 303_tls_trusted_authority_cls = {0: TAPreAgreed, 304 1: TAKeySHA1Hash, 305 2: TAX509Name, 306 3: TACertSHA1Hash} 307 308 309class _TAListField(PacketListField): 310 """ 311 Specific version that selects the right Trusted Authority (previous TA*) 312 class to be used for dissection based on idtype. 313 """ 314 315 def m2i(self, pkt, m): 316 idtype = ord(m[0]) 317 cls = self.cls 318 if idtype in _tls_trusted_authority_cls: 319 cls = _tls_trusted_authority_cls[idtype] 320 return cls(m) 321 322 323class TLS_Ext_TrustedCAInd(TLS_Ext_Unknown): # RFC 4366 324 name = "TLS Extension - Trusted CA Indication" 325 fields_desc = [ShortEnumField("type", 3, _tls_ext), 326 MayEnd(ShortField("len", None)), 327 FieldLenField("talen", None, length_of="ta"), 328 _TAListField("ta", [], Raw, 329 length_from=lambda pkt: pkt.talen)] 330 331 332class TLS_Ext_TruncatedHMAC(TLS_Ext_Unknown): # RFC 4366 333 name = "TLS Extension - Truncated HMAC" 334 fields_desc = [ShortEnumField("type", 4, _tls_ext), 335 MayEnd(ShortField("len", None))] 336 337 338class ResponderID(Packet): 339 name = "Responder ID structure" 340 fields_desc = [FieldLenField("respidlen", None, length_of="respid"), 341 StrLenField("respid", "", 342 length_from=lambda pkt: pkt.respidlen)] 343 344 def guess_payload_class(self, p): 345 return Padding 346 347 348class OCSPStatusRequest(Packet): 349 """ 350 This is the structure defined in RFC 6066, not in RFC 6960! 351 """ 352 name = "OCSPStatusRequest structure" 353 fields_desc = [FieldLenField("respidlen", None, length_of="respid"), 354 PacketListField("respid", [], ResponderID, 355 length_from=lambda pkt: pkt.respidlen), 356 FieldLenField("reqextlen", None, length_of="reqext"), 357 PacketField("reqext", "", X509_Extensions)] 358 359 def guess_payload_class(self, p): 360 return Padding 361 362 363_cert_status_type = {1: "ocsp"} 364_cert_status_req_cls = {1: OCSPStatusRequest} 365 366 367class _StatusReqField(PacketListField): 368 def m2i(self, pkt, m): 369 idtype = pkt.stype 370 cls = self.cls 371 if idtype in _cert_status_req_cls: 372 cls = _cert_status_req_cls[idtype] 373 return cls(m) 374 375 376class TLS_Ext_CSR(TLS_Ext_Unknown): # RFC 4366 377 name = "TLS Extension - Certificate Status Request" 378 fields_desc = [ShortEnumField("type", 5, _tls_ext), 379 MayEnd(ShortField("len", None)), 380 ByteEnumField("stype", None, _cert_status_type), 381 _StatusReqField("req", [], Raw, 382 length_from=lambda pkt: pkt.len - 1)] 383 384 385class TLS_Ext_UserMapping(TLS_Ext_Unknown): # RFC 4681 386 name = "TLS Extension - User Mapping" 387 fields_desc = [ShortEnumField("type", 6, _tls_ext), 388 MayEnd(ShortField("len", None)), 389 FieldLenField("umlen", None, fmt="B", length_of="um"), 390 FieldListField("um", [], 391 ByteField("umtype", 0), 392 length_from=lambda pkt: pkt.umlen)] 393 394 395class TLS_Ext_ClientAuthz(TLS_Ext_Unknown): # RFC 5878 396 """ XXX Unsupported """ 397 name = "TLS Extension - Client Authz" 398 fields_desc = [ShortEnumField("type", 7, _tls_ext), 399 MayEnd(ShortField("len", None)), 400 ] 401 402 403class TLS_Ext_ServerAuthz(TLS_Ext_Unknown): # RFC 5878 404 """ XXX Unsupported """ 405 name = "TLS Extension - Server Authz" 406 fields_desc = [ShortEnumField("type", 8, _tls_ext), 407 MayEnd(ShortField("len", None)), 408 ] 409 410 411_tls_cert_types = {0: "X.509", 1: "OpenPGP"} 412 413 414class TLS_Ext_ClientCertType(TLS_Ext_Unknown): # RFC 5081 415 name = "TLS Extension - Certificate Type (client version)" 416 fields_desc = [ShortEnumField("type", 9, _tls_ext), 417 MayEnd(ShortField("len", None)), 418 FieldLenField("ctypeslen", None, length_of="ctypes"), 419 FieldListField("ctypes", [0, 1], 420 ByteEnumField("certtypes", None, 421 _tls_cert_types), 422 length_from=lambda pkt: pkt.ctypeslen)] 423 424 425class TLS_Ext_ServerCertType(TLS_Ext_Unknown): # RFC 5081 426 name = "TLS Extension - Certificate Type (server version)" 427 fields_desc = [ShortEnumField("type", 9, _tls_ext), 428 MayEnd(ShortField("len", None)), 429 ByteEnumField("ctype", None, _tls_cert_types)] 430 431 432def _TLS_Ext_CertTypeDispatcher(m, *args, **kargs): 433 """ 434 We need to select the correct one on dissection. We use the length for 435 that, as 1 for client version would imply an empty list. 436 """ 437 tmp_len = struct.unpack("!H", m[2:4])[0] 438 if tmp_len == 1: 439 cls = TLS_Ext_ServerCertType 440 else: 441 cls = TLS_Ext_ClientCertType 442 return cls(m, *args, **kargs) 443 444 445class TLS_Ext_SupportedGroups(TLS_Ext_Unknown): 446 """ 447 This extension was known as 'Supported Elliptic Curves' before TLS 1.3 448 merged both group selection mechanisms for ECDH and FFDH. 449 """ 450 name = "TLS Extension - Supported Groups" 451 fields_desc = [ShortEnumField("type", 10, _tls_ext), 452 MayEnd(ShortField("len", None)), 453 FieldLenField("groupslen", None, length_of="groups"), 454 FieldListField("groups", [], 455 ShortEnumField("ng", None, 456 _tls_named_groups), 457 length_from=lambda pkt: pkt.groupslen)] 458 459 460class TLS_Ext_SupportedEllipticCurves(TLS_Ext_SupportedGroups): # RFC 4492 461 pass 462 463 464_tls_ecpoint_format = {0: "uncompressed", 465 1: "ansiX962_compressed_prime", 466 2: "ansiX962_compressed_char2"} 467 468 469class TLS_Ext_SupportedPointFormat(TLS_Ext_Unknown): # RFC 4492 470 name = "TLS Extension - Supported Point Format" 471 fields_desc = [ShortEnumField("type", 11, _tls_ext), 472 MayEnd(ShortField("len", None)), 473 FieldLenField("ecpllen", None, fmt="B", length_of="ecpl"), 474 FieldListField("ecpl", [0], 475 ByteEnumField("nc", None, 476 _tls_ecpoint_format), 477 length_from=lambda pkt: pkt.ecpllen)] 478 479 480class TLS_Ext_SignatureAlgorithms(TLS_Ext_Unknown): # RFC 5246 481 name = "TLS Extension - Signature Algorithms" 482 fields_desc = [ShortEnumField("type", 13, _tls_ext), 483 MayEnd(ShortField("len", None)), 484 SigAndHashAlgsLenField("sig_algs_len", None, 485 length_of="sig_algs"), 486 SigAndHashAlgsField("sig_algs", [], 487 EnumField("hash_sig", None, 488 _tls_hash_sig), 489 length_from=lambda pkt: pkt.sig_algs_len)] # noqa: E501 490 491 492class TLS_Ext_Heartbeat(TLS_Ext_Unknown): # RFC 6520 493 name = "TLS Extension - Heartbeat" 494 fields_desc = [ShortEnumField("type", 0x0f, _tls_ext), 495 MayEnd(ShortField("len", None)), 496 ByteEnumField("heartbeat_mode", 2, 497 {1: "peer_allowed_to_send", 498 2: "peer_not_allowed_to_send"})] 499 500 501class ProtocolName(Packet): 502 name = "Protocol Name" 503 fields_desc = [FieldLenField("len", None, fmt='B', length_of="protocol"), 504 StrLenField("protocol", "", 505 length_from=lambda pkt: pkt.len)] 506 507 def guess_payload_class(self, p): 508 return Padding 509 510 511class ProtocolListField(PacketListField): 512 def i2repr(self, pkt, x): 513 res = [p.protocol for p in x] 514 return "[%s]" % ", ".join(repr(x) for x in res) 515 516 517class TLS_Ext_ALPN(TLS_Ext_PrettyPacketList): # RFC 7301 518 name = "TLS Extension - Application Layer Protocol Negotiation" 519 fields_desc = [ShortEnumField("type", 0x10, _tls_ext), 520 MayEnd(ShortField("len", None)), 521 FieldLenField("protocolslen", None, length_of="protocols"), 522 ProtocolListField("protocols", [], ProtocolName, 523 length_from=lambda pkt:pkt.protocolslen)] 524 525 526class TLS_Ext_Padding(TLS_Ext_Unknown): # RFC 7685 527 name = "TLS Extension - Padding" 528 fields_desc = [ShortEnumField("type", 0x15, _tls_ext), 529 FieldLenField("len", None, length_of="padding"), 530 StrLenField("padding", "", 531 length_from=lambda pkt: pkt.len)] 532 533 534class TLS_Ext_EncryptThenMAC(TLS_Ext_Unknown): # RFC 7366 535 name = "TLS Extension - Encrypt-then-MAC" 536 fields_desc = [ShortEnumField("type", 0x16, _tls_ext), 537 MayEnd(ShortField("len", None))] 538 539 540class TLS_Ext_ExtendedMasterSecret(TLS_Ext_Unknown): # RFC 7627 541 name = "TLS Extension - Extended Master Secret" 542 fields_desc = [ShortEnumField("type", 0x17, _tls_ext), 543 MayEnd(ShortField("len", None))] 544 545 546class TLS_Ext_SessionTicket(TLS_Ext_Unknown): # RFC 5077 547 """ 548 RFC 5077 updates RFC 4507 according to most implementations, which do not 549 use another (useless) 'ticketlen' field after the global 'len' field. 550 """ 551 name = "TLS Extension - Session Ticket" 552 fields_desc = [ShortEnumField("type", 0x23, _tls_ext), 553 FieldLenField("len", None, length_of="ticket"), 554 StrLenField("ticket", "", 555 length_from=lambda pkt: pkt.len)] 556 557 558class TLS_Ext_KeyShare(TLS_Ext_Unknown): 559 name = "TLS Extension - Key Share (dummy class)" 560 fields_desc = [ShortEnumField("type", 0x33, _tls_ext), 561 MayEnd(ShortField("len", None))] 562 563 564class TLS_Ext_PreSharedKey(TLS_Ext_Unknown): 565 name = "TLS Extension - Pre Shared Key (dummy class)" 566 fields_desc = [ShortEnumField("type", 0x29, _tls_ext), 567 MayEnd(ShortField("len", None))] 568 569 570class TLS_Ext_EarlyDataIndication(TLS_Ext_Unknown): 571 name = "TLS Extension - Early Data" 572 fields_desc = [ShortEnumField("type", 0x2a, _tls_ext), 573 MayEnd(ShortField("len", None))] 574 575 576class TLS_Ext_EarlyDataIndicationTicket(TLS_Ext_Unknown): 577 name = "TLS Extension - Ticket Early Data Info" 578 fields_desc = [ShortEnumField("type", 0x2a, _tls_ext), 579 MayEnd(ShortField("len", None)), 580 IntField("max_early_data_size", 0)] 581 582 583_tls_ext_early_data_cls = {1: TLS_Ext_EarlyDataIndication, 584 4: TLS_Ext_EarlyDataIndicationTicket, 585 8: TLS_Ext_EarlyDataIndication} 586 587 588class TLS_Ext_SupportedVersions(TLS_Ext_Unknown): 589 name = "TLS Extension - Supported Versions (dummy class)" 590 fields_desc = [ShortEnumField("type", 0x2b, _tls_ext), 591 MayEnd(ShortField("len", None))] 592 593 594class TLS_Ext_SupportedVersion_CH(TLS_Ext_Unknown): 595 name = "TLS Extension - Supported Versions (for ClientHello)" 596 fields_desc = [ShortEnumField("type", 0x2b, _tls_ext), 597 MayEnd(ShortField("len", None)), 598 FieldLenField("versionslen", None, fmt='B', 599 length_of="versions"), 600 FieldListField("versions", [], 601 ShortEnumField("version", None, 602 _tls_version), 603 length_from=lambda pkt: pkt.versionslen)] 604 605 606class TLS_Ext_SupportedVersion_SH(TLS_Ext_Unknown): 607 name = "TLS Extension - Supported Versions (for ServerHello)" 608 fields_desc = [ShortEnumField("type", 0x2b, _tls_ext), 609 MayEnd(ShortField("len", None)), 610 ShortEnumField("version", None, _tls_version)] 611 612 613_tls_ext_supported_version_cls = {1: TLS_Ext_SupportedVersion_CH, 614 2: TLS_Ext_SupportedVersion_SH} 615 616 617class TLS_Ext_Cookie(TLS_Ext_Unknown): 618 name = "TLS Extension - Cookie" 619 fields_desc = [ShortEnumField("type", 0x2c, _tls_ext), 620 MayEnd(ShortField("len", None)), 621 FieldLenField("cookielen", None, length_of="cookie"), 622 XStrLenField("cookie", "", 623 length_from=lambda pkt: pkt.cookielen)] 624 625 def build(self): 626 fval = self.getfieldval("cookie") 627 if fval is None or fval == b"": 628 self.cookie = os.urandom(32) 629 return TLS_Ext_Unknown.build(self) 630 631 632_tls_psk_kx_modes = {0: "psk_ke", 1: "psk_dhe_ke"} 633 634 635class TLS_Ext_PSKKeyExchangeModes(TLS_Ext_Unknown): 636 name = "TLS Extension - PSK Key Exchange Modes" 637 fields_desc = [ShortEnumField("type", 0x2d, _tls_ext), 638 MayEnd(ShortField("len", None)), 639 FieldLenField("kxmodeslen", None, fmt='B', 640 length_of="kxmodes"), 641 FieldListField("kxmodes", [], 642 ByteEnumField("kxmode", None, 643 _tls_psk_kx_modes), 644 length_from=lambda pkt: pkt.kxmodeslen)] 645 646 647class TLS_Ext_TicketEarlyDataInfo(TLS_Ext_Unknown): 648 name = "TLS Extension - Ticket Early Data Info" 649 fields_desc = [ShortEnumField("type", 0x2e, _tls_ext), 650 MayEnd(ShortField("len", None)), 651 IntField("max_early_data_size", 0)] 652 653 654class TLS_Ext_NPN(TLS_Ext_PrettyPacketList): 655 """ 656 Defined in RFC-draft-agl-tls-nextprotoneg-03. Deprecated in favour of ALPN. 657 """ 658 name = "TLS Extension - Next Protocol Negotiation" 659 fields_desc = [ShortEnumField("type", 0x3374, _tls_ext), 660 FieldLenField("len", None, length_of="protocols"), 661 ProtocolListField("protocols", [], ProtocolName, 662 length_from=lambda pkt:pkt.len)] 663 664 665class TLS_Ext_PostHandshakeAuth(TLS_Ext_Unknown): # RFC 8446 666 name = "TLS Extension - Post Handshake Auth" 667 fields_desc = [ShortEnumField("type", 0x31, _tls_ext), 668 MayEnd(ShortField("len", None))] 669 670 671class TLS_Ext_SignatureAlgorithmsCert(TLS_Ext_Unknown): # RFC 8446 672 name = "TLS Extension - Signature Algorithms Cert" 673 fields_desc = [ShortEnumField("type", 0x32, _tls_ext), 674 MayEnd(ShortField("len", None)), 675 SigAndHashAlgsLenField("sig_algs_len", None, 676 length_of="sig_algs"), 677 SigAndHashAlgsField("sig_algs", [], 678 EnumField("hash_sig", None, 679 _tls_hash_sig), 680 length_from=lambda pkt: pkt.sig_algs_len)] # noqa: E501 681 682 683class TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown): # RFC 5746 684 name = "TLS Extension - Renegotiation Indication" 685 fields_desc = [ShortEnumField("type", 0xff01, _tls_ext), 686 MayEnd(ShortField("len", None)), 687 FieldLenField("reneg_conn_len", None, fmt='B', 688 length_of="renegotiated_connection"), 689 StrLenField("renegotiated_connection", "", 690 length_from=lambda pkt: pkt.reneg_conn_len)] 691 692 693class TLS_Ext_RecordSizeLimit(TLS_Ext_Unknown): # RFC 8449 694 name = "TLS Extension - Record Size Limit" 695 fields_desc = [ShortEnumField("type", 0x1c, _tls_ext), 696 MayEnd(ShortField("len", None)), 697 ShortField("record_size_limit", None)] 698 699 700_tls_ext_cls = {0: TLS_Ext_ServerName, 701 1: TLS_Ext_MaxFragLen, 702 2: TLS_Ext_ClientCertURL, 703 3: TLS_Ext_TrustedCAInd, 704 4: TLS_Ext_TruncatedHMAC, 705 5: TLS_Ext_CSR, 706 6: TLS_Ext_UserMapping, 707 7: TLS_Ext_ClientAuthz, 708 8: TLS_Ext_ServerAuthz, 709 9: _TLS_Ext_CertTypeDispatcher, 710 # 10: TLS_Ext_SupportedEllipticCurves, 711 10: TLS_Ext_SupportedGroups, 712 11: TLS_Ext_SupportedPointFormat, 713 13: TLS_Ext_SignatureAlgorithms, 714 0x0f: TLS_Ext_Heartbeat, 715 0x10: TLS_Ext_ALPN, 716 0x15: TLS_Ext_Padding, 717 0x16: TLS_Ext_EncryptThenMAC, 718 0x17: TLS_Ext_ExtendedMasterSecret, 719 0x1c: TLS_Ext_RecordSizeLimit, 720 0x23: TLS_Ext_SessionTicket, 721 # 0x28: TLS_Ext_KeyShare, 722 0x29: TLS_Ext_PreSharedKey, 723 0x2a: TLS_Ext_EarlyDataIndication, 724 0x2b: TLS_Ext_SupportedVersions, 725 0x2c: TLS_Ext_Cookie, 726 0x2d: TLS_Ext_PSKKeyExchangeModes, 727 # 0x2e: TLS_Ext_TicketEarlyDataInfo, 728 0x31: TLS_Ext_PostHandshakeAuth, 729 0x32: TLS_Ext_SignatureAlgorithmsCert, 730 0x33: TLS_Ext_KeyShare, 731 # 0x2f: TLS_Ext_CertificateAuthorities, #XXX 732 # 0x30: TLS_Ext_OIDFilters, #XXX 733 0x3374: TLS_Ext_NPN, 734 0xff01: TLS_Ext_RenegotiationInfo, 735 0xffce: TLS_Ext_EncryptedServerName 736 } 737 738 739class _ExtensionsLenField(FieldLenField): 740 def getfield(self, pkt, s): 741 """ 742 We try to compute a length, usually from a msglen parsed earlier. 743 If we can not find any length, we consider 'extensions_present' 744 (from RFC 5246) to be False. 745 """ 746 ext = pkt.get_field(self.length_of) 747 tmp_len = ext.length_from(pkt) 748 if tmp_len is None or tmp_len < 0: 749 v = pkt.tls_session.tls_version 750 if v is None or v < 0x0304: 751 return s, None 752 return super(_ExtensionsLenField, self).getfield(pkt, s) 753 754 def addfield(self, pkt, s, i): 755 """ 756 There is a hack with the _ExtensionsField.i2len. It works only because 757 we expect _ExtensionsField.i2m to return a string of the same size (if 758 not of the same value) upon successive calls (e.g. through i2len here, 759 then i2m when directly building the _ExtensionsField). 760 761 XXX A proper way to do this would be to keep the extensions built from 762 the i2len call here, instead of rebuilding them later on. 763 """ 764 if i is None: 765 if self.length_of is not None: 766 fld, fval = pkt.getfield_and_val(self.length_of) 767 768 tmp = pkt.tls_session.frozen 769 pkt.tls_session.frozen = True 770 f = fld.i2len(pkt, fval) 771 pkt.tls_session.frozen = tmp 772 773 i = self.adjust(pkt, f) 774 if i == 0: # for correct build if no ext and not explicitly 0 775 v = pkt.tls_session.tls_version 776 # With TLS 1.3, zero lengths are always explicit. 777 if v is None or v < 0x0304: 778 return s 779 else: 780 return s + struct.pack(self.fmt, i) 781 return s + struct.pack(self.fmt, i) 782 783 784class _ExtensionsField(StrLenField): 785 islist = 1 786 holds_packets = 1 787 788 def i2len(self, pkt, i): 789 if i is None: 790 return 0 791 return len(self.i2m(pkt, i)) 792 793 def getfield(self, pkt, s): 794 tmp_len = self.length_from(pkt) or 0 795 if tmp_len <= 0: 796 return s, [] 797 return s[tmp_len:], self.m2i(pkt, s[:tmp_len]) 798 799 def i2m(self, pkt, i): 800 if i is None: 801 return b"" 802 if isinstance(pkt, _GenericTLSSessionInheritance): 803 if not pkt.tls_session.frozen: 804 s = b"" 805 for ext in i: 806 if isinstance(ext, _GenericTLSSessionInheritance): 807 ext.tls_session = pkt.tls_session 808 s += ext.raw_stateful() 809 else: 810 s += raw(ext) 811 return s 812 return b"".join(map(raw, i)) 813 814 def m2i(self, pkt, m): 815 res = [] 816 while len(m) >= 4: 817 t = struct.unpack("!H", m[:2])[0] 818 tmp_len = struct.unpack("!H", m[2:4])[0] 819 cls = _tls_ext_cls.get(t, TLS_Ext_Unknown) 820 if cls is TLS_Ext_KeyShare: 821 # TLS_Ext_KeyShare can be : 822 # - TLS_Ext_KeyShare_CH if the message is a ClientHello 823 # - TLS_Ext_KeyShare_SH if the message is a ServerHello 824 # and all parameters are accepted by the serveur 825 # - TLS_Ext_KeyShare_HRR if message is a ServerHello and 826 # the client has not provided a sufficient "key_share" 827 # extension 828 from scapy.layers.tls.keyexchange_tls13 import ( 829 _tls_ext_keyshare_cls, _tls_ext_keyshare_hrr_cls) 830 # If SHA-256("HelloRetryRequest") == server_random, 831 # this message is a HelloRetryRequest 832 if pkt.random_bytes and \ 833 pkt.random_bytes == _tls_hello_retry_magic: 834 cls = _tls_ext_keyshare_hrr_cls.get(pkt.msgtype, TLS_Ext_Unknown) # noqa: E501 835 else: 836 cls = _tls_ext_keyshare_cls.get(pkt.msgtype, TLS_Ext_Unknown) # noqa: E501 837 elif cls is TLS_Ext_PreSharedKey: 838 from scapy.layers.tls.keyexchange_tls13 import _tls_ext_presharedkey_cls # noqa: E501 839 cls = _tls_ext_presharedkey_cls.get(pkt.msgtype, TLS_Ext_Unknown) # noqa: E501 840 elif cls is TLS_Ext_SupportedVersions: 841 cls = _tls_ext_supported_version_cls.get(pkt.msgtype, TLS_Ext_Unknown) # noqa: E501 842 elif cls is TLS_Ext_EarlyDataIndication: 843 cls = _tls_ext_early_data_cls.get(pkt.msgtype, TLS_Ext_Unknown) 844 res.append(cls(m[:tmp_len + 4], tls_session=pkt.tls_session)) 845 m = m[tmp_len + 4:] 846 if m: 847 res.append(conf.raw_layer(m)) 848 return res 849