Dissecting TLS using OpenSSL and Wireshark

security

TLS is a beast of a protocol with at least 50 extensions and over 20 years of history. This indicates that implementing can be challenging and that it is important to take a close look at its security. TLS drives the web of today. The web can not exist without it anymore. Not only that secrecy and authentication is a must-have today, it is also required by specifications like getUserMedia for WebRTC streaming.

The State Machine

Implementations of TLS usually expose an API which allows to parse and generate messages. Each time a new message is received the TLS library is responsible to update the client or server state and send out the next message 1. Cryptographic operations are executed below the API layer.

Messages can be intercepted or tampered with while they travel from one endpoint to the other. Also new messages can be injected. The task of TLS is to make sure that specific security properties of the connection like Secrecy, Forward Secrecy or Authentication are enforced.

The state machine of TLS is not formally specified 1. Therefore, each TLS library has some freedom in handling the state transitions and edge cases.

Steps in the TLS Handshake

@XargsNotBombs has illustrated the TLS handshake beautifully here. I will describe it here in a more texty way.

I am also doing here something similar like the above illustration. My approach is just more manual and simpler. I will create here a connection to the HTTP server of this blog and send some data: openssl s_client -msg -connect maxammann.org:443. This command logs all messages of the handshake as hex.

This approach has the advantage that it requires just OpenSSL and some tool to interpret binary messages like WireShark. It does not require any complex setup to look inside of encrypted TLS messages.

๐Ÿ’ป denotes a client and โ˜๏ธ a server which could be hosted in the cloud.

๐Ÿ’ป โž” โ˜๏ธ ClientHello

We will start by generating a client private $sk_C$ and public $pk_C$ key for which will be used in the elliptic curve Diffie-Hellman key exchange (ECDH).

In TLS 1.3 “static RSA and Diffie-Hellman cipher suites have been removed” 2. Key exchanges are only done using DHE. That means the names of cipher suites also are simpler now. You can query cipher suits of OpenSSL using these commands for TLS 1.2 and 1.3:

1openssl ciphers -v -s -tls1_2
2openssl ciphers -v -s -tls1_3

In my case the output for TLS 1.3 is significantly smaller. You also notice that the key exchange algorithm is no longer specified in the name of the cipher suite. The key exchange algorithm is determined in Client and Server Hello. For example the cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 states that the key exchange should happen through Elliptic Curve Diffie-Hellman Ephemeral. The site ciphersuite.info is actually quite cool as it documents all the available cipher suits out there.

Now back to the key generation. We can generate the private key using OpenSSL.

1openssl genpkey -algorithm x25519 -out -
2-----BEGIN PRIVATE KEY-----
3MC4CAQAwBQYDK2VuBCIEIAhAXnd7oaF01rCz5dUfnh8oVSONL4J0kh4I10OwljlH
4-----END PRIVATE KEY-----

For the public key:

1$ openssl pkey -in - -pubout -out -
2-----BEGIN PUBLIC KEY-----
3MCowBQYDK2VuAyEAr84Q+eKbCCSFmvV89tgxd6lRL57rpQYCX4C7eNlb1Wc=
4-----END PUBLIC KEY-----

Now we are sending the ClientHello, which starts with a Record Header:

116 03 01 01 36
  • Type is 0x16
  • Protocol Version is 3,1 (TLS 1.0) for interoperability reasons
  • Handshake Length is 0x0137

The ClientHello includes 0x0136 bytes of Handshake data:

 100000000  16 03 01 01 36 01 00 01 32 03 03 aa 17 95 f6 4f  |....6...2......O|
 200000010  48 fc fc d0 12 13 68 f8 8f 17 6f e2 57 0b 07 68  |H.....h...o.W..h|
 300000020  bb c8 5e 9f 2c 80 c5 57 55 3d 7d 20 e1 e1 5d 00  |..^.,..WU=} ..].|
 400000030  28 93 2f 4f 74 79 cf 25 63 02 b7 84 7d 81 a6 8e  |(./Oty.%c...}...|
 500000040  70 85 25 f9 d3 8d 94 fc 6e f7 42 a3 00 3e 13 02  |p.%.....n.B..>..|
 600000050  13 03 13 01 c0 2c c0 30 00 9f cc a9 cc a8 cc aa  |.....,.0........|
 700000060  c0 2b c0 2f 00 9e c0 24 c0 28 00 6b c0 23 c0 27  |.+./...$.(.k.#.'|
 800000070  00 67 c0 0a c0 14 00 39 c0 09 c0 13 00 33 00 9d  |.g.....9.....3..|
 900000080  00 9c 00 3d 00 3c 00 35 00 2f 00 ff 01 00 00 ab  |...=.<.5./......|
1000000090  00 00 00 12 00 10 00 00 0d 6d 61 78 61 6d 6d 61  |.........maxamma|
11000000a0  6e 6e 2e 6f 72 67 00 0b 00 04 03 00 01 02 00 0a  |nn.org..........|
12000000b0  00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23  |...............#|
13000000c0  00 00 00 16 00 00 00 17 00 00 00 0d 00 30 00 2e  |.............0..|
14000000d0  04 03 05 03 06 03 08 07 08 08 08 09 08 0a 08 0b  |................|
15000000e0  08 04 08 05 08 06 04 01 05 01 06 01 03 03 02 03  |................|
16000000f0  03 01 02 01 03 02 02 02 04 02 05 02 06 02 00 2b  |...............+|
1700000100  00 09 08 03 04 03 03 03 02 03 01 00 2d 00 02 01  |............-...|
1800000110  01 00 33 00 26 00 24 00 1d 00 20 9b 8a 24 e2 97  |..3.&.$... ..$..|
1900000120  70 f7 ed 95 bf 33 0e 7e 39 29 b2 10 90 35 0a 41  |p....3.~9)...5.A|
2000000130  5a b4 cd f0 1b 04 e9 ff c0 fc 50                 |Z.........P|

