Hi,
I run a PacketTunnelProvider embedded within a system extension. We have been having success using this; however we have problems with accessing certificates/private keys manually imported in the file-based keychain.
As per this, we are explicitly targeting the file-based keychain.
However when attempting to access the certificate and private key we get the following error:
System error using certificate key from keychain: Error Domain=NSOSStatusErrorDomain Code=-25308 "CSSM Exception: -2147415840 CSSMERR_CSP_NO_USER_INTERACTION" (errKCInteractionNotAllowed / errSecInteractionNotAllowed: / Interaction is not allowed
As per the online documentation, I would expect to be prompted for the access to the application:
When an app attempts to access a keychain item for a particular purpose—like using a private key to sign a document—the system looks for an entry in the item’s ACL containing the operation. If there’s no entry that lists the operation, then the system denies access and it’s up to the calling app to try something else or to notify the user.
If there is an entry that lists the operation, the system checks whether the calling app is among the entry’s trusted apps. If so, the system grants access. Otherwise, the system prompts the user for confirmation. The user may choose to Deny, Allow, or Always Allow the access. In the latter case, the system adds the app to the list of trusted apps for that entry, enabling the app to gain access in the future without prompting the user again
But I do not see that prompt, and I only see the permission denied error in my program.
I can work around this one of two ways
- Change the access control of the keychain item to
Allow all applications to access this item
. This is not preferable, as it essentially disables any ACLs for this item. - Embed the certificate in a configuration profile that is pushed down to the device via MDM or something similar. This works at a larger scale, but if I'm trying to manually test out a certificate, I don't always want to have to set this up.
Is there another way that I go about adding my application to the ACL of the keychain item?
Thanks!
OK. So there are two types of permissions to be concerned with here:
- File system permissions
- ACLs
You’re targeting the System keychain so file system permissions aren’t a problem. The System keychain file is accessible to system extensions, and launchd
daemons in general.
The issue here is the private key ACL. Keychain Access sets the ACL to a default value, which doesn’t allow for access by your sysex. You can change the ACL in Keychain Access (select the private key, choose File > Get Info, and then switch to the Access Control tab) but my experience is that this is tricky to get right. Specifically, Keychain Access has never been updated to deal with partition lists properly. Quoting the security
man page:
The "partition list" is an extra parameter in the ACL which limits access to the key based on an application's code signature.
So I’m not sure that adding your sysex to the ACL will be sufficient. You might have to run security
to tweak the partition list.
I generally try to avoid messing around with ACLs. They are tightly bound to the file-based keychain and it’s future is not bright [1], so any ACL code you write today has a limited lifespan.
The best way to avoid ACLs is to have a single program deal with your digital identity. In your case that means the sysex. So, you could do something like:
- Add an ‘import PKCS#12’ menu item to your app.
- Have it send the PKCS#12 data and the password to your sysex via XPC.
- Have the sysex import the PKCS#12 into the System keychain.
The import process sets the ACL to include the current program, your sysex, and thus it won’t have any problems using the private key.
However, this is a bunch of extra code. If this were the standard way that folks are expected to use your app then I’d say that code was justified. But I wouldn’t go down this path if you’re just trying to cobble things together for testing.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] For more on this, see TN3137 On Mac keychain APIs and implementations. One day we’ll allow daemons to use the data protection keychain. One day…