On iOS and macOS, the Keychain is the dedicated secure container for storing key materials or secrets. When using Keychain services, the
complexities of encryption are handled by the system, which ensures that the data is stored securely. Keychain also provides fine-grained access
control, allowing developers to specify the conditions under which a keychain item can be accessed. For instance, access control can be configured to
require user authentication, such as Face ID, Touch ID, or passcode, every time an application attempts to access the Keychain item. This measure
protects the keychain item from unauthorized access, even if the device has no passcode or is already unlocked.
Ask Yourself Whether
- The application requires prohibiting the use of keys in case of compromise of the application process.
- The key material is used in the context of a highly sensitive application like a e-banking mobile app.
There is a risk if you answered yes to any of those questions.
Recommended Secure Coding Practices
It’s recommended to enable user authentication by setting kSecAttrAccessControl using the SecAccessControlCreateWithFlags
function. It allows you to require user authentication (such as Face ID, Touch ID, or passcode) before accessing the keychain item.
Sensitive Code Example
The generated key can be used without authentication.
import Security
let parameters: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: 4096,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: "a-private-key"
]
]
SecKeyCreateRandomKey(parameters as CFDictionary, nil) // Noncompliant
Compliant Solution
Accessing the key will trigger a local authentication.
import Security
let parameters: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: 4096,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: "a-private-key",
kSecAttrAccessControl as String: SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.userPresence,
nil
)!
]
]
SecKeyCreateRandomKey(parameters as CFDictionary, nil)
See
developer.apple.com -
Restricting keychain item accessibility