Now we can simply import this data into Wireshark to analyze it in a simple way. I fist used CyberChef to create a properly formatted hex dump from the values and then loaded them in Wirehark. The plain OpenSSL output can be seen in openssl_messages.txt. From this file I cleaned it up by adding missing TLS record headers like 16 03 01 01 36 where the last 2 bytes specify the length of the next message. These were crafted manually in order to make it possible to parse them with wireshark. Finally, I removed the comments and put it into CyberChef to create a hexdump.

You have to tell Wireshark to generate a dummy TCP header around it, else the detection fails. The final pcap file can be downloaded here. You can now export this as JSON or use a pretty printed version (Right-click on TLS packet and “Copy > All Visible Items”)

Client Hello Header
 1TLSv1.3 Record Layer: Handshake Protocol: Client Hello
 2    Content Type: Handshake (22)
 3    Version: TLS 1.0 (0x0301)
 4    Length: 310
 5    Handshake Protocol: Client Hello
 6        Handshake Type: Client Hello (1)
 7        Length: 306
 8        # Version represents TLS 1.2 for interoparability reasons
 9        Version: TLS 1.2 (0x0303)
10        # Random value for later use
11        Random: aa1795f64f48fcfcd0121368f88f176fe2570b0768bbc85e9f2c80c557553d7d
12        # Random data as TLS 1.3 uses the PSK method for session resuming
13        Session ID Length: 32
14        Session ID: e1e15d0028932f4f7479cf256302b7847d81a68e708525f9d38d94fc6ef742a3
Advertise Ciphers and Compression
 1        # Available cipher suits 
 2        Cipher Suites Length: 62
 3        Cipher Suites (31 suites)
 4            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
 5            Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
 6            Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
 7            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
 8            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
 9            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
