Keystore provides a more secure place to create, store, and use cryptographic keys in a controlled way. When hardware-backed key storage is available and used, key material is more secure against extraction from the device, and Keymaster enforces restrictions that are difficult to subvert.
This is only true, however, if the keystore keys are known to be in hardware-backed storage. In Keymaster 1, there was no way for apps or remote servers to reliably verify if this was the case. The keystore daemon loaded the available keymaster HAL and believed whatever the HAL said with respect to hardware backing of keys.
To remedy this, Keymaster introduced key attestation in Android 7.0 (Keymaster 2) and ID attestation in Android 8.0 (Keymaster 3).
Key attestation aims to provide a way to strongly determine if an asymmetric key pair is hardware-backed, what the properties of the key are, and what constraints are applied to its usage.
ID attestation allows the device to provide proof of its hardware identifiers, such as serial number or IMEI.
Key attestation
To support key attestation, Android 7.0 introduced a set of tags, type, and method to the HAL.
Tags
Tag::ATTESTATION_CHALLENGE
Tag::INCLUDE_UNIQUE_ID
Tag::RESET_SINCE_ID_ROTATION
Type
Keymaster 2 and below
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
AttestKey
method
Keymaster 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 and below
keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain);
dev
is the keymaster device structure.keyToAttest
is the key blob returned fromgenerateKey
for which the attestation is created.attestParams
is a list of any parameters necessary for attestation. This includesTag::ATTESTATION_CHALLENGE
and possiblyTag::RESET_SINCE_ID_ROTATION
, as well asTag::APPLICATION_ID
andTag::APPLICATION_DATA
. The latter two are necessary to decrypt the key blob if they were specified during key generation.certChain
is the output parameter, which returns an array of certificates. Entry 0 is the attestation certificate, meaning it certifies the key fromkeyToAttest
and contains the attestation extension.
The attestKey
method is considered a public key operation on the
attested key, because it can be called at any time and doesn't need to meet
authorization constraints. For example, if the attested key needs user
authentication for use, an attestation can be generated without user
authentication.
Attestation certificate
The attestation certificate is a standard X.509 certificate, with an optional attestation extension that contains a description of the attested key. The certificate is signed with a certified attestation key. The attestation key might use a different algorithm than the key being attested.
The attestation certificate contains the fields in the table below and can't contain any additional fields. Some fields specify a fixed field value. CTS tests validate that the certificate content is exactly as defined.
Certificate SEQUENCE
Field name (see RFC 5280) | Value |
---|---|
tbsCertificate | TBSCertificate SEQUENCE |
signatureAlgorithm | AlgorithmIdentifier of algorithm used to sign key: ECDSA for EC keys, RSA for RSA keys. |
signatureValue | BIT STRING, signature computed on ASN.1 DER-encoded tbsCertificate. |
TBSCertificate SEQUENCE
Field name (see RFC 5280) | Value |
---|---|
version |
INTEGER 2 (means v3 certificate) |
serialNumber |
INTEGER 1 (fixed value: same on all certs) |
signature |
AlgorithmIdentifier of algorithm used to sign key: ECDSA for EC keys, RSA for RSA keys. |
issuer |
Same as the subject field of the batch attestation key. |
validity |
SEQUENCE of two dates, containing the values of
Tag::ACTIVE_DATETIME and
Tag::USAGE_EXPIRE_DATETIME.
Those values are in milliseconds since Jan 1, 1970.
See RFC 5280 for correct
date representations in certificates. If Tag::ACTIVE_DATETIME is not present, use the value of
Tag::CREATION_DATETIME . If
Tag::USAGE_EXPIRE_DATETIME is not present, use the expiration
date of the batch attestation key certificate. |
subject |
CN = "Android Keystore Key" (fixed value: same on all certs) |
subjectPublicKeyInfo |
SubjectPublicKeyInfo containing attested public key. |
extensions/Key Usage |
digitalSignature: set if key has purpose KeyPurpose::SIGN or
KeyPurpose::VERIFY . All other bits unset. |
extensions/CRL Distribution Points |
Value TBD |
extensions/"attestation" |
The OID is 1.3.6.1.4.1.11129.2.1.17; the content is defined in the Attestation Extension section below. As with all X.509 certificate extensions, the content is represented as an OCTET_STRING containing a DER encoding of the attestation SEQUENCE. |
Attestation extension
The attestation
extension contains a complete description of the keymaster
authorizations associated with the key, in a structure that directly corresponds
to the authorization lists as used in Android and the keymaster HAL. Each tag in
an authorization list is represented by an ASN.1 SEQUENCE
entry, explicitly
tagged with the keymaster tag number, but with the type descriptor (four high
order bits) masked out.
For example, in Keymaster 3, Tag::PURPOSE
is defined in
types.hal as ENUM_REP | 1
. For the attestation extension,
the ENUM_REP
value is removed, leaving tag 1
.
(For Keymaster 2 and below, KM_TAG_PURPOSE
is defined in
keymaster_defs.h.)
Values are translated in a straightforward way to ASN.1 types, per this table:
Keymaster type | ASN.1 type |
---|---|
ENUM |
INTEGER |
ENUM_REP |
SET of INTEGER |
UINT |
INTEGER |
UINT_REP |
SET of INTEGER |
ULONG |
INTEGER |
ULONG_REP |
SET of INTEGER |
DATE |
INTEGER (milliseconds since Jan 1, 1970 00:00:00 GMT) |
BOOL |
NULL (in keymaster, tag present means true, absent means false. The same semantics apply to the ASN.1 encoding) |
BIGNUM |
Not presently used, so no mapping is defined |
BYTES |
OCTET_STRING |
Schema
The attestation extension content is described by the following ASN.1 schema.
KeyDescription ::= SEQUENCE { attestationVersion INTEGER, # KM2 value is 1. KM3 value is 2. KM4 value is 3. attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL. digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, # KM4 activeDateTime [400] EXPLICIT INTEGER OPTIONAL originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, # KM4 trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, # KM4 unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, # KM4 allApplications [600] EXPLICIT NULL OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, # KM2 and KM3 only. rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, # KM3 vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, # KM4 bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, # KM4 } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, # KM4 } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
KeyDescription fields
The keymasterVersion
and attestationChallenge
fields are identified
positionally, rather than by tag, so the tags in the encoded form only specify
field type. The remaining fields are implicitly tagged as specified in the
schema.
Field name | Type | Value |
---|---|---|
attestationVersion |
INTEGER | Version of attestation schema: 1, 2, or 3. |
attestationSecurity |
SecurityLevel | The security level of this attestation. It is possible to get software attestations of hardware-backed keys. Such attestations cannot be trusted if the Android system is compromised. |
keymasterVersion |
INTEGER | Version of keymaster device: 0, 1, 2, 3, or 4. |
keymasterSecurity |
SecurityLevel | The security level of the keymaster implementation. |
attestationChallenge |
OCTET_STRING | Value of Tag::ATTESTATION_CHALLENGE , specified to attestation request. |
uniqueId |
OCTET_STRING | Optional unique ID, present if key has
Tag::INCLUDE_UNIQUE_ID |
softwareEnforced |
AuthorizationList | Optional, keymaster authorizations that are not enforced by the TEE, if any. |
teeEnforced |
AuthorizationList | Optional, Keymaster authorizations that are enforced by the TEE, if any. |
AuthorizationList fields
AuthorizationList
fields are all optional and are identified
by keymaster tag value, with the type bits masked out.
Explicit tagging is used so the fields also contain a tag indicating
their ASN.1 type, for easier parsing.
For details on each field's values, see types.hal
for Keymaster 3 and
keymaster_defs.h
for Keymaster 2 and below. Keymaster tag names
were transformed into field names by omitting the KM_TAG
prefix and changing the
remainder to camel case, so Tag::KEY_SIZE
became
keySize
.
RootOfTrust fields
The RootOfTrust
Fields are identified positionally.
Field name | Type | Value |
---|---|---|
verifiedBootKey |
OCTET_STRING | A secure hash of the key used to verify the system image. SHA-256 recommended. |
deviceLocked |
BOOLEAN | True if the bootloader is locked, which means that only signed images can be flashed, and that verified boot checking is done. |
verifiedBootState |
VerifiedBootState | State of verified boot. |
verifiedBootHash |
OCTET_STRING | A digest of all data protected by Verified Boot. For devices that use the Android Verified Boot implementation of Verified Boot, this value contains the digest of the VBMeta struct, or the Verified Boot metadata structure. To learn more about how to calculate this value, see The VBMeta Digest |
VerifiedBootState values
The values of verifiedBootState
have the following meanings:
Value | Meaning |
---|---|
Verified |
Indicates a full chain of trust extending from the bootloader to verified
partitions, including the bootloader, boot partition, and all verified
partitions. In this state, the verifiedBootKey value is the hash of the embedded
certificate, meaning the unchangeable certificate burned into ROM.This state corresponds with the green boot state as documented in the verified boot flow documentation. |
SelfSigned |
Indicates the boot partition has been verified using the embedded
certificate, and the signature is valid. The bootloader displays a warning and
the fingerprint of the public key before allowing the boot process to continue.
In this state, the verifiedBootKey value is the hash of the self-signing
certificate.This state corresponds with the yellow boot state as documented in the verified boot flow documentation. |
Unverified |
Indicates a device can be freely modified. Device integrity is left to
the user to verify out-of-band. The bootloader displays a warning to the user
before allowing the boot process to continue. In this state the verifiedBootKey value is empty.This state corresponds with the orange boot state as documented in the verified boot flow documentation. |
Failed |
Indicates the device has failed verification. No attestation certificate
actually contains this value, because in this state the bootloader halts. It's
included here for completeness. This state corresponds with the red boot state as documented in the verified boot flow documentation. |
SecurityLevel values
The values of securityLevel
have the following meanings:
Value | Meaning |
---|---|
Software |
The code that creates or manages the relevant element (attestation or key) is implemented in the Android system and could be altered if that system is compromised. |
TrustedEnvironment |
The code that creates or manages the relevant element (attestation or key) is implemented in a Trusted Execution Environment (TEE). It could be altered if the TEE is compromised, but the TEE is highly resistant to remote compromise and moderately resistant to compromise by direct hardware attack. |
StrongBox |
The code that creates or manages the relevant element (attestation or key) is implemented in a dedicated hardware security module. It could be altered if the hardware security module is compromised, but it is highly resistant to remote compromise and highly resistant to compromise by direct hardware attack. |
Unique ID
The Unique ID is a 128-bit value that identifies the device, but only for a limited period of time. The value is computed with:
HMAC_SHA256(T || C || R, HBK)
Where:
T
is the "temporal counter value", computed by dividing the value ofTag::CREATION_DATETIME
by 2592000000, dropping any remainder.T
changes every 30 days (2592000000 = 30 * 24 * 60 * 60 * 1000).C
is the value ofTag::APPLICATION_ID
R
is 1 ifTag::RESET_SINCE_ID_ROTATION
is present in the attest_params parameter to the attest_key call, or 0 if the tag is not present.HBK
is a unique hardware-bound secret known to the Trusted Execution Environment and never revealed by it. The secret contains at least 128 bits of entropy and is unique to the individual device (probabilistic uniqueness is acceptable given the 128 bits of entropy). HBK should be derived from fused key material via HMAC or AES_CMAC.
Truncate the HMAC_SHA256 output to 128 bits.
Attestation keys and certificates
Two keys, one RSA and one ECDSA, and the corresponding certificate chains, are securely provisioned into the device.
Android 12 introduces Remote Key Provisioning, and Android 13 requires devices implement it. Remote Key Provisioning provides devices in the field with per app, ECDSA P256 attestation certificates. These certificates are shorter-lived than the factory-provisioned certificates.
Multiple IMEIs
Android 14 adds support for multiple IMEIs in the Android Key Attestation record. OEMs can implement this feature by adding a KeyMint tag for a second IMEI. It is becoming increasingly common for devices to have multiple cellular radios and OEMs can now support devices with two IMEIs.
OEMs are required to have a secondary IMEI, if present on their devices, to be provisioned to the KeyMint implementation(s) so that those implementations can attest to it in the same way they attest to the first IMEI
ID attestation
Android 8.0 includes optional support for ID attestation for devices with Keymaster 3. ID attestation allows the device to provide proof of its hardware identifiers, such as serial number or IMEI. Although an optional feature, it is highly recommended that all Keymaster 3 implementations provide support for it because being able to prove the device's identity enables use cases such as true zero-touch remote configuration to be more secure (because the remote side can be certain it is talking to the right device, not a device spoofing its identity).
ID attestation works by creating copies of the device's hardware identifiers that only the Trusted Execution Environment (TEE) can access before the device leaves the factory. A user can unlock the device's bootloader and change the system software and the identifiers reported by the Android frameworks. The copies of the identifiers held by the TEE cannot be manipulated in this way, ensuring that device ID attestation only attests to the device's original hardware identifiers, thereby thwarting spoofing attempts.
The main API surface for ID attestation builds on top of the existing key attestation mechanism introduced with Keymaster 2. When requesting an attestation certificate for a key held by keymaster, the caller can request that the device's hardware identifiers be included in the attestation certificate's metadata. If the key is held in the TEE, the certificate chains back to a known root of trust. The recipient of such a certificate can verify that the certificate and its contents, including the hardware identifiers, were written by the TEE. When asked to include hardware identifiers in the attestation certificate, the TEE attests only to the identifiers held in its storage, as populated on the factory floor.
Storage properties
The storage that holds the device's identifiers needs to have these properties:
- The values derived from the device's original identifiers are copied to the storage before the device leaves the factory.
- The
destroyAttestationIds()
method can permanently destroy this copy of the identifier-derived data. Permanent destruction means the data is completely removed so neither a factory reset nor any other procedure performed on the device can restore it. This is especially important for devices where a user has unlocked the bootloader and changed the system software and modified the identifiers returned by Android frameworks. - RMA facilities should have the ability to generate fresh copies of the hardware identifier-derived data. This way, a device that passes through RMA can perform ID attestation again. The mechanism used by RMA facilities must be protected so that users cannot invoke it themselves, as that would allow them to obtain attestations of spoofed IDs.
- No code other than Keymaster trusted app in the TEE is able to read the identifier-derived data kept in the storage.
- The storage is tamper-evident: If the content of the storage has been modified, the TEE treats it the same as if the copies of the content had been destroyed and refuses all ID attestation attempts. This is implemented by signing or MACing the storage as described below.
- The storage does not hold the original identifiers. Because ID attestation involves a challenge, the caller always supplies the identifiers to be attested. The TEE only needs to verify that these match the values they originally had. Storing secure hashes of the original values rather than the values enables this verification.
Construction
To create an implementation that has the properties listed above, store the ID-derived values in the following construction S. Do not store other copies of the ID values, excepting the normal places in the system, which a device owner can modify by rooting:
S = D || HMAC(HBK, D)
where:
D = HMAC(HBK, ID1) || HMAC(HBK, ID2) || ... || HMAC(HBK, IDn)
HMAC
is the HMAC construction with an appropriate secure hash (SHA-256 recommended)HBK
is a hardware-bound key not used for any other purposeID1...IDn
are the original ID values; association of a particular value to a particular index is implementation-dependent, as different devices have different numbers of identifiers||
represents concatenation
Because the HMAC outputs are fixed size, no headers or other structure are required to be able to find individual ID hashes, or the HMAC of D. In addition to checking provided values to perform attestation, implementations need to validate S by extracting D from S, computing HMAC(HBK, D) and comparing it to the value in S to verify that no individual IDs were modified/corrupted. Also, implementations must use constant-time comparisons for all individual ID elements and the validation of S. Comparison time must be constant regardless of the number of IDs provided and the correct matching of any part of the test.
Hardware identifiers
ID attestation supports the following hardware identifiers:
- Brand name, as returned by
Build.BRAND
in Android - Device name, as returned by
Build.DEVICE
in Android - Product name, as returned by
Build.PRODUCT
in Android - Manufacturer name, as returned by
Build.MANUFACTURER
in Android - Model name, as returned by
Build.MODEL
in Android - Serial number
- IMEIs of all radios
- MEIDs of all radios
To support device ID attestation, a device attests to these identifiers. All devices running Android have the first six and they are necessary for this feature to work. If the device has any integrated cellular radios, the device must also support attestation for the IMEIs and/or MEIDs of the radios.
ID attestation is requested by performing a key attestation and including the device identifiers to attest in the request. The identifiers are tagged as:
ATTESTATION_ID_BRAND
ATTESTATION_ID_DEVICE
ATTESTATION_ID_PRODUCT
ATTESTATION_ID_MANUFACTURER
ATTESTATION_ID_MODEL
ATTESTATION_ID_SERIAL
ATTESTATION_ID_IMEI
ATTESTATION_ID_MEID
The identifier to attest is a UTF-8 encoded byte string. This format applies to numerical identifiers, as well. Each identifier to attest is expressed as a UTF-8 encoded string.
If the device does not support ID attestation (or
destroyAttestationIds()
was previously called and the device can no
longer attest its IDs), any key attestation request that includes one or more of
these tags fails with ErrorCode::CANNOT_ATTEST_IDS
.
If the device supports ID attestation and one or more of the above tags have
been included in a key attestation request, the TEE verifies the identifier
supplied with each of the tags matches its copy of the hardware identifiers. If
one or more identifiers do not match, the entire attestation fails with
ErrorCode::CANNOT_ATTEST_IDS
. It is valid for the same tag to be
supplied multiple times. This can be useful, for example, when attesting IMEIs:
A device can have multiple radios with multiple IMEIs. An attestation request is
valid if the value supplied with each ATTESTATION_ID_IMEI
matches
one of the device's radios. The same applies to all other tags.
If attestation is successful, the attested IDs is added to the attestation extension (OID 1.3.6.1.4.1.11129.2.1.17) of the issued attestation certificate, using the schema from above. Changes from the Keymaster 2 attestation schema are bolded, with comments.
Java API
This section is informational only. Keymaster implementers neither implement nor use the Java API. This is provided to help implementers understand how the feature is used by apps. System components might use it differently, which is why it's crucial this section not be treated as normative.