I'm pulling my hair out on this one and would greatly appreciate some assistance. Unfortunately my experience with SSL is quite limited so I don't know where I'm going wrong.
I need to develop an iOS app that acts as an server with mutual SSL authentication with the client. I'm using the GCDAsyncSocket library and I've managed to get the server part working fine (without SSL), however, I'm stuck getting the SSL working. I've had a look at this post, however, it doesn't explain the steps I need to perform to achieve what I want.
In terms of the certificate setup, I have the following p12 certificates:
- Self-signed Server Root CA certificate
- Server Certificate issued by the CA above (ServerCert).
- Self-signed Client Root CA certificate
- Client Certificate issued by the CA above (ClientCert).
I then installed both Root CA certificates on the iOS device and bundled the serverCert certificate in my app. When a new socket is accepted, I extract the certificate info from the p12 file (according to the apple certificate programming guide), and setup the SSL settings as follows prior to starting the SSL session:
-(NSDictionary*) loadSSLSettings
{
// Configure SSL/TLS settings
NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:4];
// Configure this connection as the server
[settings setObject:[NSNumber numberWithBool:YES]
forKey:(NSString *)kCFStreamSSLIsServer];
CFArrayRef certsArray = [self loadCertificates];
[settings setObject:(id)CFBridgingRelease(certsArray) forKey:(NSString *)kCFStreamSSLCertificates];
[settings setObject:NSStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString *)kCFStreamSSLLevel];
[settings setObject:(id)kCFBooleanTrue forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
return settings;
}
-(CFArrayRef) loadCertificates
{
// Load Certificate
NSString *path = [[NSBundle mainBundle] pathForResource:@"ServerCert" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);
return certsArray;
}
This code seems load the certificate fine, but then when I make a client connection (this is without even trying mutual SSL) using openSSL, such as:
openssl s_client -connect 192.168.2.8:1700 -state -debug
I get the following output:
> SSL_connect:before/connect initialization
> SSL_connect:SSLv2/v3 write client hello A
> SSL_connect:error in SSLv2/v3 read server hello A
And the iOS log produces this from the GCDAsyncSocket library:
Error in CFStreamSetProperty, code: 8
All I can tell is that code 8 is 'Other'.
I'm at a loss at to what is going wrong...perhaps I'm doing something fundamentally wrong, and if so I'd greatly appreciate somebody pointing it out :)
Also, once I get past this step, how do I go about validating the client certificate when it sends one through?
If I've left out any vital information, please let me know and I'll happily add it.
Thanks!