10            Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
11            Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
12            Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
13            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
14            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
15            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
16            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
17            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
18            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
19            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
20            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
21            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
22            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
23            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
24            Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
25            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
26            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
27            Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
28            Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
29            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
30            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
31            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
32            Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
33            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
34            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
35        # Compression, in TLS 1.3 compression is not allowed because of CRIME attack 
36        Compression Methods Length: 1
37        Compression Methods (1 method)
38            Compression Method: null (0)
Extensions
  1        Extensions Length: 171
  2        # Used when using multiple virtual servers in NGINX/Apache for example
  3        Extension: server_name (len=18)
  4            Type: server_name (0)
  5            Length: 18
  6            Server Name Indication extension
  7                Server Name list length: 16
  8                Server Name Type: host_name (0)
  9                Server Name length: 13
 10                Server Name: maxammann.org
 11        # Supported curves for EC cryptography
 12        Extension: supported_groups (len=12)
 13            Type: supported_groups (10)
 14            Length: 12
 15            Supported Groups List Length: 10
 16            Supported Groups (5 groups)
 17                Supported Group: x25519 (0x001d)
 18                Supported Group: secp256r1 (0x0017)
 19                Supported Group: x448 (0x001e)
 20                Supported Group: secp521r1 (0x0019)
 21                Supported Group: secp384r1 (0x0018)
 22        # Supported signature algorithms of the client, determines the certificate sent by server
 23        Extension: signature_algorithms (len=48)
 24            Type: signature_algorithms (13)
 25            Length: 48
 26            Signature Hash Algorithms Length: 46
 27            Signature Hash Algorithms (23 algorithms)
 28                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
 29                    Signature Hash Algorithm Hash: SHA256 (4)
 30                    Signature Hash Algorithm Signature: ECDSA (3)
 31                Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
 32                    Signature Hash Algorithm Hash: SHA384 (5)
 33                    Signature Hash Algorithm Signature: ECDSA (3)
 34                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
 35                    Signature Hash Algorithm Hash: SHA512 (6)
 36                    Signature Hash Algorithm Signature: ECDSA (3)
 37                Signature Algorithm: ed25519 (0x0807)
 38                    Signature Hash Algorithm Hash: Unknown (8)
 39                    Signature Hash Algorithm Signature: Unknown (7)
 40                Signature Algorithm: ed448 (0x0808)
 41                    Signature Hash Algorithm Hash: Unknown (8)
 42                    Signature Hash Algorithm Signature: Unknown (8)
 43                Signature Algorithm: rsa_pss_pss_sha256 (0x0809)
 44                    Signature Hash Algorithm Hash: Unknown (8)
 45                    Signature Hash Algorithm Signature: Unknown (9)
 46                Signature Algorithm: rsa_pss_pss_sha384 (0x080a)
 47                    Signature Hash Algorithm Hash: Unknown (8)
 48                    Signature Hash Algorithm Signature: Unknown (10)
 49                Signature Algorithm: rsa_pss_pss_sha512 (0x080b)
 50                    Signature Hash Algorithm Hash: Unknown (8)
 51                    Signature Hash Algorithm Signature: Unknown (11)
 52                Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
 53                    Signature Hash Algorithm Hash: Unknown (8)
 54                    Signature Hash Algorithm Signature: Unknown (4)
 55                Signature Algorithm: rsa_pss_rsae_sha384 (0x0805)
 56                    Signature Hash Algorithm Hash: Unknown (8)
 57                    Signature Hash Algorithm Signature: Unknown (5)
 58                Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
 59                    Signature Hash Algorithm Hash: Unknown (8)
 60                    Signature Hash Algorithm Signature: Unknown (6)
 61                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
 62                    Signature Hash Algorithm Hash: SHA256 (4)
 63                    Signature Hash Algorithm Signature: RSA (1)
 64                Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
 65                    Signature Hash Algorithm Hash: SHA384 (5)
 66                    Signature Hash Algorithm Signature: RSA (1)
 67                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
 68                    Signature Hash Algorithm Hash: SHA512 (6)
 69                    Signature Hash Algorithm Signature: RSA (1)
 70                Signature Algorithm: SHA224 ECDSA (0x0303)
 71                    Signature Hash Algorithm Hash: SHA224 (3)
 72                    Signature Hash Algorithm Signature: ECDSA (3)
 73                Signature Algorithm: ecdsa_sha1 (0x0203)
 74                    Signature Hash Algorithm Hash: SHA1 (2)
 75                    Signature Hash Algorithm Signature: ECDSA (3)
 76                Signature Algorithm: SHA224 RSA (0x0301)
 77                    Signature Hash Algorithm Hash: SHA224 (3)
 78                    Signature Hash Algorithm Signature: RSA (1)
 79                Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
 80                    Signature Hash Algorithm Hash: SHA1 (2)
 81                    Signature Hash Algorithm Signature: RSA (1)
 82                Signature Algorithm: SHA224 DSA (0x0302)
 83                    Signature Hash Algorithm Hash: SHA224 (3)
 84                    Signature Hash Algorithm Signature: DSA (2)
 85                Signature Algorithm: SHA1 DSA (0x0202)
 86                    Signature Hash Algorithm Hash: SHA1 (2)
 87                    Signature Hash Algorithm Signature: DSA (2)
 88                Signature Algorithm: SHA256 DSA (0x0402)
 89                    Signature Hash Algorithm Hash: SHA256 (4)
 90                    Signature Hash Algorithm Signature: DSA (2)
 91                Signature Algorithm: SHA384 DSA (0x0502)
 92                    Signature Hash Algorithm Hash: SHA384 (5)
 93                    Signature Hash Algorithm Signature: DSA (2)
 94                Signature Algorithm: SHA512 DSA (0x0602)
 95                    Signature Hash Algorithm Hash: SHA512 (6)
 96                    Signature Hash Algorithm Signature: DSA (2)
 97        # Specify suppor of the client for example for TLS 1.0 - 1.3
 98        Extension: supported_versions (len=9)
 99            Type: supported_versions (43)
100            Length: 9
101            Supported Versions length: 8
102            Supported Version: TLS 1.3 (0x0304)
103            Supported Version: TLS 1.2 (0x0303)
104            Supported Version: TLS 1.1 (0x0302)
105            Supported Version: TLS 1.0 (0x0301)
106        # Specifies the available modes for use of PSK (for example for 0-RTT)
107        Extension: psk_key_exchange_modes (len=2)
108            Type: psk_key_exchange_modes (45)
109            Length: 2
110            PSK Key Exchange Modes Length: 1
111            PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
112        # Public key sent by the client for encrypting the following messages (see above how pk_C and sk_C are created)
113        Extension: key_share (len=38)
114            Type: key_share (51)
115            Length: 38
116            Key Share extension
117                Client Key Share Length: 36
118                Key Share Entry: Group: x25519, Key Exchange length: 32
119                    Group: x25519 (29)
120                    Key Exchange Length: 32
121                    Key Exchange: 9b8a24e29770f7ed95bf330e7e3929b21090350a415ab4cdf01b04e9ffc0fc50

Other Extensions
 1        Extension: session_ticket (len=0)
 2            Type: session_ticket (35)
 3            Length: 0
 4            Data (0 bytes)
 5        Extension: encrypt_then_mac (len=0)
 6            Type: encrypt_then_mac (22)
 7            Length: 0
 8        Extension: extended_master_secret (len=0)
 9            Type: extended_master_secret (23)
10            Length: 0
11        Extension: ec_point_formats (len=4)
12            Type: ec_point_formats (11)
13            Length: 4
14            EC point formats Length: 3
15            Elliptic curves point formats (3)
16                EC point format: uncompressed (0)
17                EC point format: ansiX962_compressed_prime (1)
18                EC point format: ansiX962_compressed_char2 (2)

