I have a TCP Server and Client for Windows, written in Delphi. I am trying to port them to Mac, but can't seem to be able to properly configure SSL. In Windows the application has the method set to SSLv2 and a self signed openssl certificate file and key file assigned and the program provides a password.
On Mac I am trying to replicate this using AsyncSocket, but always getting handshake errors:
On Mac client I receive the error:
CFNetwork SSLHandshake failed (-9806)
The operation couldn’t be completed. (kCFStreamErrorDomainSSL error -9806.)
On Windows Server I receive the error:
Error accepting connection with SSL.
error:140EC0AF:SSL routines:SSL2_READ_INTERNAL:non sslv2 initial packet
The code I am using for TCP Client on Mac:
SecIdentityRef identityRef = NULL;
SecCertificateRef certificateRef = NULL;
SecTrustRef trustRef = NULL;
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"pfx"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;
CFStringRef password = CFSTR("test");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = errSecSuccess;
securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
identityRef = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
trustRef = (SecTrustRef)tempTrust;
} else {
NSLog(@"Certificates failed with error code %d",(int)securityError);
return;
}
SecIdentityCopyCertificate(identityRef, &certificateRef);
NSArray *certificates = [[NSArray alloc] initWithObjects:(id)identityRef, (id)certificateRef, nil];
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
(id)kCFStreamSocketSecurityLevelSSLv2, (id)kCFStreamSSLLevel,
(id)kCFBooleanFalse, (id)kCFStreamSSLAllowsExpiredCertificates,
(id)kCFBooleanFalse, (id)kCFStreamSSLAllowsExpiredRoots,
(id)kCFBooleanTrue, (id)kCFStreamSSLAllowsAnyRoot,
certificates, (id)kCFStreamSSLCertificates,
nil];
tcpClient = [[AsyncSocket alloc] initWithDelegate:self];
NSError *err = nil;
if (![tcpClient connectToHost:ip onPort:tcpPort error:&err]) {
DoLog(@"Faled to connect to TCP Server: %@", err);
} else {
[tcpClient startTLS:settings];
}
[certificates release];
[settings autorelease];
The sample.pfx file was produced using the following openssl commands:
x509 -outform der -in sample.crt -out sample.der
pkcs12 -export -out sample.pfx -inkey sample.key -in sample.crt