Search code examples
iossslios6

SecPKCS12Import does not return any items


I want to add certain CA certificates for TLS validation to the keychain of my iOS 6 application. The certificates are included in the Application Bundle. I do not want to add any identity (private key / certificate combination) which is described in several example.

The SecPKCS12Import call does not return any error, but unfortunately it does not return any certificate as well.

To let you reproduce my steps I took the Google Intermediate Certificate ('Google Internet Authority') as an example, and ran the following commands on the downloaded PEM certificate:

COT.

#convert PEM certificate to PKCS12
openssl pkcs12 -export -in google.pem -nokeys -out google.p12 -passout "pass:google"
#verification
openssl pkcs12 -in google.p12 -passin "pass:google"
MAC verified OK
Bag Attributes: <No Attributes>
subject=/C=US/O=Google Inc/CN=Google Internet Authority
issuer=/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-----BEGIN CERTIFICATE-----
MIICsDCCAhmgAwIBAgIDFXfhMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
[...]
ARlIjNvrPq86fpVg0NOTawALkSqOUMl3MynBQO+spR7EHcRbADQ/JemfTEh2Ycfl
vZqhEFBfurZkX0eTANq98ZvVfpg=
-----END CERTIFICATE-----

Afterwards I bundled the file in my application where the following code got executed:

NSMutableDictionary * options = [[[NSMutableDictionary alloc] init] autorelease];
[options setObject:@"google" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = NULL;
NSData *certData = [NSData dataWithContentsOfFile:[NSBundle pathForResource:@"google" ofType:@"p12" inDirectory:[[NSBundle mainBundle] bundlePath]]];
OSStatus result = SecPKCS12Import((CFDataRef)certData, (CFDictionaryRef)options, &items);
assert(result == errSecSuccess);
CFIndex count = CFArrayGetCount(items);
NSLog(@"Certificates found: %ld",count);

The console result output is 'Certificates found: 0'. The certData variable gets filled with the correct amount of bytes, and if I change the provided password, the results changes to errSecAuthFailed.

Do you have any idea what the problem might be?


Solution

  • I'd say that's a bug, see related question SSL Identity Certificate to run an HTTPS Server on iOS and bug SecPKCS12Import returns empty array when certificate expires after Jan 1st 10000.

    As you only want a certificate, without the private key, I'd import the certificate from a DER format file.

    $ openssl x509 -in google.pem -out google.der -outform DER
    $ openssl x509 -in google.der -noout -text
    

    Bundle DER certificate file and import it:

    NSString *path = [[NSBundle mainBundle] pathForResource:@"google" ofType:@"der"];
    NSData *derData = [NSData dataWithContentsOfFile:path];
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)derData);
    
    // add cert to KeyChain or use it as you need
    
    CFRelease(cert);