diff --git a/scapy/layers/inet.py b/scapy/layers/inet.py index aa5d0b41cea..a7f93c50768 100644 --- a/scapy/layers/inet.py +++ b/scapy/layers/inet.py @@ -466,7 +466,9 @@ class IP(Packet, IPTools): # IPField("src", "127.0.0.1"), Emph(SourceIPField("src", "dst")), Emph(DestIPField("dst", "127.0.0.1")), - PacketListField("options", [], IPOption, length_from=lambda p:p.ihl * 4 - 20)] # noqa: E501 + PacketListField("options", [], IPOption, length_from=( + lambda p: max(0, p.ihl * 4 - 20))) + ] def post_build(self, p, pay): ihl = self.ihl diff --git a/scapy/layers/tls/automaton_cli.py b/scapy/layers/tls/automaton_cli.py index 765ee5e3bd9..aec329a9c4f 100644 --- a/scapy/layers/tls/automaton_cli.py +++ b/scapy/layers/tls/automaton_cli.py @@ -31,7 +31,7 @@ from scapy.layers.tls.handshake import TLSCertificate, TLSCertificateRequest, \ TLSCertificateVerify, TLSClientHello, TLSClientKeyExchange, \ TLSEncryptedExtensions, TLSFinished, TLSServerHello, TLSServerHelloDone, \ - TLSServerKeyExchange, TLS13Certificate, TLS13ServerHello + TLSServerKeyExchange, TLS13Certificate from scapy.layers.tls.handshake_sslv2 import SSLv2ClientHello, \ SSLv2ServerHello, SSLv2ClientMasterKey, SSLv2ServerVerify, \ SSLv2ClientFinished, SSLv2ServerFinished, SSLv2ClientCertificate, \ @@ -856,7 +856,7 @@ def TLS13_WAITING_SERVERHELLO(self): @ATMT.condition(TLS13_WAITING_SERVERHELLO) def tls13_should_handle_ServerHello(self): - self.raise_on_packet(TLS13ServerHello, + self.raise_on_packet(TLSServerHello, self.TLS13_WAITING_ENCRYPTEDEXTENSIONS) @ATMT.state() diff --git a/scapy/layers/tls/basefields.py b/scapy/layers/tls/basefields.py index 752b562ec1f..2428c32012b 100644 --- a/scapy/layers/tls/basefields.py +++ b/scapy/layers/tls/basefields.py @@ -72,27 +72,27 @@ def i2m(self, pkt, x): class _TLSVersionField(ShortEnumField): """ We use the tls_version if it has been defined, else the advertised version. - Also, the legacy 0x0301 is used for TLS 1.3 packets. + Also, the legacy 0x0303 is used for TLS 1.3 packets. """ def i2h(self, pkt, x): if x is None: v = pkt.tls_session.tls_version if v: - return _tls13_version_filter(v, 0x0301) + return _tls13_version_filter(v, 0x0303) else: adv_v = pkt.tls_session.advertised_tls_version - return _tls13_version_filter(adv_v, 0x0301) + return _tls13_version_filter(adv_v, 0x0303) return x def i2m(self, pkt, x): if x is None: v = pkt.tls_session.tls_version if v: - return _tls13_version_filter(v, 0x0301) + return _tls13_version_filter(v, 0x0303) else: adv_v = pkt.tls_session.advertised_tls_version - return _tls13_version_filter(adv_v, 0x0301) + return _tls13_version_filter(adv_v, 0x0303) return x diff --git a/scapy/layers/tls/crypto/cipher_aead.py b/scapy/layers/tls/crypto/cipher_aead.py index 99b77712e0c..87b3c566ce1 100644 --- a/scapy/layers/tls/crypto/cipher_aead.py +++ b/scapy/layers/tls/crypto/cipher_aead.py @@ -206,7 +206,7 @@ def auth_decrypt(self, A, C, seq_num=None, add_length=True): P = self._cipher.decrypt(self._get_nonce(), C + mac, A) except InvalidTag: raise AEADTagError(nonce_explicit_str, - "", + b"", mac) return nonce_explicit_str, P, mac @@ -340,9 +340,10 @@ def auth_decrypt(self, A, C, seq_num): responsibility to catch it if deemed useful. If we lack the key, we raise a CipherError which contains the encrypted input. """ + C, mac = C[:-self.tag_len], C[-self.tag_len:] if False in six.itervalues(self.ready): - raise CipherError(C, mac) + raise CipherError(b"", C, mac) if hasattr(self, "pc_cls"): self._cipher.mode._initialization_vector = self._get_nonce(seq_num) @@ -353,7 +354,7 @@ def auth_decrypt(self, A, C, seq_num): try: decryptor.finalize() except InvalidTag: - raise AEADTagError(P, mac) + raise AEADTagError(b"", P, mac) else: try: if (conf.crypto_valid_advanced and @@ -366,8 +367,8 @@ def auth_decrypt(self, A, C, seq_num): A += struct.pack("!H", len(C)) P = self._cipher.decrypt(self._get_nonce(seq_num), C + mac, A) # noqa: E501 except InvalidTag: - raise AEADTagError("", mac) - return P, mac + raise AEADTagError(b"", b"", mac) + return b"", P, mac def snapshot(self): c = self.__class__(self.key, self.fixed_iv) @@ -400,8 +401,8 @@ class Cipher_AES_128_GCM_TLS13(_AEADCipher_TLS13): pc_cls = algorithms.AES pc_cls_mode = modes.GCM key_len = 16 - fixed_iv_len = 12 tag_len = 16 + fixed_iv_len = 12 class Cipher_AES_256_GCM_TLS13(Cipher_AES_128_GCM_TLS13): key_len = 32 diff --git a/scapy/layers/tls/crypto/prf.py b/scapy/layers/tls/crypto/prf.py index 5f7692ded6b..6c95f5329af 100644 --- a/scapy/layers/tls/crypto/prf.py +++ b/scapy/layers/tls/crypto/prf.py @@ -208,18 +208,26 @@ 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/extensions.py b/scapy/layers/tls/extensions.py index ffec02aa1ea..def312a8cf2 100644 --- a/scapy/layers/tls/extensions.py +++ b/scapy/layers/tls/extensions.py @@ -12,7 +12,7 @@ from scapy.fields import ByteEnumField, ByteField, EnumField, FieldLenField, \ FieldListField, IntField, PacketField, PacketListField, ShortEnumField, \ - ShortField, StrFixedLenField, StrLenField, XStrLenField + ShortField, StrFixedLenField, StrLenField, XStrLenField, ConditionalField from scapy.packet import Packet, Raw, Padding from scapy.layers.x509 import X509_Extensions from scapy.layers.tls.basefields import _tls_version @@ -46,7 +46,6 @@ 0x16: "encrypt_then_mac", # RFC 7366 0x17: "extended_master_secret", # RFC 7627 0x23: "session_ticket", # RFC 5077 - 0x28: "key_share", 0x29: "pre_shared_key", 0x2a: "early_data", 0x2b: "supported_versions", @@ -55,6 +54,8 @@ 0x2e: "ticket_early_data_info", 0x2f: "certificate_authorities", 0x30: "oid_filters", + 0x32: "signature_algorithms_cert", + 0x33: "key_share", 0x3374: "next_protocol_negotiation", # RFC-draft-agl-tls-nextprotoneg-03 0xff01: "renegotiation_info" # RFC 5746 @@ -496,13 +497,13 @@ class TLS_Ext_SessionTicket(TLS_Ext_Unknown): # RFC 5077 class TLS_Ext_KeyShare(TLS_Ext_Unknown): - name = "TLS Extension - Key Share (dummy class)" - fields_desc = [ShortEnumField("type", 0x28, _tls_ext), + name = "TLS Extension - Key Share (Unknown)" + fields_desc = [ShortEnumField("type", 0x33, _tls_ext), ShortField("len", None)] class TLS_Ext_PreSharedKey(TLS_Ext_Unknown): - name = "TLS Extension - Pre Shared Key (dummy class)" + name = "TLS Extension - Pre Shared Key (Unknown)" fields_desc = [ShortEnumField("type", 0x29, _tls_ext), ShortField("len", None)] @@ -517,12 +518,20 @@ class TLS_Ext_SupportedVersions(TLS_Ext_Unknown): name = "TLS Extension - Supported Versions" fields_desc = [ShortEnumField("type", 0x2b, _tls_ext), ShortField("len", None), - FieldLenField("versionslen", None, fmt='B', - length_of="versions"), + # Depending on whether the extension is from + # ServerHello or ClientHello, versionslen may + # or may not exist. + ConditionalField( + FieldLenField("versionslen", None, fmt='B', + length_of="versions"), + lambda x: x.len % 2), FieldListField("versions", [], ShortEnumField("version", None, _tls_version), - length_from=lambda pkt: pkt.versionslen)] + length_from=( + lambda pkt: pkt.versionslen if + pkt.len % 2 else pkt.len - (pkt.len % 2)) + )] class TLS_Ext_Cookie(TLS_Ext_Unknown): @@ -597,7 +606,6 @@ class TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown): # RFC 5746 0x16: TLS_Ext_EncryptThenMAC, 0x17: TLS_Ext_ExtendedMasterSecret, 0x23: TLS_Ext_SessionTicket, - 0x28: TLS_Ext_KeyShare, 0x29: TLS_Ext_PreSharedKey, 0x2a: TLS_Ext_EarlyData, 0x2b: TLS_Ext_SupportedVersions, @@ -605,6 +613,8 @@ class TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown): # RFC 5746 0x2d: TLS_Ext_PSKKeyExchangeModes, 0x2e: TLS_Ext_TicketEarlyDataInfo, # 0x2f: TLS_Ext_CertificateAuthorities, #XXX + # 0x32: TLS_Ext_SignatureAlgorithmsCert, #XXX + 0x33: TLS_Ext_KeyShare, # 0x30: TLS_Ext_OIDFilters, #XXX 0x3374: TLS_Ext_NPN, 0xff01: TLS_Ext_RenegotiationInfo @@ -653,9 +663,14 @@ def addfield(self, pkt, s, i): class _ExtensionsField(StrLenField): + __slots__ = ["msg_type"] islist = 1 holds_packets = 1 + def __init__(self, name, default, **kargs): + self.msg_type = kargs.pop("msg_type", lambda pkt: pkt.msgtype) + StrLenField.__init__(self, name, default, **kargs) + def i2len(self, pkt, i): if i is None: return 0 @@ -690,10 +705,10 @@ def m2i(self, pkt, m): cls = _tls_ext_cls.get(t, TLS_Ext_Unknown) if cls is TLS_Ext_KeyShare: from scapy.layers.tls.keyexchange_tls13 import _tls_ext_keyshare_cls # noqa: E501 - cls = _tls_ext_keyshare_cls.get(pkt.msgtype, TLS_Ext_Unknown) + cls = _tls_ext_keyshare_cls.get(self.msg_type(pkt), TLS_Ext_KeyShare) elif cls is TLS_Ext_PreSharedKey: from scapy.layers.tls.keyexchange_tls13 import _tls_ext_presharedkey_cls # noqa: E501 - cls = _tls_ext_presharedkey_cls.get(pkt.msgtype, TLS_Ext_Unknown) # noqa: E501 + cls = _tls_ext_presharedkey_cls.get(self.msg_type(pkt), TLS_Ext_PreSharedKey) # noqa: E501 res.append(cls(m[:tmp_len + 4], tls_session=pkt.tls_session)) m = m[tmp_len + 4:] return res diff --git a/scapy/layers/tls/handshake.py b/scapy/layers/tls/handshake.py index 79c0650e120..b7ecf9a1413 100644 --- a/scapy/layers/tls/handshake.py +++ b/scapy/layers/tls/handshake.py @@ -15,9 +15,10 @@ import struct from scapy.error import log_runtime, warning -from scapy.fields import ByteEnumField, ByteField, EnumField, Field, \ +from scapy.fields import ByteEnumField, ByteField, Field, \ FieldLenField, IntField, PacketField, PacketListField, ShortField, \ - StrFixedLenField, StrLenField, ThreeBytesField, UTCTimeField + StrFixedLenField, StrLenField, ThreeBytesField, UTCTimeField, \ + ShortEnumField from scapy.compat import bytes_hex, orb, raw from scapy.config import conf @@ -29,7 +30,9 @@ 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) from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField, _TLSSignatureField, ServerRSAParams, SigAndHashAlgsField, _tls_hash_sig, @@ -86,6 +89,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) @@ -134,7 +138,10 @@ class _SessionIDField(StrLenField): """ opaque SessionID<0..32>; section 7.4.1.2 of RFC 4346 """ - pass + def i2repr(self, pkt, x): + if x is None: + return repr(x) + return repr_hex(self.i2h(pkt, x)) class _CipherSuitesField(StrLenField): @@ -292,16 +299,26 @@ def tls_session_update(self, msg_str): if self.ext: for e in self.ext: if isinstance(e, TLS_Ext_SupportedVersions): - if self.tls_session.tls13_early_secret is None: - # this is not recomputed if there was a TLS 1.3 HRR - self.tls_session.compute_tls13_early_secrets() - break + if 0x0304 in e.versions: + if self.tls_session.tls13_early_secret is None: + # this is not recomputed if there was a TLS 1.3 HRR + self.tls_session.compute_tls13_early_secrets() + break ############################################################################### # ServerHello # ############################################################################### +# https://tools.ietf.org/html/rfc8446#section-4.1.3 +_TLS_RetryRequestMagic = b'\xcf!\xadt\xe5\x9aa\x11\xbe\x1d\x8c\x02\x1ee' + \ + b'\xb8\x91\xc2\xa2\x11\x16z\xbb\x8c^\x07\x9e\t' + \ + b'\xe2\xc8\xa83\x9c' +# Tricky old trick (see the TODO in TLSServerHello) +_TLS_RetryRequestMagic_GMT = struct.unpack("!I", _TLS_RetryRequestMagic[:4])[0] +_TLS_RetryRequestMagic_RDM = _TLS_RetryRequestMagic[4:] + + class TLSServerHello(TLSClientHello): """ TLS ServerHello, with abilities to handle extensions. @@ -318,14 +335,16 @@ class TLSServerHello(TLSClientHello): _TLSVersionField("version", None, _tls_version), # _TLSRandomBytesField("random_bytes", None, 32), - _GMTUnixTimeField("gmt_unix_time", None), - _TLSRandomBytesField("random_bytes", None, 28), + # TODO: improve those two (same in ClientHello), so that + # are only one single random_bytes when TLS 1.3 + _GMTUnixTimeField("gmt_unix_time", None), # XXX + _TLSRandomBytesField("random_bytes", None, 28), # XXX FieldLenField("sidlen", None, length_of="sid", fmt="B"), _SessionIDField("sid", "", length_from=lambda pkt: pkt.sidlen), - EnumField("cipher", None, _tls_cipher_suites), + ShortEnumField("cipher", None, _tls_cipher_suites), _CompressionMethodsField("comp", [0], _tls_compression_algs, itemfmt="B", @@ -335,17 +354,18 @@ class TLSServerHello(TLSClientHello): _ExtensionsField("ext", None, length_from=lambda pkt: (pkt.msglen - (pkt.sidlen or 0) - # noqa: E501 - 38))] + 38), + msg_type=( + lambda pkt: 6 if ( + pkt.gmt_unix_time == \ + _TLS_RetryRequestMagic_GMT and \ + pkt.random_bytes == \ + _TLS_RetryRequestMagic_RDM + ) else 2 + ) + )] # 40)) ] - @classmethod - def dispatch_hook(cls, _pkt=None, *args, **kargs): - if _pkt and len(_pkt) >= 6: - version = struct.unpack("!H", _pkt[4:6])[0] - if version == 0x0304 or version > 0x7f00: - return TLS13ServerHello - return TLSServerHello - def post_build(self, p, pay): if self.random_bytes is None: p = p[:10] + randstring(28) + p[10 + 28:] @@ -363,67 +383,31 @@ def tls_session_update(self, msg_str): """ super(TLSClientHello, self).tls_session_update(msg_str) - self.tls_session.tls_version = self.version - self.random_bytes = msg_str[10:38] - self.tls_session.server_random = (struct.pack('!I', - self.gmt_unix_time) + - self.random_bytes) - self.tls_session.sid = self.sid - - cs_cls = None - if self.cipher: - cs_val = self.cipher - if cs_val not in _tls_cipher_suites_cls: - warning("Unknown cipher suite %d from ServerHello" % cs_val) - # we do not try to set a default nor stop the execution - else: - cs_cls = _tls_cipher_suites_cls[cs_val] - - comp_cls = Comp_NULL - if self.comp: - comp_val = self.comp[0] - if comp_val not in _tls_compression_algs_cls: - err = "Unknown compression alg %d from ServerHello" % comp_val - warning(err) - comp_val = 0 - comp_cls = _tls_compression_algs_cls[comp_val] + s = self.tls_session + s.tls_version = self.version + s.server_random = (struct.pack('!I', + self.gmt_unix_time) + + self.random_bytes) - connection_end = self.tls_session.connection_end - self.tls_session.pwcs = writeConnState(ciphersuite=cs_cls, - compression_alg=comp_cls, - connection_end=connection_end, - tls_version=self.version) - self.tls_session.prcs = readConnState(ciphersuite=cs_cls, - compression_alg=comp_cls, - connection_end=connection_end, - tls_version=self.version) - - -class TLS13ServerHello(TLSClientHello): - """ TLS 1.3 ServerHello """ - name = "TLS 1.3 Handshake - Server Hello" - fields_desc = [ByteEnumField("msgtype", 2, _tls_handshake_type), - ThreeBytesField("msglen", None), - _TLSVersionField("version", None, _tls_version), - _TLSRandomBytesField("random_bytes", None, 32), - EnumField("cipher", None, _tls_cipher_suites), - _ExtensionsLenField("extlen", None, length_of="ext"), - _ExtensionsField("ext", None, - length_from=lambda pkt: (pkt.msglen - - 38))] + # EXT process + if self.ext: + for e in self.ext: + if isinstance(e, TLS_Ext_ExtendedMasterSecret): + s.extms = True + continue + if isinstance(e, TLS_Ext_SupportedVersions): + if 0x0304 in e.versions: + s.tls_version = 0x0304 + self.name = "TLS 1.3 Handshake - Server Hello" + continue - def tls_session_update(self, msg_str): - """ - Either for parsing or building, we store the server_random along with - the raw string representing this handshake message. We also store the - cipher suite (if recognized), and finally we instantiate the write and - read connection states. - """ - super(TLSClientHello, self).tls_session_update(msg_str) + is_tls13 = s.tls_version >= 0x0304 + if is_tls13 and s.server_random == _TLS_RetryRequestMagic: + self.name = "TLS 1.3 Handshake - Hello Retry Request" + # This isn't a real ServerHello. Don't process further + return - s = self.tls_session - s.tls_version = self.version - s.server_random = self.random_bytes + s.sid = self.sid cs_cls = None if self.cipher: @@ -435,34 +419,40 @@ def tls_session_update(self, msg_str): cs_cls = _tls_cipher_suites_cls[cs_val] connection_end = s.connection_end - s.pwcs = writeConnState(ciphersuite=cs_cls, - connection_end=connection_end, - tls_version=self.version) - s.triggered_pwcs_commit = True - s.prcs = readConnState(ciphersuite=cs_cls, - connection_end=connection_end, - tls_version=self.version) - s.triggered_prcs_commit = True - - if self.tls_session.tls13_early_secret is None: - # In case the connState was not pre-initialized, we could not - # compute the early secrets at the ClientHello, so we do it here. - self.tls_session.compute_tls13_early_secrets() - s.compute_tls13_handshake_secrets() - - -############################################################################### -# HelloRetryRequest # -############################################################################### - -class TLSHelloRetryRequest(_TLSHandshake): - name = "TLS 1.3 Handshake - Hello Retry Request" - fields_desc = [ByteEnumField("msgtype", 6, _tls_handshake_type), - ThreeBytesField("msglen", None), - _TLSVersionField("version", None, _tls_version), - _ExtensionsLenField("extlen", None, length_of="ext"), - _ExtensionsField("ext", None, - length_from=lambda pkt: pkt.msglen - 4)] + if is_tls13: # TLS 1.3 + # comp is ignored in TLS 1.3 + s.pwcs = writeConnState(ciphersuite=cs_cls, + connection_end=connection_end, + tls_version=s.tls_version) + s.triggered_pwcs_commit = True + s.prcs = readConnState(ciphersuite=cs_cls, + connection_end=connection_end, + tls_version=s.tls_version) + s.triggered_prcs_commit = True + if self.tls_session.tls13_early_secret is None: + # In case the connState was not pre-initialized, we could not + # compute the early secrets at the ClientHello, so we do it + # here. + self.tls_session.compute_tls13_early_secrets() + s.compute_tls13_handshake_secrets() + else: # TLS 1.2 + comp_cls = Comp_NULL + if self.comp: + comp_val = self.comp[0] + if comp_val not in _tls_compression_algs_cls: + err = ("Unknown compression alg %d from" + + "ServerHello" % comp_val) + warning(err) + comp_val = 0 + comp_cls = _tls_compression_algs_cls[comp_val] + s.pwcs = writeConnState(ciphersuite=cs_cls, + compression_alg=comp_cls, + connection_end=connection_end, + tls_version=s.tls_version) + s.prcs = readConnState(ciphersuite=cs_cls, + compression_alg=comp_cls, + connection_end=connection_end, + tls_version=s.tls_version) ############################################################################### @@ -835,7 +825,7 @@ class TLSCertificateRequest(_TLSHandshake): SigAndHashAlgsLenField("sig_algs_len", None, length_of="sig_algs"), SigAndHashAlgsField("sig_algs", [0x0403, 0x0401, 0x0201], - EnumField("hash_sig", None, _tls_hash_sig), # noqa: E501 + ByteEnumField("hash_sig", None, _tls_hash_sig), # noqa: E501 length_from=lambda pkt: pkt.sig_algs_len), # noqa: E501 FieldLenField("certauthlen", None, fmt="!H", length_of="certauth"), @@ -964,6 +954,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 # @@ -1254,7 +1257,7 @@ def post_dissection_tls_session_update(self, msg_str): _tls_handshake_cls = {0: TLSHelloRequest, 1: TLSClientHello, 2: TLSServerHello, 3: TLSHelloVerifyRequest, - 4: TLSNewSessionTicket, 6: TLSHelloRetryRequest, + 4: TLSNewSessionTicket, 8: TLSEncryptedExtensions, 11: TLSCertificate, 12: TLSServerKeyExchange, 13: TLSCertificateRequest, 14: TLSServerHelloDone, 15: TLSCertificateVerify, diff --git a/scapy/layers/tls/keyexchange.py b/scapy/layers/tls/keyexchange.py index 836008e44cc..fb0ac04e3ad 100644 --- a/scapy/layers/tls/keyexchange.py +++ b/scapy/layers/tls/keyexchange.py @@ -614,8 +614,8 @@ def register_pubkey(self): curve_name = _tls_named_curves[self.named_curve] curve = ec._CURVE_TYPES[curve_name]() - import_point = ec.EllipticCurvePublicNumbers.from_encoded_point - pubnum = import_point(curve, self.point) + import_point = ec.EllipticCurvePublicKey.from_encoded_point + pubnum = import_point(curve, self.point).public_numbers() s = self.tls_session s.server_kx_pubkey = pubnum.public_key(default_backend()) @@ -833,8 +833,9 @@ def post_dissection(self, m): # if there are kx params and keys, we assume the crypto library is ok if s.client_kx_ecdh_params: - import_point = ec.EllipticCurvePublicNumbers.from_encoded_point - pub_num = import_point(s.client_kx_ecdh_params, self.ecdh_Yc) + import_point = ec.EllipticCurvePublicKey.from_encoded_point + pub_key = import_point(s.client_kx_ecdh_params, self.ecdh_Yc) + pub_num = pub_key.public_numbers() s.client_kx_pubkey = pub_num.public_key(default_backend()) if s.server_kx_privkey and s.client_kx_pubkey: diff --git a/scapy/layers/tls/keyexchange_tls13.py b/scapy/layers/tls/keyexchange_tls13.py index 951dbeb0090..934da5c6cfd 100644 --- a/scapy/layers/tls/keyexchange_tls13.py +++ b/scapy/layers/tls/keyexchange_tls13.py @@ -119,8 +119,9 @@ def register_pubkey(self): self.pubkey = import_point(self.key_exchange) elif _tls_named_curves[self.group] != "x448": curve = ec._CURVE_TYPES[_tls_named_curves[self.group]]() - import_point = ec.EllipticCurvePublicNumbers.from_encoded_point - public_numbers = import_point(curve, self.key_exchange) + import_point = ec.EllipticCurvePublicKey.from_encoded_point + public_key = import_point(curve, self.key_exchange) + public_numbers = public_key.public_numbers() self.pubkey = public_numbers.public_key(default_backend()) def post_dissection(self, r): @@ -135,7 +136,7 @@ def extract_padding(self, s): class TLS_Ext_KeyShare_CH(TLS_Ext_Unknown): name = "TLS Extension - Key Share (for ClientHello)" - fields_desc = [ShortEnumField("type", 0x28, _tls_ext), + fields_desc = [ShortEnumField("type", 0x33, _tls_ext), ShortField("len", None), FieldLenField("client_shares_len", None, length_of="client_shares"), @@ -169,14 +170,14 @@ def post_dissection(self, r): class TLS_Ext_KeyShare_HRR(TLS_Ext_Unknown): name = "TLS Extension - Key Share (for HelloRetryRequest)" - fields_desc = [ShortEnumField("type", 0x28, _tls_ext), + fields_desc = [ShortEnumField("type", 0x33, _tls_ext), ShortField("len", None), ShortEnumField("selected_group", None, _tls_named_groups)] class TLS_Ext_KeyShare_SH(TLS_Ext_Unknown): name = "TLS Extension - Key Share (for ServerHello)" - fields_desc = [ShortEnumField("type", 0x28, _tls_ext), + fields_desc = [ShortEnumField("type", 0x33, _tls_ext), ShortField("len", None), PacketField("server_share", None, KeyShareEntry)] @@ -275,7 +276,7 @@ class PSKBinderEntry(Packet): class TLS_Ext_PreSharedKey_CH(TLS_Ext_Unknown): # XXX define post_build and post_dissection methods name = "TLS Extension - Pre Shared Key (for ClientHello)" - fields_desc = [ShortEnumField("type", 0x28, _tls_ext), + fields_desc = [ShortEnumField("type", 0x33, _tls_ext), ShortField("len", None), FieldLenField("identities_len", None, length_of="identities"), diff --git a/scapy/layers/tls/record.py b/scapy/layers/tls/record.py index 9a4925900b9..b9f57086537 100644 --- a/scapy/layers/tls/record.py +++ b/scapy/layers/tls/record.py @@ -23,7 +23,7 @@ from scapy.layers.inet import TCP from scapy.layers.tls.session import _GenericTLSSessionInheritance from scapy.layers.tls.handshake import (_tls_handshake_cls, _TLSHandshake, - TLS13ServerHello) + TLSServerHello) from scapy.layers.tls.basefields import (_TLSVersionField, _tls_version, _TLSIVField, _TLSMACField, _TLSPadField, _TLSPadLenField, @@ -34,8 +34,6 @@ from scapy.layers.tls.crypto.common import CipherError from scapy.layers.tls.crypto.h_mac import HMACError import scapy.modules.six as six -if conf.crypto_valid_advanced: - from scapy.layers.tls.crypto.cipher_aead import Cipher_CHACHA20_POLY1305 # Util @@ -195,7 +193,7 @@ def addfield(self, pkt, s, val): res += self.i2m(pkt, p) if (isinstance(pkt, _GenericTLSSessionInheritance) and _tls_version_check(pkt.tls_session.tls_version, 0x0304) and - not isinstance(pkt, TLS13ServerHello)): + not isinstance(pkt, TLSServerHello)): return s + res if not pkt.type: pkt.type = 0 @@ -282,14 +280,16 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs): responsible for low-minded extensibility choices. """ if _pkt and len(_pkt) >= 2: - byte0 = orb(_pkt[0]) - byte1 = orb(_pkt[1]) - if (byte0 not in _tls_type) or (byte1 != 3): + type_ = orb(_pkt[0]) + version_ = orb(_pkt[1]) + s = kargs.get("tls_session", None) + if (type_ not in _tls_type) or (version_ != 3): from scapy.layers.tls.record_sslv2 import SSLv2 return SSLv2 - else: - s = kargs.get("tls_session", None) - if s and _tls_version_check(s.tls_version, 0x0304): + elif s and _tls_version_check(s.tls_version, 0x0304): + # "The outer opaque_type field of a TLSCiphertext record + # is always set to the value 23" + if type_ == 23: if s.rcs and not isinstance(s.rcs.cipher, Cipher_NULL): from scapy.layers.tls.record_tls13 import TLS13 return TLS13 @@ -389,6 +389,7 @@ def pre_dissect(self, s): raise Exception("Invalid record: header is too short.") msglen = struct.unpack('!H', s[3:5])[0] + hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:] iv = mac = pad = b"" @@ -475,12 +476,7 @@ def pre_dissect(self, s): elif cipher_type == 'aead': # Authenticated encryption # crypto/cipher_aead.py prints a warning for integrity failure - if (conf.crypto_valid_advanced and - isinstance(self.tls_session.rcs.cipher, Cipher_CHACHA20_POLY1305)): # noqa: E501 - iv = b"" - cfrag, mac = self._tls_auth_decrypt(hdr, efrag) - else: - iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag) + iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag) decryption_success = True # see XXX above frag = self._tls_decompress(cfrag) diff --git a/scapy/layers/tls/record_tls13.py b/scapy/layers/tls/record_tls13.py index 30e770e7d10..db89233a5cc 100644 --- a/scapy/layers/tls/record_tls13.py +++ b/scapy/layers/tls/record_tls13.py @@ -90,7 +90,7 @@ class TLS13(_GenericTLSSessionInheritance): __slots__ = ["deciphered_len"] name = "TLS 1.3" fields_desc = [ByteEnumField("type", 0x17, _tls_type), - _TLSVersionField("version", 0x0301, _tls_version), + _TLSVersionField("version", 0x0303, _tls_version), _TLSLengthField("len", None), _TLSInnerPlaintextField("inner", TLSInnerPlaintext()), _TLSMACField("auth_tag", None)] @@ -118,7 +118,10 @@ def _tls_auth_decrypt(self, s): return e.args except AEADTagError as e: pkt_info = self.firstlayer().summary() - log_runtime.info("TLS: record integrity check failed [%s]", pkt_info) # noqa: E501 + raise + log_runtime.info( + "TLS13: record integrity check failed [%s]", pkt_info + ) return e.args def pre_dissect(self, s): @@ -134,7 +137,7 @@ def pre_dissect(self, s): else: msglen = struct.unpack('!H', s[3:5])[0] hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:] - frag, auth_tag = self._tls_auth_decrypt(efrag) + _, frag, auth_tag = self._tls_auth_decrypt(efrag) self.deciphered_len = len(frag) return hdr + frag + auth_tag + r diff --git a/scapy/layers/tls/session.py b/scapy/layers/tls/session.py index 97a1c7efd98..d70e0355448 100644 --- a/scapy/layers/tls/session.py +++ b/scapy/layers/tls/session.py @@ -448,6 +448,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 = [] @@ -521,10 +525,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)) @@ -580,8 +588,8 @@ def compute_tls13_early_secrets(self): self.tls13_psk_secret) bk = hkdf.derive_secret(self.tls13_early_secret, - b"external psk binder key", - # "resumption psk binder key", + b"ext binder", + # "res binder", b"") self.tls13_derived_secrets["binder_key"] = bk @@ -590,12 +598,12 @@ def compute_tls13_early_secrets(self): return cets = hkdf.derive_secret(self.tls13_early_secret, - b"client early traffic secret", + b"c e traffic", b"".join(self.handshake_messages)) self.tls13_derived_secrets["client_early_traffic_secret"] = cets ees = hkdf.derive_secret(self.tls13_early_secret, - b"early exporter master secret", + b"e exp master", b"".join(self.handshake_messages)) self.tls13_derived_secrets["early_exporter_secret"] = ees @@ -618,12 +626,12 @@ def compute_tls13_handshake_secrets(self): self.tls13_dhe_secret) chts = hkdf.derive_secret(self.tls13_handshake_secret, - b"client handshake traffic secret", + b"c hs traffic", b"".join(self.handshake_messages)) self.tls13_derived_secrets["client_handshake_traffic_secret"] = chts shts = hkdf.derive_secret(self.tls13_handshake_secret, - b"server handshake traffic secret", + b"s hs traffic", b"".join(self.handshake_messages)) self.tls13_derived_secrets["server_handshake_traffic_secret"] = shts @@ -645,17 +653,17 @@ def compute_tls13_traffic_secrets(self): None) cts0 = hkdf.derive_secret(self.tls13_master_secret, - b"client application traffic secret", + b"c ap traffic", b"".join(self.handshake_messages)) self.tls13_derived_secrets["client_traffic_secrets"] = [cts0] sts0 = hkdf.derive_secret(self.tls13_master_secret, - b"server application traffic secret", + b"s ap traffic", b"".join(self.handshake_messages)) self.tls13_derived_secrets["server_traffic_secrets"] = [sts0] es = hkdf.derive_secret(self.tls13_master_secret, - b"exporter master secret", + b"exp master", b"".join(self.handshake_messages)) self.tls13_derived_secrets["exporter_secret"] = es @@ -705,7 +713,7 @@ def compute_tls13_resumption_secret(self): elif self.connection_end == "client": hkdf = self.pwcs.hkdf rs = hkdf.derive_secret(self.tls13_master_secret, - b"resumption master secret", + b"res master", b"".join(self.handshake_messages)) self.tls13_derived_secrets["resumption_secret"] = rs @@ -718,10 +726,10 @@ def compute_tls13_next_traffic_secrets(self): cts = self.tls13_derived_secrets["client_traffic_secrets"] ctsN = cts[-1] - ctsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl) + ctsN_1 = hkdf.expand_label(ctsN, "traffic upd", "", hl) cts.append(ctsN_1) - stsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl) + stsN_1 = hkdf.expand_label(ctsN, "traffic upd", "", hl) cts.append(stsN_1) if self.connection_end == "server": diff --git a/test/tls.uts b/test/tls.uts index e9a8c98d11f..149273865e7 100644 --- a/test/tls.uts +++ b/test/tls.uts @@ -713,7 +713,7 @@ def _all_chacha20poly1305_tests(): ciphers = [] for t in [_chacha20poly1305_test_1]: c = Cipher_CHACHA20_POLY1305_TLS13(key=t.k, fixed_iv=t.n) - tmp1 = c.auth_decrypt(t.a, t.ct + t.tag, b"\0"*8) == (t.p, t.tag) + tmp1 = c.auth_decrypt(t.a, t.ct + t.tag, b"\0"*8) == (b"", t.p, t.tag) tmp2 = c.auth_encrypt(t.p, t.a, b"\0"*8) == t.ct + t.tag res = res and tmp1 and tmp2 return res diff --git a/test/tls13.uts b/test/tls13.uts index f8aa9b66190..8c7b58b2685 100644 --- a/test/tls13.uts +++ b/test/tls13.uts @@ -1,15 +1,18 @@ -% Tests for TLS 1.3 +% Read a TLS 1.3 session # # Try me with : # bash test/run_tests -t test/tls13.uts -F -+ Read a TLS 1.3 session # /!\ These tests will not catch our 'INTEGRITY CHECK FAILED's. /!\ # We deem the knowledge of the plaintext sufficient for passing... -= Reading TLS 1.3 test session (vectors 5 from draft-ietf-tls-tls13-vectors-00) -~ crypto +# https://tools.ietf.org/html/rfc8448#section-5 + ++ Init phase + += Load utils + import binascii from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateNumbers from cryptography.hazmat.backends import default_backend @@ -17,250 +20,332 @@ from cryptography.hazmat.backends import default_backend def clean(s): return binascii.unhexlify(''.join(c for c in s if c.isalnum())) ++ Reading TLS 1.3 test session (vectors 5 from rfc8448) +~ crypto + += Dissect ClientHello : The client initiates a handshake with an X25519 + clientHello1 = clean(""" - 16030100ae010000 aa0303d9e9898df6 - 3d43adbe64a2634f 0b63bcdc4019a3e5 26bc013a6042e05b - 14555c0000061301 130313020100007b 0000000b00090000 - 06736572766572ff 01000100000a0008 0006001d00170018 - 002800260024001d 002005efa94d13f5 adcd14219379d5a3 - 7dbce4721d9294e5 72c6651aeb761838 815b002b0003027f - 12000d0020001e04 0305030603020308 0408050806040105 - 0106010201040205 0206020202002d00 020101 + 16 03 01 00 b4 01 00 00 b0 03 03 b0 + b1 c5 a5 aa 37 c5 91 9f 2e d1 d5 c6 ff f7 fc b7 84 97 16 94 5a + 2b 8c ee 92 58 a3 46 67 7b 6f 00 00 06 13 01 13 03 13 02 01 00 + 00 81 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 + 00 00 0a 00 08 00 06 00 1d 00 17 00 18 00 33 00 26 00 24 00 1d + 00 20 e8 e8 e3 f3 b9 3a 25 ed 97 a1 4a 7d ca cb 8a 27 2c 62 88 + e5 85 c6 48 4d 05 26 2f ca d0 62 ad 1f 00 2b 00 03 02 03 04 00 + 0d 00 18 00 16 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 + 05 01 06 01 02 01 00 2d 00 02 01 01 00 1c 00 02 40 01 """) -t = TLS(clientHello1) +t1 = TLS(clientHello1) += Dissect ServerHello: The server however prefers P-256 [FIPS186] and sends a HelloRetryRequest + +# Note: The HelloRetryRequest uses the same handshake message type as +# a ServerHello and so is labeled as ServerHello here. helloRetryRequest = clean(""" - 160301000e060000 0a7f120006002800 020017 + 16 03 03 00 b0 02 00 00 ac 03 03 cf + 21 ad 74 e5 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a bb + 8c 5e 07 9e 09 e2 c8 a8 33 9c 00 13 01 00 00 84 00 33 00 02 00 + 17 00 2c 00 74 00 72 71 dc d0 4b b8 8b c3 18 91 19 39 8a 00 00 + 00 00 ee fa fc 76 c1 46 b8 23 b0 96 f8 aa ca d3 65 dd 00 30 95 + 3f 4e df 62 56 36 e5 f2 1b b2 e2 3f cc 65 4b 1b 5b 40 31 8d 10 + d1 37 ab cb b8 75 74 e3 6e 8a 1f 02 5f 7d fa 5d 6e 50 78 1b 5e + da 4a a1 5b 0c 8b e7 78 25 7d 16 aa 30 30 e9 e7 84 1d d9 e4 c0 + 34 22 67 e8 ca 0c af 57 1f b2 b7 cf f0 f9 34 b0 00 2b 00 02 03 + 04 """) -t = TLS(helloRetryRequest, tls_session=t.tls_session.mirror()) +t2 = TLS(helloRetryRequest, tls_session=t1.tls_session.mirror()) + += Dissect ClientHello again, this time using P-256 secp256r1_client_privkey = clean(""" - 11fa48d153c917ff d89dff13140760a1 - 36265d399fa9f10e 2d766d42a6c84e90 + ab 54 73 46 7e 19 34 6c eb 0a 04 14 e4 + 1d a2 1d 4d 24 45 bc 30 25 af e9 7c 4e 8d c8 d5 13 da 39 """) clientHello2 = clean(""" - 16030100cf010000 cb0303d9e9898df6 - 3d43adbe64a2634f 0b63bcdc4019a3e5 26bc013a6042e05b - 14555c0000061301 130313020100009c 0000000b00090000 - 06736572766572ff 01000100000a0008 0006001d00170018 - 0028004700450017 0041041e5a785f54 17fb18db42938435 - 34a5c0ba6e744baa 6846d0b32f4e9ea3 922724a08f2adb09 - f071f81402e7fd8c a33b76abe1cd556f d3e8fe20e0fd2e82 - 02f969002b000302 7f12000d0020001e 0403050306030203 - 0804080508060401 0501060102010402 050206020202002d 00020101 + 16 03 03 02 00 01 00 01 fc 03 03 b0 + b1 c5 a5 aa 37 c5 91 9f 2e d1 d5 c6 ff f7 fc b7 84 97 16 94 5a + 2b 8c ee 92 58 a3 46 67 7b 6f 00 00 06 13 01 13 03 13 02 01 00 + 01 cd 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 + 00 00 0a 00 08 00 06 00 1d 00 17 00 18 00 33 00 47 00 45 00 17 + 00 41 04 a6 da 73 92 ec 59 1e 17 ab fd 53 59 64 b9 98 94 d1 3b + ef b2 21 b3 de f2 eb e3 83 0e ac 8f 01 51 81 26 77 c4 d6 d2 23 + 7e 85 cf 01 d6 91 0c fb 83 95 4e 76 ba 73 52 83 05 34 15 98 97 + e8 06 57 80 00 2b 00 03 02 03 04 00 0d 00 18 00 16 04 03 05 03 + 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 00 2c 00 + 74 00 72 71 dc d0 4b b8 8b c3 18 91 19 + 39 8a 00 00 00 00 ee fa fc 76 c1 46 b8 23 b0 96 f8 aa ca d3 65 + dd 00 30 95 3f 4e df 62 56 36 e5 f2 1b b2 e2 3f cc 65 4b 1b 5b + 40 31 8d 10 d1 37 ab cb b8 75 74 e3 6e 8a 1f 02 5f 7d fa 5d 6e + 50 78 1b 5e da 4a a1 5b 0c 8b e7 78 25 7d 16 aa 30 30 e9 e7 84 + 1d d9 e4 c0 34 22 67 e8 ca 0c af 57 1f b2 b7 cf f0 f9 34 b0 00 + 2d 00 02 01 01 00 1c 00 02 40 01 00 15 00 af 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 """) -t = TLS(clientHello2, tls_session=t.tls_session.mirror()) -pubnum = t.tls_session.tls13_client_pubshares["secp256r1"].public_numbers() +t3 = TLS(clientHello2, tls_session=t2.tls_session.mirror()) +pubnum = t3.tls_session.tls13_client_pubshares["secp256r1"].public_numbers() privnum = EllipticCurvePrivateNumbers(pkcs_os2ip(secp256r1_client_privkey), pubnum) privkey = privnum.private_key(default_backend()) -t.tls_session.tls13_client_privshares["secp256r1"] = privkey +t3.tls_session.tls13_client_privshares["secp256r1"] = privkey + += Dissect ServerHello answer #secp256r1_server_privkey = clean(""" -# ff265d2062c70725 ca22513e1e6841ff -# 475e8a00421f0818 186edd1c0080cc6a +# 11 31 54 5d 0b af 79 dd ce 9b 87 f0 69 45 78 1a +# 57 dd 18 ef 37 8d cd 20 60 f8 f9 a5 69 02 7e d8 # """) serverHello = clean(""" - 1603010073020000 6f7f1296ff693075 - d8465651a9c28773 f5496542206ba390 199b9c997545d9a1 - 2666151301004900 2800450017004104 8a4d09cde58dbc04 - 1955b9a41a43c169 6dc5429ffa96f9cd 194a863ac782f181 - 59f072b4f610215d 86407dd7368b754a b2e64f2c1b3f9d45 - 7c264e2b1781a36b + 16 03 03 00 7b 02 00 00 77 03 03 bb + 34 1d 84 7f d7 89 c4 7c 38 71 72 dc 0c 9b f1 47 fc ca cb 50 43 + d8 6c a4 c5 98 d3 ff 57 1b 98 00 13 01 00 00 4f 00 33 00 45 00 + 17 00 41 04 58 3e 05 4b 7a 66 67 2a e0 20 ad 9d 26 86 fc c8 5b + 5a d4 1a 13 4a 0f 03 ee 72 b8 93 05 2b d8 5b 4c 8d e6 77 6f 5b + 04 ac 07 d8 35 40 ea b3 e3 d9 c5 47 bc 65 28 c4 31 7d 29 46 86 + 09 3a 6c ad 7d 00 2b 00 02 03 04 """) -t = TLS(serverHello, tls_session=t.tls_session.mirror()) +t4 = TLS(serverHello, tls_session=t3.tls_session.mirror()) + += Dissect Server Encoded certificate serverEncHS = clean(""" - 170301029081de4f cfd700da4573d570 - 5942f14a11e569aa 9aacc95260520102 6f74f2b2ad6abe08 - 7b53a4940ff94208 9e02d3159b1c6f11 75d7fcb51abad6fd - d4f7ff4af6590b47 16c1d90e1031e1a1 e32079f531108c6b - 9f79d6120319e0a3 73010e82d780a8f9 c3fdf8474840cdb6 - 7e4943d3808a27cd 5d9375c766a95ef4 8393c235d83ad26a - 20628671793f75df aa0be78b11fed206 6506d19a769d9d32 - adc0437784994359 ef5e452609353670 1c46004cf6fc252e - 546e797238c73b94 b073461158301f78 1498917c32dc0ece - 658a53790c667397 f7744775c2bef907 b5f7d5677b2e57fe - 7c4bfd43c7ad1ee4 6fd400c3d3c3c05f e8775f055263e98a - 692b49a818d0f698 4400c1db2f429fa8 9fb61d523398e1d0 - 2bc5c393027146c0 f326032d18cb8283 473f2b6d554df942 - c7b1a0050694c7b2 bf31a816f7ff77f1 d7db873dbb6e4646 - acabfa73c317a34c e6212a3469f549e6 cde71ab229a6f220 - acda60832b510663 02a23d02c734bd5e 71b04fb248ca47ba - 0c7b1fd28fee9b5d 86e6b1a6a2a1a43e 3831210519f54134 - c96486d11ef3125f 74969785690487e0 aa5c0a310ebf9d31 - 95ec5543af8a6ffb 710eb0a90285960d c1ccdc10ecee9669 - 9171e97eae526a17 205012ab6f262e44 31ae9a70ff2ed7bd - 966ef6bd4563f56a 7a14970dcabf97ae 7e4354db1ea27548 - c55c11542ad07bcd 6f47a7143b86c4e6 678ce7dc6d51a1b7 - 75687644d6526efa 3c864f592819e7b7 f9f1bbc02ed8821a - e66019b240b41f5e ebf9475069700030 7122f7c8a8d6c0da - a264c63183238d72 0eacb86879fab9ba 8a673c51a52c8284 - 75e3211223cd2238 bd8b8a934af3e4dd e10e788df23ad6d8 - 51d68b78082ac667 a854356415e7858b e526307332990d8c - c38a5dc4cfc22a2c a2bdd9126a2ce13d 7015264921 + 17 03 03 02 96 99 be e2 0b af 5b 7f + c7 27 bf ab 62 23 92 8a 38 1e 6d 0c f9 c4 da 65 3f 9d 2a 7b 23 + f7 de 11 cc e8 42 d5 cf 75 63 17 63 45 0f fb 8b 0c c1 d2 38 e6 + 58 af 7a 12 ad c8 62 43 11 4a b1 4a 1d a2 fa e4 26 21 ce 48 3f + b6 24 2e ab fa ad 52 56 6b 02 b3 1d 2e dd ed ef eb 80 e6 6a 99 + 00 d5 f9 73 b4 0c 4f df 74 71 9e cf 1b 68 d7 f9 c3 b6 ce b9 03 + ca 13 dd 1b b8 f8 18 7a e3 34 17 e1 d1 52 52 2c 58 22 a1 a0 3a + d5 2c 83 8c 55 95 3d 61 02 22 87 4c ce 8e 17 90 b2 29 a2 aa 0b + 53 c8 d3 77 ee 72 01 82 95 1d c6 18 1d c5 d9 0b d1 f0 10 5e d1 + e8 4a a5 f7 59 57 c6 66 18 97 07 9e 5e a5 00 74 49 e3 19 7b dc + 7c 9b ee ed dd ea fd d8 44 af a5 c3 15 ec fe 65 e5 76 af e9 09 + 81 28 80 62 0e c7 04 8b 42 d7 f5 c7 8d 76 f2 99 d6 d8 25 34 bd + d8 f5 12 fe bc 0e d3 81 4a ca 47 0c d8 00 0d 3e 1c b9 96 2b 05 + 2f bb 95 0d f6 83 a5 2c 2b a7 7e d3 71 3b 12 29 37 a6 e5 17 09 + 64 e2 ab 79 69 dc d9 80 b3 db 9b 45 8d a7 60 31 24 d6 dc 00 5e + 4d 6e 04 b4 d0 c4 ba f3 27 5d b8 27 db ba 0a 6d b0 96 72 17 1f + c0 57 b3 85 1d 7e 02 68 41 e2 97 8f bd 23 46 bb ef dd 03 76 bb + 11 08 fe 9a cc 92 18 9f 56 50 aa 5e 85 d8 e8 c7 b6 7a c5 10 db + a0 03 d3 d7 e1 63 50 bb 66 d4 50 13 ef d4 4c 9b 60 7c 0d 31 8c + 4c 7d 1a 1f 5c bc 57 e2 06 11 80 4e 37 87 d7 b4 a4 b5 f0 8e d8 + fd 70 bd ae ad e0 22 60 b1 2a b8 42 ef 69 0b 4a 3e e7 91 1e 84 + 1b 37 4e cd 5e bb bc 2a 54 d0 47 b6 00 33 6d d7 d0 c8 8b 4b c1 + 0e 58 ee 6c b6 56 de 72 47 fa 20 d8 e9 1d eb 84 62 86 08 cf 80 + 61 5b 62 e9 6c 14 91 c7 ac 37 55 eb 69 01 40 5d 34 74 fe 1a c7 + 9d 10 6a 0c ee 56 c2 57 7f c8 84 80 f9 6c b6 b8 c6 81 b7 b6 8b + 53 c1 46 09 39 08 f3 50 88 81 75 bd fb 0b 1e 31 ad 61 e3 0b a0 + ad fe 6d 22 3a a0 3c 07 83 b5 00 1a 57 58 7c 32 8a 9a fc fc fb + 97 8d 1c d4 32 8f 7d 9d 60 53 0e 63 0b ef d9 6c 0c 81 6e e2 0b + 01 00 76 8a e2 a6 df 51 fc 68 f1 72 74 0a 79 af 11 39 8e e3 be + 12 52 49 1f a9 c6 93 47 9e 87 7f 94 ab 7c 5f 8c ad 48 02 03 e6 + ab 7b 87 dd 71 e8 a0 72 91 13 df 17 f5 ee e8 6c e1 08 d1 d7 20 + 07 ec 1c d1 3c 85 a6 c1 49 62 1e 77 b7 d7 8d 80 5a 30 f0 be 03 + 0c 31 5e 54 """) -t = TLS(serverEncHS, tls_session=t.tls_session) +t5 = TLS(serverEncHS, tls_session=t4.tls_session) + += Dissect Client Finished clientFinished = clean(""" - 170301003543adad e592362412fb77d7 - 28b181c01b77cd62 a661e4125e6f9851 826e418f4c292ec6 - 3254e8b0342d65db 8a7f074eed527ea6 98a6 + 17 03 03 00 35 d7 4f 19 23 c6 62 fd + 34 13 7c 6f 50 2f 3d d2 b9 3d 95 1d 1b 3b c9 7e 42 af e2 3c 31 + ab ea 92 fe 91 b4 74 99 9e 85 e3 b7 91 ce 25 2f e8 c3 e9 f9 39 + a4 12 0c b2 """) -t = TLS(clientFinished, tls_session=t.tls_session.mirror()) +t6 = TLS(clientFinished, tls_session=t5.tls_session.mirror()) + += Dissect Client alert record clientRecord = clean(""" - 17030100131ef5c9 e7205f31a1edf9b1 - 3600fec1271e4f5d + 17 03 03 00 13 2e a6 cd f7 49 19 60 + 23 e2 b3 a4 94 91 69 55 36 42 60 47 """) -t = TLS(clientRecord, tls_session=t.tls_session) +t7 = TLS(clientRecord, tls_session=t6.tls_session) + += Dissect Server alert record serverRecord = clean(""" - 170301001350ff6e 907c508b6b191ff6 - 094faf4c0b32d6a8 + 17 03 03 00 13 51 9f c5 07 5c b0 88 + 43 49 75 9f f9 ef 6f 01 1b b4 c6 f2 """) -t = TLS(serverRecord, tls_session=t.tls_session.mirror()) +t8 = TLS(serverRecord, tls_session=t7.tls_session.mirror()) -alert = t.inner.msg[0] +alert = t8.inner.msg[0] assert(isinstance(alert, TLSAlert)) alert.level == 1 and alert.descr == 0 -= Reading TLS 1.3 test session (vectors 3 from draft-ietf-tls-tls13-vectors-00) ++ Reading TLS 1.3 test session (vectors 3 from rfc8448) ~ crypto_advanced + += Dissect ClientHello handshake message + from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey x25519_client_privkey = clean(""" - 00b4198a84ed6a7c 218702891735239d - 40b7c66505330364 3d3c67f7458ecbc9 + 49 af 42 ba 7f 79 94 85 2d 71 3e f2 78 + 4b cb ca a7 91 1d e2 6a dc 56 42 cb 63 45 40 e7 ea 50 05 """) clientHello = clean(""" - 1603010200010001 fc03039a464db650 - dcc81fed6f1fea63 5f15861574c0ed0b fb5778de7724fb92 - 7c5ef100003e1301 13031302c02bc02f cca9cca8c00ac009 - c013c023c027c014 009eccaa00330032 006700390038006b - 00160013009c002f 003c0035003d000a 0005000401000195 - 001500fc00000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000000000000 - 0000000000000000 0000000000000000 0000000b00090000 - 06736572766572ff 01000100000a0014 0012001d00170018 - 0019010001010102 01030104000b0002 0100002300000028 - 00260024001d0020 35e58b160db6124f 01a1d2475a22b72a - bd6896701eed4c7e fd6124ee231ba458 002b0007067f1203 - 030302000d002000 1e04030503060302 0308040805080604 - 0105010601020104 0205020602020200 2d00020101 + 16 03 01 00 c4 01 00 00 c0 03 03 cb + 34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12 + ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00 + 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 + 00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 + 01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d + e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d + 54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 18 00 16 + 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 + 01 00 2d 00 02 01 01 00 1c 00 02 40 01 """) -t = TLS(clientHello) -privkey = X25519PrivateKey._from_private_bytes(x25519_client_privkey) -t.tls_session.tls13_client_privshares["x25519"] = privkey +t1 = TLS(clientHello) +privkey = X25519PrivateKey.from_private_bytes(x25519_client_privkey) +t1.tls_session.tls13_client_privshares["x25519"] = privkey + += Dissect ServerHello handshake message x25519_server_privkey = clean(""" - 03d43f48ed52076f 4ce9bab73d1f39ec - 689cf304075829f5 2b90f9f13bea6f34 + b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56 + 52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e """) serverHello = clean(""" - 1603010052020000 4e7f1298e3436403 - 8683391cbec1039a a0fba2f496d8c8e6 327151cc94bbc5ef - 7390751301002800 280024001d0020a2 0ed1b7f2d96a7f12 - 568f0e460bb0fc86 dc8d1db6c07d6b10 d4dc74aaac9219 + 16 03 03 00 5a 02 00 00 56 03 03 a6 + af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 + 34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00 + 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6 + cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04 """) -t = TLS(serverHello, tls_session=t.tls_session.mirror()) +t2 = TLS(serverHello, tls_session=t1.tls_session.mirror()) + += Dissect Certificate Handshake message serverEncHS = clean(""" - 170301029c4e1f34 2dba17a54a09f7a1 - 8ffb2c6a29df17a6 db843044c52861bf 78988527ce366159 - e6a24871b704d2b9 fade56488921796d 719173a753bdfec8 - 0554c8c15e128695 450ccfdde1204ffd 2fb1ecdcd87b8070 - 644eb5a6b86ec951 aba3ed314754a2f3 14d4d2620b92da1f - 28f24b9559d76b67 a7b35c17cc231ba5 77a94fb2be59c74f - 84c8c78bf5faf4cb b2f8a37091580743 3c67d9f4e1b1923a - 3969b85a2ae9064e 34e84363aae43aa9 f58717836a017b9c - 33c3ad733c2fd3ce 288ae362764403d0 102a371047d9e49d - f9b30596262b1704 f0e9839fff5641ba a7041a4bcf9e4d46 - 7108922fc0ea0bc1 48dab2ebdd155f51 76c632be04a7c610 - 3fbc92754dba7962 4f8a09f8e8d65c17 eee87f98636fbc93 - bb734674b80d183c da904200a20d8f15 0a214902b6953209 - aa2431c3973bda3b d92a33878baca7b9 0507f433a55f2fe8 - f0db81898ebacf31 b68eaabfa27c39b6 a2453a322c005030 - 4e60bf53f0402b38 65b43fe5a7454c13 17a2dc76d1323fb1 - aa553996876a0dfe 8e789d6adf3dc85b 0636bb58a96e6aad - 851e7a6fc1dfa796 ec65e33bf9e3c05d 6de35f11e1f32731 - fb9550a60cb75e90 9345eb0edb81f99f cad883cb41d4a3ef - 7cbe671b92a8176b 472772be401b83a4 99b06b7ab0a1d9cd - 795e5ba0b67ce2d6 5c45565028824aa2 08797f405bbcf243 - 27dd69a1d986032f 544b15d110e4d8c4 681cb85c09960adb - 57fb9723eef0e0bb 275552af25fbdfc1 a4215adf14a9dba2 - 4462dd095f1a78f5 6ed6db3de139936f 14b091ab7f4adc81 - c277e68bfb6fd925 d92c06c0a4ddd105 9c071073a8a2e987 - f98948599f27bf6d 1f4369ac6c5a3323 2932fb8aa52ec4e1 - 85790dff0ef5eee0 13b4e90b5bc1cd4a c42b7ce82d856cc0 - f5d1c80400e68d61 b434cec56d437141 1e31849d4cf88862 - 8ba288548df6a19e c4 +17 03 03 02 a2 d1 ff 33 4a 56 f5 bf + f6 59 4a 07 cc 87 b5 80 23 3f 50 0f 45 e4 89 e7 f3 3a f3 5e df + 78 69 fc f4 0a a4 0a a2 b8 ea 73 f8 48 a7 ca 07 61 2e f9 f9 45 + cb 96 0b 40 68 90 51 23 ea 78 b1 11 b4 29 ba 91 91 cd 05 d2 a3 + 89 28 0f 52 61 34 aa dc 7f c7 8c 4b 72 9d f8 28 b5 ec f7 b1 3b + d9 ae fb 0e 57 f2 71 58 5b 8e a9 bb 35 5c 7c 79 02 07 16 cf b9 + b1 18 3e f3 ab 20 e3 7d 57 a6 b9 d7 47 76 09 ae e6 e1 22 a4 cf + 51 42 73 25 25 0c 7d 0e 50 92 89 44 4c 9b 3a 64 8f 1d 71 03 5d + 2e d6 5b 0e 3c dd 0c ba e8 bf 2d 0b 22 78 12 cb b3 60 98 72 55 + cc 74 41 10 c4 53 ba a4 fc d6 10 92 8d 80 98 10 e4 b7 ed 1a 8f + d9 91 f0 6a a6 24 82 04 79 7e 36 a6 a7 3b 70 a2 55 9c 09 ea d6 + 86 94 5b a2 46 ab 66 e5 ed d8 04 4b 4c 6d e3 fc f2 a8 94 41 ac + 66 27 2f d8 fb 33 0e f8 19 05 79 b3 68 45 96 c9 60 bd 59 6e ea + 52 0a 56 a8 d6 50 f5 63 aa d2 74 09 96 0d ca 63 d3 e6 88 61 1e + a5 e2 2f 44 15 cf 95 38 d5 1a 20 0c 27 03 42 72 96 8a 26 4e d6 + 54 0c 84 83 8d 89 f7 2c 24 46 1a ad 6d 26 f5 9e ca ba 9a cb bb + 31 7b 66 d9 02 f4 f2 92 a3 6a c1 b6 39 c6 37 ce 34 31 17 b6 59 + 62 22 45 31 7b 49 ee da 0c 62 58 f1 00 d7 d9 61 ff b1 38 64 7e + 92 ea 33 0f ae ea 6d fa 31 c7 a8 4d c3 bd 7e 1b 7a 6c 71 78 af + 36 87 90 18 e3 f2 52 10 7f 24 3d 24 3d c7 33 9d 56 84 c8 b0 37 + 8b f3 02 44 da 8c 87 c8 43 f5 e5 6e b4 c5 e8 28 0a 2b 48 05 2c + f9 3b 16 49 9a 66 db 7c ca 71 e4 59 94 26 f7 d4 61 e6 6f 99 88 + 2b d8 9f c5 08 00 be cc a6 2d 6c 74 11 6d bd 29 72 fd a1 fa 80 + f8 5d f8 81 ed be 5a 37 66 89 36 b3 35 58 3b 59 91 86 dc 5c 69 + 18 a3 96 fa 48 a1 81 d6 b6 fa 4f 9d 62 d5 13 af bb 99 2f 2b 99 + 2f 67 f8 af e6 7f 76 91 3f a3 88 cb 56 30 c8 ca 01 e0 c6 5d 11 + c6 6a 1e 2a c4 c8 59 77 b7 c7 a6 99 9b bf 10 dc 35 ae 69 f5 51 + 56 14 63 6c 0b 9b 68 c1 9e d2 e3 1c 0b 3b 66 76 30 38 eb ba 42 + f3 b3 8e dc 03 99 f3 a9 f2 3f aa 63 97 8c 31 7f c9 fa 66 a7 3f + 60 f0 50 4d e9 3b 5b 84 5e 27 55 92 c1 23 35 ee 34 0b bc 4f dd + d5 02 78 40 16 e4 b3 be 7e f0 4d da 49 f4 b4 40 a3 0c b5 d2 af + 93 98 28 fd 4a e3 79 4e 44 f9 4d f5 a6 31 ed e4 2c 17 19 bf da + bf 02 53 fe 51 75 be 89 8e 75 0e dc 53 37 0d 2b """) -t = TLS(serverEncHS, tls_session=t.tls_session) +t3 = TLS(serverEncHS, tls_session=t2.tls_session) + += Dissect client Handshake Record clientFinished = clean(""" - 1703010035161e94 818226d7bd618063 - 0804644debc52bdd 661034243217ac45 a084228c82086baa - 4893ecfc969624d6 8e19d88c3e67ccb4 8bdf + 17 03 03 00 35 75 ec 4d c2 38 cc e6 + 0b 29 80 44 a7 1e 21 9c 56 cc 77 b0 51 7f e9 b9 3c 7a 4b fc 44 + d8 7f 38 f8 03 38 ac 98 fc 46 de b3 84 bd 1c ae ac ab 68 67 d7 + 26 c4 05 46 """) -t = TLS(clientFinished, tls_session=t.tls_session.mirror()) +t4 = TLS(clientFinished, tls_session=t3.tls_session.mirror()) + += Dissect HandshakeRecord (NewSessionTicket) serverRecord1 = clean(""" - 17030100bbe6b3e9 89df694688f29f5d - a42d9f56053fc6d2 f73ee23accad26f9 599ee4dcf4e0cf9e - de80128b48156a65 e5e47dee679a8401 1234862b6728fb12 - be5198d5c023d6f2 0c355fc417a5eade 1aff0bf9ecba14c8 - 7277ea7aeb30055e a4d9b37bc12f7517 27ca7a1efc9285f8 - ed5e9e3be42ff475 30f2b7347a90618b 6f7f4eba9b8b6564 - f2159fcfcf09e4b6 2b4b09bb129e7c76 5c877966ca66e5cd - a84cdb6087a07fc0 50c97f275568623c 5d0f459d2b1133d1 - d5d37cd441192da7 + 17 03 03 00 de 3a 6b 8f 90 41 4a 97 + d6 95 9c 34 87 68 0d e5 13 4a 2b 24 0e 6c ff ac 11 6e 95 d4 1d + 6a f8 f6 b5 80 dc f3 d1 1d 63 c7 58 db 28 9a 01 59 40 25 2f 55 + 71 3e 06 1d c1 3e 07 88 91 a3 8e fb cf 57 53 ad 8e f1 70 ad 3c + 73 53 d1 6d 9d a7 73 b9 ca 7f 2b 9f a1 b6 c0 d4 a3 d0 3f 75 e0 + 9c 30 ba 1e 62 97 2a c4 6f 75 f7 b9 81 be 63 43 9b 29 99 ce 13 + 06 46 15 13 98 91 d5 e4 c5 b4 06 f1 6e 3f c1 81 a7 7c a4 75 84 + 00 25 db 2f 0a 77 f8 1b 5a b0 5b 94 c0 13 46 75 5f 69 23 2c 86 + 51 9d 86 cb ee ac 87 aa c3 47 d1 43 f9 60 5d 64 f6 50 db 4d 02 + 3e 70 e9 52 ca 49 fe 51 37 12 1c 74 bc 26 97 68 7e 24 87 46 d6 + df 35 30 05 f3 bc e1 86 96 12 9c 81 53 55 6b 3b 6c 67 79 b3 7b + f1 59 85 68 4f """) -t = TLS(serverRecord1, tls_session=t.tls_session.mirror()) +t5 = TLS(serverRecord1, tls_session=t4.tls_session.mirror()) + += Dissect client application_data record clientRecord1 = clean(""" - 170301004341b540 bf5adeaf9d209001 - 9f0733e281964724 526678a1946852cf 6f586dffacf1151d - bf7c9262ef6ae960 4a423fff339fd7e4 0cc3e7604ae661f0 - afa2f775c3668867 + 17 03 03 00 43 a2 3f 70 54 b6 2c 94 + d0 af fa fe 82 28 ba 55 cb ef ac ea 42 f9 14 aa 66 bc ab 3f 2b + 98 19 a8 a5 b4 6b 39 5b d5 4a 9a 20 44 1e 2b 62 97 4e 1f 5a 62 + 92 a2 97 70 14 bd 1e 3d ea e6 3a ee bb 21 69 49 15 e4 """) -t = TLS(clientRecord1, tls_session=t.tls_session.mirror()) -app_data = t.inner.msg[0] -assert(app_data.data == b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01') +t6 = TLS(clientRecord1, tls_session=t5.tls_session.mirror()) +app_data = t6.inner.msg[0] +data = clean(""" + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e + 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 + 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 + """) +assert(app_data.data == data) + += Dissect server application_data record serverRecord2 = clean(""" - 17030100438c3168 1fb21f820ef0603c - dc3b9d3deedeb2bb 615aa418fb2590a0 9b0dec00c2299feb - 17c4206f89ab28d2 7a605e288ac9bd69 657593addd1046be - 51b23940f8746634 + 17 03 03 00 43 2e 93 7e 11 ef 4a c7 + 40 e5 38 ad 36 00 5f c4 a4 69 32 fc 32 25 d0 5f 82 aa 1b 36 e3 + 0e fa f9 7d 90 e6 df fc 60 2d cb 50 1a 59 a8 fc c4 9c 4b f2 e5 + f0 a2 1c 00 47 c2 ab f3 32 54 0d d0 32 e1 67 c2 95 5d + """) +t7 = TLS(serverRecord2, tls_session=t6.tls_session.mirror()) +app_data = t7.inner.msg[0] +data = clean(""" + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e + 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 + 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 """) -t = TLS(serverRecord2, tls_session=t.tls_session.mirror()) -app_data = t.inner.msg[0] -assert(app_data.data == b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01') +assert(app_data.data == data) + += Dissect client alert record clientRecord2 = clean(""" - 17030100131ce9b1 f21ba236bca94455 - ab2aad71c666534a + 17 03 03 00 13 c9 87 27 60 65 56 66 + b7 4d 7f f1 15 3e fd 6d b6 d0 b0 e3 """) -t = TLS(clientRecord2, tls_session=t.tls_session.mirror()) -alert = t.inner.msg[0] +t8 = TLS(clientRecord2, tls_session=t7.tls_session.mirror()) +alert = t8.inner.msg[0] assert(isinstance(alert, TLSAlert)) assert(alert.level == 1 and alert.descr == 0) += Dissect server alert record + serverRecord3 = clean(""" - 1703010013aabcdb 9d293d23fb00deb7 - 11b562afeddffeed + 17 03 03 00 13 b5 8f d6 71 66 eb f5 + 99 d2 47 20 cf be 7e fa 7a 88 64 a9 + """) -t = TLS(serverRecord3, tls_session=t.tls_session.mirror()) -alert = t.inner.msg[0] +t9 = TLS(serverRecord3, tls_session=t8.tls_session.mirror()) +alert = t9.inner.msg[0] assert(isinstance(alert, TLSAlert)) alert.level == 1 and alert.descr == 0 diff --git a/test/tls13_debug.uts b/test/tls13_debug.uts new file mode 100644 index 00000000000..cc422d154cc --- /dev/null +++ b/test/tls13_debug.uts @@ -0,0 +1,44 @@ +% TLS 1.3 session - DEBUG + ++ Debug - use data of https://tls13.ulfheim.net/ +~ crypto +* So that it's easy to see what goes wrong + += Run tests + +import binascii +from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateNumbers +from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey +from cryptography.hazmat.backends import default_backend + +def clean(s): + return binascii.unhexlify(''.join(c for c in s if c.isalnum())) + +privatekey_client = hex_bytes("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") + +clientHello = TLS( + clean("""16 03 01 00 ca 01 00 00 c6 03 03 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 06 13 01 13 02 13 03 01 00 00 77 00 00 00 18 00 16 00 00 13 65 78 61 6d 70 6c 65 2e 75 6c 66 68 65 69 6d 2e 6e 65 74 00 0a 00 08 00 06 00 1d 00 17 00 18 00 0d 00 14 00 12 04 03 08 04 04 01 05 03 08 05 05 01 08 06 06 01 02 01 00 33 00 26 00 24 00 1d 00 20 35 80 72 d6 36 58 80 d1 ae ea 32 9a df 91 21 38 38 51 ed 21 a2 8e 3b 75 e9 65 d0 d2 cd 16 62 54 00 2d 00 02 01 01 00 2b 00 03 02 03 04 """) +) + +privkey = X25519PrivateKey.from_private_bytes(privatekey_client) +clientHello.tls_session.tls13_client_privshares["x25519"] = privkey + +# ServerHello + +privatekey_server = hex_bytes("909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf") + +tls_session=clientHello.tls_session.mirror() +privkey = X25519PrivateKey.from_private_bytes(privatekey_server) +tls_session.tls13_server_privshare["x25519"] = privkey + +serverHello = TLS( + clean("""16 03 03 00 7a 02 00 00 76 03 03 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 20 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 13 01 00 00 2e 00 33 00 24 00 1d 00 20 9f d7 ad 6d cf f4 29 8d d3 f9 6d 5b 1b 2a f9 10 a0 53 5b 14 88 d7 f8 fa bb 34 9a 98 28 80 b6 15 00 2b 00 02 03 04 """), + tls_session=tls_session +) + +# Server CHange Cipher Spec + +serverChangeCipherSpec = TLS( + clean("14 03 03 00 01 01 "), + tls_session=tls_session +) \ No newline at end of file diff --git a/tls-13-handshake.pcap b/tls-13-handshake.pcap new file mode 100644 index 00000000000..22495170883 Binary files /dev/null and b/tls-13-handshake.pcap differ