diff --git a/doc/notebooks/tls/notebook4_tls13.ipynb b/doc/notebooks/tls/notebook4_tls13.ipynb index 84a72211c32..da27d2e6b9b 100644 --- a/doc/notebooks/tls/notebook4_tls13.ipynb +++ b/doc/notebooks/tls/notebook4_tls13.ipynb @@ -10,16 +10,22 @@ "\"Handshake" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dissecting the handshake" + ] + }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "from scapy.all import *\n", - "load_layer('tls')" + "load_layer('tls')\n", + "conf.logLevel = logging.INFO" ] }, { @@ -28,6 +34,7 @@ "metadata": {}, "outputs": [], "source": [ + "# ClientHello\n", "record1_str = open('raw_data/tls_session_13/01_cli.raw', 'rb').read()\n", "record1 = TLS(record1_str)\n", "sess = record1.tls_session\n", @@ -40,38 +47,42 @@ "metadata": {}, "outputs": [], "source": [ - "record2_str = open('raw_data/tls_session_13/02_srv.raw', 'rb').read()\n", - "record2 = TLS(record2_str, tls_session=sess.mirror())\n", - "record2.show()" + "# The PFS relies on the ECDH secret below being kept from observers, and deleted right after the key exchange\n", + "from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey\n", + "\n", + "# Used in records 2-6 + 8\n", + "x25519_client_privkey = open('raw_data/tls_session_13/cli_key.raw', 'rb').read()\n", + "sess.tls13_client_privshares[\"x25519\"] = X25519PrivateKey.from_private_bytes(x25519_client_privkey)\n", + "\n", + "# Used in records 7 + 9\n", + "x25519_server_privkey = open('raw_data/tls_session_13/srv_key.raw', 'rb').read()\n", + "sess.tls13_server_privshare[\"x25519\"] = X25519PrivateKey.from_private_bytes(x25519_server_privkey)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [], "source": [ - "record3_str = open('raw_data/tls_session_13/03_cli.raw', 'rb').read()\n", - "record3 = TLS(record3_str, tls_session=sess.mirror())\n", - "record3.show()" + "# ServerHello + ChangeCipherSpec (middlebox compatibility)\n", + "record2_str = open('raw_data/tls_session_13/02_srv.raw', 'rb').read()\n", + "record2 = TLS(record2_str, tls_session=sess.mirror())\n", + "record2.show()" ] }, { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ - "# The PFS relies on the ECDH secret below being kept from observers, and deleted right after the key exchange\n", - "#from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateNumbers\n", - "#from cryptography.hazmat.backends import default_backend\n", - "#secp256r1_client_privkey = open('raw_data/tls_session_13/cli_key.raw', 'rb').read()\n", - "#pubnum = sess.tls13_client_pubshares[\"secp256r1\"].public_numbers()\n", - "#privnum = EllipticCurvePrivateNumbers(pkcs_os2ip(secp256r1_client_privkey), pubnum)\n", - "#privkey = privnum.private_key(default_backend())\n", - "#sess.tls13_client_privshares[\"secp256r1\"] = privkey" + "# Encrypted Extensions\n", + "record3_str = open('raw_data/tls_session_13/03_srv.raw', 'rb').read()\n", + "record3 = TLS(record3_str, tls_session=sess)\n", + "record3.show()" ] }, { @@ -82,8 +93,9 @@ }, "outputs": [], "source": [ + "# Certificate\n", "record4_str = open('raw_data/tls_session_13/04_srv.raw', 'rb').read()\n", - "record4 = TLS(record4_str, tls_session=sess.mirror())\n", + "record4 = TLS(record4_str, tls_session=sess)\n", "record4.show()" ] }, @@ -93,6 +105,7 @@ "metadata": {}, "outputs": [], "source": [ + "# Certificate verify\n", "record5_str = open('raw_data/tls_session_13/05_srv.raw', 'rb').read()\n", "record5 = TLS(record5_str, tls_session=sess)\n", "record5.show()" @@ -104,11 +117,57 @@ "metadata": {}, "outputs": [], "source": [ - "record6_str = open('raw_data/tls_session_13/06_cli.raw', 'rb').read()\n", - "record6 = TLS(record6_str, tls_session=sess.mirror())\n", + "# Finished\n", + "record6_str = open('raw_data/tls_session_13/06_srv.raw', 'rb').read()\n", + "record6 = TLS(record6_str, tls_session=sess)\n", "record6.show()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Client ChangeCipherSpec (middlebox compatibility) + Finished\n", + "record7_str = open('raw_data/tls_session_13/07_cli.raw', 'rb').read()\n", + "record7 = TLS(record7_str, tls_session=sess.mirror())\n", + "record7.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dissecting some data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Client application data\n", + "record8_str = open('raw_data/tls_session_13/08_cli.raw', 'rb').read()\n", + "record8 = TLS(record8_str, tls_session=sess)\n", + "record8.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Server application data\n", + "record9_str = open('raw_data/tls_session_13/09_srv.raw', 'rb').read()\n", + "record9 = TLS(record9_str, tls_session=sess.mirror())\n", + "record9.show()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -122,21 +181,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.13" + "pygments_lexer": "ipython3", + "version": "3.10.5" } }, "nbformat": 4, diff --git a/doc/notebooks/tls/raw_data/tls_session_13/01_cli.raw b/doc/notebooks/tls/raw_data/tls_session_13/01_cli.raw index 720269449ed..dae6d676159 100644 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/01_cli.raw and b/doc/notebooks/tls/raw_data/tls_session_13/01_cli.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/02_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/02_srv.raw index 3c119721eb9..a44e0450df8 100644 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/02_srv.raw and b/doc/notebooks/tls/raw_data/tls_session_13/02_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/03_cli.raw b/doc/notebooks/tls/raw_data/tls_session_13/03_cli.raw deleted file mode 100644 index b526cd708ef..00000000000 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/03_cli.raw and /dev/null differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/03_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/03_srv.raw new file mode 100644 index 00000000000..c0ae12ac8bf Binary files /dev/null and b/doc/notebooks/tls/raw_data/tls_session_13/03_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/04_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/04_srv.raw index 469e99d5d40..55358cc0b4b 100644 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/04_srv.raw and b/doc/notebooks/tls/raw_data/tls_session_13/04_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/05_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/05_srv.raw index 03253fcc347..42a5a2311d2 100644 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/05_srv.raw and b/doc/notebooks/tls/raw_data/tls_session_13/05_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/06_cli.raw b/doc/notebooks/tls/raw_data/tls_session_13/06_cli.raw deleted file mode 100644 index 127631c031d..00000000000 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/06_cli.raw and /dev/null differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/06_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/06_srv.raw new file mode 100644 index 00000000000..f889afc1455 Binary files /dev/null and b/doc/notebooks/tls/raw_data/tls_session_13/06_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/07_cli.raw b/doc/notebooks/tls/raw_data/tls_session_13/07_cli.raw new file mode 100644 index 00000000000..f98f681c0aa Binary files /dev/null and b/doc/notebooks/tls/raw_data/tls_session_13/07_cli.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/07_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/07_srv.raw deleted file mode 100644 index 99f5f8dd12e..00000000000 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/07_srv.raw and /dev/null differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/08_cli.raw b/doc/notebooks/tls/raw_data/tls_session_13/08_cli.raw index 7d2a14f107e..179980edb3b 100644 Binary files a/doc/notebooks/tls/raw_data/tls_session_13/08_cli.raw and b/doc/notebooks/tls/raw_data/tls_session_13/08_cli.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/09_srv.raw b/doc/notebooks/tls/raw_data/tls_session_13/09_srv.raw new file mode 100644 index 00000000000..41d9c01d7bb Binary files /dev/null and b/doc/notebooks/tls/raw_data/tls_session_13/09_srv.raw differ diff --git a/doc/notebooks/tls/raw_data/tls_session_13/cli_key.raw b/doc/notebooks/tls/raw_data/tls_session_13/cli_key.raw index 46873d5457b..de91279c9fe 100644 --- a/doc/notebooks/tls/raw_data/tls_session_13/cli_key.raw +++ b/doc/notebooks/tls/raw_data/tls_session_13/cli_key.raw @@ -1 +1 @@ -�H�S��؝�`�6&]9���-vmB��N� \ No newline at end of file + !"#$%&'()*+,-./0123456789:;<=>? \ No newline at end of file diff --git a/doc/notebooks/tls/raw_data/tls_session_13/srv_key.raw b/doc/notebooks/tls/raw_data/tls_session_13/srv_key.raw new file mode 100644 index 00000000000..643390219c4 --- /dev/null +++ b/doc/notebooks/tls/raw_data/tls_session_13/srv_key.raw @@ -0,0 +1 @@ +�������������������������������� \ No newline at end of file diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py index 3a5ea73614e..c804ffef664 100644 --- a/scapy/layers/ipsec.py +++ b/scapy/layers/ipsec.py @@ -170,6 +170,7 @@ def data_for_encryption(self): from cryptography.exceptions import InvalidTag from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import ( + aead, Cipher, algorithms, modes, @@ -225,11 +226,18 @@ def __init__(self, name, cipher, mode, block_size=None, iv_size=None, self.mode = mode self.icv_size = icv_size - if modes and self.mode is not None: - self.is_aead = issubclass(self.mode, - modes.ModeWithAuthenticationTag) - else: - self.is_aead = False + self.is_aead = False + # If using cryptography.hazmat.primitives.cipher.aead + self.ciphers_aead_api = False + + if modes: + if self.mode is not None: + self.is_aead = issubclass(self.mode, + modes.ModeWithAuthenticationTag) + elif self.cipher in (aead.AESGCM, aead.AESCCM, + aead.ChaCha20Poly1305): + self.is_aead = True + self.ciphers_aead_api = True if block_size is not None: self.block_size = block_size @@ -339,36 +347,49 @@ def pad(self, esp): return esp - def encrypt(self, sa, esp, key, esn_en=False, esn=0): + def encrypt(self, sa, esp, key, icv_size=None, esn_en=False, esn=0): """ Encrypt an ESP packet :param sa: the SecurityAssociation associated with the ESP packet. :param esp: an unencrypted _ESPPlain packet with valid padding :param key: the secret key used for encryption + :param icv_size: the length of the icv used for integrity check :esn_en: extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm :esn: extended sequence number (32 MSB) :return: a valid ESP packet encrypted with this algorithm """ + if icv_size is None: + icv_size = self.icv_size if self.is_aead else 0 data = esp.data_for_encryption() if self.cipher: mode_iv = self._format_mode_iv(algo=self, sa=sa, iv=esp.iv) - cipher = self.new_cipher(key, mode_iv) - encryptor = cipher.encryptor() - + aad = None if self.is_aead: if esn_en: aad = struct.pack('!LLL', esp.spi, esn, esp.seq) else: aad = struct.pack('!LL', esp.spi, esp.seq) - encryptor.authenticate_additional_data(aad) - data = encryptor.update(data) + encryptor.finalize() - data += encryptor.tag[:self.icv_size] + if self.ciphers_aead_api: + # New API + if self.cipher == aead.AESCCM: + cipher = self.cipher(key, tag_length=icv_size) + else: + cipher = self.cipher(key) + data = cipher.encrypt(mode_iv, data, aad) else: - data = encryptor.update(data) + encryptor.finalize() + cipher = self.new_cipher(key, mode_iv) + encryptor = cipher.encryptor() + + if self.is_aead: + encryptor.authenticate_additional_data(aad) + data = encryptor.update(data) + encryptor.finalize() + data += encryptor.tag[:icv_size] + else: + data = encryptor.update(data) + encryptor.finalize() return ESP(spi=esp.spi, seq=esp.seq, data=esp.iv + data) @@ -397,21 +418,33 @@ def decrypt(self, sa, esp, key, icv_size=None, esn_en=False, esn=0): if self.cipher: mode_iv = self._format_mode_iv(sa=sa, iv=iv) - cipher = self.new_cipher(key, mode_iv, icv) - decryptor = cipher.decryptor() - + aad = None if self.is_aead: - # Tag value check is done during the finalize method if esn_en: - decryptor.authenticate_additional_data( - struct.pack('!LLL', esp.spi, esn, esp.seq)) + aad = struct.pack('!LLL', esp.spi, esn, esp.seq) else: - decryptor.authenticate_additional_data( - struct.pack('!LL', esp.spi, esp.seq)) - try: - data = decryptor.update(data) + decryptor.finalize() - except InvalidTag as err: - raise IPSecIntegrityError(err) + aad = struct.pack('!LL', esp.spi, esp.seq) + if self.ciphers_aead_api: + # New API + if self.cipher == aead.AESCCM: + cipher = self.cipher(key, tag_length=icv_size) + else: + cipher = self.cipher(key) + try: + data = cipher.decrypt(mode_iv, data + icv, aad) + except InvalidTag as err: + raise IPSecIntegrityError(err) + else: + cipher = self.new_cipher(key, mode_iv, icv) + decryptor = cipher.decryptor() + + if self.is_aead: + # Tag value check is done during the finalize method + decryptor.authenticate_additional_data(aad) + try: + data = decryptor.update(data) + decryptor.finalize() + except InvalidTag as err: + raise IPSecIntegrityError(err) # extract padlen and nh padlen = orb(data[-2]) @@ -453,22 +486,33 @@ def decrypt(self, sa, esp, key, icv_size=None, esn_en=False, esn=0): format_mode_iv=_aes_ctr_format_mode_iv) _salt_format_mode_iv = lambda sa, iv, **kw: sa.crypt_salt + iv CRYPT_ALGOS['AES-GCM'] = CryptAlgo('AES-GCM', - cipher=algorithms.AES, - mode=modes.GCM, + cipher=aead.AESGCM, + key_size=(16, 24, 32), + mode=None, salt_size=4, block_size=1, iv_size=8, icv_size=16, format_mode_iv=_salt_format_mode_iv) - if hasattr(modes, 'CCM'): - CRYPT_ALGOS['AES-CCM'] = CryptAlgo('AES-CCM', - cipher=algorithms.AES, - mode=modes.CCM, - block_size=1, - iv_size=8, - salt_size=3, - icv_size=16, - format_mode_iv=_salt_format_mode_iv) + CRYPT_ALGOS['AES-CCM'] = CryptAlgo('AES-CCM', + cipher=aead.AESCCM, + mode=None, + key_size=(16, 24, 32), + block_size=1, + iv_size=8, + salt_size=3, + icv_size=16, + format_mode_iv=_salt_format_mode_iv) + CRYPT_ALGOS['CHACHA20-POLY1305'] = CryptAlgo('CHACHA20-POLY1305', + cipher=aead.ChaCha20Poly1305, + mode=None, + key_size=32, + block_size=1, + iv_size=8, + salt_size=4, + icv_size=16, + format_mode_iv=_salt_format_mode_iv) # noqa: E501 + # XXX: RFC7321 states that DES *MUST NOT* be implemented. # XXX: Keep for backward compatibility? # Using a TripleDES cipher algorithm for DES is done by using the same 64 @@ -822,7 +866,9 @@ class SecurityAssociation(object): SUPPORTED_PROTOS = (IP, IPv6) def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None, - auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None, esn_en=False, esn=0): # noqa: E501 + crypt_icv_size=None, + auth_algo=None, auth_key=None, + tunnel_header=None, nat_t_header=None, esn_en=False, esn=0): """ :param proto: the IPsec proto to use (ESP or AH) :param spi: the Security Parameters Index of this SA @@ -830,6 +876,8 @@ def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None, packets :param crypt_algo: the encryption algorithm name (only used with ESP) :param crypt_key: the encryption key (only used with ESP) + :param crypt_icv_size: change the default size of the crypt_algo + (only used with ESP) :param auth_algo: the integrity algorithm name :param auth_key: the integrity key :param tunnel_header: an instance of a IP(v6) header that will be used @@ -872,6 +920,7 @@ def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None, self.crypt_algo = CRYPT_ALGOS['NULL'] self.crypt_key = None self.crypt_salt = None + self.crypt_icv_size = crypt_icv_size if auth_algo: if auth_algo not in AUTH_ALGOS: @@ -928,6 +977,7 @@ def _encrypt_esp(self, pkt, seq_num=None, iv=None, esn_en=None, esn=None): esp = self.crypt_algo.pad(esp) esp = self.crypt_algo.encrypt(self, esp, self.crypt_key, + self.crypt_icv_size, esn_en=esn_en or self.esn_en, esn=esn or self.esn) @@ -1046,6 +1096,7 @@ def _decrypt_esp(self, pkt, verify=True, esn_en=None, esn=None): self.auth_algo.verify(encrypted, self.auth_key) esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key, + self.crypt_icv_size or self.crypt_algo.icv_size or self.auth_algo.icv_size, esn_en=esn_en or self.esn_en, diff --git a/scapy/layers/tls/record.py b/scapy/layers/tls/record.py index db34fb82843..c75957cd208 100644 --- a/scapy/layers/tls/record.py +++ b/scapy/layers/tls/record.py @@ -338,8 +338,11 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs): return _TLSEncryptedContent # Check TLS 1.3 if s and _tls_version_check(s.tls_version, 0x0304): - if (s.rcs and not isinstance(s.rcs.cipher, Cipher_NULL) and - byte0 == 0x17): + _has_cipher = lambda x: ( + x and not isinstance(x.cipher, Cipher_NULL) + ) + if (_has_cipher(s.rcs) or _has_cipher(s.prcs)) and \ + byte0 == 0x17: from scapy.layers.tls.record_tls13 import TLS13 return TLS13 if plen < 5: diff --git a/test/configs/bsd.utsc b/test/configs/bsd.utsc index 27cc5baf588..f1ac3007460 100644 --- a/test/configs/bsd.utsc +++ b/test/configs/bsd.utsc @@ -27,7 +27,6 @@ "kw_ko": [ "linux", "windows", - "crypto_advanced", "ipv6", "vcan_socket" ] diff --git a/test/configs/linux.utsc b/test/configs/linux.utsc index aee9a9fa522..87d6b71c649 100644 --- a/test/configs/linux.utsc +++ b/test/configs/linux.utsc @@ -27,7 +27,6 @@ "kw_ko": [ "osx", "windows", - "crypto_advanced", "ipv6" ] } diff --git a/test/configs/windows.utsc b/test/configs/windows.utsc index 9b29faeafb5..0f7ad559324 100644 --- a/test/configs/windows.utsc +++ b/test/configs/windows.utsc @@ -25,7 +25,6 @@ }, "kw_ko": [ "brotli", - "crypto_advanced", "ipv6", "linux", "mock_read_routes_bsd", diff --git a/test/scapy/layers/ipsec.uts b/test/scapy/layers/ipsec.uts index 9b139f3b5dd..b2c4ded6d11 100644 --- a/test/scapy/layers/ipsec.uts +++ b/test/scapy/layers/ipsec.uts @@ -1695,6 +1695,7 @@ p sa = SecurityAssociation(ESP, spi=0x222, crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce', + crypt_icv_size=8, auth_algo='NULL', auth_key=None) e = sa.encrypt(p) @@ -1702,7 +1703,7 @@ e assert(isinstance(e, IP)) * after encryption packet should be encapsulated with the given ip tunnel header -assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22') +assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2') assert(e.chksum != p.chksum) assert(e.proto == socket.IPPROTO_ESP) assert(e.haslayer(ESP)) @@ -1749,7 +1750,8 @@ p sa = SecurityAssociation(ESP, spi=0x222, crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce', - auth_algo='NULL', auth_key=None) + auth_algo='NULL', auth_key=None, + tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22')) e = sa.encrypt(p) e @@ -3720,7 +3722,7 @@ e = sa.encrypt(p) e assert(isinstance(e, IPv6)) -assert(e.src == '11::22' and e.dst == '22::11') +assert(e.src == 'aa::bb' and e.dst == 'bb::aa') assert(e.nh == socket.IPPROTO_ESP) assert(e.haslayer(ESP)) assert(not e.haslayer(TCP)) @@ -3753,7 +3755,7 @@ e = sa.encrypt(p) e assert(isinstance(e, IPv6)) -assert(e.src == '11::22' and e.dst == '22::11') +assert(e.src == 'aa::bb' and e.dst == 'bb::aa') assert(e.nh == socket.IPPROTO_ESP) assert(e.haslayer(ESP)) assert(not e.haslayer(TCP)) diff --git a/test/tls/tests_tls_netaccess.uts b/test/tls/tests_tls_netaccess.uts index f447a9b5b53..834cfbf131a 100644 --- a/test/tls/tests_tls_netaccess.uts +++ b/test/tls/tests_tls_netaccess.uts @@ -343,7 +343,7 @@ test_tls_client("1305", "0304", client_auth=True) test_tls_client("1305", "0304", key_update=True) = Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and session resumption -~ crypto_advanced +~ crypto_advanced not_pypy test_tls_client("1305", "0304", client_auth=True, sess_in_out=True) diff --git a/test/tls13.uts b/test/tls13.uts index 0c12b098d45..6d8463cdc45 100644 --- a/test/tls13.uts +++ b/test/tls13.uts @@ -396,8 +396,8 @@ assert(m[1].certs[0].cert[1].cA == False) assert(m[1].certs[0].cert[1].isSelfSigned() == True) assert(m[1].certs[0].cert[1].issuer['commonName'] == 'rsa') assert(m[1].certs[0].cert[1].keyUsage == ['digitalSignature', 'keyEncipherment']) -assert(m[1].certs[0].cert[1].notAfter_str == 'Jul 30 01:23:59 2026 GMT') -assert(m[1].certs[0].cert[1].notBefore_str == 'Jul 30 01:23:59 2016 GMT') +assert(m[1].certs[0].cert[1].notAfter_str == '2026-07-30 01:23:59 UTC') +assert(m[1].certs[0].cert[1].notBefore_str == '2016-07-30 01:23:59 UTC') assert(m[1].certs[0].cert[1].serial == 2) assert(m[1].certs[0].cert[1].sigAlg == 'sha256WithRSAEncryption') assert(m[1].certs[0].cert[1].signatureLen == 128) @@ -619,56 +619,6 @@ m = t.inner.msg[0] assert(isinstance(m, TLSApplicationData)) assert(m.data == payload) -= TLS_Ext_EncryptedServerName(), dissect -~ crypto_advanced - -from scapy.layers.tls.extensions import TLS_Ext_EncryptedServerName - -clientHello3 = clean(""" -16030102c4010002c003034b1 40e7d15fc8db422cec056fbaf 0285d306df4eedad1bc6ea57d 5114e6bd52a20a5b9c7445955 e296b886469c974648cda0a68 -5d3c06d884e388f6475c32e03 2d0024130113031302c02bc02 fcca9cca8c02cc030c00ac009 c013c01400330039002f00350 00a0100025300170000ff0100 -0100000a000e000c001d00170 018001901000101000b000201 00002300000010000b0009086 87474702f312e310005000501 000000000033006b0069001d0 -02037adee0aacc37b08d47222 caf6a5097a800fcf8406ae118 38f6348294d2dde1200170041 048b127c905d6d487a40b8b19 c99c56aa1a8c208218c178dae -02568547b2ce8f538a530b858 a7a2f608d66e148baa5693d03 c519b45017c63f48c5a4c1238 707bc002b0009080304030303 020301000d001800160403050 -3060308040805080604010501 060102030201002d00020101f fce016e1301001d0020912e86 b776ee552a6bb1e2c70d7b467 770b190432237cc743a93091d -ce24623500208bc16fdcbbc7c 8756808c94f70464d68297975 f33be90e1a200633f5eb2d4c6 101249e073bff833782e57e88 2519a53ef8bde4c94a7878a2f -8461aec57802440007c7b2dab 986d9bc79257ce00ca6a998b1 fadb0114161069d364ccebae8 dab6c88151f297daeaecfd2e1 a598a486e2efc9561298f8dd5 -f35d184f0e87768777d253e68 952b730a24b342fde10df4f8e 82afdc2f10c2481634d92015d 9d5e6a9566494735d9c079115 bdeb0cd019098d1cf847c53ef -4aac41560cacdc7ce166399df 5b0c0af91d5be3f7d8224755a aa6046de52875f9ef9ac15372 7ce08019bc2648beb4b1418cb 4979ff7eaeedaec2b15695508 -4d5a480cb939fdc7f00e6cc6f c0f9675276a9d607686c4d779 d4bb7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d4eaf 386acc17dea11e37a09f63da3 -d059243b35f449e891255ac7b 4f631509d7060f001c0002400 1 -""") -t = TLS(clientHello3) -clientESNI = t.msg[0].ext[11] -assert isinstance(clientESNI, TLS_Ext_EncryptedServerName) and clientESNI.cipher == 4865 - - -= TLS_Ext_EncryptedServerName(), basic instantiation -~ crypto_advanced - -esni = TLS_Ext_EncryptedServerName(key_exchange_group=29,encrypted_sni=clean(""" -ffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235 -00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337 -82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f -adb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e -87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c -079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6 -046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939 -fdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d -4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f -""")) -assert esni.key_exchange_group == 29 and esni.encrypted_sni==clean(""" -ffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235 -00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337 -82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f -adb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e -87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c -079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6 -046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939 -fdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d -4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f -""") - = Decrypt a TLS 1.3 session - Decrypt and parse server Application Data ~ crypto_advanced # Values from RFC8448, section 3 @@ -1180,3 +1130,55 @@ m = t.inner.msg[0] assert(isinstance(m, TLSAlert)) assert(m.level == 1) assert(m.descr == 0) + +# --- Misc + += TLS_Ext_EncryptedServerName(), dissect +~ crypto_advanced + +from scapy.layers.tls.extensions import TLS_Ext_EncryptedServerName + +clientHello3 = clean(""" +16030102c4010002c003034b1 40e7d15fc8db422cec056fbaf 0285d306df4eedad1bc6ea57d 5114e6bd52a20a5b9c7445955 e296b886469c974648cda0a68 +5d3c06d884e388f6475c32e03 2d0024130113031302c02bc02 fcca9cca8c02cc030c00ac009 c013c01400330039002f00350 00a0100025300170000ff0100 +0100000a000e000c001d00170 018001901000101000b000201 00002300000010000b0009086 87474702f312e310005000501 000000000033006b0069001d0 +02037adee0aacc37b08d47222 caf6a5097a800fcf8406ae118 38f6348294d2dde1200170041 048b127c905d6d487a40b8b19 c99c56aa1a8c208218c178dae +02568547b2ce8f538a530b858 a7a2f608d66e148baa5693d03 c519b45017c63f48c5a4c1238 707bc002b0009080304030303 020301000d001800160403050 +3060308040805080604010501 060102030201002d00020101f fce016e1301001d0020912e86 b776ee552a6bb1e2c70d7b467 770b190432237cc743a93091d +ce24623500208bc16fdcbbc7c 8756808c94f70464d68297975 f33be90e1a200633f5eb2d4c6 101249e073bff833782e57e88 2519a53ef8bde4c94a7878a2f +8461aec57802440007c7b2dab 986d9bc79257ce00ca6a998b1 fadb0114161069d364ccebae8 dab6c88151f297daeaecfd2e1 a598a486e2efc9561298f8dd5 +f35d184f0e87768777d253e68 952b730a24b342fde10df4f8e 82afdc2f10c2481634d92015d 9d5e6a9566494735d9c079115 bdeb0cd019098d1cf847c53ef +4aac41560cacdc7ce166399df 5b0c0af91d5be3f7d8224755a aa6046de52875f9ef9ac15372 7ce08019bc2648beb4b1418cb 4979ff7eaeedaec2b15695508 +4d5a480cb939fdc7f00e6cc6f c0f9675276a9d607686c4d779 d4bb7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d4eaf 386acc17dea11e37a09f63da3 +d059243b35f449e891255ac7b 4f631509d7060f001c0002400 1 +""") +t = TLS(clientHello3) +clientESNI = t.msg[0].ext[11] +assert isinstance(clientESNI, TLS_Ext_EncryptedServerName) and clientESNI.cipher == 4865 + + += TLS_Ext_EncryptedServerName(), basic instantiation +~ crypto_advanced + +esni = TLS_Ext_EncryptedServerName(key_exchange_group=29,encrypted_sni=clean(""" +ffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235 +00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337 +82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f +adb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e +87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c +079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6 +046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939 +fdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d +4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f +""")) +assert esni.key_exchange_group == 29 and esni.encrypted_sni==clean(""" +ffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235 +00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337 +82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f +adb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e +87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c +079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6 +046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939 +fdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d +4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f +""")