โ˜๏ธ โž” ๐Ÿ’ป Server Hello

The server will also generate a public and private key for DH key exchange. This is done in the same way as in Client Hello (openssl genpkey -algorithm x25519). So now we have the keys $sk_S$ and public $pk_S$.

Disassembly
 1TLSv1.3 Record Layer: Handshake Protocol: Server Hello
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 122
 5    Handshake Protocol: Server Hello
 6        Handshake Type: Server Hello (2)
 7        Length: 118
 8        # Same as in Client Hello: We need to disguise as TLS 1.2
 9        Version: TLS 1.2 (0x0303)
10        # Random value which will be used later on (TODO: Where?!)
11        Random: debc41503f1f52ec094f9bdf2c0f941db8928069d202f352201b337bea4ed436
12        Session ID Length: 32
13        # Session ID of the client, this is no longer sued in TLS 1.3
14        Session ID: e1e15d0028932f4f7479cf256302b7847d81a68e708525f9d38d94fc6ef742a3
15        # The selected cipher suite
16        Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
17        # Compression method selected by client
18        Compression Method: null (0)
19        Extensions Length: 46
20        # Specifies that we are using TLS 1.3
21        Extension: supported_versions (len=2)
22            Type: supported_versions (43)
23            Length: 2
24            Supported Version: TLS 1.3 (0x0304)
25        # Contains the public key of the server which is used in DH (see above how pk_S and sk_S are created)
26        Extension: key_share (len=36)
27            Type: key_share (51)
28            Length: 36
29            Key Share extension
30                Key Share Entry: Group: x25519, Key Exchange length: 32
31                    Group: x25519 (29)
32                    Key Exchange Length: 32
33                    Key Exchange: 8cbdb10a727ffe655f368521b39a16146d55ff144a0f95235ccd1925c31f6137

Now we are ready to calculate the keys which are used in the encryption of the following handshake messages. The server calculates $sk_S * pk_C$. Now we calculate the SHA256 hash of all sent bytes so far, except the record headers. This includes Client and Server Hello so far. This is also called the transcript hash.

The transcript hash and secret are now fed to a KDF procedure. From this data we derive multiple secrets using HKDF-Extract and HKDF-Expand-Label specified in RFC-5869.

We have now (RFC8446 7.1)

  • client_handshake_traffic_secret
  • server_handshake_traffic_secret.

From these secrets we can derive keys and IVs: (RFC8446 7.3):

  • client_handshake_key & client_handshake_iv
  • server_handshake_key & server_handshake_iv.

The cool thing is that because of the Diffie Hellman key exchange the client can calculate the same values as it has the transcript hash, client private key and the server public key. That means client_handshake_traffic_secret = server_handshake_traffic_secret and the same for the IV.

โ˜๏ธ โž” ๐Ÿ’ป Change Cipher Spec

This record is sent to disguise as TLS 1.2.

Disassembly
1TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
2    Content Type: Change Cipher Spec (20)
3    Version: TLS 1.2 (0x0303)
4    Length: 1
5    Change Cipher Spec Message

โ˜๏ธ โž” ๐Ÿ’ป Encrypted Extensions (Encrypted ๐Ÿ”)

This is the first message which is encrypted using the server handshake keys and IVs like described in Server Hello. An AEAD authentification tag possibly is included to achive integrity.

This handshake record contains more extensions which are transmitted encrypted.

Other Extensions
 1TLSv1.3 Record Layer: Handshake Protocol: Encrypted Extensions
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 10
 5    Handshake Protocol: Encrypted Extensions
 6        Handshake Type: Encrypted Extensions (8)
 7        Length: 6
 8        Extensions Length: 4
 9        Extension: server_name (len=0)
10            Type: server_name (0)
11            Length: 0

โ˜๏ธ โž” ๐Ÿ’ป Certificate (๐Ÿ”)

This message contains the certificate chain. Certificates are encoded in DER. Wireshark makes it easy to look into the certificates. Certificate chains are basically just a list of certificates. If you want to play with certificates then you can use the OpenSSL CLI. The command openssl verify -verbose -CAfile ca.pem chain.pem verifies a chain. ca.pem would be a root certificate which you trust. chain.pem contains all the files in an ASCII format separated by new lines. OpenSSl reports then whether it is fine or not. When using the openssl s_client -connect command you also see the certificates and verbose output about the validation.

Certificate Hello
 1TLSv1.3 Record Layer: Handshake Protocol: Certificate
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 2485
 5    Handshake Protocol: Certificate
 6        Handshake Type: Certificate (11)
 7        Length: 2481
 8        Certificate Request Context Length: 0
 9        Certificates Length: 2477
