Use kSecAttrAccessControl to only protect the private key in a SecIdentityRef

I try to use SecPKCS12Import to retrieve SecIdentityRef from PKCS#12 blob and store SecCertificateRef & SecKeyRef into keychain separately, so that I can use kSecAttrAccessControl to only protect private key with TouchID. The same code works on iOS, but not on Mac.

The problem is SecPKCS12Import already saved the identity into keychain. I tried to delete the stored identity, however, no matter using SecItemDelete with transient reference or persistent reference of identity or delete both SecCertficateRef and SecKeyRef, the record will be deleted from keychain -> My Certificates and keychain -> Keys, but alwasy leave the certficate in keychain -> Certificates. If I use SecItemAdd to add certificate back, I got errSecDuplicateItem, using SecItemCopyMatching or SecItemDelete, I got errSecItemNotFound. The strange part is, even I open keychain app to manually delete the cert, I got error prompt saying deleting item not found, but after that, the cert disppear from keychain -> Certificates.

Since I cannot delete identity and the add it back with access control attributes. I tried to use SecItemImport to avoid saving identity into keychain. However, this API only returns list of SecCertificateRef instead of SecIdentityRef. I found similar issue discussed on https://forums.developer.apple.com/thread/31711

Is there anyway to retreive identity from PKCS#12 blob and make kSecAttrAccessControl protect the private key only?

Have you tried calling

SecItemUpdate
to change the
kSecAttrAccessControl
value on the private key item?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I tried SecItemUpdate which doesn't return error, but also doesn't make any effect on the key item since using SecItemCopyMatching to retrieve identity or key, or using key for signing doesn't prompt TouchID or password. I can also see the key in keychian -> Keys. But if I use SecKeyGeneratePair with with kSecAttrAccessControl to generate key pair, I don't see the key in keychain -> Keys

I see that you’ve raised this question via other channels, so I’m going to bow out here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Currently facing the same issue with a SecKeychainItemRef

A SecKeychainItemRef means you’re using the legacy keychain API, which can only talk to the file-based keychain, which doesn’t support this type of access control.

If you’re unfamiliar with the various keychain APIs and implementations on the Mac, see On Mac Keychains.

Share and Enjoy

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

Hi,

I face the same issue. I need to import an identity from PKCS12 and protect it with TouchID (BiometryCurrentSet).

According to this post (and several others), my understanding is:

  • AccessControl is only available with data-protected keychains
  • Both SecPKCS12Import and SecItemImport import to file-based keychains
  • The suggested alternative is to use a private keychain, get the identity and use SecItemAdd + kSecUseDataProtectionKeychain
  • Attach the AccessControl to the underlying private key (using SecItemAdd + kSecAttrAccessControl or using SecItemUpdate)

However SecItemAdd fails in all situations:

  • Will return error -26276 when adding identity (undocumented error code)
  • Will return error -50 when adding private key

Did I missed something ?

Will return error -26276 when adding identity (undocumented error code)

You’re right that this is not documented. Using the Darwin source I was able to track it down as errSecInternal, which is not exactly helpful )-:

I need to import an identity from PKCS12 and protect it with TouchID (.biometryCurrentSet).

There is a minefield of bugs and missing features that make this quite tricky. I think I might see a way through but I’m not going to post the details here because a) it’s super ugly, and b) I don’t have time to test it to make sure it works [1]. If you really need a solution, open a DTS tech support incident and I’ll carve out the time to investigate this properly.

If you do open a TSI, make sure to reference this thread.

Share and Enjoy

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

[1] I’ve no problems posting ugly code but I draw the line at ugly code that doesn’t work (-:

Have you tried calling 

SecItemUpdate

to change the 

kSecAttrAccessControl

value on the private key item?

I'm currently struggling trying to do just that in a context where I have a private key inside the Secure Enclave further protected by an application password which I want to change. I have been unsuccessful getting the queryand attributesToUpdate dictionaries right though, with SecItemUpdate returning either errSecParam or errSecNoSuchAttr. Am I on the right track here or am I trying to do something that is not possible?

I'm currently struggling trying to do just that in a context where I have a private key inside the Secure Enclave further protected by an application password which I want to change.

I recommend that you start a new thread for this. Tag it with Security so that I see it.

Why? Because the thread is about SecPKCS12Import and, by definition, you can’t import an SE-protected key.

ps I want to be clear about terminology here. Keys are not inside the SE. Rather, they are protected by the SE. That is, the key is actually stored in the keychain but it’s wrapped in a way that only the SE can use it. This is a common source of confusion, largely brought about by misleading docs. We’ve recently fixed that, yay!, resulting in Protecting keys with the Secure Enclave.

Share and Enjoy

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

Use kSecAttrAccessControl to only protect the private key in a SecIdentityRef
 
 
Q