SecPKCS12Import not returning certificates when there’s no identity

I have a .p12 file which contains two certificates, but no identities. When attempting to use SecPKCS12Import against it it returns a success code, but the CFArray is empty:

func testParsingCert() throws {
let bundle = Bundle(for: Self.self)
let certificateURL = bundle.url(forResource: TestConstants.SERVER_CERTIFICATE_NAME, withExtension: TestConstants.CERTIFICATE_FILE_EXTENSION)!
let certificateData = try! Data(contentsOf: certificateURL)
var importResult: CFArray? = nil
let err = SecPKCS12Import(
certificateData as NSData,
[kSecImportExportPassphrase as String: TestConstants.DEFAULT_CERT_PASSWORD] as NSDictionary,
&importResult
)
guard err == errSecSuccess else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil)
}
let identityDictionaries = importResult as! [[String:Any]]
var chain: CFArray
chain = identityDictionaries[0][kSecImportItemCertChain as String] as! CFArray
print(chain)
}

Above code fails with

Test Case '-[TAKTrackerTests.CertificateSigningRequestTests testParsingCert]' started.
Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range

as the identityDictionaries result contains no results (nor does importResult)

The specific use case for this is that users can do Certificate Enrollment against a server with a self-signed certificate, so they need to be able to upload the trust store prior to connecting for identities.

Replies

Thanks for opening a DevForums thread about this.

This is a known limitation of SecPKCS12Import. It focuses on importing an identity from a PKCS#12 rather providing a general PKCS#12 API.

IMPORTANT I believe you’re working on iOS. Be aware that the macOS implementation of SecPKCS12Import1 is quite different from the iOS one. However, my understanding is that this issue affects both.

I’m pretty sure we have a bug on file about this already, but I was unable to find its number. Thus, it’s probably best if you file your own bug. Please post your bug number, just for the record.

The easiest solution here would be to change your server infrastructure to return the certificates in a more standard format for certificates, like PEM or DER. Both of these are relatively straightforward to import.

If you can’t do that on the server side then I think your only option to write or acquire a library that can do it on iOS. iOS doesn’t have any built-in APIs that can help with this. There’s no general PKCS#12 container API, or even an ASN.1 API [1].

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Although there is SwiftASN1, which is cool.

Thanks Quinn! We unfortunately have no control over the server implementation of this, and iOS is the singular platform unable to parse the .p12 files coming in. I think we're going to end up pulling in OpenSSL to be able to parse them - I do already have SwiftANS1 as well as the Swift Certificates libraries which are indeed cool - just not able to handle the .p12 files.

I'll get a bug report posted and reply back here with the number once I do. It is unfortunate that something literally named after the container it is parsing can't get the data structures without the identity, but that's how it goes sometimes.

Thanks,

Cory