10        Certificates (2477 bytes)
Let's Encrypt Certificate for maxammann.org
  1            Certificate Length: 1338
  2            Certificate: 308205363082041ea00302010202120400ca5961d39c1622093596f2132488f93e300d06โ€ฆ (id-at-commonName=www.maxammann.org)
  3                signedCertificate
  4                    version: v3 (2)
  5                    serialNumber: 0x0400ca5961d39c1622093596f2132488f93e
  6                    signature (sha256WithRSAEncryption)
  7                        Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
  8                    issuer: rdnSequence (0)
  9                        rdnSequence: 3 items (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
 10                            RDNSequence item: 1 item (id-at-countryName=US)
 11                                RelativeDistinguishedName item (id-at-countryName=US)
 12                                    Id: 2.5.4.6 (id-at-countryName)
 13                                    CountryName: US
 14                            RDNSequence item: 1 item (id-at-organizationName=Let's Encrypt)
 15                                RelativeDistinguishedName item (id-at-organizationName=Let's Encrypt)
 16                                    Id: 2.5.4.10 (id-at-organizationName)
 17                                    DirectoryString: printableString (1)
 18                                        printableString: Let's Encrypt
 19                            RDNSequence item: 1 item (id-at-commonName=R3)
 20                                RelativeDistinguishedName item (id-at-commonName=R3)
 21                                    Id: 2.5.4.3 (id-at-commonName)
 22                                    DirectoryString: printableString (1)
 23                                        printableString: R3
 24                    validity
 25                        notBefore: utcTime (0)
 26                            utcTime: 2021-03-28 01:43:58 (UTC)
 27                        notAfter: utcTime (0)
 28                            utcTime: 2021-06-26 01:43:58 (UTC)
 29                    subject: rdnSequence (0)
 30                        rdnSequence: 1 item (id-at-commonName=www.maxammann.org)
 31                            RDNSequence item: 1 item (id-at-commonName=www.maxammann.org)
 32                                RelativeDistinguishedName item (id-at-commonName=www.maxammann.org)
 33                                    Id: 2.5.4.3 (id-at-commonName)
 34                                    DirectoryString: printableString (1)
 35                                        printableString: www.maxammann.org
 36                    subjectPublicKeyInfo
 37                        algorithm (rsaEncryption)
 38                            Algorithm Id: 1.2.840.113549.1.1.1 (rsaEncryption)
 39                        subjectPublicKey: 3082010a0282010100b8ad1a3825f4aa8f8cdf5221a5d98d29f93be72f470397e07e1cecโ€ฆ
 40                            modulus: 0x00b8ad1a3825f4aa8f8cdf5221a5d98d29f93be72f470397e07e1ceca379376bf1b148d1โ€ฆ
 41                            publicExponent: 65537
 42                    extensions: 9 items
 43                        Extension (id-ce-keyUsage)
 44                            Extension Id: 2.5.29.15 (id-ce-keyUsage)
 45                            critical: True
 46                            Padding: 5
 47                            KeyUsage: a0
 48                                1... .... = digitalSignature: True
 49                                .0.. .... = contentCommitment: False
 50                                ..1. .... = keyEncipherment: True
 51                                ...0 .... = dataEncipherment: False
 52                                .... 0... = keyAgreement: False
 53                                .... .0.. = keyCertSign: False
 54                                .... ..0. = cRLSign: False
 55                                .... ...0 = encipherOnly: False
 56                                0... .... = decipherOnly: False
 57                        Extension (id-ce-extKeyUsage)
 58                            Extension Id: 2.5.29.37 (id-ce-extKeyUsage)
 59                            KeyPurposeIDs: 2 items
 60                                KeyPurposeId: 1.3.6.1.5.5.7.3.1 (id-kp-serverAuth)
 61                                KeyPurposeId: 1.3.6.1.5.5.7.3.2 (id-kp-clientAuth)
 62                        Extension (id-ce-basicConstraints)
 63                            Extension Id: 2.5.29.19 (id-ce-basicConstraints)
 64                            critical: True
 65                            BasicConstraintsSyntax [0 length]
 66                        Extension (id-ce-subjectKeyIdentifier)
 67                            Extension Id: 2.5.29.14 (id-ce-subjectKeyIdentifier)
 68                            SubjectKeyIdentifier: 12b43a1e54091741afc831d1e4de7babcb110ebe
 69                        Extension (id-ce-authorityKeyIdentifier)
 70                            Extension Id: 2.5.29.35 (id-ce-authorityKeyIdentifier)
 71                            AuthorityKeyIdentifier
 72                                keyIdentifier: 142eb317b75856cbae500940e61faf9d8b14c2c6
 73                        Extension (id-pe-authorityInfoAccess)
 74                            Extension Id: 1.3.6.1.5.5.7.1.1 (id-pe-authorityInfoAccess)
 75                            AuthorityInfoAccessSyntax: 2 items
 76                                AccessDescription
 77                                    accessMethod: 1.3.6.1.5.5.7.48.1 (id-ad-ocsp)
 78                                    accessLocation: 6
 79                                        uniformResourceIdentifier: http://r3.o.lencr.org
 80                                AccessDescription
 81                                    accessMethod: 1.3.6.1.5.5.7.48.2 (id-ad-caIssuers)
 82                                    accessLocation: 6
 83                                        uniformResourceIdentifier: http://r3.i.lencr.org/
 84                        Extension (id-ce-subjectAltName)
 85                            Extension Id: 2.5.29.17 (id-ce-subjectAltName)
 86                            GeneralNames: 2 items
 87                                GeneralName: dNSName (2)
 88                                    dNSName: maxammann.org
 89                                GeneralName: dNSName (2)
 90                                    dNSName: www.maxammann.org
 91                        Extension (id-ce-certificatePolicies)
 92                            Extension Id: 2.5.29.32 (id-ce-certificatePolicies)
 93                            CertificatePoliciesSyntax: 2 items
 94                                PolicyInformation
 95                                    policyIdentifier: 2.23.140.1.2.1 (joint-iso-itu-t.23.140.1.2.1)
 96                                PolicyInformation
 97                                    policyIdentifier: 1.3.6.1.4.1.44947.1.1.1 (iso.3.6.1.4.1.44947.1.1.1)
 98                                    policyQualifiers: 1 item
 99                                        PolicyQualifierInfo
100                                            Id: 1.3.6.1.5.5.7.2.1 (id-qt-cps)
101                                            DirectoryString: http://cps.letsencrypt.org
102                        Extension (SignedCertificateTimestampList)
103                            Extension Id: 1.3.6.1.4.1.11129.2.4.2 (SignedCertificateTimestampList)
104                            Serialized SCT List Length: 239
105                            Signed Certificate Timestamp (Cloudflare 'Nimbus2021' Log)
106                                Serialized SCT Length: 118
107                                SCT Version: 0
108                                Log ID: 4494652eb0eeceafc44007d8a8fe28c0dae682bed8cb31b53fd33396b5b681a8
109                                Timestamp: Mar 28, 2021 02:43:58.350000000 UTC
110                                Extensions length: 0
111                                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
112                                    Signature Hash Algorithm Hash: SHA256 (4)
113                                    Signature Hash Algorithm Signature: ECDSA (3)
114                                Signature Length: 71
115                                Signature: 304502201c5b58adfa5df8abf6077d94b765750a24d32b49b3af2dcf5c65efaf32c949d6โ€ฆ
116                            Signed Certificate Timestamp (Google 'Xenon2021' log)
117                                Serialized SCT Length: 117
118                                SCT Version: 0
119                                Log ID: 7d3ef2f88fff88556824c2c0ca9e5289792bc50e78097f2e6a9768997e22f0d7
120                                Timestamp: Mar 28, 2021 02:43:58.382000000 UTC
121                                Extensions length: 0
122                                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
123                                    Signature Hash Algorithm Hash: SHA256 (4)
124                                    Signature Hash Algorithm Signature: ECDSA (3)
125                                Signature Length: 70
126                                Signature: 30440220030a54d2296566cab9b5fa3e6505566e5e014d48f15f6cd8727896e2cc352eb3โ€ฆ
127                algorithmIdentifier (sha256WithRSAEncryption)
128                    Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
129                Padding: 0
130                encrypted: 8c770bcf525fc99d9f8f04d279b724bbb2bebc42184e671aa392b058265b097de2d9f668โ€ฆ
131            Extensions Length: 0
DST Root CA X3 Certificate for Let's Encrypt
  1            Certificate Length: 1129
  2            Certificate: 308204653082034da0030201020210400175048314a4c8218c84a90c16cddf300d06092aโ€ฆ (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
  3                signedCertificate
  4                    version: v3 (2)
  5                    serialNumber: 0x400175048314a4c8218c84a90c16cddf
  6                    signature (sha256WithRSAEncryption)
  7                        Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
  8                    issuer: rdnSequence (0)
  9                        rdnSequence: 2 items (id-at-commonName=DST Root CA X3,id-at-organizationName=Digital Signature Trust Co.)
 10                            RDNSequence item: 1 item (id-at-organizationName=Digital Signature Trust Co.)
 11                                RelativeDistinguishedName item (id-at-organizationName=Digital Signature Trust Co.)
 12                                    Id: 2.5.4.10 (id-at-organizationName)
 13                                    DirectoryString: printableString (1)
 14                                        printableString: Digital Signature Trust Co.
 15                            RDNSequence item: 1 item (id-at-commonName=DST Root CA X3)
 16                                RelativeDistinguishedName item (id-at-commonName=DST Root CA X3)
 17                                    Id: 2.5.4.3 (id-at-commonName)
 18                                    DirectoryString: printableString (1)
 19                                        printableString: DST Root CA X3
 20                    validity
 21                        notBefore: utcTime (0)
 22                            utcTime: 2020-10-07 19:21:40 (UTC)
 23                        notAfter: utcTime (0)
 24                            utcTime: 2021-09-29 19:21:40 (UTC)
 25                    subject: rdnSequence (0)
 26                        rdnSequence: 3 items (id-at-commonName=R3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
 27                            RDNSequence item: 1 item (id-at-countryName=US)
 28                                RelativeDistinguishedName item (id-at-countryName=US)
 29                                    Id: 2.5.4.6 (id-at-countryName)
 30                                    CountryName: US
 31                            RDNSequence item: 1 item (id-at-organizationName=Let's Encrypt)
 32                                RelativeDistinguishedName item (id-at-organizationName=Let's Encrypt)
 33                                    Id: 2.5.4.10 (id-at-organizationName)
 34                                    DirectoryString: printableString (1)
 35                                        printableString: Let's Encrypt
 36                            RDNSequence item: 1 item (id-at-commonName=R3)
 37                                RelativeDistinguishedName item (id-at-commonName=R3)
 38                                    Id: 2.5.4.3 (id-at-commonName)
 39                                    DirectoryString: printableString (1)
 40                                        printableString: R3
 41                    subjectPublicKeyInfo
 42                        algorithm (rsaEncryption)
 43                            Algorithm Id: 1.2.840.113549.1.1.1 (rsaEncryption)
 44                        subjectPublicKey: 3082010a0282010100bb021528ccf6a094d30f12ec8d5592c3f882f199a67a4288a75d26โ€ฆ
 45                            modulus: 0x00bb021528ccf6a094d30f12ec8d5592c3f882f199a67a4288a75d26aab52bb9c54cb1afโ€ฆ
 46                            publicExponent: 65537
 47                    extensions: 8 items
 48                        Extension (id-ce-basicConstraints)
 49                            Extension Id: 2.5.29.19 (id-ce-basicConstraints)
 50                            critical: True
 51                            BasicConstraintsSyntax
 52                                cA: True
 53                                pathLenConstraint: 0
 54                        Extension (id-ce-keyUsage)
 55                            Extension Id: 2.5.29.15 (id-ce-keyUsage)
 56                            critical: True
 57                            Padding: 1
 58                            KeyUsage: 86
 59                                1... .... = digitalSignature: True
 60                                .0.. .... = contentCommitment: False
 61                                ..0. .... = keyEncipherment: False
 62                                ...0 .... = dataEncipherment: False
 63                                .... 0... = keyAgreement: False
 64                                .... .1.. = keyCertSign: True
 65                                .... ..1. = cRLSign: True
 66                                .... ...0 = encipherOnly: False
 67                                0... .... = decipherOnly: False
 68                        Extension (id-pe-authorityInfoAccess)
 69                            Extension Id: 1.3.6.1.5.5.7.1.1 (id-pe-authorityInfoAccess)
 70                            AuthorityInfoAccessSyntax: 1 item
 71                                AccessDescription
 72                                    accessMethod: 1.3.6.1.5.5.7.48.2 (id-ad-caIssuers)
 73                                    accessLocation: 6
 74                                        uniformResourceIdentifier: http://apps.identrust.com/roots/dstrootcax3.p7c
 75                        Extension (id-ce-authorityKeyIdentifier)
 76                            Extension Id: 2.5.29.35 (id-ce-authorityKeyIdentifier)
 77                            AuthorityKeyIdentifier
 78                                keyIdentifier: c4a7b1a47b2c71fadbe14b9075ffc41560858910
 79                        Extension (id-ce-certificatePolicies)
 80                            Extension Id: 2.5.29.32 (id-ce-certificatePolicies)
 81                            CertificatePoliciesSyntax: 2 items
 82                                PolicyInformation
 83                                    policyIdentifier: 2.23.140.1.2.1 (joint-iso-itu-t.23.140.1.2.1)
 84                                PolicyInformation
 85                                    policyIdentifier: 1.3.6.1.4.1.44947.1.1.1 (iso.3.6.1.4.1.44947.1.1.1)
 86                                    policyQualifiers: 1 item
 87                                        PolicyQualifierInfo
 88                                            Id: 1.3.6.1.5.5.7.2.1 (id-qt-cps)
 89                                            DirectoryString: http://cps.root-x1.letsencrypt.org
 90                        Extension (id-ce-cRLDistributionPoints)
 91                            Extension Id: 2.5.29.31 (id-ce-cRLDistributionPoints)
 92                            CRLDistPointsSyntax: 1 item
 93                                DistributionPoint
 94                                    distributionPoint: fullName (0)
 95                                        fullName: 1 item
 96                                            GeneralName: uniformResourceIdentifier (6)
 97                                                uniformResourceIdentifier: http://crl.identrust.com/DSTROOTCAX3CRL.crl
 98                        Extension (id-ce-subjectKeyIdentifier)
 99                            Extension Id: 2.5.29.14 (id-ce-subjectKeyIdentifier)
100                            SubjectKeyIdentifier: 142eb317b75856cbae500940e61faf9d8b14c2c6
101                        Extension (id-ce-extKeyUsage)
102                            Extension Id: 2.5.29.37 (id-ce-extKeyUsage)
103                            KeyPurposeIDs: 2 items
104                                KeyPurposeId: 1.3.6.1.5.5.7.3.1 (id-kp-serverAuth)
105                                KeyPurposeId: 1.3.6.1.5.5.7.3.2 (id-kp-clientAuth)
106                algorithmIdentifier (sha256WithRSAEncryption)
107                    Algorithm Id: 1.2.840.113549.1.1.11 (sha256WithRSAEncryption)
108                Padding: 0
109                encrypted: d94ce0c9f584883731dbbb13e2b3fc8b6b62126c58b7497e3c02b7a81f2861ebcee02e73โ€ฆ
110            Extensions Length: 0

โ˜๏ธ โž” ๐Ÿ’ป Certificate Verify (๐Ÿ”)

Because the server is generating ephemeral keys for each session (optional in TLS 1.2, mandatory in TLS 1.3) the session is not inherently tied to the certificate as it was in previous versions of TLS, when the certificate’s public/private key were used for key exchange.

To prove that the server owns the server certificate (giving the certificate validity in this TLS session), it signs a hash of the handshake messages using the certificate’s private key. The signature can be proven valid by the client by using the certificate’s public key. (@XargsNotBombs)

Disassembly
 1TLSv1.3 Record Layer: Handshake Protocol: Certificate Verify
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 264
 5    Handshake Protocol: Certificate Verify
 6        Handshake Type: Certificate Verify (15)
 7        Length: 260
 8        Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
 9            Signature Hash Algorithm Hash: Unknown (8)
10            Signature Hash Algorithm Signature: Unknown (4)
11        Signature length: 256
12        Signature: 9adbef9d1b56a66dcd7e86eb8fbc826e66c3ea46802d757fc700576594835ad7bc66f1adโ€ฆ

โ˜๏ธ โž” ๐Ÿ’ป Finish (๐Ÿ”)

The Finish contains verify data. A finished key is derived from the server_handshake_traffic_secret (RFC8446 4.4.4). This key is used to create an HMAC of the hash of the transcript of sent messages.

Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Finished
2    Content Type: Handshake (22)
3    Version: TLS 1.2 (0x0303)
4    Length: 52
5    Handshake Protocol: Finished
6        Handshake Type: Finished (20)
7        Length: 48
8        Verify Data

๐Ÿ’ป โž” โ˜๏ธ Change Cipher Spec

This message if not encrypted and is only here for backward compatibility with TLS 1.2.

Disassembly
1TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
2    Content Type: Change Cipher Spec (20)
3    Version: TLS 1.2 (0x0303)
4    Length: 1
5    Change Cipher Spec Message

๐Ÿ’ป โž” โ˜๏ธ Finished (๐Ÿ”)

This is the first message which is encrypted using the client handshake keys and IVs like described in Server Hello. The verify data is constructed in the same way as the last Finished, just that client_handshake_traffic_secret is used.

Disassembly
1TLSv1.3 Record Layer: Handshake Protocol: Finished
2    Content Type: Handshake (22)
3    Version: TLS 1.2 (0x0303)
4    Length: 52
5    Handshake Protocol: Finished
6        Handshake Type: Finished (20)
7        Length: 48
8        Verify Data

โ˜๏ธ โž” ๐Ÿ’ป New Session Ticket (๐Ÿ”)

The server provides a session ticket that the client can use to start a new session later. Successfully resuming a connection in this way will skip most of the computation and network delay in session startup.

Because each session ticket is meant to be single-use, and because the server expects a browser to open multiple connections, it makes a size vs. speed decision to provide the client with two session tickets for each negotiated session. (@XargsNotBombs)

One could think that the server just has a database of valid Session Ticket and looks them up if a ticket is received. This is not needed usually though. The server has a ticket encryption key $k_t$. When creating a ticket the server encrypts some pre shared key $psk$ with $k_t$ and sends $enc(psk)$ and $psk$ to the client. When a session ticket is received the server can check it by decrypting $enc(psk)$ and comparing it with $psk$.

Disassembly
 1TLSv1.3 Record Layer: Handshake Protocol: New Session Ticket
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 265
 5    Handshake Protocol: New Session Ticket
 6        Handshake Type: New Session Ticket (4)
 7        Length: 261
 8        TLS Session Ticket
 9            # Lifetime of this ticket
10            Session Ticket Lifetime Hint: 300 seconds (5 minutes)
11            # Milliseconds which have to be added to the generation date when sending this ticket back to the server. This prevents correlaction between the resumed session and the session which created this ticket.
12            Session Ticket Age Add: 4125054233
13            # A unique per ticket value
14            Session Ticket Nonce Length: 8
15            Session Ticket Nonce: 0000000000000000
16            Session Ticket Length: 240
17            # Data which is meaningful to the server to resume the session.
18            Session Ticket: 85d9d71b78d02770ec876056db0e96cdb56cf40a05269064b9eb082759fdea509db4bca2โ€ฆ
19            Extensions Length: 0

โ˜๏ธ โž” ๐Ÿ’ป New Session Ticket (๐Ÿ”)

An additional ticket for session resumption.

Disassembly
 1TLSv1.3 Record Layer: Handshake Protocol: New Session Ticket
 2    Content Type: Handshake (22)
 3    Version: TLS 1.2 (0x0303)
 4    Length: 265
 5    Handshake Protocol: New Session Ticket
 6        Handshake Type: New Session Ticket (4)
 7        Length: 261
 8        TLS Session Ticket
 9            Session Ticket Lifetime Hint: 300 seconds (5 minutes)
10            Session Ticket Age Add: 763549134
11            Session Ticket Nonce Length: 8
12            Session Ticket Nonce: 0000000000000001
13            Session Ticket Length: 240
14            Session Ticket: 85d9d71b78d02770ec876056db0e96cd3f58b452a549a597259c839dec496d4d37dc6296โ€ฆ
15            Extensions Length: 0

Application Data

For transmitting application data a new key is derived from the secrets. The procedure is similar to that in Server Hello. Just some other derivation function are used. See RFC8446 4.4.4 - Master Secret.


  1. Messy State of the Union ↩︎

  2. RFC8446 1.2 ↩︎

Do you have questions? Send an email to max@maxammann.org