Posted by Shawn Willden, Software Engineer
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
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.
History of Keystore
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
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.
Why use key attestation?
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.