8

I recently needed to configure CocoaHttpServer, which we're using in our application with success, to handle HTTPS connections coming from a client application (running on Android devices). This is fine - there is copious sample code which allows for this, and we were able to enable the secure server without issue.

In practice we were seeing incredibly long SSL negotiation phases while the client was doing its handshaking with our server - upwards of 70 seconds.

Through a long series of searches, I found that the delay was because of the calculation of Diffie-Hellman parameters used by default when SSL is enabled in CFSocket. This thread is where I first started to find the answer to my issue.

To match what our Windows server was doing (using a less-secure SSL cipher) I needed to set the cipher explicitly on the Mac, which isn't easy when using AsyncSocket as a wrapper for the socket communications.

Our Windows server was using: TLS_RSA_WITH_RC4_128_MD5 )(0x04) RC4 128 bits MD5 RSA

Our Macintosh server was using: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x039) AES 256 bits SHA-1 Ephemeral Diffie-Hellman key exchange using RSA certificate

The difference in "security" is large, but likely not worth the effort/computation/delay that we were seeing. Security Theater?

Brian Criscuolo
  • 181
  • 1
  • 5
  • A +1 for your efforts, and for working the phrase "Security Theater?" into your post :-) – Jarret Hardie Dec 24 '09 at 01:08
  • 1
    This is useful, but you should split out the answer and post it as an answer to this question, so this doesn't live forever on the Unanswered page. (It's totally kosher to answer your own question.) – benzado Dec 24 '09 at 01:54

2 Answers2

4

Please note that there are different ciphers that can be chosen - I chose to use the same one as our Windows implementation for consistency.

With information from another question mentioned above, I figured out how to set the cipher for CFSocket to use the same as Windows, and the code appears to be now quite a bit better - like it really works! CFSocket isn't directly exposing the SecureTransport support, which makes this kind of hard, but defining a particular key makes it work nicely.

For posterity, here's the code I've added to -onSocketWillConnect: in our HTTPConnection class:

// define this value; it isn't exposed by CFSocketStream.h
const extern CFStringRef kCFStreamPropertySocketSSLContext;

...

CFReadStreamRef stream = [sock getCFReadStream];
CFDataRef data = (CFDataRef) CFReadStreamCopyProperty(stream, kCFStreamPropertySocketSSLContext);

// Extract the SSLContextRef from the CFData
SSLContextRef sslContext;
CFDataGetBytes(data, CFRangeMake(0, sizeof(SSLContextRef)), (UInt8*)&sslContext);
SSLCipherSuite *ciphers = (SSLCipherSuite *)malloc(1 * sizeof(SSLCipherSuite));
ciphers[0] = SSL_RSA_WITH_RC4_128_MD5; // Basic cipher - not Diffie-Hellman
SSLSetEnabledCiphers(sslContext, ciphers, 1);

I hope this helps anyone working through the same issue as I - I'd be happy to share some more code and advice if needed.

Georg Schölly
  • 124,188
  • 49
  • 220
  • 267
Brian Criscuolo
  • 181
  • 1
  • 5
  • I'd like to contact Brian Criscuolo, but see no way to do that from StackOverflow. I have a Q about enabling this for my server. thing is, i'm using CFSocketRef with a runloop, not CFReadStreamRefs, so don't know how to make my server support HTTPS... you mention sample code, but i'm having trouble finding that? – David M. Cotter Jun 13 '18 at 23:46
0

For what it's worth, I contributed a patch to CocoaAsyncSocket about a week before you had this issue. Sorry that I didn't notice your question back then. :-)

Aidan Steele
  • 10,999
  • 6
  • 38
  • 59