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 49a47166352..d5a9ee7e358 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -34,7 +34,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, @@ -96,6 +97,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) @@ -447,6 +449,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 @@ -1184,6 +1193,19 @@ 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 24b2d111b8a..386e3428737 100644 --- a/scapy/layers/tls/session.py +++ b/scapy/layers/tls/session.py @@ -445,6 +445,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 = [] @@ -518,10 +522,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))