28 Eylül 2017
Android's keystore has been available for many years, providing app developers with a way to use cryptographic keys for authentication and encryption. Keystore keeps the key material out of the app's process space, so that the app cannot inadvertently reveal it to the user where it could be phished, leak it through some other channel, or have it compromised in the event of a compromise of the app. Many devices also provide hardware-based security for keystore keys in secure hardware, which keeps the key material out of the Android system entirely, so that the key material cannot be leaked even by a Linux kernel compromise. In the vast majority of Android devices, secure hardware is a special mode of the main CPU, with hardware-enforced isolation from the Linux kernel and Android userspace. Alternatively, some devices use a separate secure microprocessor.
Android provides APIs that allow the app to determine whether a given keystore key is in secure hardware, but these APIs could be unreliable if the operating system has been compromised. Key attestation provides a way for a device's secure hardware to verify that an asymmetric key is in secure hardware, protected against compromise of the Android OS.
Keystore was originally introduced in Android 4.0 and keys were encrypted with the user's passcode. In Android 4.1 the infrastructure to use device secure hardware was added.
Up until Android 6.0, Keystore supported RSA and ECDSA. In Android 6.0, Keystore was significantly enhanced, adding support for AES and HMAC. Also, other crucial elements of cryptographic operations, such as RSA padding1 and AES block chaining2 modes were moved into secure hardware.
In Android 6.0, Keystore also gained the ability to restrict the ways in which a particular key could be used. The most obviously useful restriction that can be applied is user authentication binding. This allows a key's usage to be "bound" to the user's passcode—their PIN, pattern, or password—or fingerprint. For passcode authentication binding, the app developer can specify a timeout in seconds. If more than the specified time has elapsed since the user last entered their passcode, the secure hardware refuses any requests to use the key. Fingerprint-bound keys require a new user authentication each time the key is used.
Other, more technical, restrictions can be applied to Android 6.0+ keys as well. In particular, at point of key creation or import, it is necessary to specify the cryptographic purposes (encrypt, decrypt, sign, or verify) for which the key may be used, as well as padding and block modes, digests, source of entropy for initialization vectors or nonces, and other details of the cryptographic operation. Because the specified information is permanently and cryptographically bound to the key material, Keystore won't allow the key to be used in any other way. Therefore, an attacker who gains control of the app or the system can't misuse the key. To help prevent attacks, developers should specify the narrowest possible range of uses for a given key.
One of the most important changes to Android Keystore was introduced in Android 7.0. New devices that launch with Android 7.0+ with a secure lock screen must have secure hardware and support hardware-based passcode authentication and keystore keys. Prior to Android 7.0, secure hardware support was widespread, but over the next few years it will become universal.
In Android 8.0, key attestation was made mandatory for all new devices that ship with Google Play installed.
Suppose you're developing an app to provide a bank's customers with access to their bank balance, transaction history, and bill pay system. Security is important; you don't want anyone who picks up the user's phone to have access to their the bank account. One approach would be to use the user's web site password. But that's often inconvenient for the user because web sites often demand long, complex passwords, which are inconvenient on a small touchscreen.
With Android Keystore, you can generate an asymmetric authentication key, such as a 256-bit ECDSA key, and have each user sign in with their complex web password once, then register the public key in the bank's customer account database. Each time they open the app, you can execute a challenge-response authentication protocol using that ECDSA key. Further, if you make the key authentication-bound, the user can authenticate with their lock screen passcode or fingerprint each time they open the app. That allows them to use the simpler and more convenient authentication mechanism on their phone.
If an attacker compromises Android and attempts to extract the key, they shouldn't be able to because the key is in secure hardware.
As an app developer, key attestation allows you to verify on your server that the ECDSA key your app requested actually lives in secure hardware. Note that there's little point in using the attestation in your app itself; if the Android OS is uncompromised and trustworthy, then you can just use the KeyInfo class introduced in 6.0 to discover whether the key is in secure hardware. If it is compromised, then that API and any attempt you make to validate the attestation on device are both unreliable.
Note that key attestation is distinct from SafetyNet attestation. They're the same concept, but attest to different things and come from different places. Keystore key attestation affirms that a crypto key lives in secure hardware and has specific characteristics. SafetyNet attestation affirms that a device is real (not an emulator) and that it's running known software. SafetyNet uses Keystore key attestation under the covers, so if you want to know about device integrity use that. If you want to confirm that your key is in secure hardware, use key attestation.
For details and sample code, see the key attestation training article on developer.android.com.