title: IOS Mutual Authentication
body: <p>I'm trying to implement mutual authentication in IOS 5 but i'm having troubles:</p>
  
  <pre><code>{NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1200 \"An SSL error has occurred and a secure connection to the server cannot be made.\" UserInfo=0x18d830 {NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., _kCFNetworkCFStreamSSLErrorOriginalValue=-9800, _kCFStreamPropertySSLClientCertificateState=0, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSErrorFailingURLStringKey=https://192.168.24.110:8081/t01.json, kCFStreamPropertySSLPeerTrust=&lt;SecTrustRef: 0xceaa2d0&gt;, NSErrorFailingURLKey=https://192.168.24.110:8081/t01.json}
  </code></pre>
  
  <p>I generated keys, certificates and pkcs12 for server (either self signed or with a fake CA I always got that problem) and client this way:</p>
  
  <pre><code>openssl genrsa -out client.key 1024
  openssl req -new -key client.key -out client.csr
  
  self-signed
  openssl req -new -key ca.key -x509 -days 1095 -out ca.crt
  
  CA signed
  openssl x509 -req -days 365 -in client.csr -CA server.crt -CAkey server.key -CAcreateserial -out client.crt
  
  CRT to PEM
  openssl x509 -in client.crt -out client.der -outform DER
  openssl x509 -in client.der -inform DER -out client.pem -outform PEM
  
  PEM TO PKCS 12
  openssl pkcs12 -export -in client.pem -inkey client.key -out client.p12
  </code></pre>
  
  <p>The resulting client.p12 file works perfectly when I import it in the browser (FF15). So the problem is not locate in the previous steps.</p>
  
  <p>IOS side I tried this example: <a href="http://vanjakom.wordpress.com/tag/nsurlconnection/" rel="nofollow noreferrer">http://vanjakom.wordpress.com/tag/nsurlconnection/</a></p>
  
  <p>and this is what I wrote when I found that example not working:</p>
  
  <pre><code>// Returns an array containing the certificate
  - (CFArrayRef)getCertificate:(SecIdentityRef) identity {
      SecCertificateRef certificate = nil;
  
      SecIdentityCopyCertificate(identity, &amp;certificate);
      SecCertificateRef certs[1] = { certificate };
  
      CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL);
  
      SecPolicyRef myPolicy   = SecPolicyCreateBasicX509();
      SecTrustRef myTrust;
  
      OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &amp;myTrust);
      if (status == noErr) {
          NSLog(@"No Err creating certificate");
      } else {
          NSLog(@"Possible Err Creating certificate");
      }
      return array;
  }
  
  // Returns the identity
  - (SecIdentityRef)getClientCertificate {
      SecIdentityRef identityApp = nil;
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *documentsDirectoryPath = [paths objectAtIndex:0];
      NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:@"file12.p12"]; 
      NSData *PKCS12Data = [NSData dataWithContentsOfFile:myFilePath];
  
      CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
      CFStringRef password = CFSTR("password");
      const void *keys[] = { kSecImportExportPassphrase };//kSecImportExportPassphrase };
      const void *values[] = { password };
      CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
      CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
      OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &amp;items);
      CFRelease(options);
      CFRelease(password);
      if (securityError == errSecSuccess) {
          NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
          CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
          identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
      } else {
          NSLog(@"Error opening Certificate.");
      }
  
      return identityApp;
  }
  
  - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
      if ([challenge previousFailureCount] == 0) {
          SecIdentityRef identity = [self getClientCertificate];  // Go get a SecIdentityRef
          CFArrayRef certs = [self getCertificate:identity]; // Get an array of certificates
          // Convert the CFArrayRef to a NSArray
          NSArray *myArray = (__bridge NSArray *)certs;
  
          // Create the NSURLCredential
          NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent];
  
          // Send
          [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];    
      } else {
          // Failed
          [[challenge sender] cancelAuthenticationChallenge:challenge];
      }
  }
  
  - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
  {
      return YES;
  }
  </code></pre>
  
  <p>In both cases I can't autheticate the client. 
  Moreover I also installed the server.crt certificate on the device (iPhone/iPad) but I keep receiving "Error Domain=NSURLErrorDomain Code=-1200".</p>
  
  <p>Any ideas?
  Thank you.</p>