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) 2007, 2008, 2009 Arnaud Ebalard 5# 2015, 2016, 2017 Maxence Tury 6# 2019 Romain Perez 7 8""" 9TLS handshake fields & logic. 10 11This module covers the handshake TLS subprotocol, except for the key exchange 12mechanisms which are addressed with keyexchange.py. 13""" 14 15import math 16import os 17import struct 18 19from scapy.error import log_runtime, warning 20from scapy.fields import ( 21 ByteEnumField, 22 ByteField, 23 Field, 24 FieldLenField, 25 IntField, 26 PacketField, 27 PacketLenField, 28 PacketListField, 29 ShortEnumField, 30 ShortField, 31 StrFixedLenField, 32 StrLenField, 33 ThreeBytesField, 34 UTCTimeField, 35) 36 37from scapy.compat import hex_bytes, orb, raw 38from scapy.config import conf 39from scapy.packet import Packet, Raw, Padding 40from scapy.utils import randstring, repr_hex 41from scapy.layers.x509 import OCSP_Response 42from scapy.layers.tls.cert import Cert 43from scapy.layers.tls.basefields import (_tls_version, _TLSVersionField, 44 _TLSClientVersionField) 45from scapy.layers.tls.extensions import (_ExtensionsLenField, _ExtensionsField, 46 _cert_status_type, 47 TLS_Ext_PostHandshakeAuth, 48 TLS_Ext_SupportedVersion_CH, 49 TLS_Ext_SignatureAlgorithms, 50 TLS_Ext_SupportedVersion_SH, 51 TLS_Ext_EarlyDataIndication, 52 _tls_hello_retry_magic, 53 TLS_Ext_ExtendedMasterSecret, 54 TLS_Ext_EncryptThenMAC) 55from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField, 56 _TLSSignatureField, ServerRSAParams, 57 SigAndHashAlgsField, _tls_hash_sig, 58 SigAndHashAlgsLenField) 59from scapy.layers.tls.session import (_GenericTLSSessionInheritance, 60 readConnState, writeConnState) 61from scapy.layers.tls.keyexchange_tls13 import TLS_Ext_PreSharedKey_CH 62from scapy.layers.tls.crypto.compression import (_tls_compression_algs, 63 _tls_compression_algs_cls, 64 Comp_NULL, _GenericComp, 65 _GenericCompMetaclass) 66from scapy.layers.tls.crypto.suites import (_tls_cipher_suites, 67 _tls_cipher_suites_cls, 68 _GenericCipherSuite, 69 _GenericCipherSuiteMetaclass) 70from scapy.layers.tls.crypto.hkdf import TLS13_HKDF 71 72if conf.crypto_valid: 73 from cryptography.hazmat.backends import default_backend 74 from cryptography.hazmat.primitives import hashes 75 76 77############################################################################### 78# Generic TLS Handshake message # 79############################################################################### 80 81_tls_handshake_type = {0: "hello_request", 1: "client_hello", 82 2: "server_hello", 3: "hello_verify_request", 83 4: "session_ticket", 6: "hello_retry_request", 84 8: "encrypted_extensions", 11: "certificate", 85 12: "server_key_exchange", 13: "certificate_request", 86 14: "server_hello_done", 15: "certificate_verify", 87 16: "client_key_exchange", 20: "finished", 88 21: "certificate_url", 22: "certificate_status", 89 23: "supplemental_data", 24: "key_update"} 90 91 92class _TLSHandshake(_GenericTLSSessionInheritance): 93 """ 94 Inherited by other Handshake classes to get post_build(). 95 Also used as a fallback for unknown TLS Handshake packets. 96 """ 97 name = "TLS Handshake Generic message" 98 fields_desc = [ByteEnumField("msgtype", None, _tls_handshake_type), 99 ThreeBytesField("msglen", None), 100 StrLenField("msg", "", 101 length_from=lambda pkt: pkt.msglen)] 102 103 def post_build(self, p, pay): 104 tmp_len = len(p) 105 if self.msglen is None: 106 l2 = tmp_len - 4 107 p = struct.pack("!I", (orb(p[0]) << 24) | l2) + p[4:] 108 return p + pay 109 110 def guess_payload_class(self, p): 111 return conf.padding_layer 112 113 def tls_session_update(self, msg_str): 114 """ 115 Covers both post_build- and post_dissection- context updates. 116 """ 117 # RFC8446 sect 4.4.1 118 # "Note, however, that subsequent post-handshake authentications do not 119 # include each other, just the messages through the end of the main 120 # handshake." 121 if self.tls_session.post_handshake: 122 self.tls_session.post_handshake_messages.append(msg_str) 123 else: 124 self.tls_session.handshake_messages.append(msg_str) 125 self.tls_session.handshake_messages_parsed.append(self) 126 127 128############################################################################### 129# HelloRequest # 130############################################################################### 131 132class TLSHelloRequest(_TLSHandshake): 133 name = "TLS Handshake - Hello Request" 134 fields_desc = [ByteEnumField("msgtype", 0, _tls_handshake_type), 135 ThreeBytesField("msglen", None)] 136 137 def tls_session_update(self, msg_str): 138 """ 139 Message should not be added to the list of handshake messages 140 that will be hashed in the finished and certificate verify messages. 141 """ 142 return 143 144 145############################################################################### 146# ClientHello fields # 147############################################################################### 148 149class _GMTUnixTimeField(UTCTimeField): 150 """ 151 "The current time and date in standard UNIX 32-bit format (seconds since 152 the midnight starting Jan 1, 1970, GMT, ignoring leap seconds)." 153 """ 154 155 def i2h(self, pkt, x): 156 if x is not None: 157 return x 158 return 0 159 160 def i2m(self, pkt, x): 161 return int(x) if x is not None else 0 162 163 164class _TLSRandomBytesField(StrFixedLenField): 165 def i2repr(self, pkt, x): 166 if x is None: 167 return repr(x) 168 return repr_hex(self.i2h(pkt, x)) 169 170 171class _SessionIDField(StrLenField): 172 """ 173 opaque SessionID<0..32>; section 7.4.1.2 of RFC 4346 174 """ 175 pass 176 177 178class _CipherSuitesField(StrLenField): 179 __slots__ = ["itemfmt", "itemsize", "i2s", "s2i"] 180 islist = 1 181 182 def __init__(self, name, default, dico, length_from=None, itemfmt="!H"): 183 StrLenField.__init__(self, name, default, length_from=length_from) 184 self.itemfmt = itemfmt 185 self.itemsize = struct.calcsize(itemfmt) 186 i2s = self.i2s = {} 187 s2i = self.s2i = {} 188 for k in dico.keys(): 189 i2s[k] = dico[k] 190 s2i[dico[k]] = k 191 192 def any2i_one(self, pkt, x): 193 if isinstance(x, (_GenericCipherSuite, _GenericCipherSuiteMetaclass)): 194 x = x.val 195 if isinstance(x, bytes): 196 x = self.s2i[x] 197 return x 198 199 def i2repr_one(self, pkt, x): 200 fmt = "0x%%0%dx" % self.itemsize 201 return self.i2s.get(x, fmt % x) 202 203 def any2i(self, pkt, x): 204 if x is None: 205 return None 206 if not isinstance(x, list): 207 x = [x] 208 return [self.any2i_one(pkt, z) for z in x] 209 210 def i2repr(self, pkt, x): 211 if x is None: 212 return "None" 213 tmp_len = [self.i2repr_one(pkt, z) for z in x] 214 if len(tmp_len) == 1: 215 tmp_len = tmp_len[0] 216 else: 217 tmp_len = "[%s]" % ", ".join(tmp_len) 218 return tmp_len 219 220 def i2m(self, pkt, val): 221 if val is None: 222 val = [] 223 return b"".join(struct.pack(self.itemfmt, x) for x in val) 224 225 def m2i(self, pkt, m): 226 res = [] 227 itemlen = struct.calcsize(self.itemfmt) 228 while m: 229 res.append(struct.unpack(self.itemfmt, m[:itemlen])[0]) 230 m = m[itemlen:] 231 return res 232 233 def i2len(self, pkt, i): 234 if i is None: 235 return 0 236 return len(i) * self.itemsize 237 238 239class _CompressionMethodsField(_CipherSuitesField): 240 241 def any2i_one(self, pkt, x): 242 if isinstance(x, (_GenericComp, _GenericCompMetaclass)): 243 x = x.val 244 if isinstance(x, str): 245 x = self.s2i[x] 246 return x 247 248 249############################################################################### 250# ClientHello # 251############################################################################### 252 253class TLSClientHello(_TLSHandshake): 254 """ 255 TLS ClientHello, with abilities to handle extensions. 256 257 The Random structure follows the RFC 5246: while it is 32-byte long, 258 many implementations use the first 4 bytes as a gmt_unix_time, and then 259 the remaining 28 byts should be completely random. This was designed in 260 order to (sort of) mitigate broken RNGs. If you prefer to show the full 261 32 random bytes without any GMT time, just comment in/out the lines below. 262 """ 263 name = "TLS Handshake - Client Hello" 264 fields_desc = [ByteEnumField("msgtype", 1, _tls_handshake_type), 265 ThreeBytesField("msglen", None), 266 _TLSClientVersionField("version", None, _tls_version), 267 268 # _TLSRandomBytesField("random_bytes", None, 32), 269 _GMTUnixTimeField("gmt_unix_time", None), 270 _TLSRandomBytesField("random_bytes", None, 28), 271 272 FieldLenField("sidlen", None, fmt="B", length_of="sid"), 273 _SessionIDField("sid", "", 274 length_from=lambda pkt: pkt.sidlen), 275 276 FieldLenField("cipherslen", None, fmt="!H", 277 length_of="ciphers"), 278 _CipherSuitesField("ciphers", None, 279 _tls_cipher_suites, itemfmt="!H", 280 length_from=lambda pkt: pkt.cipherslen), 281 282 FieldLenField("complen", None, fmt="B", length_of="comp"), 283 _CompressionMethodsField("comp", [0], 284 _tls_compression_algs, 285 itemfmt="B", 286 length_from=lambda pkt: pkt.complen), # noqa: E501 287 288 _ExtensionsLenField("extlen", None, length_of="ext"), 289 _ExtensionsField("ext", None, 290 length_from=lambda pkt: (pkt.msglen - 291 (pkt.sidlen or 0) - # noqa: E501 292 (pkt.cipherslen or 0) - # noqa: E501 293 (pkt.complen or 0) - # noqa: E501 294 40))] 295 296 def post_build(self, p, pay): 297 if self.random_bytes is None: 298 p = p[:10] + randstring(28) + p[10 + 28:] 299 300 # if no ciphersuites were provided, we add a few usual, supported 301 # ciphersuites along with the appropriate extensions 302 if self.ciphers is None: 303 cipherstart = 39 + (self.sidlen or 0) 304 s = b"001ac02bc023c02fc027009e0067009c003cc009c0130033002f000a" 305 p = p[:cipherstart] + hex_bytes(s) + p[cipherstart + 2:] 306 if self.ext is None: 307 ext_len = b'\x00\x2c' 308 ext_reneg = b'\xff\x01\x00\x01\x00' 309 ext_sn = b'\x00\x00\x00\x0f\x00\r\x00\x00\nsecdev.org' 310 ext_sigalg = b'\x00\r\x00\x08\x00\x06\x04\x03\x04\x01\x02\x01' 311 ext_supgroups = b'\x00\n\x00\x04\x00\x02\x00\x17' 312 p += ext_len + ext_reneg + ext_sn + ext_sigalg + ext_supgroups 313 314 return super(TLSClientHello, self).post_build(p, pay) 315 316 def tls_session_update(self, msg_str): 317 """ 318 Either for parsing or building, we store the client_random 319 along with the raw string representing this handshake message. 320 """ 321 super(TLSClientHello, self).tls_session_update(msg_str) 322 s = self.tls_session 323 s.advertised_tls_version = self.version 324 # This ClientHello could be a 1.3 one. Let's store the sid 325 # in all cases 326 if self.sidlen and self.sidlen > 0: 327 s.sid = self.sid 328 self.random_bytes = msg_str[10:38] 329 s.client_random = (struct.pack('!I', self.gmt_unix_time) + 330 self.random_bytes) 331 332 # No distinction between a TLS 1.2 ClientHello and a TLS 333 # 1.3 ClientHello when dissecting : TLS 1.3 CH will be 334 # parsed as TLSClientHello 335 if self.ext: 336 for e in self.ext: 337 if isinstance(e, TLS_Ext_SupportedVersion_CH): 338 for ver in sorted(e.versions, reverse=True): 339 # RFC 8701: GREASE of TLS will send unknown versions 340 # here. We have to ignore them 341 if ver in _tls_version: 342 s.advertised_tls_version = ver 343 break 344 if s.sid: 345 s.middlebox_compatibility = True 346 if isinstance(e, TLS_Ext_SignatureAlgorithms): 347 s.advertised_sig_algs = e.sig_algs 348 if isinstance(e, TLS_Ext_PostHandshakeAuth): 349 s.post_handshake_auth = True 350 351 352class TLS13ClientHello(_TLSHandshake): 353 """ 354 TLS 1.3 ClientHello, with abilities to handle extensions. 355 356 The Random structure is 32 random bytes without any GMT time 357 """ 358 name = "TLS 1.3 Handshake - Client Hello" 359 fields_desc = [ByteEnumField("msgtype", 1, _tls_handshake_type), 360 ThreeBytesField("msglen", None), 361 _TLSClientVersionField("version", None, _tls_version), 362 363 _TLSRandomBytesField("random_bytes", None, 32), 364 365 FieldLenField("sidlen", None, fmt="B", length_of="sid"), 366 _SessionIDField("sid", "", 367 length_from=lambda pkt: pkt.sidlen), 368 369 FieldLenField("cipherslen", None, fmt="!H", 370 length_of="ciphers"), 371 _CipherSuitesField("ciphers", None, 372 _tls_cipher_suites, itemfmt="!H", 373 length_from=lambda pkt: pkt.cipherslen), 374 375 FieldLenField("complen", None, fmt="B", length_of="comp"), 376 _CompressionMethodsField("comp", [0], 377 _tls_compression_algs, 378 itemfmt="B", 379 length_from=lambda pkt: pkt.complen), # noqa: E501 380 381 _ExtensionsLenField("extlen", None, length_of="ext"), 382 _ExtensionsField("ext", None, 383 length_from=lambda pkt: (pkt.msglen - 384 (pkt.sidlen or 0) - # noqa: E501 385 (pkt.cipherslen or 0) - # noqa: E501 386 (pkt.complen or 0) - # noqa: E501 387 40))] 388 389 def post_build(self, p, pay): 390 if self.random_bytes is None: 391 p = p[:6] + randstring(32) + p[6 + 32:] 392 # We don't call the post_build function from class _TLSHandshake 393 # to compute the message length because we need that value now 394 # for the HMAC in binder 395 tmp_len = len(p) 396 if self.msglen is None: 397 sz = tmp_len - 4 398 p = struct.pack("!I", (orb(p[0]) << 24) | sz) + p[4:] 399 s = self.tls_session 400 if self.ext: 401 for e in self.ext: 402 if isinstance(e, TLS_Ext_PreSharedKey_CH): 403 if s.client_session_ticket: 404 # For a resumed PSK, the hash function use 405 # to compute the binder must be the same 406 # as the one used to establish the original 407 # connection. For that, we assume that 408 # the ciphersuite associate with the ticket 409 # is given as argument to tlsSession 410 # (see layers/tls/automaton_cli.py for an 411 # example) 412 res_suite = s.tls13_ticket_ciphersuite 413 cs_cls = _tls_cipher_suites_cls[res_suite] 414 hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) 415 hash_len = hkdf.hash.digest_size 416 s.compute_tls13_early_secrets(external=False) 417 else: 418 # For out of band PSK, SHA-256 is used as default 419 # hash functions for HKDF 420 hkdf = TLS13_HKDF("sha256") 421 hash_len = hkdf.hash.digest_size 422 s.compute_tls13_early_secrets(external=True) 423 424 # RFC8446 4.2.11.2 425 # "Each entry in the binders list is computed as an HMAC 426 # over a transcript hash (see Section 4.4.1) containing a 427 # partial ClientHello up to and including the 428 # PreSharedKeyExtension.identities field." 429 # PSK Binders field is : 430 # - PSK Binders length (2 bytes) 431 # - First PSK Binder length (1 byte) + 432 # HMAC (hash_len bytes) 433 # The PSK Binder is computed in the same way as the 434 # Finished message with binder_key as BaseKey 435 436 handshake_context = b"" 437 if s.tls13_retry: 438 for m in s.handshake_messages: 439 handshake_context += m 440 handshake_context += p[:-hash_len - 3] 441 442 binder_key = s.tls13_derived_secrets["binder_key"] 443 psk_binder = hkdf.compute_verify_data(binder_key, 444 handshake_context) 445 446 # Here, we replaced the last 32 bytes of the packet by the 447 # new HMAC values computed over the ClientHello (without 448 # the binders) 449 p = p[:-hash_len] + psk_binder 450 451 return p + pay 452 453 def tls_session_update(self, msg_str): 454 """ 455 Either for parsing or building, we store the client_random 456 along with the raw string representing this handshake message. 457 """ 458 super(TLS13ClientHello, self).tls_session_update(msg_str) 459 s = self.tls_session 460 461 if self.sidlen and self.sidlen > 0: 462 s.sid = self.sid 463 s.middlebox_compatibility = True 464 465 self.random_bytes = msg_str[6:38] 466 s.client_random = self.random_bytes 467 if self.ext: 468 for e in self.ext: 469 if isinstance(e, TLS_Ext_SupportedVersion_CH): 470 for ver in sorted(e.versions, reverse=True): 471 # RFC 8701: GREASE of TLS will send unknown versions 472 # here. We have to ignore them 473 if ver in _tls_version: 474 s.advertised_tls_version = ver 475 break 476 if isinstance(e, TLS_Ext_SignatureAlgorithms): 477 s.advertised_sig_algs = e.sig_algs 478 if isinstance(e, TLS_Ext_PostHandshakeAuth): 479 s.post_handshake_auth = True 480 481 482############################################################################### 483# ServerHello # 484############################################################################### 485 486 487class TLSServerHello(_TLSHandshake): 488 """ 489 TLS ServerHello, with abilities to handle extensions. 490 491 The Random structure follows the RFC 5246: while it is 32-byte long, 492 many implementations use the first 4 bytes as a gmt_unix_time, and then 493 the remaining 28 byts should be completely random. This was designed in 494 order to (sort of) mitigate broken RNGs. If you prefer to show the full 495 32 random bytes without any GMT time, just comment in/out the lines below. 496 """ 497 name = "TLS Handshake - Server Hello" 498 fields_desc = [ByteEnumField("msgtype", 2, _tls_handshake_type), 499 ThreeBytesField("msglen", None), 500 _TLSVersionField("version", None, _tls_version), 501 502 # _TLSRandomBytesField("random_bytes", None, 32), 503 _GMTUnixTimeField("gmt_unix_time", None), 504 _TLSRandomBytesField("random_bytes", None, 28), 505 506 FieldLenField("sidlen", None, length_of="sid", fmt="B"), 507 _SessionIDField("sid", "", 508 length_from=lambda pkt: pkt.sidlen), 509 510 ShortEnumField("cipher", None, _tls_cipher_suites), 511 _CompressionMethodsField("comp", [0], 512 _tls_compression_algs, 513 itemfmt="B", 514 length_from=lambda pkt: 1), 515 516 _ExtensionsLenField("extlen", None, length_of="ext"), 517 _ExtensionsField("ext", None, 518 length_from=lambda pkt: ( 519 pkt.msglen - (pkt.sidlen or 0) - 40 520 ))] 521 522 @classmethod 523 def dispatch_hook(cls, _pkt=None, *args, **kargs): 524 if _pkt and len(_pkt) >= 6: 525 version = struct.unpack("!H", _pkt[4:6])[0] 526 if version == 0x0304 or version > 0x7f00: 527 return TLS13ServerHello 528 return TLSServerHello 529 530 def build(self, *args, **kargs): 531 if self.getfieldval("sid") == b"" and self.tls_session: 532 self.sid = self.tls_session.sid 533 return super(TLSServerHello, self).build(*args, **kargs) 534 535 def post_build(self, p, pay): 536 if self.random_bytes is None: 537 p = p[:10] + randstring(28) + p[10 + 28:] 538 return super(TLSServerHello, self).post_build(p, pay) 539 540 def tls_session_update(self, msg_str): 541 """ 542 Either for parsing or building, we store the server_random 543 along with the raw string representing this handshake message. 544 We also store the session_id, the cipher suite (if recognized), 545 the compression method, and finally we instantiate the pending write 546 and read connection states. Usually they get updated later on in the 547 negotiation when we learn the session keys, and eventually they 548 are committed once a ChangeCipherSpec has been sent/received. 549 """ 550 super(TLSServerHello, self).tls_session_update(msg_str) 551 552 s = self.tls_session 553 s.tls_version = self.version 554 if hasattr(self, 'gmt_unix_time'): 555 self.random_bytes = msg_str[10:38] 556 s.server_random = (struct.pack('!I', self.gmt_unix_time) + 557 self.random_bytes) 558 else: 559 s.server_random = self.random_bytes 560 s.sid = self.sid 561 562 if self.ext: 563 for e in self.ext: 564 if isinstance(e, TLS_Ext_ExtendedMasterSecret): 565 self.tls_session.extms = True 566 if isinstance(e, TLS_Ext_EncryptThenMAC): 567 self.tls_session.encrypt_then_mac = True 568 569 cs_cls = None 570 if self.cipher: 571 cs_val = self.cipher 572 if cs_val not in _tls_cipher_suites_cls: 573 warning("Unknown cipher suite %d from ServerHello", cs_val) 574 # we do not try to set a default nor stop the execution 575 else: 576 cs_cls = _tls_cipher_suites_cls[cs_val] 577 578 comp_cls = Comp_NULL 579 if self.comp: 580 comp_val = self.comp[0] 581 if comp_val not in _tls_compression_algs_cls: 582 err = "Unknown compression alg %d from ServerHello" 583 warning(err, comp_val) 584 comp_val = 0 585 comp_cls = _tls_compression_algs_cls[comp_val] 586 587 connection_end = s.connection_end 588 s.pwcs = writeConnState(ciphersuite=cs_cls, 589 compression_alg=comp_cls, 590 connection_end=connection_end, 591 tls_version=self.version) 592 s.prcs = readConnState(ciphersuite=cs_cls, 593 compression_alg=comp_cls, 594 connection_end=connection_end, 595 tls_version=self.version) 596 597 598_tls_13_server_hello_fields = [ 599 ByteEnumField("msgtype", 2, _tls_handshake_type), 600 ThreeBytesField("msglen", None), 601 _TLSVersionField("version", 0x0303, _tls_version), 602 _TLSRandomBytesField("random_bytes", None, 32), 603 FieldLenField("sidlen", None, length_of="sid", fmt="B"), 604 _SessionIDField("sid", "", 605 length_from=lambda pkt: pkt.sidlen), 606 ShortEnumField("cipher", None, _tls_cipher_suites), 607 _CompressionMethodsField("comp", [0], 608 _tls_compression_algs, 609 itemfmt="B", 610 length_from=lambda pkt: 1), 611 _ExtensionsLenField("extlen", None, length_of="ext"), 612 _ExtensionsField("ext", None, 613 length_from=lambda pkt: (pkt.msglen - 614 38)) 615] 616 617 618class TLS13ServerHello(TLSServerHello): 619 """ TLS 1.3 ServerHello """ 620 name = "TLS 1.3 Handshake - Server Hello" 621 fields_desc = _tls_13_server_hello_fields 622 623 # ServerHello and HelloRetryRequest has the same structure and the same 624 # msgId. We need to check the server_random value to determine which it is. 625 @classmethod 626 def dispatch_hook(cls, _pkt=None, *args, **kargs): 627 if _pkt and len(_pkt) >= 38: 628 # If SHA-256("HelloRetryRequest") == server_random, 629 # this message is a HelloRetryRequest 630 random_bytes = _pkt[6:38] 631 if random_bytes == _tls_hello_retry_magic: 632 return TLS13HelloRetryRequest 633 return TLS13ServerHello 634 635 def post_build(self, p, pay): 636 if self.random_bytes is None: 637 p = p[:6] + randstring(32) + p[6 + 32:] 638 return super(TLS13ServerHello, self).post_build(p, pay) 639 640 def tls_session_update(self, msg_str): 641 """ 642 Either for parsing or building, we store the server_random along with 643 the raw string representing this handshake message. We also store the 644 cipher suite (if recognized), and finally we instantiate the write and 645 read connection states. 646 """ 647 s = self.tls_session 648 s.server_random = self.random_bytes 649 s.ciphersuite = self.cipher 650 s.tls_version = self.version 651 # Check extensions 652 if self.ext: 653 for e in self.ext: 654 if isinstance(e, TLS_Ext_SupportedVersion_SH): 655 s.tls_version = e.version 656 break 657 658 if s.tls_version < 0x304: 659 # This means that the server does not support TLS 1.3 and ignored 660 # the initial TLS 1.3 ClientHello. tls_version has been updated 661 return TLSServerHello.tls_session_update(self, msg_str) 662 else: 663 _TLSHandshake.tls_session_update(self, msg_str) 664 665 cs_cls = None 666 if self.cipher: 667 cs_val = self.cipher 668 if cs_val not in _tls_cipher_suites_cls: 669 warning("Unknown cipher suite %d from ServerHello", cs_val) 670 # we do not try to set a default nor stop the execution 671 else: 672 cs_cls = _tls_cipher_suites_cls[cs_val] 673 674 connection_end = s.connection_end 675 if connection_end == "server": 676 s.pwcs = writeConnState(ciphersuite=cs_cls, 677 connection_end=connection_end, 678 tls_version=s.tls_version) 679 680 if not s.middlebox_compatibility: 681 s.triggered_pwcs_commit = True 682 elif connection_end == "client": 683 s.prcs = readConnState(ciphersuite=cs_cls, 684 connection_end=connection_end, 685 tls_version=s.tls_version) 686 if not s.middlebox_compatibility: 687 s.triggered_prcs_commit = True 688 689 if s.tls13_early_secret is None: 690 # In case the connState was not pre-initialized, we could not 691 # compute the early secrets at the ClientHello, so we do it here. 692 s.compute_tls13_early_secrets() 693 s.compute_tls13_handshake_secrets() 694 if connection_end == "server": 695 shts = s.tls13_derived_secrets["server_handshake_traffic_secret"] 696 s.pwcs.tls13_derive_keys(shts) 697 elif connection_end == "client": 698 shts = s.tls13_derived_secrets["server_handshake_traffic_secret"] 699 s.prcs.tls13_derive_keys(shts) 700 701 702############################################################################### 703# HelloRetryRequest # 704############################################################################### 705 706class TLS13HelloRetryRequest(_TLSHandshake): 707 name = "TLS 1.3 Handshake - Hello Retry Request" 708 709 fields_desc = _tls_13_server_hello_fields 710 711 def build(self): 712 fval = self.getfieldval("random_bytes") 713 if fval is None: 714 self.random_bytes = _tls_hello_retry_magic 715 if self.getfieldval("sid") == b"" and self.tls_session: 716 self.sid = self.tls_session.sid 717 return _TLSHandshake.build(self) 718 719 def tls_session_update(self, msg_str): 720 s = self.tls_session 721 s.tls13_retry = True 722 s.tls13_client_pubshares = {} 723 # RFC8446 sect 4.4.1 724 # If the server responds to a ClientHello with a HelloRetryRequest 725 # The value of the first ClientHello is replaced by a message_hash 726 if s.client_session_ticket: 727 cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite] 728 hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) 729 hash_len = hkdf.hash.digest_size 730 else: 731 cs_cls = _tls_cipher_suites_cls[self.cipher] 732 hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) 733 hash_len = hkdf.hash.digest_size 734 735 handshake_context = struct.pack("B", 254) 736 handshake_context += struct.pack("B", 0) 737 handshake_context += struct.pack("B", 0) 738 handshake_context += struct.pack("B", hash_len) 739 digest = hashes.Hash(hkdf.hash, backend=default_backend()) 740 digest.update(s.handshake_messages[0]) 741 handshake_context += digest.finalize() 742 s.handshake_messages[0] = handshake_context 743 super(TLS13HelloRetryRequest, self).tls_session_update(msg_str) 744 745 746############################################################################### 747# EncryptedExtensions # 748############################################################################### 749 750 751class TLSEncryptedExtensions(_TLSHandshake): 752 name = "TLS 1.3 Handshake - Encrypted Extensions" 753 fields_desc = [ByteEnumField("msgtype", 8, _tls_handshake_type), 754 ThreeBytesField("msglen", None), 755 _ExtensionsLenField("extlen", None, length_of="ext"), 756 _ExtensionsField("ext", None, 757 length_from=lambda pkt: pkt.msglen - 2)] 758 759 def post_build_tls_session_update(self, msg_str): 760 self.tls_session_update(msg_str) 761 762 s = self.tls_session 763 connection_end = s.connection_end 764 765 # Check if the server early_data extension is present in 766 # EncryptedExtensions message (if so, early data was accepted by the 767 # server) 768 early_data_accepted = False 769 if self.ext: 770 for e in self.ext: 771 if isinstance(e, TLS_Ext_EarlyDataIndication): 772 early_data_accepted = True 773 774 # If the serveur did not accept early_data, we change prcs traffic 775 # encryption keys. Otherwise, the the keys will be updated after the 776 # EndOfEarlyData message 777 if connection_end == "server": 778 if not early_data_accepted: 779 s.prcs = readConnState(ciphersuite=type(s.wcs.ciphersuite), 780 connection_end=connection_end, 781 tls_version=s.tls_version) 782 783 chts = s.tls13_derived_secrets["client_handshake_traffic_secret"] # noqa: E501 784 s.prcs.tls13_derive_keys(chts) 785 786 if not s.middlebox_compatibility: 787 s.rcs = self.tls_session.prcs 788 s.triggered_prcs_commit = False 789 else: 790 s.triggered_prcs_commit = True 791 792 def post_dissection_tls_session_update(self, msg_str): 793 self.tls_session_update(msg_str) 794 s = self.tls_session 795 connection_end = s.connection_end 796 797 # Check if the server early_data extension is present in 798 # EncryptedExtensions message (if so, early data was accepted by the 799 # server) 800 early_data_accepted = False 801 if self.ext: 802 for e in self.ext: 803 if isinstance(e, TLS_Ext_EarlyDataIndication): 804 early_data_accepted = True 805 806 # If the serveur did not accept early_data, we change pwcs traffic 807 # encryption key. Otherwise, the the keys will be updated after the 808 # EndOfEarlyData message 809 if connection_end == "client": 810 if not early_data_accepted: 811 s.pwcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite), 812 connection_end=connection_end, 813 tls_version=s.tls_version) 814 chts = s.tls13_derived_secrets["client_handshake_traffic_secret"] # noqa: E501 815 s.pwcs.tls13_derive_keys(chts) 816 if not s.middlebox_compatibility: 817 s.wcs = self.tls_session.pwcs 818 s.triggered_pwcs_commit = False 819 else: 820 s.triggered_pwcs_commit = True 821 822############################################################################### 823# Certificate # 824############################################################################### 825 826# XXX It might be appropriate to rewrite this mess with basic 3-byte FieldLenField. # noqa: E501 827 828 829class _ASN1CertLenField(FieldLenField): 830 """ 831 This is mostly a 3-byte FieldLenField. 832 """ 833 def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x): 834 self.length_of = length_of 835 self.adjust = adjust 836 Field.__init__(self, name, default, fmt="!I") 837 838 def i2m(self, pkt, x): 839 if x is None: 840 if self.length_of is not None: 841 fld, fval = pkt.getfield_and_val(self.length_of) 842 f = fld.i2len(pkt, fval) 843 x = self.adjust(pkt, f) 844 return x 845 846 def addfield(self, pkt, s, val): 847 return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4] 848 849 def getfield(self, pkt, s): 850 return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0]) # noqa: E501 851 852 853class _ASN1CertListField(StrLenField): 854 islist = 1 855 856 def i2len(self, pkt, i): 857 if i is None: 858 return 0 859 return len(self.i2m(pkt, i)) 860 861 def getfield(self, pkt, s): 862 """ 863 Extract Certs in a loop. 864 XXX We should provide safeguards when trying to parse a Cert. 865 """ 866 tmp_len = None 867 if self.length_from is not None: 868 tmp_len = self.length_from(pkt) 869 870 lst = [] 871 ret = b"" 872 m = s 873 if tmp_len is not None: 874 m, ret = s[:tmp_len], s[tmp_len:] 875 while m: 876 c_len = struct.unpack("!I", b'\x00' + m[:3])[0] 877 lst.append((c_len, Cert(m[3:3 + c_len]))) 878 m = m[3 + c_len:] 879 return m + ret, lst 880 881 def i2m(self, pkt, i): 882 def i2m_one(i): 883 if isinstance(i, str): 884 return i 885 if isinstance(i, Cert): 886 s = i.der 887 tmp_len = struct.pack("!I", len(s))[1:4] 888 return tmp_len + s 889 890 (tmp_len, s) = i 891 if isinstance(s, Cert): 892 s = s.der 893 return struct.pack("!I", tmp_len)[1:4] + s 894 895 if i is None: 896 return b"" 897 if isinstance(i, str): 898 return i 899 if isinstance(i, Cert): 900 i = [i] 901 return b"".join(i2m_one(x) for x in i) 902 903 def any2i(self, pkt, x): 904 return x 905 906 907class _ASN1CertField(StrLenField): 908 def i2len(self, pkt, i): 909 if i is None: 910 return 0 911 return len(self.i2m(pkt, i)) 912 913 def getfield(self, pkt, s): 914 tmp_len = None 915 if self.length_from is not None: 916 tmp_len = self.length_from(pkt) 917 ret = b"" 918 m = s 919 if tmp_len is not None: 920 m, ret = s[:tmp_len], s[tmp_len:] 921 c_len = struct.unpack("!I", b'\x00' + m[:3])[0] 922 len_cert = (c_len, Cert(m[3:3 + c_len])) 923 m = m[3 + c_len:] 924 return m + ret, len_cert 925 926 def i2m(self, pkt, i): 927 def i2m_one(i): 928 if isinstance(i, str): 929 return i 930 if isinstance(i, Cert): 931 s = i.der 932 tmp_len = struct.pack("!I", len(s))[1:4] 933 return tmp_len + s 934 935 (tmp_len, s) = i 936 if isinstance(s, Cert): 937 s = s.der 938 return struct.pack("!I", tmp_len)[1:4] + s 939 940 if i is None: 941 return b"" 942 return i2m_one(i) 943 944 def any2i(self, pkt, x): 945 return x 946 947 948class TLSCertificate(_TLSHandshake): 949 """ 950 XXX We do not support RFC 5081, i.e. OpenPGP certificates. 951 """ 952 name = "TLS Handshake - Certificate" 953 fields_desc = [ByteEnumField("msgtype", 11, _tls_handshake_type), 954 ThreeBytesField("msglen", None), 955 _ASN1CertLenField("certslen", None, length_of="certs"), 956 _ASN1CertListField("certs", [], 957 length_from=lambda pkt: pkt.certslen)] 958 959 @classmethod 960 def dispatch_hook(cls, _pkt=None, *args, **kargs): 961 if _pkt: 962 tls_session = kargs.get("tls_session", None) 963 if tls_session and (tls_session.tls_version or 0) >= 0x0304: 964 return TLS13Certificate 965 return TLSCertificate 966 967 def post_dissection_tls_session_update(self, msg_str): 968 self.tls_session_update(msg_str) 969 connection_end = self.tls_session.connection_end 970 if connection_end == "client": 971 self.tls_session.server_certs = [x[1] for x in self.certs] 972 else: 973 self.tls_session.client_certs = [x[1] for x in self.certs] 974 975 976class _ASN1CertAndExt(_GenericTLSSessionInheritance): 977 name = "Certificate and Extensions" 978 fields_desc = [_ASN1CertField("cert", ""), 979 FieldLenField("extlen", None, length_of="ext"), 980 _ExtensionsField("ext", [], 981 length_from=lambda pkt: pkt.extlen)] 982 983 def extract_padding(self, s): 984 return b"", s 985 986 987class _ASN1CertAndExtListField(PacketListField): 988 def m2i(self, pkt, m): 989 return self.cls(m, tls_session=pkt.tls_session) 990 991 992class TLS13Certificate(_TLSHandshake): 993 name = "TLS 1.3 Handshake - Certificate" 994 fields_desc = [ByteEnumField("msgtype", 11, _tls_handshake_type), 995 ThreeBytesField("msglen", None), 996 FieldLenField("cert_req_ctxt_len", None, fmt="B", 997 length_of="cert_req_ctxt"), 998 StrLenField("cert_req_ctxt", "", 999 length_from=lambda pkt: pkt.cert_req_ctxt_len), 1000 _ASN1CertLenField("certslen", None, length_of="certs"), 1001 _ASN1CertAndExtListField("certs", [], _ASN1CertAndExt, 1002 length_from=lambda pkt: pkt.certslen)] # noqa: E501 1003 1004 def post_dissection_tls_session_update(self, msg_str): 1005 self.tls_session_update(msg_str) 1006 connection_end = self.tls_session.connection_end 1007 if connection_end == "client": 1008 if self.certs: 1009 sc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')] 1010 self.tls_session.server_certs = sc 1011 else: 1012 if self.certs: 1013 cc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')] 1014 self.tls_session.client_certs = cc 1015 1016 1017############################################################################### 1018# ServerKeyExchange # 1019############################################################################### 1020 1021class TLSServerKeyExchange(_TLSHandshake): 1022 name = "TLS Handshake - Server Key Exchange" 1023 fields_desc = [ByteEnumField("msgtype", 12, _tls_handshake_type), 1024 ThreeBytesField("msglen", None), 1025 _TLSServerParamsField("params", None, 1026 length_from=lambda pkt: pkt.msglen), 1027 _TLSSignatureField("sig", None, 1028 length_from=lambda pkt: pkt.msglen - len(pkt.params))] # noqa: E501 1029 1030 def build(self, *args, **kargs): 1031 r""" 1032 We overload build() method in order to provide a valid default value 1033 for params based on TLS session if not provided. This cannot be done by 1034 overriding i2m() because the method is called on a copy of the packet. 1035 1036 The 'params' field is built according to key_exchange.server_kx_msg_cls 1037 which should have been set after receiving a cipher suite in a 1038 previous ServerHello. Usual cases are: 1039 1040 - None: for RSA encryption or fixed FF/ECDH. This should never happen, 1041 as no ServerKeyExchange should be generated in the first place. 1042 - ServerDHParams: for ephemeral FFDH. In that case, the parameter to 1043 server_kx_msg_cls does not matter. 1044 - ServerECDH\*Params: for ephemeral ECDH. There are actually three 1045 classes, which are dispatched by _tls_server_ecdh_cls_guess on 1046 the first byte retrieved. The default here is b"\03", which 1047 corresponds to ServerECDHNamedCurveParams (implicit curves). 1048 1049 When the Server\*DHParams are built via .fill_missing(), the session 1050 server_kx_privkey will be updated accordingly. 1051 """ 1052 fval = self.getfieldval("params") 1053 if fval is None: 1054 s = self.tls_session 1055 if s.pwcs: 1056 if s.pwcs.key_exchange.export: 1057 cls = ServerRSAParams(tls_session=s) 1058 else: 1059 cls = s.pwcs.key_exchange.server_kx_msg_cls(b"\x03") 1060 cls = cls(tls_session=s) 1061 try: 1062 cls.fill_missing() 1063 except Exception: 1064 if conf.debug_dissector: 1065 raise 1066 else: 1067 cls = Raw() 1068 self.params = cls 1069 1070 fval = self.getfieldval("sig") 1071 if fval is None: 1072 s = self.tls_session 1073 if s.pwcs and s.client_random: 1074 if not s.pwcs.key_exchange.anonymous: 1075 p = self.params 1076 if p is None: 1077 p = b"" 1078 m = s.client_random + s.server_random + raw(p) 1079 cls = _TLSSignature(tls_session=s) 1080 cls._update_sig(m, s.server_key) 1081 else: 1082 cls = Raw() 1083 else: 1084 cls = Raw() 1085 self.sig = cls 1086 1087 return _TLSHandshake.build(self, *args, **kargs) 1088 1089 def post_dissection(self, pkt): 1090 """ 1091 While previously dissecting Server*DHParams, the session 1092 server_kx_pubkey should have been updated. 1093 1094 XXX Add a 'fixed_dh' OR condition to the 'anonymous' test. 1095 """ 1096 s = self.tls_session 1097 if s.prcs and s.prcs.key_exchange.no_ske: 1098 pkt_info = pkt.firstlayer().summary() 1099 log_runtime.info("TLS: useless ServerKeyExchange [%s]", pkt_info) 1100 if (s.prcs and 1101 not s.prcs.key_exchange.anonymous and 1102 s.client_random and s.server_random and 1103 s.server_certs and len(s.server_certs) > 0): 1104 m = s.client_random + s.server_random + raw(self.params) 1105 sig_test = self.sig._verify_sig(m, s.server_certs[0]) 1106 if not sig_test: 1107 pkt_info = pkt.firstlayer().summary() 1108 log_runtime.info("TLS: invalid ServerKeyExchange signature [%s]", pkt_info) # noqa: E501 1109 1110 1111############################################################################### 1112# CertificateRequest # 1113############################################################################### 1114 1115_tls_client_certificate_types = {1: "rsa_sign", 1116 2: "dss_sign", 1117 3: "rsa_fixed_dh", 1118 4: "dss_fixed_dh", 1119 5: "rsa_ephemeral_dh_RESERVED", 1120 6: "dss_ephemeral_dh_RESERVED", 1121 20: "fortezza_dms_RESERVED", 1122 64: "ecdsa_sign", 1123 65: "rsa_fixed_ecdh", 1124 66: "ecdsa_fixed_ecdh"} 1125 1126 1127class _CertTypesField(_CipherSuitesField): 1128 pass 1129 1130 1131class _CertAuthoritiesField(StrLenField): 1132 """ 1133 XXX Rework this with proper ASN.1 parsing. 1134 """ 1135 islist = 1 1136 1137 def getfield(self, pkt, s): 1138 tmp_len = self.length_from(pkt) 1139 return s[tmp_len:], self.m2i(pkt, s[:tmp_len]) 1140 1141 def m2i(self, pkt, m): 1142 res = [] 1143 while len(m) > 1: 1144 tmp_len = struct.unpack("!H", m[:2])[0] 1145 if len(m) < tmp_len + 2: 1146 res.append((tmp_len, m[2:])) 1147 break 1148 dn = m[2:2 + tmp_len] 1149 res.append((tmp_len, dn)) 1150 m = m[2 + tmp_len:] 1151 return res 1152 1153 def i2m(self, pkt, i): 1154 return b"".join(map(lambda x_y: struct.pack("!H", x_y[0]) + x_y[1], i)) 1155 1156 def addfield(self, pkt, s, val): 1157 return s + self.i2m(pkt, val) 1158 1159 def i2len(self, pkt, val): 1160 if val is None: 1161 return 0 1162 else: 1163 return len(self.i2m(pkt, val)) 1164 1165 1166class TLSCertificateRequest(_TLSHandshake): 1167 name = "TLS Handshake - Certificate Request" 1168 fields_desc = [ByteEnumField("msgtype", 13, _tls_handshake_type), 1169 ThreeBytesField("msglen", None), 1170 FieldLenField("ctypeslen", None, fmt="B", 1171 length_of="ctypes"), 1172 _CertTypesField("ctypes", [1, 64], 1173 _tls_client_certificate_types, 1174 itemfmt="!B", 1175 length_from=lambda pkt: pkt.ctypeslen), 1176 SigAndHashAlgsLenField("sig_algs_len", None, 1177 length_of="sig_algs"), 1178 SigAndHashAlgsField("sig_algs", [0x0403, 0x0401, 0x0201], 1179 ShortEnumField("hash_sig", None, _tls_hash_sig), # noqa: E501 1180 length_from=lambda pkt: pkt.sig_algs_len), # noqa: E501 1181 FieldLenField("certauthlen", None, fmt="!H", 1182 length_of="certauth"), 1183 _CertAuthoritiesField("certauth", [], 1184 length_from=lambda pkt: pkt.certauthlen)] # noqa: E501 1185 1186 1187class TLS13CertificateRequest(_TLSHandshake): 1188 name = "TLS 1.3 Handshake - Certificate Request" 1189 fields_desc = [ByteEnumField("msgtype", 13, _tls_handshake_type), 1190 ThreeBytesField("msglen", None), 1191 FieldLenField("cert_req_ctxt_len", None, fmt="B", 1192 length_of="cert_req_ctxt"), 1193 StrLenField("cert_req_ctxt", "", 1194 length_from=lambda pkt: pkt.cert_req_ctxt_len), 1195 _ExtensionsLenField("extlen", None, length_of="ext"), 1196 _ExtensionsField("ext", None, 1197 length_from=lambda pkt: pkt.msglen - 1198 pkt.cert_req_ctxt_len - 3)] 1199 1200 def tls_session_update(self, msg_str): 1201 super(TLS13CertificateRequest, self).tls_session_update(msg_str) 1202 self.tls_session.tls13_cert_req_ctxt = self.cert_req_ctxt 1203 1204 1205############################################################################### 1206# ServerHelloDone # 1207############################################################################### 1208 1209 1210class TLSServerHelloDone(_TLSHandshake): 1211 name = "TLS Handshake - Server Hello Done" 1212 fields_desc = [ByteEnumField("msgtype", 14, _tls_handshake_type), 1213 ThreeBytesField("msglen", None)] 1214 1215 1216############################################################################### 1217# CertificateVerify # 1218############################################################################### 1219 1220class TLSCertificateVerify(_TLSHandshake): 1221 name = "TLS Handshake - Certificate Verify" 1222 fields_desc = [ByteEnumField("msgtype", 15, _tls_handshake_type), 1223 ThreeBytesField("msglen", None), 1224 _TLSSignatureField("sig", None, 1225 length_from=lambda pkt: pkt.msglen)] 1226 1227 # See https://datatracker.ietf.org/doc/html/rfc8446#section-4.4 for how to compute 1228 # the signature. 1229 1230 def build(self, *args, **kargs): 1231 sig = self.getfieldval("sig") 1232 if sig is None: 1233 s = self.tls_session 1234 m = b"".join(s.handshake_messages) 1235 if s.post_handshake: 1236 m += b"".join(s.post_handshake_messages) 1237 tls_version = s.tls_version 1238 if tls_version is None: 1239 tls_version = s.advertised_tls_version 1240 if tls_version >= 0x0304: 1241 if s.connection_end == "client": 1242 context_string = b"TLS 1.3, client CertificateVerify" 1243 elif s.connection_end == "server": 1244 context_string = b"TLS 1.3, server CertificateVerify" 1245 m = b"\x20" * 64 + context_string + b"\x00" + s.wcs.hash.digest(m) # noqa: E501 1246 self.sig = _TLSSignature(tls_session=s) 1247 if s.connection_end == "client": 1248 self.sig._update_sig(m, s.client_key) 1249 elif s.connection_end == "server": 1250 # should be TLS 1.3 only 1251 self.sig._update_sig(m, s.server_key) 1252 return _TLSHandshake.build(self, *args, **kargs) 1253 1254 def post_dissection(self, pkt): 1255 s = self.tls_session 1256 m = b"".join(s.handshake_messages) 1257 if s.post_handshake: 1258 m += b"".join(s.post_handshake_messages) 1259 tls_version = s.tls_version 1260 if tls_version is None: 1261 tls_version = s.advertised_tls_version 1262 if tls_version >= 0x0304: 1263 if s.connection_end == "client": 1264 context_string = b"TLS 1.3, server CertificateVerify" 1265 elif s.connection_end == "server": 1266 context_string = b"TLS 1.3, client CertificateVerify" 1267 m = b"\x20" * 64 + context_string + b"\x00" + s.rcs.hash.digest(m) 1268 1269 if s.connection_end == "server": 1270 if s.client_certs and len(s.client_certs) > 0: 1271 sig_test = self.sig._verify_sig(m, s.client_certs[0]) 1272 if not sig_test: 1273 pkt_info = pkt.firstlayer().summary() 1274 log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info) # noqa: E501 1275 elif s.connection_end == "client": 1276 # should be TLS 1.3 only 1277 if s.server_certs and len(s.server_certs) > 0: 1278 sig_test = self.sig._verify_sig(m, s.server_certs[0]) 1279 if not sig_test: 1280 pkt_info = pkt.firstlayer().summary() 1281 log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info) # noqa: E501 1282 1283 1284############################################################################### 1285# ClientKeyExchange # 1286############################################################################### 1287 1288class _TLSCKExchKeysField(PacketField): 1289 __slots__ = ["length_from"] 1290 holds_packet = 1 1291 1292 def __init__(self, name, length_from=None): 1293 self.length_from = length_from 1294 PacketField.__init__(self, name, None, None) 1295 1296 def m2i(self, pkt, m): 1297 """ 1298 The client_kx_msg may be either None, EncryptedPreMasterSecret 1299 (for RSA encryption key exchange), ClientDiffieHellmanPublic, 1300 or ClientECDiffieHellmanPublic. When either one of them gets 1301 dissected, the session context is updated accordingly. 1302 """ 1303 tmp_len = self.length_from(pkt) 1304 tbd, rem = m[:tmp_len], m[tmp_len:] 1305 1306 s = pkt.tls_session 1307 cls = None 1308 1309 if s.prcs and s.prcs.key_exchange: 1310 cls = s.prcs.key_exchange.client_kx_msg_cls 1311 1312 if cls is None: 1313 return Raw(tbd) / Padding(rem) 1314 1315 return cls(tbd, tls_session=s) / Padding(rem) 1316 1317 1318class TLSClientKeyExchange(_TLSHandshake): 1319 """ 1320 This class mostly works like TLSServerKeyExchange and its 'params' field. 1321 """ 1322 name = "TLS Handshake - Client Key Exchange" 1323 fields_desc = [ByteEnumField("msgtype", 16, _tls_handshake_type), 1324 ThreeBytesField("msglen", None), 1325 _TLSCKExchKeysField("exchkeys", 1326 length_from=lambda pkt: pkt.msglen)] 1327 1328 def build(self, *args, **kargs): 1329 fval = self.getfieldval("exchkeys") 1330 if fval is None: 1331 s = self.tls_session 1332 if s.prcs: 1333 cls = s.prcs.key_exchange.client_kx_msg_cls 1334 cls = cls(tls_session=s) 1335 else: 1336 cls = Raw() 1337 self.exchkeys = cls 1338 return _TLSHandshake.build(self, *args, **kargs) 1339 1340 def tls_session_update(self, msg_str): 1341 """ 1342 Finalize the EXTMS messages and compute the hash 1343 """ 1344 super(TLSClientKeyExchange, self).tls_session_update(msg_str) 1345 1346 if self.tls_session.extms: 1347 to_hash = b''.join(self.tls_session.handshake_messages) 1348 # https://tools.ietf.org/html/rfc7627#section-3 1349 if self.tls_session.tls_version >= 0x303: 1350 # TLS 1.2 uses the same Hash as the PRF 1351 from scapy.layers.tls.crypto.hash import _tls_hash_algs 1352 hash_object = _tls_hash_algs.get( 1353 self.tls_session.prcs.prf.hash_name 1354 )() 1355 self.tls_session.session_hash = hash_object.digest(to_hash) 1356 else: 1357 # Previous TLS version use concatenation of MD5 & SHA1 1358 from scapy.layers.tls.crypto.hash import Hash_MD5, Hash_SHA 1359 self.tls_session.session_hash = ( 1360 Hash_MD5().digest(to_hash) + Hash_SHA().digest(to_hash) 1361 ) 1362 if self.tls_session.pre_master_secret: 1363 self.tls_session.compute_ms_and_derive_keys() 1364 1365 if not self.tls_session.master_secret: 1366 # There are still no master secret (we're just passive) 1367 if self.tls_session.use_nss_master_secret_if_present(): 1368 # we have a NSS file 1369 self.tls_session.compute_ms_and_derive_keys() 1370 1371 1372############################################################################### 1373# Finished # 1374############################################################################### 1375 1376class _VerifyDataField(StrLenField): 1377 def getfield(self, pkt, s): 1378 if pkt.tls_session.tls_version == 0x0300: 1379 sep = 36 1380 elif pkt.tls_session.tls_version and pkt.tls_session.tls_version >= 0x0304: 1381 sep = pkt.tls_session.rcs.hash.hash_len 1382 else: 1383 sep = 12 1384 return s[sep:], s[:sep] 1385 1386 1387class TLSFinished(_TLSHandshake): 1388 name = "TLS Handshake - Finished" 1389 fields_desc = [ByteEnumField("msgtype", 20, _tls_handshake_type), 1390 ThreeBytesField("msglen", None), 1391 _VerifyDataField("vdata", None)] 1392 1393 def build(self, *args, **kargs): 1394 fval = self.getfieldval("vdata") 1395 if fval is None: 1396 s = self.tls_session 1397 handshake_msg = b"".join(s.handshake_messages) 1398 if s.post_handshake: 1399 handshake_msg += b"".join(s.post_handshake_messages) 1400 con_end = s.connection_end 1401 tls_version = s.tls_version 1402 if tls_version is None: 1403 tls_version = s.advertised_tls_version 1404 if tls_version < 0x0304: 1405 ms = s.master_secret 1406 self.vdata = s.wcs.prf.compute_verify_data(con_end, "write", 1407 handshake_msg, ms) 1408 else: 1409 self.vdata = s.compute_tls13_verify_data(con_end, "write", 1410 handshake_msg) 1411 return _TLSHandshake.build(self, *args, **kargs) 1412 1413 def post_dissection(self, pkt): 1414 s = self.tls_session 1415 if not s.frozen: 1416 handshake_msg = b"".join(s.handshake_messages) 1417 if s.post_handshake: 1418 handshake_msg += b"".join(s.post_handshake_messages) 1419 tls_version = s.tls_version 1420 if tls_version is None: 1421 tls_version = s.advertised_tls_version 1422 if tls_version < 0x0304 and s.master_secret is not None: 1423 ms = s.master_secret 1424 con_end = s.connection_end 1425 verify_data = s.rcs.prf.compute_verify_data(con_end, "read", 1426 handshake_msg, ms) 1427 if self.vdata != verify_data: 1428 pkt_info = pkt.firstlayer().summary() 1429 log_runtime.info("TLS: invalid Finished received [%s]", pkt_info) # noqa: E501 1430 elif tls_version >= 0x0304: 1431 con_end = s.connection_end 1432 verify_data = s.compute_tls13_verify_data(con_end, "read", 1433 handshake_msg) 1434 if self.vdata != verify_data: 1435 pkt_info = pkt.firstlayer().summary() 1436 log_runtime.info("TLS: invalid Finished received [%s]", pkt_info) # noqa: E501 1437 1438 def post_build_tls_session_update(self, msg_str): 1439 self.tls_session_update(msg_str) 1440 s = self.tls_session 1441 tls_version = s.tls_version 1442 if tls_version is None: 1443 tls_version = s.advertised_tls_version 1444 if tls_version >= 0x0304 and not s.post_handshake: 1445 s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite), 1446 connection_end=s.connection_end, 1447 tls_version=s.tls_version) 1448 s.triggered_pwcs_commit = True 1449 if s.connection_end == "server": 1450 s.compute_tls13_traffic_secrets() 1451 elif s.connection_end == "client": 1452 s.compute_tls13_traffic_secrets_end() 1453 s.compute_tls13_resumption_secret() 1454 if s.connection_end == "client": 1455 s.post_handshake = True 1456 s.post_handshake_messages = [] 1457 1458 def post_dissection_tls_session_update(self, msg_str): 1459 self.tls_session_update(msg_str) 1460 s = self.tls_session 1461 tls_version = s.tls_version 1462 if tls_version is None: 1463 tls_version = s.advertised_tls_version 1464 if tls_version >= 0x0304 and not s.post_handshake: 1465 s.prcs = readConnState(ciphersuite=type(s.rcs.ciphersuite), 1466 connection_end=s.connection_end, 1467 tls_version=s.tls_version) 1468 s.triggered_prcs_commit = True 1469 if s.connection_end == "client": 1470 s.compute_tls13_traffic_secrets() 1471 elif s.connection_end == "server": 1472 s.compute_tls13_traffic_secrets_end() 1473 s.compute_tls13_resumption_secret() 1474 if s.connection_end == "server": 1475 s.post_handshake = True 1476 s.post_handshake_messages = [] 1477 1478 1479# Additional handshake messages 1480 1481############################################################################### 1482# HelloVerifyRequest # 1483############################################################################### 1484 1485class TLSHelloVerifyRequest(_TLSHandshake): 1486 """ 1487 Defined for DTLS, see RFC 6347. 1488 """ 1489 name = "TLS Handshake - Hello Verify Request" 1490 fields_desc = [ByteEnumField("msgtype", 21, _tls_handshake_type), 1491 ThreeBytesField("msglen", None), 1492 FieldLenField("cookielen", None, 1493 fmt="B", length_of="cookie"), 1494 StrLenField("cookie", "", 1495 length_from=lambda pkt: pkt.cookielen)] 1496 1497 1498############################################################################### 1499# CertificateURL # 1500############################################################################### 1501 1502_tls_cert_chain_types = {0: "individual_certs", 1503 1: "pkipath"} 1504 1505 1506class URLAndOptionalHash(Packet): 1507 name = "URLAndOptionHash structure for TLSCertificateURL" 1508 fields_desc = [FieldLenField("urllen", None, length_of="url"), 1509 StrLenField("url", "", 1510 length_from=lambda pkt: pkt.urllen), 1511 FieldLenField("hash_present", None, 1512 fmt="B", length_of="hash", 1513 adjust=lambda pkt, x: int(math.ceil(x / 20.))), # noqa: E501 1514 StrLenField("hash", "", 1515 length_from=lambda pkt: 20 * pkt.hash_present)] 1516 1517 def guess_payload_class(self, p): 1518 return Padding 1519 1520 1521class TLSCertificateURL(_TLSHandshake): 1522 """ 1523 Defined in RFC 4366. PkiPath structure of section 8 is not implemented yet. 1524 """ 1525 name = "TLS Handshake - Certificate URL" 1526 fields_desc = [ByteEnumField("msgtype", 21, _tls_handshake_type), 1527 ThreeBytesField("msglen", None), 1528 ByteEnumField("certchaintype", None, _tls_cert_chain_types), 1529 FieldLenField("uahlen", None, length_of="uah"), 1530 PacketListField("uah", [], URLAndOptionalHash, 1531 length_from=lambda pkt: pkt.uahlen)] 1532 1533 1534############################################################################### 1535# CertificateStatus # 1536############################################################################### 1537 1538class ThreeBytesLenField(FieldLenField): 1539 def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x): 1540 FieldLenField.__init__(self, name, default, length_of=length_of, 1541 fmt='!I', adjust=adjust) 1542 1543 def i2repr(self, pkt, x): 1544 if x is None: 1545 return 0 1546 return repr(self.i2h(pkt, x)) 1547 1548 def addfield(self, pkt, s, val): 1549 return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4] 1550 1551 def getfield(self, pkt, s): 1552 return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0]) # noqa: E501 1553 1554 1555_cert_status_cls = {1: OCSP_Response} 1556 1557 1558class _StatusField(PacketLenField): 1559 def m2i(self, pkt, m): 1560 idtype = pkt.status_type 1561 cls = self.cls 1562 if idtype in _cert_status_cls: 1563 cls = _cert_status_cls[idtype] 1564 return cls(m) 1565 1566 1567class TLSCertificateStatus(_TLSHandshake): 1568 name = "TLS Handshake - Certificate Status" 1569 fields_desc = [ByteEnumField("msgtype", 22, _tls_handshake_type), 1570 ThreeBytesField("msglen", None), 1571 ByteEnumField("status_type", 1, _cert_status_type), 1572 ThreeBytesLenField("responselen", None, 1573 length_of="response"), 1574 _StatusField("response", None, Raw, 1575 length_from=lambda pkt: pkt.responselen)] 1576 1577 1578############################################################################### 1579# SupplementalData # 1580############################################################################### 1581 1582class SupDataEntry(Packet): 1583 name = "Supplemental Data Entry - Generic" 1584 fields_desc = [ShortField("sdtype", None), 1585 FieldLenField("len", None, length_of="data"), 1586 StrLenField("data", "", 1587 length_from=lambda pkt:pkt.len)] 1588 1589 def guess_payload_class(self, p): 1590 return Padding 1591 1592 1593class UserMappingData(Packet): 1594 name = "User Mapping Data" 1595 fields_desc = [ByteField("version", None), 1596 FieldLenField("len", None, length_of="data"), 1597 StrLenField("data", "", 1598 length_from=lambda pkt: pkt.len)] 1599 1600 def guess_payload_class(self, p): 1601 return Padding 1602 1603 1604class SupDataEntryUM(Packet): 1605 name = "Supplemental Data Entry - User Mapping" 1606 fields_desc = [ShortField("sdtype", None), 1607 FieldLenField("len", None, length_of="data", 1608 adjust=lambda pkt, x: x + 2), 1609 FieldLenField("dlen", None, length_of="data"), 1610 PacketListField("data", [], UserMappingData, 1611 length_from=lambda pkt:pkt.dlen)] 1612 1613 def guess_payload_class(self, p): 1614 return Padding 1615 1616 1617class TLSSupplementalData(_TLSHandshake): 1618 name = "TLS Handshake - Supplemental Data" 1619 fields_desc = [ByteEnumField("msgtype", 23, _tls_handshake_type), 1620 ThreeBytesField("msglen", None), 1621 ThreeBytesLenField("sdatalen", None, length_of="sdata"), 1622 PacketListField("sdata", [], SupDataEntry, 1623 length_from=lambda pkt: pkt.sdatalen)] 1624 1625 1626############################################################################### 1627# NewSessionTicket # 1628############################################################################### 1629 1630class TLSNewSessionTicket(_TLSHandshake): 1631 """ 1632 XXX When knowing the right secret, we should be able to read the ticket. 1633 """ 1634 name = "TLS Handshake - New Session Ticket" 1635 fields_desc = [ByteEnumField("msgtype", 4, _tls_handshake_type), 1636 ThreeBytesField("msglen", None), 1637 IntField("lifetime", 0xffffffff), 1638 FieldLenField("ticketlen", None, length_of="ticket"), 1639 StrLenField("ticket", "", 1640 length_from=lambda pkt: pkt.ticketlen)] 1641 1642 @classmethod 1643 def dispatch_hook(cls, _pkt=None, *args, **kargs): 1644 s = kargs.get("tls_session", None) 1645 if s and s.tls_version and s.tls_version >= 0x0304: 1646 return TLS13NewSessionTicket 1647 return TLSNewSessionTicket 1648 1649 def post_dissection_tls_session_update(self, msg_str): 1650 self.tls_session_update(msg_str) 1651 if self.tls_session.connection_end == "client": 1652 self.tls_session.client_session_ticket = self.ticket 1653 1654 1655class TLS13NewSessionTicket(_TLSHandshake): 1656 """ 1657 Uncomment the TicketField line for parsing a RFC 5077 ticket. 1658 """ 1659 name = "TLS 1.3 Handshake - New Session Ticket" 1660 fields_desc = [ByteEnumField("msgtype", 4, _tls_handshake_type), 1661 ThreeBytesField("msglen", None), 1662 IntField("ticket_lifetime", 0xffffffff), 1663 IntField("ticket_age_add", 0), 1664 FieldLenField("noncelen", None, fmt="B", 1665 length_of="ticket_nonce"), 1666 StrLenField("ticket_nonce", "", 1667 length_from=lambda pkt: pkt.noncelen), 1668 FieldLenField("ticketlen", None, length_of="ticket"), 1669 # TicketField("ticket", "", 1670 StrLenField("ticket", "", 1671 length_from=lambda pkt: pkt.ticketlen), 1672 _ExtensionsLenField("extlen", None, length_of="ext"), 1673 _ExtensionsField("ext", None, 1674 length_from=lambda pkt: (pkt.msglen - 1675 (pkt.ticketlen or 0) - # noqa: E501 1676 pkt.noncelen or 0) - 13)] # noqa: E501 1677 1678 def build(self): 1679 fval = self.getfieldval("ticket") 1680 if fval == b"": 1681 # Here, the ticket is just a random 48-byte label 1682 # The ticket may also be a self-encrypted and self-authenticated 1683 # value 1684 self.ticket = os.urandom(48) 1685 1686 fval = self.getfieldval("ticket_nonce") 1687 if fval == b"": 1688 # Nonce is randomly chosen 1689 self.ticket_nonce = os.urandom(32) 1690 1691 fval = self.getfieldval("ticket_lifetime") 1692 if fval == 0xffffffff: 1693 # ticket_lifetime is set to 12 hours 1694 self.ticket_lifetime = 43200 1695 1696 fval = self.getfieldval("ticket_age_add") 1697 if fval == 0: 1698 # ticket_age_add is a random 32-bit value 1699 self.ticket_age_add = struct.unpack("!I", os.urandom(4))[0] 1700 1701 return _TLSHandshake.build(self) 1702 1703 def post_dissection_tls_session_update(self, msg_str): 1704 if self.tls_session.connection_end == "client": 1705 self.tls_session.client_session_ticket = self.ticket 1706 1707 1708############################################################################### 1709# EndOfEarlyData # 1710############################################################################### 1711 1712class TLS13EndOfEarlyData(_TLSHandshake): 1713 name = "TLS 1.3 Handshake - End Of Early Data" 1714 1715 fields_desc = [ByteEnumField("msgtype", 5, _tls_handshake_type), 1716 ThreeBytesField("msglen", None)] 1717 1718 1719############################################################################### 1720# KeyUpdate # 1721############################################################################### 1722_key_update_request = {0: "update_not_requested", 1: "update_requested"} 1723 1724 1725class TLS13KeyUpdate(_TLSHandshake): 1726 name = "TLS 1.3 Handshake - Key Update" 1727 fields_desc = [ByteEnumField("msgtype", 24, _tls_handshake_type), 1728 ThreeBytesField("msglen", None), 1729 ByteEnumField("request_update", 0, _key_update_request)] 1730 1731 def post_build_tls_session_update(self, msg_str): 1732 s = self.tls_session 1733 s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite), 1734 connection_end=s.connection_end, 1735 tls_version=s.tls_version) 1736 s.triggered_pwcs_commit = True 1737 s.compute_tls13_next_traffic_secrets(s.connection_end, "write") 1738 1739 def post_dissection_tls_session_update(self, msg_str): 1740 s = self.tls_session 1741 s.prcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite), 1742 connection_end=s.connection_end, 1743 tls_version=s.tls_version) 1744 s.triggered_prcs_commit = True 1745 if s.connection_end == "server": 1746 s.compute_tls13_next_traffic_secrets("client", "read") 1747 elif s.connection_end == "client": 1748 s.compute_tls13_next_traffic_secrets("server", "read") 1749 1750 1751############################################################################### 1752# All handshake messages defined in this module # 1753############################################################################### 1754 1755_tls_handshake_cls = {0: TLSHelloRequest, 1: TLSClientHello, 1756 2: TLSServerHello, 3: TLSHelloVerifyRequest, 1757 4: TLSNewSessionTicket, 1758 8: TLSEncryptedExtensions, 11: TLSCertificate, 1759 12: TLSServerKeyExchange, 13: TLSCertificateRequest, 1760 14: TLSServerHelloDone, 15: TLSCertificateVerify, 1761 16: TLSClientKeyExchange, 20: TLSFinished, 1762 21: TLSCertificateURL, 22: TLSCertificateStatus, 1763 23: TLSSupplementalData} 1764 1765_tls13_handshake_cls = {1: TLS13ClientHello, 2: TLS13ServerHello, 1766 4: TLS13NewSessionTicket, 5: TLS13EndOfEarlyData, 1767 8: TLSEncryptedExtensions, 11: TLS13Certificate, 1768 13: TLS13CertificateRequest, 15: TLSCertificateVerify, 1769 20: TLSFinished, 24: TLS13KeyUpdate} 1770