I’m trying to use the TLS Session Resumption feature in TLS 1.2 and 1.3. I first tested this on iOS, but it didn’t work as expected. To investigate via packet capture, I ran the same code on macOS and saw the same issue.
Using URLSession to establish a WebSocket connection, I captured packets in Wireshark to check if Session Resumption was working. The behavior differed from what I expected:
1st TLS handshake – Client Hello does not contain the session_ticket extension (required for session resumption per the TLS spec).
2nd TLS handshake – Client Hello does not contain a pre_shared_key.
Test apps:
https://github.com/sf-jed-kyung/tls-session-resumption-test
Test environment: Xcode 16.3, macOS 15.6, OpenSSL 3.5.1
This repo contains:
tls-urlsession-macos – WebSocket via URLSession (shows missing extensions).
tls-openssl-macos – Manual TLS handshake via OpenSSL (shows both session_ticket and pre_shared_key).
To run this, adjust Header Search Paths and Library Search Paths for your local OpenSSL install.
URLSession – 1st Client Hello
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 512
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 508
Version: TLS 1.2 (0x0303)
Random: 0502b10cf04223658...
Session ID Length: 32
Session ID: e3b276b14f2deaced...
Cipher Suites Length: 42
Cipher Suites (21 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 393
...
Extension: server_name (len=26) name=echo.websocket.events
Extension: extended_master_secret (len=0)
Extension: renegotiation_info (len=1)
Extension: supported_groups (len=12)
Extension: ec_point_formats (len=2)
Extension: application_layer_protocol_negotiation (len=11)
Extension: status_request (len=5)
Extension: signature_algorithms (len=22)
Extension: signed_certificate_timestamp (len=0)
Extension: key_share (len=43) x25519
Extension: psk_key_exchange_modes (len=2)
Extension: supported_versions (len=7) TLS 1.3, TLS 1.2
Extension: compress_certificate (len=3)
...
URLSession – 2nd Client Hello
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 512
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 508
Version: TLS 1.2 (0x0303)
Random: 1e485f35ad66c8598...
Session ID Length: 32
Session ID: 99d02000c7ed403a5...
Cipher Suites Length: 42
Cipher Suites (21 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 393
...
Extension: server_name (len=26) name=echo.websocket.events
Extension: extended_master_secret (len=0)
Extension: renegotiation_info (len=1)
Extension: supported_groups (len=12)
Extension: ec_point_formats (len=2)
Extension: application_layer_protocol_negotiation (len=11)
Extension: status_request (len=5)
Extension: signature_algorithms (len=22)
Extension: signed_certificate_timestamp (len=0)
Extension: key_share (len=43) x25519
Extension: psk_key_exchange_modes (len=2)
Extension: supported_versions (len=7) TLS 1.3, TLS 1.2
Extension: compress_certificate (len=3)
...
OpenSSL – 1st Client Hello
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 1564
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 1560
Version: TLS 1.2 (0x0303)
Random: aec30b0aad542252...
Session ID Length: 32
Session ID: f7ee7178cab8716a625...
Cipher Suites Length: 60
Cipher Suites (30 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 1427
Extension: renegotiation_info (len=1)
Extension: server_name (len=26) name=echo.websocket.events
Extension: ec_point_formats (len=4)
Extension: supported_groups (len=18)
Extension: session_ticket (len=0)
Extension: application_layer_protocol_negotiation (len=11)
Extension: encrypt_then_mac (len=0)
Extension: extended_master_secret (len=0)
Extension: signature_algorithms (len=54)
Extension: supported_versions (len=5) TLS 1.3, TLS 1.2
Extension: psk_key_exchange_modes (len=2)
Extension: key_share (len=1258) X25519MLKEM768, x25519
OpenSSL – 2nd Client Hello
Transport Layer Security
TLSv1.3 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 1716
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 1712
Version: TLS 1.2 (0x0303)
Random: 3fb3938a88166e4eb...
Session ID Length: 32
Session ID: 7f13e54a231c17ccff70...
Cipher Suites Length: 60
Cipher Suites (30 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 1579
Extension: renegotiation_info (len=1)
Extension: server_name (len=26) name=echo.websocket.events
Extension: ec_point_formats (len=4)
Extension: supported_groups (len=18)
Extension: session_ticket (len=0)
Extension: application_layer_protocol_negotiation (len=11)
Extension: encrypt_then_mac (len=0)
Extension: extended_master_secret (len=0)
Extension: signature_algorithms (len=54)
Extension: supported_versions (len=5) TLS 1.3, TLS 1.2
Extension: psk_key_exchange_modes (len=2)
Extension: key_share (len=1258) X25519MLKEM768, x25519
Extension: pre_shared_key (len=148)
Since the Client Hello is generated by the client, I believe the session_ticket should be included in the first handshake regardless of server support. However, URLSession omits it entirely.
Question: How can I enable TLS Session Resumption when using URLSession?
Topic:
App & System Services
SubTopic:
Networking