diff --git a/scapy/layers/tls/crypto/prf.py b/scapy/layers/tls/crypto/prf.py index caa708ae2c7..ebc90b44c5d 100644 --- a/scapy/layers/tls/crypto/prf.py +++ b/scapy/layers/tls/crypto/prf.py @@ -207,18 +207,25 @@ def __init__(self, hash_name="SHA256", tls_version=0x0303): warning("Unknown TLS version") def compute_master_secret(self, pre_master_secret, - client_random, server_random): + 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 4c49524d2bc..a03bbaab73c 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -29,7 +29,8 @@ from scapy.layers.tls.basefields import (_tls_version, _TLSVersionField, _TLSClientVersionField) from scapy.layers.tls.extensions import (_ExtensionsLenField, _ExtensionsField, - _cert_status_type, TLS_Ext_SupportedVersions) # noqa: E501 + _cert_status_type, TLS_Ext_SupportedVersions, + TLS_Ext_ExtendedMasterSecret) # noqa: E501 from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField, _TLSSignatureField, ServerRSAParams, SigAndHashAlgsField, _tls_hash_sig, @@ -86,6 +87,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) @@ -370,6 +372,13 @@ def tls_session_update(self, msg_str): self.random_bytes) self.tls_session.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 @@ -962,6 +971,22 @@ 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 + """ + + self.tls_session.handshake_messages.append(msg_str) + self.tls_session.handshake_messages_parsed.append(self) + + if self.tls_session.extms: + hash_object = self.tls_session.pwcs.hash + to_hash = b''.join(self.tls_session.handshake_messages) + self.tls_session.session_hash = hash_object.digest(to_hash) + + + + ############################################################################### # Finished # diff --git a/scapy/layers/tls/session.py b/scapy/layers/tls/session.py index 8155946875c..ed4189a1356 100644 --- a/scapy/layers/tls/session.py +++ b/scapy/layers/tls/session.py @@ -449,6 +449,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 = [] @@ -522,10 +526,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))