Two way SSL failed on WatchOS2.1

I was trying to communicate with a service with two way SSL from a watch.


I found the connection was cancelled immediately after the client (watch) provide the client certificate, by calling completeHandler(NSURLSessionAuthChallengeUseCredential, credential).

The error got is "NSURLErrorDomain Code=-999 cancelled".


But I've tried run the same piece of code on a phone, it did succeed. Apart from two way ssl, all other requests work fine on the watch.


Since, the frameworks on watchOS and iOS are different, I am wondering if that might be an issue for WatchOS? Or is there anything specifically need to be configured for the watch?

Cheers.

Here's the sample code:



#pragma mark - NSURLSessionDelegate -

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler

{

NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];


if ([challenge previousFailureCount] == 0) {

NSString *authMethod = [protectionSpace authenticationMethod];

if (authMethod == NSURLAuthenticationMethodServerTrust) {

completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);

} else if (authMethod == NSURLAuthenticationMethodClientCertificate) {

NSError *error;

NSBundle *bundle = [NSBundle mainBundle];

NSURL *certificateURL = [bundle URLForResource:@"2048sha2" withExtension:@"p12"];

NSData *p12data = [[NSData alloc] initWithContentsOfURL:certificateURL options:NSDataReadingUncached error:&error];

CFDataRef inP12data = (__bridge CFDataRef)p12data;

SecIdentityRef myIdentity;

SecTrustRef myTrust;

OSStatus status = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

SecCertificateRef myCertificate;

SecIdentityCopyCertificate(myIdentity, &myCertificate);

const void *certs[] = { myCertificate };

CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

CFRelease(myCertificate);

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

CFRelease(certsArray);


completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

} else {

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);

}

} else {

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);

}

}



OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)

{

OSStatus securityError = errSecSuccess;


CFStringRef password = CFSTR("password");

const void *keys[] = { kSecImportExportPassphrase };

const void *values[] = { password };


CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);


CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

securityError = SecPKCS12Import(inP12data, options, &items);


if (securityError == 0) {

CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);

const void *tempIdentity = NULL;

tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);

*identity = (SecIdentityRef)tempIdentity;

const void *tempTrust = NULL;

tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);

*trust = (SecTrustRef)tempTrust;

}


if (options) {

CFRelease(options);

}


return securityError;

}

I have the same issue in watchOS 3.0 GM. Have you found a solution to this problem?

Have you verified that you’re loading the certificate from the bundle on the watch? You’ll need to include it in both the iOS App and watchOS Extension bundles.

Yes, the .p12 file is loaded correctly on watchOS using the SecPKCS12Import() function.


I found this Stackoverflow question: http://stackoverflow.com/questions/35568750/two-way-ssl-failed-on-watchos2-1-but-same-code-works-on-ios9-1

I think it's from the same person who started this thread. Apparently Apple has confirmed the issue.


I have filed a bug with Apple #28366254.

Two way SSL failed on WatchOS2.1
 
 
Q