
Keychain data protection overview
Many apps need to handle passwords and other short but sensitive bits of data, such as keys and login tokens. The iOS and iPadOS Keychain provides a secure way to store these items.
Keychain items are encrypted using two different AES-256-GCM keys: a table key (metadata) and a per-row key (secret key). Keychain metadata (all attributes other than kSecValue) is encrypted with the metadata key to speed searches while the secret value (kSecValueData) is encrypted with the secret key. The meta-data key is protected by the Secure Enclave but is cached in the application processor to allow fast queries of the keychain. The secret key always requires a round trip through the Secure Enclave.
The Keychain is implemented as a SQLite database, stored on the file system. There is only one database and the securityd
daemon determines which Keychain items each process or app can access. Keychain access APIs result in calls to the daemon, which queries the app’s “Keychain-access-groups”, “application-identifier” and “application-group” entitlements. Rather than limiting access to a single process, access groups allow Keychain items to be shared between apps.
Keychain items can only be shared between apps from the same developer. This is managed by requiring third-party apps to use access groups with a prefix allocated to them through the Apple Developer Programme through application groups. The prefix requirement and application group uniqueness are enforced through code signing, provisioning profiles and the Apple Developer Programme.
Keychain data is protected using a class structure similar to the one used in file Data Protection. These classes have behaviours equivalent to file Data Protection classes but use distinct keys and are part of APIs that are named differently.
Availability | File Data Protection | Keychain Data Protection |
---|---|---|
When unlocked | NSFileProtectionComplete | kSecAttrAccessibleWhenUnlocked |
While locked | NSFileProtectionCompleteUnless Open | N/A |
After first unlock | NSFileProtectionCompleteUntil FirstUserAuthentication | kSecAttrAccessibleAfterFirstUnlock |
Always | NSFileProtectionNone | kSecAttrAccessibleAlways |
Passcode enabled | N/A | kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly |
Apps that utilise background refresh services can use kSecAttrAccessibleAfterFirstUnlock for Keychain items that need to be accessed during background updates.
The class kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly behaves the same as kSecAttrAccessibleWhenUnlocked; however, it’s available only when the device is configured with a passcode. This class exists only in the system Keybag; they:
Don’t sync to iCloud Keychain
Aren’t backed up
Aren’t included in escrow keybags
If the passcode is removed or reset, the items are rendered useless by discarding the class keys.
Other Keychain classes have a “This device only” counterpart which is always protected with the UID when being copied from the device during a backup, rendering it useless if restored to a different device. Apple has carefully balanced security and usability by choosing Keychain classes that depend on the type of information being secured and when it’s needed by iOS and iPadOS. For example, a VPN certificate must always be available so the device keeps a continuous connection, but it’s classified as “non-migratory” so it can’t be moved to another device.