iOS keychain: Life cycle of Secure Enclave protected RSA keys

Hello! Apologies for some basic-sounding questions, but I am new to iOS and I'm having some trouble finding documentation for some features.

Just to check my assumptions:

  1. iOS keychain RSA keys marked kSecAttrAccessibleWhenUnlockedThisDeviceOnly are protected by some Secure Enclave key, right? Can you point me to documentation of this?

  2. Such RSA keys ( kSecAttrAccessibleWhenUnlockedThisDeviceOnly ) are present in device backups, right?

  • https://developer.apple.com/documentation/security/ksecattraccessiblewhenunlockedthisdeviceonly

  • The documentation I've found indicates that they are not available on a different device. I am taking that to mean that they are backed up and restorable on the same device.

  1. If so, does this function survive a factory reset of a device? Or is a factory reset considered a 'different device?'

  2. Is there a way to prevent a backup of a kSecAttrAccessibleWhenUnlockedThisDeviceOnly key?

  3. Is there a 'good' way to migrate a kSecAttrAccessibleWhenUnlockedThisDeviceOnly RSA key to a different device? (I understand this is at cross-purposes with making a key kSecAttrAccessibleWhenUnlockedThisDeviceOnly) I can roll my own transport, but I'm wondering if someone has already thought about this.

Thanks!

iOS keychain RSA keys marked kSecAttrAccessibleWhenUnlockedThisDeviceOnly are protected by some Secure Enclave key, right?

No. They are protected by the general keychain but not the Secure Enclave. The SE can only protect EC keys (specifically, SECG secp256r1 keys).

Can you point me to documentation of this?

The definitive reference for this is the Apple Platform Security document.

Such RSA keys (kSecAttrAccessibleWhenUnlockedThisDeviceOnly) are present in device backups, right?

Yes, although your ability to restore them can vary. See the table in this post and it’s companion information upthread.

If so, does this function survive a factory reset of a device? Or is a factory reset considered a 'different device?'

I’m not sure what you mean by “factory reset”. If you’re talking about Settings > General > Reset > Erase All Content and Settings then, no, that’s not a different device. That is, restoring the backup will restore these keychain items.

Is there a way to prevent a backup of a kSecAttrAccessibleWhenUnlockedThisDeviceOnly key?

You can use an EC key protected by the SE. Erasing the device does result in a ‘new’ SE.

You can use biometrics.

You can wrap the key with a value that’s not backed up.

Is there a 'good' way to migrate a kSecAttrAccessibleWhenUnlockedThisDeviceOnly RSA key to a different device?

Drop the ThisDeviceOnly? That’s the obvious path forward here. Beyond that you’d need to implement something custom, like your own import/export feature.

Oh, and stop using RSA (-:

Share and Enjoy

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

Thank you!

There's one small misunderstanding, I think, because I used vague language.

iOS keychain RSA keys marked kSecAttrAccessibleWhenUnlockedThisDeviceOnly are protected by some Secure Enclave key, right?

Yes, you cannot put a non-EC key into the SE, but I'd like an RSA (sorry) key that is just encrypted by some key in the SE. I thought the following guide was indicating how to do that (just stick kSecAttrAccessibleWhenUnlockedThisDeviceOnly on your RSA key), but I guess I misread that.

https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave

Is there a 'good' way (easy, already implemented in a library or something) to encrypt an RSA key with some SE key?

Thanks again!

Is there a 'good' way (easy, already implemented in a library or something) to encrypt an RSA key with some SE key?

I’m not aware of a library to do this but it shouldn’t be too hard. The only gotcha I can think of is that you mustn’t store the resulting encrypted key as kSecClassKey because the data is no longer in the standard format for an RSA key. Rather, store the item as a kSecClassGenericPassword.

The basic strategy would be:

  1. Generate an RSA key pair not in the keychain (SecKeyCreateRandomKey without setting kSecAttrIsPermanent).

  2. Get the external representation of the private key (SecKeyCopyExternalRepresentation).

  3. Generate an EC key pair with the private key protected by the SE, as described in Storing Keys in the Secure Enclave.

  4. Use SecKeyCreateEncryptedData to encrypt the RSA key with the EC key.

  5. Store that in the keychain as kSecClassGenericPassword.

Share and Enjoy

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

when I try to use these keys for networking I get and error from inside borinssl

I’ve responded over on your dedicated thread.

Share and Enjoy

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

iOS keychain: Life cycle of Secure Enclave protected RSA keys
 
 
Q