SecItemCopyMatching returns a secure enclave a ref after migrating to a new iPhone 15?

I have an app that creates a private key in the secure enclave with a unique alias. It is created with the kSecAttrTokenIDSecureEnclave flag.

According to the docs, such private keys should never leave the enclave under any circumstances and definitely not restored on new devices.

After migrating to a new iPhone 15 the app does not offer to create a new private key in the enclave, but rather it is able to find the unique alias of the private key in the new phone. i.e. as if it found the private key on the new phone's secure enclave

I believe (/hope) that in practice the object I get in the new iPhone from SecItemCopyMatching is not usable.

  1. I assume this is a bug that should be fixed by apple?
  2. How can I detect that this SecItemCopyMatching result is stale so I can ignore it and prompt the user to create a new keypair on the secure enclave?

Thanks

Replies

I believe … that in practice the object I get in the new iPhone from SecItemCopyMatching is not usable.

That’s my expectation.

such private keys should never leave the enclave under any circumstances

You need to be careful about wording here. This private key is not stored on the SE, but rather it’s protected by the SE. I talked about this in detail in the Keys Aren’t Stored in the Secure Enclave section of SecItem: Pitfalls and Best Practices.

Share and Enjoy

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

Add a Comment

From your article:

In reality, SE-protected keys are stored in the standard keychain database alongside all your other keychain items. The difference is that the key is wrapped in such a way that only the SE can use it. So, the key is protected by the SE, not stored in the SE.

This is in line with the scenario we've been able to reproduce the issue with:

  1. Create a SE-protected key-pair on the app
  2. Backup the iPhone
  3. Erase and restore the iPhone from the backup
  4. The app is still able to find the key via SecItemCopyMatching but the key is not able to sign.

I assume the the Keychain is restored but the key material is not, hence the unusable key-pair.

My follow-up question is: How can I detect this situation and preemptively invalidate that unusable key pair? I want to avoid having the user signing on something and then prompt him to refresh the key on error. Ideally I would like to detect this situation in the background without having the user sign on something (i.e. use his Face Id since the key-pair is biometrics protected)