kCFStreamErrorDomainSSL Error -9802

Our app connects to our to HTTPS server using a self-signed certificate which has been working fine for years now, but when I tried launching it with Xcode9/iOS 11 beta I am getting SSL failure errors, in particular the kCFStreamErrorDomainSSL Error -9802. I can't seem to find what this error means.

network_config_register_boringssl_log_debug_updates Failed to register for BoringSSL log debug updates
 network_config_register_boringssl_log_debug_updates Failed to register for BoringSSL log debug updates
[Error] Calling AuthenticationHandlerWithError: (null)
TIC TCP Conn Failed [1:0x1c4164c80]: 3:-9802 Err(-9802)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
 HTTP load failed (error code: -1200 [3:-9802]) for Task <A3954377-95A4-40CF-B080-45910A5870E7>.<1>
 Task <A3954377-95A4-40CF-B080-45910A5870E7>.<1> finished with error - code: -1200


Any idea what might be going on?

Replies

Error -9802 is

errSSLFatalAlert
, which is pretty generic TLS negotiation failure. It’s likely that your server is using one of legacy crypto facilities that have been remove in iOS 11. My App Transport Security pinned post lists these and have references to the the WWDC 2017 talk about this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Our SSL endpoints are managed by Google Cloud Platform, so I don't think the problem is there. Strangely enough, the problem just went away. I switched to a different set of URLs and then back to the original set and now everything just works again as expected.

I have been running into similar issues with the default Firebase configuration suggested by their docs, which is all built on the Google Cloud Platform. When launching the app, even though I've commented out every network call or connection to Firebase with the exception of FirebaseApp.configure(), and the app freezes on the launch screen storyboard and returns

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)


The interesting and frustrating part about all this is that the app has been working flawlessly all throughout development. Now I've hit a wall with this error and I'm at a complete dead stop until this fixes itself...


Any thoughts are appreciated! I will post back if I find anything...


EDIT:

I forgot that when I disable App Transport Security in the plist a new error is logged just before the previous one. it reads:

nw_coretls_read_one_record tls_handshake_process: [-9802]


Notice it has the same -9802 on the end... I hope this is something on my end and not Google messing with the TLS settings of the Firebase servers...

I forgot that when I disable App Transport Security in the plist a new error is logged just before the previous one.

Does the connection then go through? Or is this just another symptom of this hard error?

If the connection fails with ATS disabled then you have deeper TLS issues. The next step in investigating those is to look at a packet trace (per QA1176) to see which end is triggering the failure.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Same problem here with a server certificate issued by our own internal CA. This has been working for years up to and including with iOS 10 (NSURLConnection with custom trust anchor validation in NSURLConnectionDelegate, using our own CA certificate bundled with the app). Interestingly, it starts working once I add a NSExceptionRequiresForwardSecrecy = NO exception for the domain to the app's plist. However, all cipher suite requirements according to [1] are fulfilled, and the negotiated cipher is TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384. Furthermore, connection to the very same server with the same TLS configuration works fine if a certificate signed by a system-trusted CA is used, so it can't really be a forward secrecy/cipher suite issue.


It appears that in iOS 11, ATS forbids the use of certificates from CAs not trusted by the system/user ([1] also says so), even if the app does custom validation, and NSExceptionRequiresForwardSecrecy somewhat unexpectedly works around it. Maybe it's time to start using certificates from an official CA and employ pinning (e.g. with TrustKit) instead.


[1] https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW57

Maybe it's time to start using certificates from an official CA …

Regardless of what else is going on here, this is the right thing to do. There are some good reasons to use a custom CA (for example, you’re working in an enterprise environment, or you’re talking to a local accessory that has no fixed DNS name) but if you have a server that’s accessible at a fixed DNS name via the wider Internet then using a non-CA issued certificate is just making your life unnecessarily hard.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

My code relies on the detection of "bad client certificate" alerts and it was working fine under iOS 10. Under iOS 11 the URL loading system reports -9802 instead. Though when using CFNetwork Socket API (as used by 3rd party SocketRocket - websocket lib) the expected -9825 is reported.


I monitor the TLS traffic and know for certain that the correct alert is delivered to the client.


Can you go into detail as to why this genic -9802 might be reported when a bad client certificate alert (42) was reported?


--

Update:


As I have full control over the incomming byte stream I was able to modify the SSL alert. This way I was able to test all alerts ranging from 40-50.

I found that multiple SSL Alerts are propagated differently (bold). Even though _kCFStreamErrorCodeKey indicates it would hold the acctual CFStreamError.


Note: no_certificate_RESERVED(41) is deprectated, therefore I don't care about the test result.Here is my results:

TLS 1.2 AlertCFStreamURL loading system: Code=-120? {_kCFStreamErrorCodeKey = [see below]>}
handshake_failure(40),-9824-9802
no_certificate_RESERVED(41),-9806-9825
bad_certificate(42),-9825-9802
unsupported_certificate(43),-9826-9826
certificate_revoked(44),-9827-9827
certificate_expired(45),-9828-9828
certificate_unknown(46),-9829-9829
illegal_parameter(47),-9830-9802
unknown_ca(48),-9831-9831
access_denied(49),-9832-9802
decode_error(50),-9833-9802