Posted by Shawn Willden, Software Engineer
Android's keystore has been available for many years, providing app developerswith a way to use cryptographic keys for authentication and encryption. Keystorekeeps the key material out of the app's process space, so that the app cannotinadvertently reveal it to the user where it could be phished, leak it throughsome other channel, or have it compromised in the event of a compromise of theapp. Many devices also provide hardware-based security for keystore keys insecure hardware, which keeps the key material out of the Android systementirely, so that the key material cannot be leaked even by a Linux kernelcompromise. In the vast majority of Android devices, secure hardware is aspecial mode of the main CPU, with hardware-enforced isolation from the Linuxkernel and Android userspace. Alternatively, some devices use a separate securemicroprocessor.
Android provides APIs that allow the app to determine whether a given keystorekey is in secure hardware, but these APIs could be unreliable if the operatingsystem has been compromised. Key attestation provides a way for a device'ssecure hardware to verify that an asymmetric key is in secure hardware,protected against compromise of the Android OS.
History of Keystore
Keystore was originally introduced in Android 4.0 and keys were encrypted withthe user's passcode. In Android 4.1 the infrastructure to use device securehardware was added.
Up until Android 6.0, Keystore supported RSA and ECDSA. In Android 6.0, Keystorewas significantly enhanced, adding support for AES and HMAC. Also, other crucialelements 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 aparticular key could be used. The most obviously useful restriction that can beapplied 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 inseconds. If more than the specified time has elapsed since the user last enteredtheir passcode, the secure hardware refuses any requests to use the key.Fingerprint-bound keys require a new user authentication each time the key isused.
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 specifythe cryptographic purposes (encrypt, decrypt, sign, or verify) for which the keymay be used, as well as padding and block modes, digests, source of entropy forinitialization vectors or nonces, and other details of the cryptographicoperation. Because the specified information is permanently andcryptographically bound to the key material, Keystore won't allow the key to beused in any other way. Therefore, an attacker who gains control of the app orthe system can't misuse the key. To help prevent attacks, developers shouldspecify the narrowest possible range of uses for a given key.
One of the most important changes to Android Keystore was introduced in Android7.0. New devices that launch with Android 7.0+ with a secure lock screen musthave secure hardware and support hardware-based passcode authentication andkeystore keys. Prior to Android 7.0, secure hardware support was widespread, butover the next few years it will become universal.
In Android 8.0, key attestation was made mandatory for all new devices that shipwith Google Play installed.
Why use key attestation?
Suppose you're developing an app to provide a bank's customers with access totheir bank balance, transaction history, and bill pay system. Security isimportant; you don't want anyone who picks up the user's phone to have access totheir the bank account. One approach would be to use the user's web sitepassword. But that's often inconvenient for the user because web sites oftendemand long, complex passwords, which are inconvenient on a small touchscreen.
With Android Keystore, you can generate an asymmetric authentication key, suchas a 256-bit ECDSA key, and have each user sign in with their complex webpassword once, then register the public key in the bank's customer accountdatabase. Each time they open the app, you can execute a challenge-responseauthentication protocol using that ECDSA key. Further, if you make the keyauthentication-bound, the user can authenticate with their lock screen passcodeor fingerprint each time they open the app. That allows them to use the simplerand more convenient authentication mechanism on their phone.
If an attacker compromises Android and attempts to extract the key, theyshouldn't be able to because the key is in secure hardware.
As an app developer, key attestation allows you to verify on your server thatthe ECDSA key your app requested actually lives in secure hardware. Note thatthere's little point in using the attestation in your app itself; if the AndroidOS is uncompromised and trustworthy, then you can just use the KeyInfoclass introduced in 6.0 to discover whether the key is in secure hardware. If itis compromised, then that API and any attempt you make to validate theattestation on device are both unreliable.
Note that key attestation is distinct from SafetyNetattestation. They're the same concept, but attest to different things andcome from different places. Keystore key attestation affirms that a crypto keylives in secure hardware and has specific characteristics. SafetyNet attestationaffirms that a device is real (not an emulator) and that it's running knownsoftware. SafetyNet uses Keystore key attestation under the covers, so if youwant to know about device integrity use that. If you want to confirm that yourkey is in secure hardware, use key attestation.
For details and sample code, see the keyattestation training article on developer.android.com.
Notes
Keystore supports the recommended OAEP and PSS padding modes for RSA encryption andsigning, respectively, as well as the older PKCS#1 v1.5 modes.↩
Keystore supports GCM, CBC and ECB block chaining modes.↩