• 09/10/2022

TLS experiments with openssl-s_client – TLS Handshake Protocol Revisited

13.6.3 TLS experiments with openssl-s_client

So, what kind of experiments can we do using openssl-s˙client to better understand how TLS works under the hood? Well, we could start by looking into the protocol messages of an actual TLS session. As an example, we could perform a TLS handshake with the Packt web server:

# openssl s_client -connect packtpub.com:443 -msg

The output corresponding to the preceding command gives a detailed view of the TLS handshake, including all TLS messages, their length in bytes, and their hex dumps:

>>> TLS 1.0, RecordHeader [length 0005]
   16 03 01 01 35
>>> TLS 1.3, Handshake [length 0135], ClientHello
   01 00 01 31 03 03 1c 29 cd 91 3f dc 5e 9e 6b 4f
   — snip —
<<< TLS 1.2, RecordHeader [length 0005]
   16 03 03 00 7a
<<< TLS 1.3, Handshake [length 007a], ServerHello
   02 00 00 76 03 03 5f f0 44 0e 05 69 25 78 14 cb
   — snip —
<<< TLS 1.2, RecordHeader [length 0005]
   14 03 03 00 01
<<< TLS 1.2, RecordHeader [length 0005]
   17 03 03 09 f4

<<< TLS 1.3, InnerContent [length 0001]
   16
<<< TLS 1.3, Handshake [length 000a], EncryptedExtensions
   08 00 00 06 00 04 00 00 00 00
<<< TLS 1.3, Handshake [length 0956], Certificate
   0b 00 09 52 00 00 09 4e 00 05 73 30 82 05 6f 30
   — snip —
depth=2 C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
verify return:1
depth=1 C = US, O = “Cloudflare, Inc.”, CN = Cloudflare Inc ECC CA-3
verify return:1
depth=0 C = US, ST = California, L = San Francisco, O = “Cloudflare, Inc.”, CN = packtpub.com
verify return:1
<<< TLS 1.3, \index{OpenSSL client!TLS experiments}Handshake [length 004f], CertificateVerify
   0f 00 00 4b 04 03 00 47 30 45 02 20 7f f9 da ed
   — snip —
<<< TLS 1.3, Handshake [length 0034], Finished
   14 00 00 30 2a 64 1c 8f e0 f9 f1 ab 2b 3d 7b e8
   — snip —
>>> TLS 1.2, RecordHeader [length 0005]
   14 03 03 00 01
>>> TLS 1.3, ChangeCipherSpec [length 0001]
   01
>>> TLS 1.2, RecordHeader [length 0005]
   17 03 03 00 45
>>> TLS 1.2, InnerContent [length 0001]
   16
>>> TLS 1.3, Handshake [length 0034], Finished
   14 00 00 30 c1 23 05 61 7b 03 8e c9 d9 b5 1e de
   — snip —

Note that the TLS messages sent by the client are denoted by ¿¿¿ and the TLS messages sent by the server by ¡¡¡. In addition, the command’s output includes the certificate presented by the server and the cryptographic settings of the TLS session:

Certificate chain
   0 s:C = US, ST = California, L = San Francisco, O = “Cloudflare, Inc.”, CN = packtpub.com
      i:C = US, O = “Cloudflare, Inc.”, CN = Cloudflare Inc ECC CA-3
      a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA256
      v:NotBefore: Apr  7 00:00:00 2023 GMT; NotAfter: Apr  6 23:59:59 2024 GMT
   1 s:C = US, O = “Cloudflare, Inc.”, CN = Cloudflare Inc ECC CA-3
     i:C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
     a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
     v:NotBefore: Jan 27 12:48:08 2020 GMT; NotAfter: Dec 31 23:59:59 2024 GMT
   —
   Server certificate
   —–BEGIN CERTIFICATE—–
   MIIFbzCCBRWgAwIBAgIQCjUceIvorTtWOHsotymexDAKBggqhkjOPQQDAjBKMQsw
   — snip —
   —–END CERTIFICATE—–
   subject=C = US, ST = California, L = San Francisco, O = “Cloudflare, Inc.”,
   CN = packtpub.com
   issuer=C = US, O = “Cloudflare, Inc.”, CN = Cloudflare Inc ECC CA-3
   —
   No client certificate CA names sent
   Peer signing digest: SHA256
   Peer signature type: ECDSA
   Server Temp Key: X25519, 253 bits
   —
   SSL handshake has read 2686 bytes and written 394 bytes
   Verification: OK

   —
   New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
   Server public key is 256 bit
   — snip —

Next, we might want to know what the ClientHello message sent by openssl-s˙client to the Packt web server actually looks like. This can be done using the -trace option:

# openssl s_client -connect packtpub.com:443 -trace

The corresponding output contains detailed information about ClientHello and the values of its parameters:

