Question

I am writing an application that is communicating with a server which requires the client to authenticate itself using a client certificate. I need to extract the certificate from a .p12 file in the application bundle and add it to the application keychain.

I've been trying to figure out how to get it working from Apple's "Certificate, Key, and Trust Services Tasks for iOS", but to me it seems incomplete and does not specify how I add anything to the keychain(?).

I am quite lost and any help is appriciated, thanks in advance!

Was it helpful?

Solution

"Certificate, Key, and Trust Services Tasks for iOS" does contain sufficient information to extract certificate from a .p12 file.

  • from listing 2-1 demonstrate how you can extract SecIdentityRef

  • from listing 2-2 second line (// 1) shows how you can copy SecCertificateRef out of SecIdentityRef.

example loading p12 file, extract certificate, install to keychain. (error handling and memory management was not included)

  NSString * password = @"Your-P12-File-Password";
  NSString * path = [[NSBundle mainBundle]
                     pathForResource:@"Your-P12-File" ofType:@"p12"];

  // prepare password
  CFStringRef cfPassword = CFStringCreateWithCString(NULL,
                                                     password.UTF8String,
                                                     kCFStringEncodingUTF8);
  const void *keys[]   = { kSecImportExportPassphrase };
  const void *values[] = { cfPassword };
  CFDictionaryRef optionsDictionary
  = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1,
                                                  NULL, NULL);

  // prepare p12 file content
  NSData * fileContent = [[NSData alloc] initWithContentsOfFile:path];
  CFDataRef cfDataOfFileContent = (__bridge CFDataRef)fileContent;

  // extract p12 file content into items (array)
  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  OSStatus status = errSecSuccess;
  status = SecPKCS12Import(cfDataOfFileContent,
                           optionsDictionary,
                           &items);
  // TODO: error handling on status

  // extract identity
  CFDictionaryRef yourIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
  const void *tempIdentity = NULL;
  tempIdentity = CFDictionaryGetValue(yourIdentityAndTrust,
                                      kSecImportItemIdentity);

  SecIdentityRef yourIdentity = (SecIdentityRef)tempIdentity;


  // get certificate from identity
  SecCertificateRef yourCertificate = NULL;
  status = SecIdentityCopyCertificate(yourIdentity, &yourCertificate);


  // at last, install certificate into keychain
  const void *keys2[]   = {    kSecValueRef,             kSecClass };
  const void *values2[] = { yourCertificate,  kSecClassCertificate };
  CFDictionaryRef dict
  = CFDictionaryCreate(kCFAllocatorDefault, keys2, values2,
                                            2, NULL, NULL);
  status = SecItemAdd(dict, NULL);

  // TODO: error handling on status
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top