Extracting certificate/identity from System Keychain on iOS

Hi,

I am facing issues extracting system certificates/identity on an iOS device.

I am using the following code to get all identities from my system keychain ( not the app level keychain)

        let getquery = [kSecMatchLimit: kSecMatchLimitAll,
                             kSecReturnRef: true,
                             kSecClass: kSecClassIdentity] 
         as CFDictionary

        var item: CFTypeRef?
        let status = SecItemCopyMatching(getquery, &item)

        guard status != errSecSuccess else {
            let key = item as! SecKey
            print(key)
            return;
        }

This works if I run this for MacOS as target platform but returns -25300 for my iOS app. I have the same identities/certificates installed. For iOS it is at “general->VPN and device management->Configuration profiles->{profile name} (which shows “contains: Certificate”} and for MacOS it is at “Keychain Access”.

How I downloaded the certificates: visited the site on my browser and downloaded it through safari, in settings verified it using passwords. So I didn’t download it from code.

Do I have to add some permission in info.plist or something. I didn’t add it for the MacOS app. Or is this even possible, with all the sandbox features and how iOS app were not able to access keychain items before. But I couldn’t find anything as such about this issue and it looks like it is possible.

I also tried another query which again worked on my MacOS target platform and gave me all certificates from system keychain

      let dic : NSDictionary = [kSecMatchLimit: kSecMatchLimitAll,
                                kSecReturnAttributes: kCFBooleanTrue!,
                                kSecReturnRef: kCFBooleanTrue!,
                                kSecClass: kSecClassCertificate]

      var result : CFTypeRef?
      let resultCode : OSStatus = SecItemCopyMatching(dic, &result)

      if resultCode == errSecSuccess { print(result) }

I also looked at https://developer.apple.com/library/archive/qa/qa1745/_index.html for some reference. I didn’t get the part of "reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app's keychain using the function SecPKCS12Import”. If I can get any example of reading in a PKCS#12 blob that’d be very helpful as well.

Thanks.

This works if I run this for macOS as target platform but returns -25300 for my iOS app.

Right. This is exactly the situation that QA1745 covers. When you import credentials using a system UI, and that includes a configuration profile, they are placed in an Apple-only keychain access group. There is no way for non-Apple code to read them.

This works on macOS because the entire keychain architecture is different on macOS. For more background on that, see On Mac Keychains.

There isn’t a general way forward here. Any solution will very much depend on your specific circumstances. So, what are you trying to do with this digital identity?

Share and Enjoy

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

@eskimo

So little context: I am working on an app which uses objective-c and apple api and a c++ framework called Qt.

A typical workflow for my problem would be:

(objective-c) - A user visits a website on WKWebView which requires certification authentication -> a dialog pops up to choose from a list of certificates for authentication -> I get the certificate and private key(if possible) from the certificate chosen.

(c++/Qt) - I set up Ssl using certificate and privateKey which is required for sending Network Requests( get and post) to that the same certificate authenticated url.

Thanks for the background.

Are you building this app for a managed environment? So, you’d expect these digital identities to be installed via MDM.

Or are you building this for general users? So, you’d expect the user to install these digital identities themselves.

Share and Enjoy

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

@eskimo

Yes, the digital identities are installed via MDM.

Yes, the digital identities are installed via MDM.

That makes things challenging. QA1745 is really old, so I recently dug into this again as part of a DTS tech support incident, just to make sure that things haven’t changed in the intervening 10 years. Sadly, they have not. There’s still no way to install a digital identity in a configuration profile such that it’s accessible to a standard iOS app.

There are a variety of ways you can work around this, although none of them are great. The option I actively recommend is that you switch your server from mutual TLS to SSO. At that point the app doesn’t need to do anything to support authentication.

If switching your server isn’t possible, another option is to set up a new server that returns PKCS#12 blobs and their passwords, using SSO to authenticate the client. Your app contacts that server to get its digital identity, and then uses that digital identity to talk to your main server.

Share and Enjoy

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

Extracting certificate/identity from System Keychain on iOS
 
 
Q