Sent Record
Header:
  Version = TLS 1.0 (0x301)
  Content Type = Handshake (22)
  Length = 309
   ClientHello, Length=305
     client_version=0x303 (TLS 1.2)
     Random:
       gmt_unix_time=0xF96120B2
       random_bytes (len=28): 2C2985BC3763DE — snip —
     session_id (len=32): 16BB585F1BAA7C — snip —
     cipher_suites (len=62)
       {0x13, 0x02} TLS_AES_256_GCM_SHA384
       {0x13, 0x03} TLS_CHACHA20_POLY1305_SHA256
       {0x13, 0x01} TLS_AES_128_GCM_SHA256
       — snip —
     compression_methods (len=1)
       No Compression (0x00)
     extensions, length = 170

       extension_type=server_name(0), length=17
         0000 – 00 0f 00 00 0c 70 61 63-6b 74 70 75 62 2e 63   …..packtpub.c
         000f – 6f 6d                                        om
       extension_type=ec_point_formats(11), length=4
         uncompressed (0)
         ansiX962_compressed_prime (1)
         ansiX962_compressed_char2 (2)
       extension_type=supported_groups(10), length=22
         ecdh_x25519 (29)
         secp256r1 (P-256) (23)
         ecdh_x448 (30)
         — snip —
       extension_type=session_ticket(35), length=0
       extension_type=encrypt_then_mac(22), length=0
       extension_type=extended_master_secret(23), length=0
       extension_type=signature_algorithms(13), length=42
         ecdsa_secp256r1_sha256 (0x0403)
         ecdsa_secp384r1_sha384 (0x0503)
         ecdsa_secp521r1_sha512 (0x0603)
         — snip —
       \index{OpenSSL client!TLS experiments}extension_type=supported_versions(43), length=5
         TLS 1.3 (772)
         TLS 1.2 (771)
       extension_type=psk_key_exchange_modes(45), length=2
          psk_dhe_ke (1)
       extension_type=key_share(51), length=38
          NamedGroup: ecdh_x25519 (29)
          key_exchange:  (len=32): F00D50A5796047 — snip —

Now let’s take a look at the states of the OpenSSL client state machine as the TLS connection to the Packt web server is being established. We can do this by executing the following command:

# openssl s_client -connect packtpub.com:443 -state

In the corresponding output, we can see that openssl-s˙client starts by sending ClientHello. After that, it transitions through a sequence of states where it receives the ServerHello, EncryptedExtensions, Certificate, CertificateVerify, and Finished messages from the TLS server. As a final step, the client sends its Finished message, thereby completing the TLS handshake:

SSL_connect:before SSL initialization
SSL_connect:SSLv3/TLS write client hello
SSL_connect:SSLv3/TLS write client hello
SSL_connect:SSLv3/TLS read server hello
SSL_connect:TLSv1.3 read encrypted extensions
— snip —
SSL_connect:SSLv3/TLS read server certificate
SSL_connect:TLSv1.3 read server certificate verify
SSL_connect:SSLv3/TLS read finished
SSL_connect:SSLv3/TLS write change cipher spec
SSL_connect:SSLv3/TLS write finished

Moreover, we can examine the details of TLS extensions that the Packt web server transmitted using the following command:

# openssl s_client -connect packtpub.com:443 -tlsextdebug

The corresponding output lists all TLS extensions sent by the server as well as their values in hexadecimal representation:

TLS server extension “key share” (id=51), len=36
   0000 – 00 1d 00 20 08 3c 18 21-98 94 30 17 a1 37 00 8f   …
.<.!..0..7..
   0010 – c4 07 6f 93 69 46 3a 94-bc 08 f3 82 61 82 ac a7   ..o.iF:…..a…
   0020 – 73 bb 1e 3f                                     s..?
TLS server extension “supported versions” (id=43), len=2
   0000 – 03 04                                           ..
TLS server extension “server name” (id=0), len=0
— snip —

Finally, let’s examine the OCSP response for the digital certificate that the Packt web server has presented to openssl-s˙client. We can do this using the following command:

# openssl s_client -connect packtpub.com:443 -status

The corresponding output shows the OCSP response status, the status of the certificate when the response was generated, and other details:

— snip —
OCSP response:
======================================
OCSP Response Data:
   OCSP Response Status: successful (0x0)
   Response Type: Basic OCSP Response
   Version: 1 (0x0)
   Responder Id: A5CE37EAEBB0750E946788B445FAD9241087961F
   Produced At: Apr 29 20:42:45 2023 GMT
   Responses:
   Certificate ID:
       Hash Algorithm: sha1

       Issuer Name Hash: 12D78B402C356206FA827F8ED8922411B4ACF504
       Issuer Key Hash: A5CE37EAEBB0750E946788B445FAD9241087961F
       Serial Number: 0A351C788BE8AD3B56387B28B7299EC4
   Cert Status: good
   This Update: Apr 29 20:27:01 2023 GMT
   Next Update: May  6 19:42:01 2023 GMT
   Signature Algorithm: ecdsa-with-SHA256
   Signature Value:
       30:44:02:20:17:4b:4e:d7:99:e4:ec:b3:ea:75:5a:33:bc:7b:
       c7:da:69:30:03:20:99:48:b5:f6:e3:78:a4:dd:ff:78:04:3a:
       02:20:6f:0a:b8:07:b0:40:9e:2c:16:96:6f:de:11:73:1a:fb:
       3d:74:d4:9a:77:61:ae:8e:ac:8d:42:fb:f1:d4:e5:d7
======================================
   — snip —

We encourage you to explore further options of the openssl-s˙client tool and experiment with other hosts. You can also adjust the list of signature algorithms or curves that the openssl-s˙client supports and observe how the TLS server responds, especially if it does not support any of the algorithms from that list.

Leave a Reply

Your email address will not be published. Required fields are marked *