0

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
Nostradamus
  • 668
  • 6
  • 18
  • First you need to connect anyway. Then you need to call `startTLS` in `socket:didConnectToHost:port:` delegate's method if needed. – k06a Feb 25 '15 at 22:16
  • If I call `startTLS` in `sock:didConnectToHost:port` then I am getting the following error on the server side: `Error accepting connection with SSL. error:00000006:lib(0):func(0):EVP lib` – Nostradamus Feb 27 '15 at 11:02

0 Answers0