From 6a797e2b945e729c5f4a056a7dd84c24d0b6aac4 Mon Sep 17 00:00:00 2001 From: Adam Janovsky Date: Thu, 23 Aug 2018 15:03:10 +0200 Subject: [PATCH 1/2] Added extms support to TLS --- scapy/layers/tls/crypto/prf.py | 13 ++++++++++--- scapy/layers/tls/handshake.py | 31 ++++++++++++++++++++++++++++++- scapy/layers/tls/keyexchange.py | 21 +++++++++++++++------ scapy/layers/tls/session.py | 10 +++++++++- test/tls.uts | 31 +++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/scapy/layers/tls/crypto/prf.py b/scapy/layers/tls/crypto/prf.py index 9cd2b79f88d..5d1b39b6f8d 100644 --- a/scapy/layers/tls/crypto/prf.py +++ b/scapy/layers/tls/crypto/prf.py @@ -207,19 +207,26 @@ def __init__(self, hash_name="SHA256", tls_version=0x0303): else: warning("Unknown TLS version") - def compute_master_secret(self, pre_master_secret, - client_random, server_random): + def compute_master_secret(self, pre_master_secret, client_random, + server_random, extms=False, handshake_hash=None): """ Return the 48-byte master_secret, computed from pre_master_secret, client_random and server_random. See RFC 5246, section 6.3. + Supports Extended Master Secret Derivation, see RFC 7627 """ seed = client_random + server_random + label = b'master secret' + + if extms is True and handshake_hash is not None: + seed = handshake_hash + label = b'extended master secret' + if self.tls_version < 0x0300: return None elif self.tls_version == 0x0300: return self.prf(pre_master_secret, seed, 48) else: - return self.prf(pre_master_secret, b"master secret", seed, 48) + return self.prf(pre_master_secret, label, seed, 48) def derive_key_block(self, master_secret, server_random, client_random, req_len): diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py index 7a81acde443..61d4a9f843a 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -48,7 +48,8 @@ TLS_Ext_SignatureAlgorithms, TLS_Ext_SupportedVersion_SH, TLS_Ext_EarlyDataIndication, - _tls_hello_retry_magic) + _tls_hello_retry_magic, + TLS_Ext_ExtendedMasterSecret) from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField, _TLSSignatureField, ServerRSAParams, SigAndHashAlgsField, _tls_hash_sig, @@ -111,6 +112,7 @@ def tls_session_update(self, msg_str): """ Covers both post_build- and post_dissection- context updates. """ + self.tls_session.handshake_messages.append(msg_str) self.tls_session.handshake_messages_parsed.append(self) @@ -540,6 +542,13 @@ def tls_session_update(self, msg_str): s.server_random = self.random_bytes s.sid = self.sid + # EXTMS + if self.ext: + for e in self.ext: + if isinstance(e, TLS_Ext_ExtendedMasterSecret): + self.tls_session.extms = True + break + cs_cls = None if self.cipher: cs_val = self.cipher @@ -1296,6 +1305,26 @@ def build(self, *args, **kargs): self.exchkeys = cls return _TLSHandshake.build(self, *args, **kargs) + def tls_session_update(self, msg_str): + """ + Finalize the EXTMS messages and compute the hash + """ + super(TLSClientKeyExchange, self).tls_session_update(msg_str) + + if self.tls_session.extms: + to_hash = b''.join(self.tls_session.handshake_messages) + if self.tls_session.tls_version >= 0x303: + # TLS 1.2 uses the default hash from cipher suite + hash_object = self.tls_session.pwcs.hash + self.tls_session.session_hash = hash_object.digest(to_hash) + else: + # Previous TLS version use concatenation of MD5 & SHA1 + from scapy.layers.tls.crypto.hash import Hash_MD5, Hash_SHA + self.tls_session.session_hash = ( + Hash_MD5().digest(to_hash) + Hash_SHA().digest(to_hash) + ) + self.tls_session.compute_ms_and_derive_keys() + ############################################################################### # Finished # diff --git a/scapy/layers/tls/keyexchange.py b/scapy/layers/tls/keyexchange.py index f20845b9a74..4bc43b009bf 100644 --- a/scapy/layers/tls/keyexchange.py +++ b/scapy/layers/tls/keyexchange.py @@ -743,7 +743,11 @@ def fill_missing(self): if s.client_kx_privkey and s.server_kx_pubkey: pms = s.client_kx_privkey.exchange(s.server_kx_pubkey) s.pre_master_secret = pms - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + # If extms is set (extended master secret), the key will + # need the session hash to be computed. This is provided + # by the TLSClientKeyExchange. Same in all occurrences + s.compute_ms_and_derive_keys() def post_build(self, pkt, pay): if not self.dh_Yc: @@ -773,7 +777,8 @@ def post_dissection(self, m): if s.server_kx_privkey and s.client_kx_pubkey: ZZ = s.server_kx_privkey.exchange(s.client_kx_pubkey) s.pre_master_secret = ZZ - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + s.compute_ms_and_derive_keys() def guess_payload_class(self, p): return Padding @@ -805,7 +810,8 @@ def fill_missing(self): if s.client_kx_privkey and s.server_kx_pubkey: pms = s.client_kx_privkey.exchange(ec.ECDH(), s.server_kx_pubkey) s.pre_master_secret = pms - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + s.compute_ms_and_derive_keys() def post_build(self, pkt, pay): if not self.ecdh_Yc: @@ -830,7 +836,8 @@ def post_dissection(self, m): if s.server_kx_privkey and s.client_kx_pubkey: ZZ = s.server_kx_privkey.exchange(ec.ECDH(), s.client_kx_pubkey) s.pre_master_secret = ZZ - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + s.compute_ms_and_derive_keys() # RSA Encryption (standard & export) @@ -893,7 +900,8 @@ def pre_dissect(self, m): warning(err) s.pre_master_secret = pms - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + s.compute_ms_and_derive_keys() return pms @@ -908,7 +916,8 @@ def post_build(self, pkt, pay): s = self.tls_session s.pre_master_secret = enc - s.compute_ms_and_derive_keys() + if not s.extms or s.session_hash: + s.compute_ms_and_derive_keys() if s.server_tmp_rsa_key is not None: enc = s.server_tmp_rsa_key.encrypt(pkt, t="pkcs") diff --git a/scapy/layers/tls/session.py b/scapy/layers/tls/session.py index fbc912d6855..6ab6d52fe60 100644 --- a/scapy/layers/tls/session.py +++ b/scapy/layers/tls/session.py @@ -453,6 +453,10 @@ def __init__(self, self.handshake_messages = [] self.handshake_messages_parsed = [] + # Flag, whether we derive the secret as Extended MS or not + self.extms = False + self.session_hash = None + # All exchanged TLS packets. # XXX no support for now # self.exchanged_pkts = [] @@ -526,10 +530,14 @@ def compute_master_secret(self): warning("Missing client_random while computing master_secret!") if self.server_random is None: warning("Missing server_random while computing master_secret!") + if self.extms and self.session_hash is None: + warning("Missing session hash while computing master secret!") ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret, self.client_random, - self.server_random) + self.server_random, + self.extms, + self.session_hash) self.master_secret = ms if conf.debug_tls: log_runtime.debug("TLS: master secret: %s", repr_hex(ms)) diff --git a/test/tls.uts b/test/tls.uts index d9414a34cbe..32c40d0a766 100644 --- a/test/tls.uts +++ b/test/tls.uts @@ -979,6 +979,37 @@ assert(rec_fin.mac == b'\xecguD\xa8\x87$<7+\n\x94\x1e9\x96\xfa') assert(isinstance(rec_fin.msg[0], _TLSEncryptedContent)) rec_fin.msg[0].load == b'7\\)`\xaa`\x7ff\xcd\x10\xa9v\xa3*\x17\x1a' += Reading TLS test session - Extended master secret +~ test + +# See https://github.com/secdev/scapy/issues/2784 + +from scapy.layers.tls.cert import PrivKey +from scapy.layers.tls.handshake import TLSFinished +from scapy.layers.tls.record import TLS + +chello_extms = hex_bytes(b'1603010200010001fc0303f8b3dbcb70ed3804009c15af4a4298720619b70d1ad4f24d0e99de9e93ce3c3b201c3b2cf3266bcba19b29479ec66fe815f7db0a6b976111f70958395e7aeebaba003e130213031301c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000175000b000403000102000a000c000a001d0017001e00190018337400000010000e000c02683208687474702f312e31001600000017000000310000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d0020e8410f5ab09d96b05f10183ccd9e93a057a73290b4c9e1c254cdfc299fc01d41001500d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') +shello_extms = hex_bytes(b'160303005502000051030320a54032477ea3a963b8a700090459f11f1f4ad1896e1d75745b7e2bdc51dde0200600f552db6c51b97a309717ff847bb6e8fef1ce2601544413fda7b66075b887009d000009ff0100010000170000160303036e0b00036a0003670003643082036030820248a003020102020900eb73b71c3e2f9fdc300d06092a864886f70d01010b05003045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464301e170d3139303231353135313430335a170d3239303231323135313430335a3045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c746430820122300d06092a864886f70d01010105000382010f003082010a0282010100d2f7d36b233a5619368fc3a7db0f2364dc71986dd4eebcbee85b783e139cfeb0a80de50147c936aa84230e2fa2eb91ef1737410387b932440ac7cfda3c5966eef88f688bcbee6a5d0dfaa075b77dfe836f2cb318375ff5be2b35f6d62dd7c4b147224f67d53d95c7fcc11cda7bc622369b4d4a685655169fb28f66e511724f0c9af2f74ea4cdf09b92f917246a582f67fade3eff7eca2c794d713c13f80cd53f847aa196d0adc04494790a628e327f4b53d05b83025c3ea541195f953ce6fc37edcc68a8fd6eca621f38bc08bc2d8d72cfcdf85c68f9f4f4485b32133c63299f85ffd62bde5a9d585e5a896f08319448277f19e86d5d6878bc53768b2ef9b3210203010001a3533051301d0603551d0e041604148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35301f0603551d230418301680148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101003c001f0f5d106072e0beedfa47895329d4623422080e66caa4beb4c3d9b6868fa107467d6160e512ede7cbbefdeb17c09b9f594f86f1a9922c982ccf9655d4d67eda061f667eeb25fe7203bea00e40f150a490a78ca963d87c185ade8b7c294f5052fb1e1edb3403831e33e4026c8e56717cb77bc32321858be37a77fe7f5511ef8c2013c86e2730c5b2366875131cae0c7616fdc7c8605696133e7a685f20203c0db8e0ff1d1a5991d2f058f48f20b10a5fb0df27a1f9874cc0fe8d6ebf77e9a7ba38490e9d63241a0fb3fd7701ff3b130c9aa7aa77770280b7003c1bb5e0784c34aacb74ce8114960e50eee04602a7ab20e5c878028e4292e90e40fd631fee16030300040e000000') +finished_extms = hex_bytes(b'160303010610000102010007534dd8642e57edd33d156d8002f70562864c1dfe5d721763e8e4ef2c03fb14b4e4eac1864c41fcce57367f95798f04954ef957deb934536b0ac39a72c14f772d0f64b7cc0d8260e2019748fc65fd6f382da6d4f873afe6fc1fa17e786cf6c72b6a46950d2030c7b42ed10f2c4dba37282001132ddb151a44f6face6b049338217784cf2a5ac6a054a2a1d205fb7657d7affa14113c43314b54b28164423455174f57eb50f6eea0836ba1c68616db720641bf18f0cdf7bb729c9cc0b4cfeee8aeed94e00573210eb5328cbcca4ccb1aa29a910c5b5f2c96cf3a431e9677980400d574244ff6bfdabf36ba9dda84703f5760d607e4b731d4f1dc16372b0feac11403030001011603030028269118aa98b35c71e35034f35c23c78d55c04662cdb71c11b1ef862e3b4ebf8ace2aff053257bb08') +key = base64_bytes(b'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFM5OU5ySXpwV0dUYVAKdzZmYkR5TmszSEdZYmRUdXZMN29XM2crRTV6K3NLZ041UUZIeVRhcWhDTU9MNkxya2U4WE4wRURoN2t5UkFySAp6OW84V1didStJOW9pOHZ1YWwwTitxQjF0MzMrZzI4c3N4ZzNYL1crS3pYMjFpM1h4TEZISWs5bjFUMlZ4L3pCCkhOcDd4aUkybTAxS2FGWlZGcCt5ajJibEVYSlBESnJ5OTA2a3pmQ2JrdmtYSkdwWUwyZjYzajcvZnNvc2VVMXgKUEJQNEROVS9oSHFobHRDdHdFU1VlUXBpampKL1MxUFFXNE1DWEQ2bFFSbGZsVHptL0RmdHpHaW8vVzdLWWg4NAp2QWk4TFkxeXo4MzRYR2o1OVBSSVd6SVRQR01wbjRYLzFpdmVXcDFZWGxxSmJ3Z3hsRWduZnhub2JWMW9lTHhUCmRvc3UrYk1oQWdNQkFBRUNnZ0VBSGQ5NTBISHNrTVNCTlZvL0tvVzZQVTM1eDl2Rml3aXUvN2YwRHRZNEpOaGUKODVpNTFiQm9UVHpvdWRtRStGWnh4SmZPWFBHYkI4TWF3N0JxOXFDeU1xUi9xZzRoa21EOVREMXcrenBBWFFtLwpkRlRuMk85OW5MQUJ0RElmeTYzT2JJUXZPa1MzczczZHpIcUpkWDFZMnVLaXp5WjNFeFZoQjZmR3Fpa09ScU1BCmNYbjJSRzN1UXFNWk4yUkVUK1hFYWdsa1dkbGphVTdaTC9CbklRT2xGS0h2ZzVSeGFwWGpJbTM2NnFUVStreGEKWDJFZnllOUJycWxWK0o4cnYzODVjRDBQc3RkSVFTQzMxZFBzUHMrSnJMVlBKQVpGZTBLVk1lYkk2ODU1cERYZApGd1ZGcC9BOXhFa3NwRW1jS0tnL1ZkZ3JQZUxMQmxhVm9mMVhPeUhWQVFLQmdRRHhPdXFGaXJvNTNQNGZQUGlMCkFnTTNvRnpmY2xwdDFMdnduelprUmVMU1NvVFBvZSt1R2xMdTBpS3lMUHBjWm1DTCt0bldsSXBheHRYOU1CRmUKOWNvMlJpSU9WM2JZM0ZpOTBLYjlvN3NyZURhaWE5NElHNGlBYktyWjJJdktBZmFkWnBqb1hBTXZpWnBEYWxGYgprZWVCd29nV0sreTdic2EwU1RYTGVMdjF5d0tCZ1FEZjRwT2lUZ3RBNFdtMXo2WFB4Z0ZCa3A3OWVjaWhINTlICnF1cVJNNkhtQ2YzSnZqZzJCZnYyb2hYNTlTU2VnZTI5ek0yZEhmVGhSeW1vZlg5VkpyMnRYY2FhVWpkRnp1Ui8Kcm1EblJMTjVDTUFnUWNCU3M5UXFCaXdTM0hqVmpML1REcFMvblJwY2VCQnNZTFYvR1YvQkpvWDkxTlVodVRXcwpjQ0VvRmNVOVF3S0JnUUNjbCtGTHhTMTBpSGZTY1hMcVVla2l3QS9wNFVMQWoxdGRMUTFTOUdiMG1ma3pDKzBaCitPNmpKM2ZzYi9RcDdTOTVUdU1BUDdhOGpOeTJtZkI4MDFOci9nVDNpR0dYRHhyd1JUVlI2MnFDSW14YzdXYloKbm4zeTJCZmtpSVRlSW40ajJVa2pkUytBT1hRUmxUK3hFTHJXNmlBTFBJSlZmZWl4ZWVEWTc4d2NGd0tCZ0Z5aQoxcTFvbDNWd0Q1cGY0ZDdYc2Z0YzNKWkxCcjNNWk01MXBQc1JueUtjN2JyRkQyTWpGTDlYRDdyT09TbXczeHNTCm05MHY0UHc1d3IzcHQzOFhPWko3WThyRXpBUUJlRUJ3ZWI0WGloOUJoS1dVTHl6SkpiZUJ1RWpSbXRuWmxDR1QKUGU4TzVUSnZwM1FBaS9pY0dpZkVkZHF5YnNHMmJjUDgzV3RGbnNnYkFvR0FMOHF4VUx3bGlMck1ML3c3aEJNegpXSHdKM21PK0NXbzFWR3p4bi9lK3I2ejVTUW03M0VuYzlSZnVkN3RBWmU1QUhXYXVSR3RNaVNoY0J1bkl5Q0g1CnU2Q2laZU5UOTBRdElLRmVCS09QSk5WNDR1QzJtK0xKQkNGa0hzU085MHp0dHZzcmVyU0tiNG5oZ2tiZDhxQ24KbDVFZFBpZEx2NXdiY0tyc3dIVzZYSm89Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=') +# Load key +ssl_key = PrivKey(key) + +# Load TLS session +r1 = TLS(chello_extms) +r1.tls_session.server_rsa_key = ssl_key +r2 = TLS(shello_extms, tls_session=r1.tls_session.mirror()) +r3 = TLS(finished_extms, tls_session=r2.tls_session.mirror()) + +r3 + +assert r3.tls_session.extms +assert r3.tls_session.session_hash == b'\n\x8b\xe0\x08S\xb9f|\xd4\x1f\xc5\x8f\xdb\xfaj\xc6\xb4Aj\\j~B)Ep\x07\x90\xc6/\x18\x1e\x99\x1e\x8d.\xe2,B\xe1\x10ZJ\x10^\xect(' + +l3 = r3.getlayer(TLS, 3) +assert isinstance(l3.msg[0], TLSFinished) +assert l3.msg[0][TLSFinished].vdata == b'\x00\x1fG\xd8VD@\x0ctK\xeee' + ### ### Other/bug tests ### From d5451c0184013bd6bf525af0c985fe1a206f81a5 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Mon, 14 Sep 2020 17:43:55 +0000 Subject: [PATCH 2/2] Use Hash from PRF for TLS 1.2 --- scapy/layers/tls/crypto/prf.py | 7 +++---- scapy/layers/tls/handshake.py | 8 ++++++-- test/tls.uts | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/scapy/layers/tls/crypto/prf.py b/scapy/layers/tls/crypto/prf.py index 5d1b39b6f8d..210f9108c09 100644 --- a/scapy/layers/tls/crypto/prf.py +++ b/scapy/layers/tls/crypto/prf.py @@ -203,6 +203,8 @@ def __init__(self, hash_name="SHA256", tls_version=0x0303): elif hash_name == "SHA512": self.prf = _tls12_SHA512PRF else: + if hash_name in ["MD5", "SHA"]: + self.hash_name = "SHA256" self.prf = _tls12_SHA256PRF else: warning("Unknown TLS version") @@ -293,10 +295,7 @@ def compute_verify_data(self, con_end, read_or_write, s2 = _tls_hash_algs["SHA"]().digest(handshake_msg) verify_data = self.prf(master_secret, label, s1 + s2, 12) else: - if self.hash_name in ["MD5", "SHA"]: - h = _tls_hash_algs["SHA256"]() - else: - h = _tls_hash_algs[self.hash_name]() + h = _tls_hash_algs[self.hash_name]() s = h.digest(handshake_msg) verify_data = self.prf(master_secret, label, s, 12) diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py index 61d4a9f843a..65458e9e53c 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -1313,9 +1313,13 @@ def tls_session_update(self, msg_str): if self.tls_session.extms: to_hash = b''.join(self.tls_session.handshake_messages) + # https://tools.ietf.org/html/rfc7627#section-3 if self.tls_session.tls_version >= 0x303: - # TLS 1.2 uses the default hash from cipher suite - hash_object = self.tls_session.pwcs.hash + # TLS 1.2 uses the same Hash as the PRF + from scapy.layers.tls.crypto.hash import _tls_hash_algs + hash_object = _tls_hash_algs.get( + self.tls_session.prcs.prf.hash_name + )() self.tls_session.session_hash = hash_object.digest(to_hash) else: # Previous TLS version use concatenation of MD5 & SHA1 diff --git a/test/tls.uts b/test/tls.uts index 32c40d0a766..40e80840392 100644 --- a/test/tls.uts +++ b/test/tls.uts @@ -1010,6 +1010,26 @@ l3 = r3.getlayer(TLS, 3) assert isinstance(l3.msg[0], TLSFinished) assert l3.msg[0][TLSFinished].vdata == b'\x00\x1fG\xd8VD@\x0ctK\xeee' +# RC4 case + +chello_extms = hex_bytes(b'160301008501000081030360037703ac90bb5e29ae0fca71b68dd8133b17b7060c13779d34f69d5c3255110000060005000400ff01000052337400000010000e000c02683208687474702f312e310016000000170000000d0030002e040305030603080708080809080a080b080408050806040105010601030302030301020103020202040205020602') +shello_extms = hex_bytes(b'1603030055020000510303c985430a03add71566a952a16249e471cd3226c0792ba42c444f574e4752440120e835d66cd3293b9fcb157d5c477848d654a2d3a42fc92bcf9c472171188f69610005000009ff0100010000170000160303036e0b00036a0003670003643082036030820248a003020102020900eb73b71c3e2f9fdc300d06092a864886f70d01010b05003045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464301e170d3139303231353135313430335a170d3239303231323135313430335a3045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c746430820122300d06092a864886f70d01010105000382010f003082010a0282010100d2f7d36b233a5619368fc3a7db0f2364dc71986dd4eebcbee85b783e139cfeb0a80de50147c936aa84230e2fa2eb91ef1737410387b932440ac7cfda3c5966eef88f688bcbee6a5d0dfaa075b77dfe836f2cb318375ff5be2b35f6d62dd7c4b147224f67d53d95c7fcc11cda7bc622369b4d4a685655169fb28f66e511724f0c9af2f74ea4cdf09b92f917246a582f67fade3eff7eca2c794d713c13f80cd53f847aa196d0adc04494790a628e327f4b53d05b83025c3ea541195f953ce6fc37edcc68a8fd6eca621f38bc08bc2d8d72cfcdf85c68f9f4f4485b32133c63299f85ffd62bde5a9d585e5a896f08319448277f19e86d5d6878bc53768b2ef9b3210203010001a3533051301d0603551d0e041604148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35301f0603551d230418301680148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101003c001f0f5d106072e0beedfa47895329d4623422080e66caa4beb4c3d9b6868fa107467d6160e512ede7cbbefdeb17c09b9f594f86f1a9922c982ccf9655d4d67eda061f667eeb25fe7203bea00e40f150a490a78ca963d87c185ade8b7c294f5052fb1e1edb3403831e33e4026c8e56717cb77bc32321858be37a77fe7f5511ef8c2013c86e2730c5b2366875131cae0c7616fdc7c8605696133e7a685f20203c0db8e0ff1d1a5991d2f058f48f20b10a5fb0df27a1f9874cc0fe8d6ebf77e9a7ba38490e9d63241a0fb3fd7701ff3b130c9aa7aa77770280b7003c1bb5e0784c34aacb74ce8114960e50eee04602a7ab20e5c878028e4292e90e40fd631fee16030300040e000000') +finished_extms = hex_bytes(b'16030301061000010201004971b89ae4355a001c49ccb49ed0664a9090a2dc0c14c97563b6dd98f13004ac5327c97abf10617b1f5d19b1f6e1091ccf159693497ebda262aedba2f3b76ae217d56477cad45e2ea129c324083701c2e99e65b6d63f916f963de8d98c5357d22272c032a30acccd673d1556d01e22e206186bcda3a5845d6dacee260ab66f47ea86a4c0081faa082b398f2c65da35264428f320c354b97cd96c986da43c8510e914ffb7f8bb73baee2530c4533ae2d6a922771af689c15b42c53428978510a3e3e90a3806f77fc1cb35c2c3f34dd7e3f831a79bc59b333f0c9e8be49390cd2a8e1c88dafbb9e3e24d1e0530703dbff7cd1c516fcc21a7d484f2111f985f03f8140303000101160303002457ed5c62171e4720a5890cf9ef09323f6e2db063aeebea776a54b879ffb6a69182d15cae') + +# Load TLS session +r1 = TLS(chello_extms) +r1.tls_session.server_rsa_key = ssl_key +r2 = TLS(shello_extms, tls_session=r1.tls_session.mirror()) +r3 = TLS(finished_extms, tls_session=r2.tls_session.mirror()) + +assert r3.tls_session.extms +assert r3.tls_session.pwcs.prf.hash_name == "SHA256" +assert r3.tls_session.session_hash == b'2\xdc\xf5\xcb\xbc\x99\xc6IV\xba\x0f.\x0bdq\x1f=\xef\xdaW\xfc*A\x9b\xe2?b\xccKW\xe9\xb7' + +l3 = r3.getlayer(TLS, 3) +assert isinstance(l3.msg[0], TLSFinished) +assert l3.msg[0][TLSFinished].vdata == b'\x15\xd6\xd5\xea\x84\xee\xb3\xdd\xd6\x10\xd8\x11' + ### ### Other/bug tests ###