1## This file is part of Scapy 2## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard 3## 2015, 2016, 2017 Maxence Tury 4## This program is published under a GPLv2 license 5 6""" 7TLS session handler. 8""" 9 10import random 11import socket 12import struct 13 14from scapy.config import conf 15from scapy.compat import * 16import scapy.modules.six as six 17from scapy.error import log_runtime, warning 18from scapy.packet import Packet 19from scapy.utils import repr_hex, strxor 20from scapy.layers.tls.crypto.compression import Comp_NULL 21from scapy.layers.tls.crypto.hkdf import TLS13_HKDF 22from scapy.layers.tls.crypto.prf import PRF 23 24# Note the following import may happen inside connState.__init__() 25# in order to avoid to avoid cyclical dependancies. 26# from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL 27 28 29############################################################################### 30### Connection states ### 31############################################################################### 32 33class connState(object): 34 """ 35 From RFC 5246, section 6.1: 36 A TLS connection state is the operating environment of the TLS Record 37 Protocol. It specifies a compression algorithm, an encryption 38 algorithm, and a MAC algorithm. In addition, the parameters for 39 these algorithms are known: the MAC key and the bulk encryption keys 40 for the connection in both the read and the write directions. 41 Logically, there are always four connection states outstanding: the 42 current read and write states, and the pending read and write states. 43 All records are processed under the current read and write states. 44 The security parameters for the pending states can be set by the TLS 45 Handshake Protocol, and the ChangeCipherSpec can selectively make 46 either of the pending states current, in which case the appropriate 47 current state is disposed of and replaced with the pending state; the 48 pending state is then reinitialized to an empty state. It is illegal 49 to make a state that has not been initialized with security 50 parameters a current state. The initial current state always 51 specifies that no encryption, compression, or MAC will be used. 52 53 (For practical reasons, Scapy scraps these two last lines, through the 54 implementation of dummy ciphers and MAC with TLS_NULL_WITH_NULL_NULL.) 55 56 These attributes and behaviours are mostly mapped in this class. 57 Also, note that Scapy may make a current state out of a pending state 58 which has been initialized with dummy security parameters. We need 59 this in order to know when the content of a TLS message is encrypted, 60 whether we possess the right keys to decipher/verify it or not. 61 For instance, when Scapy parses a CKE without knowledge of any secret, 62 and then a CCS, it needs to know that the following Finished 63 is encrypted and signed according to a new cipher suite, even though 64 it cannot decipher the message nor verify its integrity. 65 """ 66 def __init__(self, 67 connection_end="server", 68 read_or_write="read", 69 seq_num=0, 70 compression_alg=Comp_NULL, 71 ciphersuite=None, 72 tls_version=0x0303): 73 74 self.tls_version = tls_version 75 76 # It is the user's responsibility to keep the record seq_num 77 # under 2**64-1. If this value gets maxed out, the TLS class in 78 # record.py will crash when trying to encode it with struct.pack(). 79 self.seq_num = seq_num 80 81 self.connection_end = connection_end 82 self.row = read_or_write 83 84 if ciphersuite is None: 85 from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL 86 ciphersuite = TLS_NULL_WITH_NULL_NULL 87 self.ciphersuite = ciphersuite(tls_version=tls_version) 88 89 if not self.ciphersuite.usable: 90 warning("TLS ciphersuite not useable. Is the cryptography Python module installed ?") 91 return 92 93 self.compression = compression_alg() 94 self.key_exchange = ciphersuite.kx_alg() 95 self.cipher = ciphersuite.cipher_alg() 96 self.hash = ciphersuite.hash_alg() 97 98 if tls_version > 0x0200: 99 if ciphersuite.cipher_alg.type == "aead": 100 self.hmac = None 101 self.mac_len = self.cipher.tag_len 102 else: 103 self.hmac = ciphersuite.hmac_alg() 104 self.mac_len = self.hmac.hmac_len 105 else: 106 self.hmac = ciphersuite.hmac_alg() # should be Hmac_NULL 107 self.mac_len = self.hash.hash_len 108 109 if tls_version >= 0x0304: 110 self.hkdf = TLS13_HKDF(self.hash.name.lower()) 111 else: 112 self.prf = PRF(ciphersuite.hash_alg.name, tls_version) 113 114 115 def debug_repr(self, name, secret): 116 if conf.debug_tls and secret: 117 log_runtime.debug("TLS: %s %s %s: %s", 118 self.connection_end, 119 self.row, 120 name, 121 repr_hex(secret)) 122 123 def derive_keys(self, 124 client_random=b"", 125 server_random=b"", 126 master_secret=b""): 127 #XXX Can this be called over a non-usable suite? What happens then? 128 129 cs = self.ciphersuite 130 131 # Derive the keys according to the cipher type and protocol version 132 key_block = self.prf.derive_key_block(master_secret, 133 server_random, 134 client_random, 135 cs.key_block_len) 136 137 # When slicing the key_block, keep the right half of the material 138 skip_first = False 139 if ((self.connection_end == "client" and self.row == "read") or 140 (self.connection_end == "server" and self.row == "write")): 141 skip_first = True 142 143 pos = 0 144 cipher_alg = cs.cipher_alg 145 146 ### MAC secret (for block and stream ciphers) 147 if (cipher_alg.type == "stream") or (cipher_alg.type == "block"): 148 start = pos 149 if skip_first: 150 start += cs.hmac_alg.key_len 151 end = start + cs.hmac_alg.key_len 152 mac_secret = key_block[start:end] 153 self.debug_repr("mac_secret", mac_secret) 154 pos += 2*cs.hmac_alg.key_len 155 else: 156 mac_secret = None 157 158 ### Cipher secret 159 start = pos 160 if skip_first: 161 start += cipher_alg.key_len 162 end = start + cipher_alg.key_len 163 cipher_secret = key_block[start:end] 164 if cs.kx_alg.export: 165 reqLen = cipher_alg.expanded_key_len 166 cipher_secret = self.prf.postprocess_key_for_export(cipher_secret, 167 client_random, 168 server_random, 169 self.connection_end, 170 self.row, 171 reqLen) 172 self.debug_repr("cipher_secret", cipher_secret) 173 pos += 2*cipher_alg.key_len 174 175 ### Implicit IV (for block and AEAD ciphers) 176 start = pos 177 if cipher_alg.type == "block": 178 if skip_first: 179 start += cipher_alg.block_size 180 end = start + cipher_alg.block_size 181 elif cipher_alg.type == "aead": 182 if skip_first: 183 start += cipher_alg.fixed_iv_len 184 end = start + cipher_alg.fixed_iv_len 185 186 ### Now we have the secrets, we can instantiate the algorithms 187 if cs.hmac_alg is None: # AEAD 188 self.hmac = None 189 self.mac_len = cipher_alg.tag_len 190 else: 191 self.hmac = cs.hmac_alg(mac_secret) 192 self.mac_len = self.hmac.hmac_len 193 194 if cipher_alg.type == "stream": 195 cipher = cipher_alg(cipher_secret) 196 elif cipher_alg.type == "block": 197 # We set an IV every time, even though it does not matter for 198 # TLS 1.1+ as it requires an explicit IV. Indeed the cipher.iv 199 # would get updated in TLS.post_build() or TLS.pre_dissect(). 200 iv = key_block[start:end] 201 if cs.kx_alg.export: 202 reqLen = cipher_alg.block_size 203 iv = self.prf.generate_iv_for_export(client_random, 204 server_random, 205 self.connection_end, 206 self.row, 207 reqLen) 208 cipher = cipher_alg(cipher_secret, iv) 209 self.debug_repr("block iv", iv) 210 elif cipher_alg.type == "aead": 211 fixed_iv = key_block[start:end] 212 nonce_explicit_init = 0 213 # If you ever wanted to set a random nonce_explicit, use this: 214 #exp_bit_len = cipher_alg.nonce_explicit_len * 8 215 #nonce_explicit_init = random.randint(0, 2**exp_bit_len - 1) 216 cipher = cipher_alg(cipher_secret, fixed_iv, nonce_explicit_init) 217 self.debug_repr("aead fixed iv", fixed_iv) 218 self.cipher = cipher 219 220 def sslv2_derive_keys(self, key_material): 221 """ 222 There is actually only one key, the CLIENT-READ-KEY or -WRITE-KEY. 223 224 Note that skip_first is opposite from the one with SSLv3 derivation. 225 226 Also, if needed, the IV should be set elsewhere. 227 """ 228 skip_first = True 229 if ((self.connection_end == "client" and self.row == "read") or 230 (self.connection_end == "server" and self.row == "write")): 231 skip_first = False 232 233 cipher_alg = self.ciphersuite.cipher_alg 234 235 start = 0 236 if skip_first: 237 start += cipher_alg.key_len 238 end = start + cipher_alg.key_len 239 cipher_secret = key_material[start:end] 240 self.cipher = cipher_alg(cipher_secret) 241 self.debug_repr("cipher_secret", cipher_secret) 242 243 def tls13_derive_keys(self, key_material): 244 cipher_alg = self.ciphersuite.cipher_alg 245 key_len = cipher_alg.key_len 246 iv_len = cipher_alg.fixed_iv_len 247 write_key = self.hkdf.expand_label(key_material, b"key", b"", key_len) 248 write_iv = self.hkdf.expand_label(key_material, b"iv", b"", iv_len) 249 self.cipher = cipher_alg(write_key, write_iv) 250 251 def snapshot(self): 252 """ 253 This is used mostly as a way to keep the cipher state and the seq_num. 254 """ 255 snap = connState(connection_end=self.connection_end, 256 read_or_write=self.row, 257 seq_num=self.seq_num, 258 compression_alg=type(self.compression), 259 ciphersuite=type(self.ciphersuite), 260 tls_version=self.tls_version) 261 snap.cipher = self.cipher.snapshot() 262 if self.hmac: 263 snap.hmac.key = self.hmac.key 264 return snap 265 266 def __repr__(self): 267 def indent(s): 268 if s and s[-1] == '\n': 269 s = s[:-1] 270 s = '\n'.join('\t' + x for x in s.split('\n')) + '\n' 271 return s 272 273 res = "Connection end : %s\n" % self.connection_end.upper() 274 res += "Cipher suite : %s (0x%04x)\n" % (self.ciphersuite.name, 275 self.ciphersuite.val) 276 res += "Compression : %s (0x%02x)\n" % (self.compression.name, 277 self.compression.val) 278 tabsize = 4 279 return res.expandtabs(tabsize) 280 281 282class readConnState(connState): 283 def __init__(self, **kargs): 284 connState.__init__(self, read_or_write="read", **kargs) 285 286class writeConnState(connState): 287 def __init__(self, **kargs): 288 connState.__init__(self, read_or_write="write", **kargs) 289 290 291############################################################################### 292### TLS session ### 293############################################################################### 294 295class tlsSession(object): 296 """ 297 This is our TLS context, which gathers information from both sides of the 298 TLS connection. These sides are represented by a readConnState instance and 299 a writeConnState instance. Along with overarching network attributes, a 300 tlsSession object also holds negotiated, shared information, such as the 301 key exchange parameters and the master secret (when available). 302 303 The default connection_end is "server". This corresponds to the expected 304 behaviour for static exchange analysis (with a ClientHello parsed first). 305 """ 306 def __init__(self, 307 ipsrc=None, ipdst=None, 308 sport=None, dport=None, sid=None, 309 connection_end="server", 310 wcs=None, rcs=None): 311 312 # Use this switch to prevent additions to the 'handshake_messages'. 313 self.frozen = False 314 315 ### Network settings 316 self.ipsrc = ipsrc 317 self.ipdst = ipdst 318 self.sport = sport 319 self.dport = dport 320 self.sid = sid 321 322 # Our TCP socket. None until we send (or receive) a packet. 323 self.sock = None 324 325 ### Connection states 326 self.connection_end = connection_end 327 328 if wcs is None: 329 # Instantiate wcs with dummy values. 330 self.wcs = writeConnState(connection_end=connection_end) 331 self.wcs.derive_keys() 332 else: 333 self.wcs = wcs 334 335 if rcs is None: 336 # Instantiate rcs with dummy values. 337 self.rcs = readConnState(connection_end=connection_end) 338 self.rcs.derive_keys() 339 else: 340 self.rcs = rcs 341 342 # The pending write/read states are updated by the building/parsing 343 # of various TLS packets. They get committed to self.wcs/self.rcs 344 # once Scapy builds/parses a ChangeCipherSpec message, or for certain 345 # other messages in case of TLS 1.3. 346 self.pwcs = None 347 self.triggered_pwcs_commit = False 348 self.prcs = None 349 self.triggered_prcs_commit = False 350 351 352 ### Certificates and private keys 353 354 # The server certificate chain, as a list of Cert instances. 355 # Either we act as server and it has to be provided, or it is expected 356 # to be sent by the server through a Certificate message. 357 # The server certificate should be self.server_certs[0]. 358 self.server_certs = [] 359 360 # The server private key, as a PrivKey instance, when acting as server. 361 # XXX It would be nice to be able to provide both an RSA and an ECDSA 362 # key in order for the same Scapy server to support both families of 363 # cipher suites. See INIT_TLS_SESSION() in automaton_srv.py. 364 # (For now server_key holds either one of both types for DHE 365 # authentication, while server_rsa_key is used only for RSAkx.) 366 self.server_key = None 367 self.server_rsa_key = None 368 #self.server_ecdsa_key = None 369 370 # Back in the dreadful EXPORT days, US servers were forbidden to use 371 # RSA keys longer than 512 bits for RSAkx. When their usual RSA key 372 # was longer than this, they had to create a new key and send it via 373 # a ServerRSAParams message. When receiving such a message, 374 # Scapy stores this key in server_tmp_rsa_key as a PubKey instance. 375 self.server_tmp_rsa_key = None 376 377 # When client authentication is performed, we need at least a 378 # client certificate chain. If we act as client, we also have 379 # to provide the key associated with the first certificate. 380 self.client_certs = [] 381 self.client_key = None 382 383 384 ### Ephemeral key exchange parameters 385 386 # These are the group/curve parameters, needed to hold the information 387 # e.g. from receiving an SKE to sending a CKE. Usually, only one of 388 # these attributes will be different from None. 389 self.client_kx_ffdh_params = None 390 self.client_kx_ecdh_params = None 391 392 # These are PrivateKeys and PublicKeys from the appropriate FFDH/ECDH 393 # cryptography module, i.e. these are not raw bytes. Usually, only one 394 # in two will be different from None, e.g. when being a TLS client you 395 # will need the client_kx_privkey (the serialized public key is not 396 # actually registered) and you will receive a server_kx_pubkey. 397 self.client_kx_privkey = None 398 self.client_kx_pubkey = None 399 self.server_kx_privkey = None 400 self.server_kx_pubkey = None 401 402 # When using TLS 1.3, the tls13_client_pubshares will contain every 403 # potential key share (equate the 'client_kx_pubkey' before) the client 404 # offered, indexed by the id of the FFDH/ECDH group. These dicts 405 # effectively replace the four previous attributes. 406 self.tls13_client_privshares = {} 407 self.tls13_client_pubshares = {} 408 self.tls13_server_privshare = {} 409 self.tls13_server_pubshare = {} 410 411 412 ### Negotiated session parameters 413 414 # The advertised TLS version found in the ClientHello (and 415 # EncryptedPreMasterSecret if used). If acting as server, it is set to 416 # the value advertised by the client in its ClientHello. 417 # The default value corresponds to TLS 1.2 (and TLS 1.3, incidentally). 418 self.advertised_tls_version = 0x0303 419 420 # The agreed-upon TLS version found in the ServerHello. 421 self.tls_version = None 422 423 # These attributes should eventually be known to both sides (SSLv3-TLS 1.2). 424 self.client_random = None 425 self.server_random = None 426 self.pre_master_secret = None 427 self.master_secret = None 428 429 # A session ticket received by the client. 430 self.client_session_ticket = None 431 432 # These attributes should only be used with SSLv2 connections. 433 # We need to keep the KEY-MATERIAL here because it may be reused. 434 self.sslv2_common_cs = [] 435 self.sslv2_connection_id = None 436 self.sslv2_challenge = None 437 self.sslv2_challenge_clientcert = None 438 self.sslv2_key_material = None 439 440 # These attributes should only be used with TLS 1.3 connections. 441 self.tls13_psk_secret = None 442 self.tls13_early_secret = None 443 self.tls13_dhe_secret = None 444 self.tls13_handshake_secret = None 445 self.tls13_master_secret = None 446 self.tls13_derived_secrets = {} 447 448 # Handshake messages needed for Finished computation/validation. 449 # No record layer headers, no HelloRequests, no ChangeCipherSpecs. 450 self.handshake_messages = [] 451 self.handshake_messages_parsed = [] 452 453 # All exchanged TLS packets. 454 #XXX no support for now 455 #self.exchanged_pkts = [] 456 457 458 def __setattr__(self, name, val): 459 if name == "connection_end": 460 if hasattr(self, "rcs") and self.rcs: 461 self.rcs.connection_end = val 462 if hasattr(self, "wcs") and self.wcs: 463 self.wcs.connection_end = val 464 if hasattr(self, "prcs") and self.prcs: 465 self.prcs.connection_end = val 466 if hasattr(self, "pwcs") and self.pwcs: 467 self.pwcs.connection_end = val 468 super(tlsSession, self).__setattr__(name, val) 469 470 471 ### Mirroring 472 473 def mirror(self): 474 """ 475 This function takes a tlsSession object and swaps the IP addresses, 476 ports, connection ends and connection states. The triggered_commit are 477 also swapped (though it is probably overkill, it is cleaner this way). 478 479 It is useful for static analysis of a series of messages from both the 480 client and the server. In such a situation, it should be used every 481 time the message being read comes from a different side than the one 482 read right before, as the reading state becomes the writing state, and 483 vice versa. For instance you could do: 484 485 client_hello = open('client_hello.raw').read() 486 <read other messages> 487 488 m1 = TLS(client_hello) 489 m2 = TLS(server_hello, tls_session=m1.tls_session.mirror()) 490 m3 = TLS(server_cert, tls_session=m2.tls_session) 491 m4 = TLS(client_keyexchange, tls_session=m3.tls_session.mirror()) 492 """ 493 494 self.ipdst, self.ipsrc = self.ipsrc, self.ipdst 495 self.dport, self.sport = self.sport, self.dport 496 497 self.rcs, self.wcs = self.wcs, self.rcs 498 if self.rcs: 499 self.rcs.row = "read" 500 if self.wcs: 501 self.wcs.row = "write" 502 503 self.prcs, self.pwcs = self.pwcs, self.prcs 504 if self.prcs: 505 self.prcs.row = "read" 506 if self.pwcs: 507 self.pwcs.row = "write" 508 509 self.triggered_prcs_commit, self.triggered_pwcs_commit = \ 510 self.triggered_pwcs_commit, self.triggered_prcs_commit 511 512 if self.connection_end == "client": 513 self.connection_end = "server" 514 elif self.connection_end == "server": 515 self.connection_end = "client" 516 517 return self 518 519 520 ### Secrets management for SSLv3 to TLS 1.2 521 522 def compute_master_secret(self): 523 if self.pre_master_secret is None: 524 warning("Missing pre_master_secret while computing master_secret!") 525 if self.client_random is None: 526 warning("Missing client_random while computing master_secret!") 527 if self.server_random is None: 528 warning("Missing server_random while computing master_secret!") 529 530 ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret, 531 self.client_random, 532 self.server_random) 533 self.master_secret = ms 534 if conf.debug_tls: 535 log_runtime.debug("TLS: master secret: %s", repr_hex(ms)) 536 537 def compute_ms_and_derive_keys(self): 538 self.compute_master_secret() 539 self.prcs.derive_keys(client_random=self.client_random, 540 server_random=self.server_random, 541 master_secret=self.master_secret) 542 self.pwcs.derive_keys(client_random=self.client_random, 543 server_random=self.server_random, 544 master_secret=self.master_secret) 545 546 547 ### Secrets management for SSLv2 548 549 def compute_sslv2_key_material(self): 550 if self.master_secret is None: 551 warning("Missing master_secret while computing key_material!") 552 if self.sslv2_challenge is None: 553 warning("Missing challenge while computing key_material!") 554 if self.sslv2_connection_id is None: 555 warning("Missing connection_id while computing key_material!") 556 557 km = self.pwcs.prf.derive_key_block(self.master_secret, 558 self.sslv2_challenge, 559 self.sslv2_connection_id, 560 2*self.pwcs.cipher.key_len) 561 self.sslv2_key_material = km 562 if conf.debug_tls: 563 log_runtime.debug("TLS: master secret: %s", repr_hex(self.master_secret)) 564 log_runtime.debug("TLS: key material: %s", repr_hex(km)) 565 566 def compute_sslv2_km_and_derive_keys(self): 567 self.compute_sslv2_key_material() 568 self.prcs.sslv2_derive_keys(key_material=self.sslv2_key_material) 569 self.pwcs.sslv2_derive_keys(key_material=self.sslv2_key_material) 570 571 572 ### Secrets management for TLS 1.3 573 574 def compute_tls13_early_secrets(self): 575 """ 576 Ciphers key and IV are updated accordingly for 0-RTT data. 577 self.handshake_messages should be ClientHello only. 578 """ 579 # we use the prcs rather than the pwcs in a totally arbitrary way 580 if self.prcs is None: 581 # too soon 582 return 583 584 hkdf = self.prcs.hkdf 585 586 self.tls13_early_secret = hkdf.extract(None, 587 self.tls13_psk_secret) 588 589 bk = hkdf.derive_secret(self.tls13_early_secret, 590 b"external psk binder key", 591 #"resumption psk binder key", 592 b"") 593 self.tls13_derived_secrets["binder_key"] = bk 594 595 if len(self.handshake_messages) > 1: 596 # these secrets are not defined in case of HRR 597 return 598 599 cets = hkdf.derive_secret(self.tls13_early_secret, 600 b"client early traffic secret", 601 b"".join(self.handshake_messages)) 602 self.tls13_derived_secrets["client_early_traffic_secret"] = cets 603 604 ees = hkdf.derive_secret(self.tls13_early_secret, 605 b"early exporter master secret", 606 b"".join(self.handshake_messages)) 607 self.tls13_derived_secrets["early_exporter_secret"] = ees 608 609 if self.connection_end == "server": 610 self.prcs.tls13_derive_keys(cets) 611 elif self.connection_end == "client": 612 self.pwcs.tls13_derive_keys(cets) 613 614 def compute_tls13_handshake_secrets(self): 615 """ 616 Ciphers key and IV are updated accordingly for Handshake data. 617 self.handshake_messages should be ClientHello...ServerHello. 618 """ 619 if self.tls13_early_secret is None: 620 warning("No early secret. This is abnormal.") 621 622 hkdf = self.prcs.hkdf 623 624 self.tls13_handshake_secret = hkdf.extract(self.tls13_early_secret, 625 self.tls13_dhe_secret) 626 627 chts = hkdf.derive_secret(self.tls13_handshake_secret, 628 b"client handshake traffic secret", 629 b"".join(self.handshake_messages)) 630 self.tls13_derived_secrets["client_handshake_traffic_secret"] = chts 631 632 shts = hkdf.derive_secret(self.tls13_handshake_secret, 633 b"server handshake traffic secret", 634 b"".join(self.handshake_messages)) 635 self.tls13_derived_secrets["server_handshake_traffic_secret"] = shts 636 637 if self.connection_end == "server": 638 self.prcs.tls13_derive_keys(chts) 639 self.pwcs.tls13_derive_keys(shts) 640 elif self.connection_end == "client": 641 self.pwcs.tls13_derive_keys(chts) 642 self.prcs.tls13_derive_keys(shts) 643 644 def compute_tls13_traffic_secrets(self): 645 """ 646 Ciphers key and IV are updated accordingly for Application data. 647 self.handshake_messages should be ClientHello...ServerFinished. 648 """ 649 hkdf = self.prcs.hkdf 650 651 self.tls13_master_secret = hkdf.extract(self.tls13_handshake_secret, 652 None) 653 654 cts0 = hkdf.derive_secret(self.tls13_master_secret, 655 b"client application traffic secret", 656 b"".join(self.handshake_messages)) 657 self.tls13_derived_secrets["client_traffic_secrets"] = [cts0] 658 659 sts0 = hkdf.derive_secret(self.tls13_master_secret, 660 b"server application traffic secret", 661 b"".join(self.handshake_messages)) 662 self.tls13_derived_secrets["server_traffic_secrets"] = [sts0] 663 664 es = hkdf.derive_secret(self.tls13_master_secret, 665 b"exporter master secret", 666 b"".join(self.handshake_messages)) 667 self.tls13_derived_secrets["exporter_secret"] = es 668 669 if self.connection_end == "server": 670 #self.prcs.tls13_derive_keys(cts0) 671 self.pwcs.tls13_derive_keys(sts0) 672 elif self.connection_end == "client": 673 #self.pwcs.tls13_derive_keys(cts0) 674 self.prcs.tls13_derive_keys(sts0) 675 676 def compute_tls13_traffic_secrets_end(self): 677 cts0 = self.tls13_derived_secrets["client_traffic_secrets"][0] 678 if self.connection_end == "server": 679 self.prcs.tls13_derive_keys(cts0) 680 elif self.connection_end == "client": 681 self.pwcs.tls13_derive_keys(cts0) 682 683 def compute_tls13_verify_data(self, connection_end, read_or_write): 684 shts = "server_handshake_traffic_secret" 685 chts = "client_handshake_traffic_secret" 686 if read_or_write == "read": 687 hkdf = self.rcs.hkdf 688 if connection_end == "client": 689 basekey = self.tls13_derived_secrets[shts] 690 elif connection_end == "server": 691 basekey = self.tls13_derived_secrets[chts] 692 elif read_or_write == "write": 693 hkdf = self.wcs.hkdf 694 if connection_end == "client": 695 basekey = self.tls13_derived_secrets[chts] 696 elif connection_end == "server": 697 basekey = self.tls13_derived_secrets[shts] 698 699 if not hkdf or not basekey: 700 warning("Missing arguments for verify_data computation!") 701 return None 702 #XXX this join() works in standard cases, but does it in all of them? 703 handshake_context = b"".join(self.handshake_messages) 704 return hkdf.compute_verify_data(basekey, handshake_context) 705 706 def compute_tls13_resumption_secret(self): 707 """ 708 self.handshake_messages should be ClientHello...ClientFinished. 709 """ 710 if self.connection_end == "server": 711 hkdf = self.prcs.hkdf 712 elif self.connection_end == "client": 713 hkdf = self.pwcs.hkdf 714 rs = hkdf.derive_secret(self.tls13_master_secret, 715 b"resumption master secret", 716 b"".join(self.handshake_messages)) 717 self.tls13_derived_secrets["resumption_secret"] = rs 718 719 def compute_tls13_next_traffic_secrets(self): 720 """ 721 Ciphers key and IV are updated accordingly. 722 """ 723 hkdf = self.prcs.hkdf 724 hl = hkdf.hash.digest_size 725 726 cts = self.tls13_derived_secrets["client_traffic_secrets"] 727 ctsN = cts[-1] 728 ctsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl) 729 cts.append(ctsN_1) 730 731 sts = self.tls13_derived_secrets["server_traffic_secrets"] 732 stsN = sts[-1] 733 stsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl) 734 cts.append(stsN_1) 735 736 if self.connection_end == "server": 737 self.prcs.tls13_derive_keys(ctsN_1) 738 self.pwcs.tls13_derive_keys(stsN_1) 739 elif self.connection_end == "client": 740 self.pwcs.tls13_derive_keys(ctsN_1) 741 self.prcs.tls13_derive_keys(stsN_1) 742 743 ### Tests for record building/parsing 744 745 def consider_read_padding(self): 746 # Return True if padding is needed. Used by TLSPadField. 747 return (self.rcs.cipher.type == "block" and 748 not (False in six.itervalues(self.rcs.cipher.ready))) 749 750 def consider_write_padding(self): 751 # Return True if padding is needed. Used by TLSPadField. 752 return self.wcs.cipher.type == "block" 753 754 def use_explicit_iv(self, version, cipher_type): 755 # Return True if an explicit IV is needed. Required for TLS 1.1+ 756 # when either a block or an AEAD cipher is used. 757 if cipher_type == "stream": 758 return False 759 return version >= 0x0302 760 761 762 ### Python object management 763 764 def hash(self): 765 s1 = struct.pack("!H", self.sport) 766 s2 = struct.pack("!H", self.dport) 767 family = socket.AF_INET 768 if ':' in self.ipsrc: 769 family = socket.AF_INET6 770 s1 += socket.inet_pton(family, self.ipsrc) 771 s2 += socket.inet_pton(family, self.ipdst) 772 return strxor(s1, s2) 773 774 def eq(self, other): 775 ok = False 776 if (self.sport == other.sport and self.dport == other.dport and 777 self.ipsrc == other.ipsrc and self.ipdst == other.ipdst): 778 ok = True 779 780 if (not ok and 781 self.dport == other.sport and self.sport == other.dport and 782 self.ipdst == other.ipsrc and self.ipsrc == other.ipdst): 783 ok = True 784 785 if ok: 786 if self.sid and other.sid: 787 return self.sid == other.sid 788 return True 789 790 return False 791 792 def __repr__(self): 793 sid = repr(self.sid) 794 if len(sid) > 12: 795 sid = sid[:11] + "..." 796 return "%s:%s > %s:%s" % (self.ipsrc, str(self.sport), 797 self.ipdst, str(self.dport)) 798 799############################################################################### 800### Session singleton ### 801############################################################################### 802 803class _GenericTLSSessionInheritance(Packet): 804 """ 805 Many classes inside the TLS module need to get access to session-related 806 information. For instance, an encrypted TLS record cannot be parsed without 807 some knowledge of the cipher suite being used and the secrets which have 808 been negotiated. Passing information is also essential to the handshake. 809 To this end, various TLS objects inherit from the present class. 810 """ 811 __slots__ = ["tls_session", "rcs_snap_init", "wcs_snap_init"] 812 name = "Dummy Generic TLS Packet" 813 fields_desc = [] 814 815 def __init__(self, _pkt="", post_transform=None, _internal=0, 816 _underlayer=None, tls_session=None, **fields): 817 try: 818 setme = self.tls_session is None 819 except: 820 setme = True 821 822 if setme: 823 if tls_session is None: 824 self.tls_session = tlsSession() 825 else: 826 self.tls_session = tls_session 827 828 self.rcs_snap_init = self.tls_session.rcs.snapshot() 829 self.wcs_snap_init = self.tls_session.wcs.snapshot() 830 831 Packet.__init__(self, _pkt=_pkt, post_transform=post_transform, 832 _internal=_internal, _underlayer=_underlayer, 833 **fields) 834 835 def __getattr__(self, attr): 836 """ 837 The tls_session should be found only through the normal mechanism. 838 """ 839 if attr == "tls_session": 840 return None 841 return super(_GenericTLSSessionInheritance, self).__getattr__(attr) 842 843 def tls_session_update(self, msg_str): 844 """ 845 post_{build, dissection}_tls_session_update() are used to update the 846 tlsSession context. The default definitions below, along with 847 tls_session_update(), may prevent code duplication in some cases. 848 """ 849 pass 850 851 def post_build_tls_session_update(self, msg_str): 852 self.tls_session_update(msg_str) 853 854 def post_dissection_tls_session_update(self, msg_str): 855 self.tls_session_update(msg_str) 856 857 def copy(self): 858 pkt = Packet.copy(self) 859 pkt.tls_session = self.tls_session 860 return pkt 861 862 def clone_with(self, payload=None, **kargs): 863 pkt = Packet.clone_with(self, payload=payload, **kargs) 864 pkt.tls_session = self.tls_session 865 return pkt 866 867 def raw_stateful(self): 868 return super(_GenericTLSSessionInheritance, self).__bytes__() 869 870 def str_stateful(self): 871 return self.raw_stateful() 872 873 def __bytes__(self): 874 """ 875 The __bytes__ call has to leave the connection states unchanged. 876 We also have to delete raw_packet_cache in order to access post_build. 877 878 For performance, the pending connStates are not snapshotted. 879 This should not be an issue, but maybe pay attention to this. 880 881 The previous_freeze_state prevents issues with calling a raw() calling 882 in turn another raw(), which would unfreeze the session too soon. 883 """ 884 s = self.tls_session 885 rcs_snap = s.rcs.snapshot() 886 wcs_snap = s.wcs.snapshot() 887 rpc_snap = self.raw_packet_cache 888 889 s.wcs = self.rcs_snap_init 890 891 self.raw_packet_cache = None 892 previous_freeze_state = s.frozen 893 s.frozen = True 894 built_packet = super(_GenericTLSSessionInheritance, self).__bytes__() 895 s.frozen = previous_freeze_state 896 897 s.rcs = rcs_snap 898 s.wcs = wcs_snap 899 self.raw_packet_cache = rpc_snap 900 901 return built_packet 902 __str__ = __bytes__ 903 904 def show2(self): 905 """ 906 Rebuild the TLS packet with the same context, and then .show() it. 907 We need self.__class__ to call the subclass in a dynamic way. 908 909 Howether we do not want the tls_session.{r,w}cs.seq_num to be updated. 910 We have to bring back the init states (it's possible the cipher context 911 has been updated because of parsing) but also to keep the current state 912 and restore it afterwards (the raw() call may also update the states). 913 """ 914 s = self.tls_session 915 rcs_snap = s.rcs.snapshot() 916 wcs_snap = s.wcs.snapshot() 917 918 s.rcs = self.rcs_snap_init 919 920 built_packet = raw(self) 921 s.frozen = True 922 self.__class__(built_packet, tls_session=s).show() 923 s.frozen = False 924 925 s.rcs = rcs_snap 926 s.wcs = wcs_snap 927 928 # Uncomment this when the automata update IPs and ports properly 929 #def mysummary(self): 930 # return "TLS %s" % repr(self.tls_session) 931 932 933############################################################################### 934### Multiple TLS sessions ### 935############################################################################### 936 937class _tls_sessions(object): 938 def __init__(self): 939 self.sessions = {} 940 941 def add(self, session): 942 s = self.find(session) 943 if s: 944 log_runtime.info("TLS: previous session shall not be overwritten") 945 return 946 947 h = session.hash() 948 if h in self.sessions: 949 self.sessions[h].append(session) 950 else: 951 self.sessions[h] = [session] 952 953 def rem(self, session): 954 s = self.find(session) 955 if s: 956 log_runtime.info("TLS: previous session shall not be overwritten") 957 return 958 959 h = session.hash() 960 self.sessions[h].remove(session) 961 962 def find(self, session): 963 h = session.hash() 964 if h in self.sessions: 965 for k in self.sessions[h]: 966 if k.eq(session): 967 if conf.tls_verbose: 968 log_runtime.info("TLS: found session matching %s", k) 969 return k 970 if conf.tls_verbose: 971 log_runtime.info("TLS: did not find session matching %s", session) 972 return None 973 974 def __repr__(self): 975 res = [("First endpoint", "Second endpoint", "Session ID")] 976 for l in self.sessions.values(): 977 for s in l: 978 src = "%s[%d]" % (s.ipsrc, s.sport) 979 dst = "%s[%d]" % (s.ipdst, s.dport) 980 sid = repr(s.sid) 981 if len(sid) > 12: 982 sid = sid[:11] + "..." 983 res.append((src, dst, sid)) 984 colwidth = (max([len(y) for y in x]) for x in zip(*res)) 985 fmt = " ".join(map(lambda x: "%%-%ds"%x, colwidth)) 986 return "\n".join(map(lambda x: fmt % x, res)) 987 988 989conf.tls_sessions = _tls_sessions() 990conf.tls_verbose = False 991 992