I'm unable to connect to a secure websocket connection due to the error below on an iOS device (iOS 12 & 13).
It seems there is a failure validating the certificate for the end-point but I can't find a way to determine the reason. I can connect to the websocket end-point from a browser client. I also verified the certificate using https://www.ssllabs.com/ssltest/ and don't see any issues. The SSL certificate is issued from Let's Encrypt.
Below is the console output I could capture from the device and console app on my mac laptop.
XCODE DEBUG CONSOLE
2020-04-29 16:18:03.501170-0700 [BoringSSL] boringssl_context_handle_fatal_alert(1873) [C12.1:1][0x1151122e0] write alert, level: fatal, description: certificate unknown
2020-04-29 16:18:03.501366-0700 [BoringSSL] boringssl_context_error_print(1863) boringssl ctx 0x282eb41b0: 4450062232:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-283.102.1/ssl/handshake.cc:369:
2020-04-29 16:18:03.510648-0700 [BoringSSL] boringssl_session_handshake_incomplete(164) [C12.1:1][0x1151122e0] SSL library error
2020-04-29 16:18:03.510740-0700 [BoringSSL] boringssl_session_handshake_error_print(111) [C12.1:1][0x1151122e0] 4450062232:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-283.102.1/ssl/handshake.cc:369:
2020-04-29 16:18:03.510837-0700 [BoringSSL] nw_protocol_boringssl_handshake_negotiate_proceed(726) [C12.1:1][0x1151122e0] handshake failed at state 12288
2020-04-29 16:18:03.532541-0700 [strings] ERROR: Network.NWError not found in table Error of bundle CFBundle 0x109308b40 (framework, loaded)
error: Optional("The operation couldn’t be completed. (NETWORK.NWERROR error 2.)")
MAC CONSOLE APP
default 16:18:03.712414-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: waiting for data to read [2]
default 16:18:03.712477-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: waiting for data to read [2]
default 16:18:03.712583-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: waiting for data to read [2]
default 16:18:03.712646-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: waiting for data to read [2]
default 16:18:03.712707-0700 boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Reading SSL3_RT_HANDSHAKE 122 bytes
default 16:18:03.713628-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_hello_retry_request
default 16:18:03.713687-0700 boringssl_context_add_handshake_message_pending(578) [C12.1:1][0x1151122e0] Adding message(2)
default 16:18:03.713747-0700 boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Writing SSL3_RT_CHANGE_CIPHER_SPEC 1 bytes
default 16:18:03.713807-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_server_hello
default 16:18:03.713865-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_encrypted_extensions
default 16:18:03.714153-0700 boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Reading SSL3_RT_HANDSHAKE 10 bytes
default 16:18:03.714219-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_certificate_request
default 16:18:03.714277-0700 boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Reading SSL3_RT_HANDSHAKE 3105 bytes
default 16:18:03.714335-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_server_certificate
default 16:18:03.714395-0700 boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_server_certificate_verify
default 16:18:03.714452-0700 boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Reading SSL3_RT_HANDSHAKE 264 bytes
default 16:18:03.714628-0700 boringssl_context_copy_peer_sct_list(1003) [C12.1:1][0x1151122e0] SSL_get0_signed_cert_timestamp_list returned no SCT extension data
default 16:18:03.714914-0700 boringssl_helper_create_sec_trust_with_certificates(607) [C12.1:1][0x1151122e0] SecTrustCreateWithCertificates result: 0
default 16:18:03.714973-0700 boringssl_helper_create_sec_trust_with_certificates(612) [C12.1:1][0x1151122e0] SecTrustSetOCSPResponse result: 0
default 16:18:03.715033-0700 boringssl_helper_create_sec_trust_with_certificates(621) [C12.1:1][0x1151122e0] No TLS-provided SCTs
default 16:18:03.715167-0700 boringssl_context_certificate_verify_callback(2071) [C12.1:1][0x1151122e0] Asyncing for verify block
default 16:18:03.715225-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
default 16:18:03.715418-0700 boringssl_context_certificate_verify_callback(2040) [C12.1:1][0x1151122e0] Verification already in progress.
default 16:18:03.715481-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
default 16:18:03.716084-0700 boringssl_context_certificate_verify_callback(2040) [C12.1:1][0x1151122e0] Verification already in progress.
default 16:18:03.716145-0700 boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
default 16:19:16.180121-0700 boringssl_context_message_handler(2258) [C6.1:2][0x11321ccb0] Writing SSL3_RT_ALERT 2 bytes
default 16:19:16.180202-0700 boringssl_context_handle_warning_alert(1893) [C6.1:2][0x11321ccb0] write alert, level: warning, description: close notify
default 16:19:16.180285-0700 boringssl_session_disconnect(504) [C6.1:2][0x11321ccb0] SSL_shutdown 0
default 16:19:16.181104-0700 nw_protocol_boringssl_remove_input_handler(1012) [C6.1:2][0x11321ccb0] nw_protocol_boringssl_remove_input_handler forced true
default 16:19:16.181169-0700 nw_protocol_boringssl_remove_input_handler(1030) [C6.1:2][0x11321ccb0] Transferring nw_protocol_boringssl_t handle back into ARC for autorelease
default 16:19:33.510159-0700 boringssl_context_message_handler(2258) [C8.1:2][0x11328fd50] Writing SSL3_RT_ALERT 2 bytes
default 16:19:33.510247-0700 boringssl_context_handle_warning_alert(1893) [C8.1:2][0x11328fd50] write alert, level: warning, description: close notify
default 16:19:33.510309-0700 boringssl_session_disconnect(504) [C8.1:2][0x11328fd50] SSL_shutdown 0
default 16:19:33.510922-0700 nw_protocol_boringssl_remove_input_handler(1012) [C8.1:2][0x11328fd50] nw_protocol_boringssl_remove_input_handler forced true
default 16:19:33.511105-0700 nw_protocol_boringssl_remove_input_handler(1030) [C8.1:2][0x11328fd50] Transferring nw_protocol_boringssl_t handle back into ARC for autorelease
The NGINX server block for the end-point is:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name me.example.com;
ssl_certificate /etc/letsencrypt/live/me.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/me.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/me.example.com/chain.pem;
location /ws {
proxy_pass http://upstreamserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protocol $scheme;
}
}
Any thoughts on why this is an issue on iOS?
I've also asked this question on SO:
Thanks in advance for any help/hints.
There are a few things going on here; first you are correct that the handshake is failing due to the client not being unable to verify the server's certificate. The reason the client cannot verify the certificate on the server is because there is are no SCT (Signed Certificate Timestamps) values provided to the client for verification. Also the OSCP response is 0. Notice the lines:
boringssl_context_info_handler(1983) [C12.1:1][0x1151122e0] Client handshake state: TLS 1.3 client read_server_certificate_verify
boringssl_context_message_handler(2258) [C12.1:1][0x1151122e0] Reading SSL3_RT_HANDSHAKE 264 bytes
boringssl_context_copy_peer_sct_list(1003) [C12.1:1][0x1151122e0] SSL_get0_signed_cert_timestamp_list returned no SCT extension data
boringssl_helper_create_sec_trust_with_certificates(607) [C12.1:1][0x1151122e0] SecTrustCreateWithCertificates result: 0
boringssl_helper_create_sec_trust_with_certificates(612) [C12.1:1][0x1151122e0] SecTrustSetOCSPResponse result: 0
boringssl_helper_create_sec_trust_with_certificates(621) [C12.1:1][0x1151122e0] No TLS-provided SCTs
boringssl_context_certificate_verify_callback(2071) [C12.1:1][0x1151122e0] Asyncing for verify block
boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
boringssl_context_certificate_verify_callback(2040) [C12.1:1][0x1151122e0] Verification already in progress.
boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
boringssl_context_certificate_verify_callback(2040) [C12.1:1][0x1151122e0] Verification already in progress.
boringssl_session_handshake_incomplete(170) [C12.1:1][0x1151122e0] Handshake incomplete: certificate evaluation result pending [16]
boringssl_context_message_handler(2258) [C6.1:2][0x11321ccb0] Writing SSL3_RT_ALERT 2 bytes
Second, the reason this works in the browser is because your browser may not be setting up the TLS connection with TLS 1.3. This means that certificate verification on both sides is not as strict as an iOS client trying to setup the connection as TLS 1.3. If the connection on browser side does work with TLS 1.3, the browser may not be failing on the lack of SCT data like iOS does.
My recommendation would be to try this again with embedded SCT values on the certificate, or, you could manually evaluate the trust yourself and decide if this should be a failure. I highly encourage you to take a look at my first recommendation as this will get you what you actually need over the long term.
<https://support.apple.com/en-us/HT205280>
Matt Eaton
DTS Engineering, CoreOS
meaton3 at apple.com