1

I am trying to post to a server that supports TLS 1.2 -- at least when I perform a GET in a browser I can verify that the communication uses TLS 1.2 and that the cert is validated by a cert authority. However, when I try to POST in my code to that server using AFNetworking iOS 9.0 (13A4305g) / Xcode 7-beta4 I'm getting a handshake failure.

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializerWithContentType:@"application/x-www-form-urlencoded"];    
manager.responseSerializer = [AFJSONResponseSerializer serializer];    
[manager POST:requestString parameters:@{ @"apiKey" : MY_API_KEY,
                                          @"payload" : [MyParams paramsForPOSTAsJSON] }
  success:^(AFHTTPRequestOperation *operation, NSDictionary *responseDict) {
      ...
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      myLog(@"Communication failed: %@", error);
}];

The failure:

2015-08-06 15:01:08.398 MyApp[1795:394055] CFNetwork SSLHandshake failed (-9824)
2015-08-06 15:01:08.409 MyApp[1795:394055] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
2015-08-06 15:01:08.412 MyApp[1795:393999] MyClass sendDataToServer Communication failed: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." ...

Am I missing something? How can I dig deeper? Suppose it is a problem with the server and not the code - how could I snoop that?

Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • This might be related to http://stackoverflow.com/questions/31820284/ssl-ios9-sslhandshake-failed-i-checked-with-openssl-my-server-works-with-tls where the problem was that iOS9 needed not only TLS1.2 but also specific ciphers (forward secrecy). – Steffen Ullrich Aug 07 '15 at 00:33
  • @SteffenUllrich That looks very promising. The site I was hitting does not have all the required cyphers as far as I can tell. I'll see what happens once I get that sorted out. – Ben Flynn Aug 07 '15 at 03:34

1 Answers1

9

Steffen led me to the answer, and it was indeed that I needed the appropriate ciphers. An easy way to look at the supported ciphers on a port is the cipherscan tool. The ciphers supported for App Transport Security can be found here. Once I was able to test on a fully configured website, I did not need any kind of whitelisting. For TLS sites without the ciphers, I can set NSThirdPartyExceptionRequiresForwardSecrecy to false.

UPDATE

If you take beta 3 or above of OS X El Capitan, you can use the following command:

nscurl --verbose --ats-diagnostics <host>

This will tell you what entries you would need to add to your whitelist in order to make the connection succeed. This is a great help in demystifying SSL failures of type CFNetwork SSLHandshake failed (-9801).

Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • Also note that: "Certificates must use at least an SHA256 fingerprint with either a 2048 bit or greater RSA key, or a 256 bit or greater Elliptic-Curve (ECC) key." – Ben Flynn Aug 20 '15 at 15:27
  • Can a iOS Client have ATS turned off and still able to connect to a TLS 1.2 only server? My app is not ready for ATS yet, but the back end server is configured to TLS 1.2, when the client connect to the server for authorization process, the web server generated a ticket and sent it back to the iOS client, however, when I use the same ticket to make further call to the back end server, the ticket can not be recognized by the server. When I compare the iOS client ticket with the Windows API Tester ticket (this is working), the iOS client ticket is much shorter. Sorry, I'm a newbie. – JIANG Mar 17 '17 at 17:50