| <html devsite> |
| <head> |
| <title>Key Attestation</title> |
| <meta name="project_path" value="/_project.yaml" /> |
| <meta name="book_path" value="/_book.yaml" /> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| //www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <p> |
| 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 |
| keymaster1 enforces restrictions in a hard-to-subvert way. |
| </p> |
| <p> |
| This is only true, however, if the keystore keys are known to be in |
| hardware-backed storage. There is presently no way for apps or remote servers to |
| reliably verify if this is the case. The keystore daemon loads the available |
| keymaster HAL and believes whatever the HAL says with respect to hardware |
| backing of keys. |
| </p> |
| <p> |
| 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. |
| </p> |
| <h2 id="java-api">Java API</h2> |
| <p class="note"> |
| Note: This section is informational only. Keymaster2 implementers neither |
| implement nor use the Java API. This is provided to help implementers understand |
| how the feature is used by applications. System components may use it |
| differently, which is why it's crucial this section not be treated as normative. |
| </p> |
| |
| <section class="expandable"> |
| <h4 class="showalways">How application developers use attestation</h4> |
| <ul> |
| <li>Creates a key generation request, specifying a key alias and key generation |
| parameters for an EC or RSA key pair.</li> |
| <li>Sets the "attestation challenge" for the request, with |
| <code>KeyPairGenerator.setAttestationChallenge(byte[])</code>. This both |
| provides challenge data (which may be empty), and indicates that an attestation |
| is requested.</li> |
| <li>Generates the key pair.</li> |
| <li>Requests the certificate chain from <code>AndroidKeyStore</code>. The first |
| certificate in the chain is the attestation; the other certificates provide the |
| chain of trust back to and including the root attestation key.</li> |
| </ul> |
| <p> |
| This example generates a key pair and requests an attestation. |
| </p> |
| |
| <pre class="prettyprint">// Create KeyPairGenerator and set generation parameters for an ECDSA key pair |
| // using the NIST P-256 curve. "Key1" is the key alias. |
| KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance( |
| KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); |
| keyPairGenerator.initialize( |
| new KeyGenParameterSpec.Builder("Key1", KeyProperties.PURPOSE_SIGN) |
| .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) |
| .setDigests(KeyProperties.DIGEST_SHA256, |
| KeyProperties.DIGEST_SHA384, |
| KeyProperties.DIGEST_SHA512) |
| // Only permit the private key to be used if the user |
| // authenticated within the last five minutes. |
| .setUserAuthenticationRequired(true) |
| .setUserAuthenticationValidityDurationSeconds(5 * 60) |
| // Request an attestation with challenge "hello world". |
| .setAttestationChallenge("hello world".toBytes()); |
| .build()); |
| // Generate the key pair. This will result in calls to both generate_key() and |
| // attest_key() at the keymaster2 HAL. |
| KeyPair keyPair = keyPairGenerator.generateKeyPair(); |
| // Get the certificate chain |
| KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); |
| keyStore.load(null); |
| Certificate[] certs = keyStore.getCertificateChain("Key1"); |
| // certs[0] is the attestation certificate. certs[1] signs certs[0], etc., |
| // up to certs[certs.length - 1]. |
| </pre> |
| </section> |
| |
| <h2 id="hal-changes">HAL changes</h2> |
| <p> |
| To support key attestation, Android 7.1 introduced a set of tags, type, and |
| method to the HAL. |
| </p> |
| <p> |
| <strong>Tags</strong> |
| </p> |
| <ul> |
| <li><code>KM_TAG_ATTESTATION_CHALLENGE</code></li> |
| <li><code>KM_TAG_INCLUDE_UNIQUE_ID</code></li> |
| <li><code>KM_TAG_RESET_SINCE_ID_ROTATION</code> </li> |
| </ul> |
| <p> |
| <strong>Type</strong> |
| </p> |
| |
| <pre class="prettyprint">typedef struct { |
| keymaster_blob_t* entries; |
| size_t entry_count; |
| } keymaster_cert_chain_t; |
| </pre> |
| |
| <p> |
| <strong><code>Attest_key</code> method</strong></p> |
| |
| <pre class="prettyprint">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); |
| </pre> |
| |
| <ul> |
| <li><code>dev</code> is the keymaster device structure.</li> |
| <li><code>key_to_attest</code> is the key blob returned from |
| <code>generate_key</code> for which the attestation will be created.</li> |
| <li><code>attest_params</code> is a list of any parameters necessary for |
| attestation. This includes <code>KM_TAG_ATTESTATION_CHALLENGE</code> and |
| possibly <code>KM_TAG_RESET_SINCE_ID_ROTATION</code>, as well as |
| <code>KM_TAG_APPLICATION_ID</code> and <code>KM_TAG_APPLICATION_DATA</code>. The |
| latter two are necessary to decrypt the key blob if they were specified during |
| key generation.</li> |
| <li><code>cert_chain</code> is the output parameter, which returns an array of |
| certificates. Entry 0 is the attestation certificate, meaning it |
| certifies the key from <code>key_to_attest</code> and contains the |
| attestation extension.</li> |
| </ul> |
| |
| <p> |
| The <code>attest_key</code> 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. |
| </p> |
| <h2 id="attestation-certificate">Attestation certificate</h2> |
| <p> |
| 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 factory-provisioned <a |
| href="#attestation-keys-and-certificates">attestation key</a> that uses the same |
| algorithm as the key being attested (RSA for RSA, EC for EC). |
| </p> |
| <p> |
| 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. |
| </p> |
| <h3 id="certificate-sequence">Certificate SEQUENCE</h3> |
| <table> |
| <tr> |
| <th>Field name (see |
| <a href="https://tools.ietf.org/html/rfc5280">RFC 5280</a>) |
| </th> |
| <th>Value</th> |
| </tr> |
| <tr> |
| <td><a href="https://tools.ietf.org/html/rfc5280#section-4.1.1.1">tbsCertificate</a></td> |
| <td><a href="#tbscertificate-sequence">TBSCertificate SEQUENCE</a></td> |
| </tr> |
| <tr> |
| <td><a href="https://tools.ietf.org/html/rfc5280#section-4.1.1.2">signatureAlgorithm</a></td> |
| <td>AlgorithmIdentifier of algorithm used to sign key:<br /> |
| ECDSA for EC keys, RSA for RSA keys.</td> |
| </tr> |
| <tr> |
| <td><a href="https://tools.ietf.org/html/rfc5280#section-4.1.1.3">signatureValue</a></td> |
| <td>BIT STRING, signature computed on ASN.1 DER-encoded tbsCertificate.</td> |
| </tr> |
| </table> |
| |
| <h3 id="tbscertificate-sequence">TBSCertificate SEQUENCE</h3> |
| |
| <table> |
| <tr> |
| <th>Field name (see |
| <a href="https://tools.ietf.org/html/rfc5280">RFC 5280</a>)</th> |
| <th>Value</th> |
| </tr> |
| <tr> |
| <td><code>version</code></td> |
| <td>INTEGER 2 (means v3 certificate)</td> |
| </tr> |
| <tr> |
| <td><code>serialNumber</code></td> |
| <td>INTEGER 1 (fixed value: same on <em>all</em> certs)</td> |
| </tr> |
| <tr> |
| <td><code>signature</code></td> |
| <td>AlgorithmIdentifier of algorithm used to sign key: ECDSA for EC keys, |
| RSA for RSA keys.</td> |
| </tr> |
| <tr> |
| <td><code>issuer</code></td> |
| <td>Same as the subject field of the batch attestation key.</td> |
| </tr> |
| <tr> |
| <td><code>validity</code></td> |
| <td>SEQUENCE of two dates, containing the values of |
| <code>KM_TAG_ACTIVE_DATETIME</code> and |
| <code>KM_TAG_USAGE_EXPIRE_DATETIME</code>. Those values are in milliseconds |
| since Jan 1, 1970. See <a href="https://tools.ietf.org/html/rfc5280">RFC |
| 5280</a> for correct date representations in certificates.<br /> |
| If <code>KM_TAG_ACTIVE_DATETIME</code> is not present, use the value of |
| <code>KM_TAG_CREATION_DATETIME</code>. If |
| <code>KM_TAG_USAGE_EXPIRE_DATETIME</code> is not present, use the expiration |
| date of the batch attestation key certificate.</td> |
| </tr> |
| <tr> |
| <td><code>subject</code></td> |
| <td>CN = "Android Keystore Key" (fixed value: same on <em>all</em> certs)</td> |
| </tr> |
| <tr> |
| <td><code>subjectPublicKeyInfo</code></td> |
| <td>SubjectPublicKeyInfo containing attested public key.</td> |
| </tr> |
| <tr> |
| <td><code>extensions/Key Usage</code></td> |
| <td>digitalSignature: set if key has purpose <code>KM_PURPOSE_SIGN</code> or |
| <code>KM_PURPOSE_VERIFY</code>. All other bits unset.</td> |
| </tr> |
| <tr> |
| <td><code>extensions/CRL Distribution Points</code></td> |
| <td>Value TBD</td> |
| </tr> |
| <tr> |
| <td><code>extensions/"attestation"</code></td> |
| <td>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.</td> |
| </tr> |
| </table> |
| |
| <h2 id="attestation-extension">Attestation extension</h2> |
| <p> |
| 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, <code>KM_TAG_PURPOSE</code> is defined in |
| keymaster_defs.h as <code>KM_ENUM_REP</code> | 1. For the attestation extension, |
| the <code>KM_ENUM_REP</code> value is removed, leaving tag 1. |
| </p> |
| <p> |
| Values are translated in a straightforward way to ASN.1 types, per this table: |
| </p> |
| <table> |
| <tr> |
| <th>Keymaster type</th> |
| <th>ASN.1 type</th> |
| </tr> |
| <tr> |
| <td><code>KM_ENUM</code></td> |
| <td>INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_ENUM_REP</code></td> |
| <td>SET of INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_UINT</code></td> |
| <td>INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_UINT_REP</code></td> |
| <td>SET of INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_ULONG</code></td> |
| <td>INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_ULONG_REP</code></td> |
| <td>SET of INTEGER</td> |
| </tr> |
| <tr> |
| <td><code>KM_DATE</code></td> |
| <td>INTEGER (milliseconds since Jan 1, 1970 00:00:00 GMT)</td> |
| </tr> |
| <tr> |
| <td><code>KM_BOOL</code></td> |
| <td>NULL (in keymaster, tag present means true, absent means false.<br /> |
| The same semantics apply to the ASN.1 encoding)</td> |
| </tr> |
| <tr> |
| <td><code>KM_BIGNUM</code></td> |
| <td>Not presently used, so no mapping is defined</td> |
| </tr> |
| <tr> |
| <td><code>KM_BYTES</code></td> |
| <td>OCTET_STRING</td> |
| </tr> |
| </table> |
| <p class="note"> |
| <strong>Note:</strong> Some tags are omitted from the schema and should not be |
| included in attestations. For example, the values of <code>KM_TAG_USER_ID</code> |
| and <code>KM_TAG_SECURE_USER_ID</code> have no meaning off-device, and |
| <code>KM_TAG_MIN_MAC_LENGTH</code> and <code>KM_TAG_CALLER_NONCE</code> are |
| useless with asymmetric keys. |
| </p> |
| |
| <h3 id="schema">Schema</h3> |
| <p> |
| The attestation extension content is described by the following ASN.1 schema: |
| </p> |
| |
| <pre class="prettyprint"> |
| KeyDescription ::= SEQUENCE { |
| attestationVersion INTEGER, |
| attestationSecurityLevel SecurityLevel, |
| keymasterVersion INTEGER, |
| keymasterSecurityLevel SecurityLevel, |
| attestationChallenge OCTET_STRING, |
| uniqueId OCTET_STRING, |
| softwareEnforced AuthorizationList, |
| teeEnforced AuthorizationList, |
| } |
| |
| SecurityLevel ::= ENUMERATED { |
| Software (0), |
| TrustedEnvironment (1), |
| } |
| 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, |
| 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, |
| allApplications [600] EXPLICIT NULL OPTIONAL, |
| applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, |
| creationDateTime [701] EXPLICIT INTEGER OPTIONAL, |
| origin [702] EXPLICIT INTEGER OPTIONAL, |
| rollbackResistant [703] EXPLICIT NULL OPTIONAL, |
| rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, |
| osVersion [705] EXPLICIT INTEGER OPTIONAL, |
| osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, |
| } |
| RootOfTrust ::= SEQUENCE { |
| verifiedBootKey OCTET_STRING, |
| deviceLocked BOOLEAN, |
| verifiedBootState VerifiedBootState, |
| } |
| |
| VerifiedBootState ::= ENUMERATED { |
| Verified (0), |
| SelfSigned (1), |
| Unverified (2), |
| Failed (3), |
| }</pre> |
| |
| |
| <h3 id="keydescription-fields">KeyDescription fields</h3> |
| <p> |
| 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. |
| </p> |
| <table> |
| <tr> |
| <th>Field name</th> |
| <th>Type</th> |
| <th>Value</th> |
| </tr> |
| <tr> |
| <td><code>attestationVersion</code></td> |
| <td>INTEGER</td> |
| <td>1</td> |
| </tr> |
| <tr> |
| <td><code>attestationSecurity</code></td> |
| <td>SecurityLevel</td> |
| <td>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.</td> |
| </tr> |
| <tr> |
| <td><code>keymasterVersion</code></td> |
| <td>INTEGER</td> |
| <td>Version of keymaster device, 0, 1, or 2.</td> |
| </tr> |
| <tr> |
| <td><code>keymasterSecurity</code></td> |
| <td>SecurityLevel</td> |
| <td>The security level of the keymaster implementation.</td> |
| </tr> |
| <tr> |
| <td><code>attestationChallenge</code></td> |
| <td>OCTET_STRING</td> |
| <td>Value of <code>KM_TAG_ATTESTATION_CHALLENGE</code>, specified to |
| attestation request.</td> |
| </tr> |
| <tr> |
| <td><code>uniqueId</code></td> |
| <td>OCTET_STRING</td> |
| <td>Optional unique ID, present if key has |
| <code>KM_TAG_INCLUDE_UNIQUE_ID</code></td> |
| </tr> |
| <tr> |
| <td><code>softwareEnforced</code></td> |
| <td>AuthorizationList</td> |
| <td>Optional, keymaster authorizations that are not enforced by the TEE, if |
| any.</td> |
| </tr> |
| <tr> |
| <td><code>teeEnforced</code></td> |
| <td>AuthorizationList</td> |
| <td>Optional, Keymaster authorizations that are enforced by the TEE, if any.</td> |
| </tr> |
| </table> |
| |
| <h3 id="authorizationlist-fields">AuthorizationList fields</h3> |
| <p> |
| 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. |
| </p> |
| <p> |
| See keymaster_defs.h for details on each field's values. Keymaster tag names |
| were transformed into field names by omitting the KM_TAG prefix and changing the |
| remainder to camel case, so <code>KM_TAG_KEY_SIZE</code> became |
| <code>keySize</code>. |
| </p> |
| <p class="note"> |
| <strong>Note</strong>: Many tags from keymaster_defs.h are not included in the |
| schema. Some tags are not applicable to asymmetric keys, some have no meaning |
| off-device, etc. |
| </p> |
| |
| <h3 id="rootoftrust-fields">RootOfTrust fields</h3> |
| <p> |
| The RootOfTrust Fields are identified positionally. |
| </p> |
| <table> |
| <tr> |
| <th>Field name</th> |
| <th>Type</th> |
| <th>Value</th> |
| </tr> |
| <tr> |
| <td><code>verifiedBootKey</code></td> |
| <td>OCTET_STRING</td> |
| <td>A secure hash of the key used to verify the system image. SHA-256 |
| recommended.</td> |
| </tr> |
| <tr> |
| <td><code>deviceLocked</code></td> |
| <td>BOOLEAN</td> |
| <td>True if the bootloader is locked, which means that only signed images can |
| be flashed, and that verified boot checking is done.</td> |
| </tr> |
| <tr> |
| <td><code>verifiedBootState</code></td> |
| <td>VerifiedBootState</td> |
| <td>State of verified boot.</td> |
| </tr> |
| <tr> |
| <td><code>osVersion</code></td> |
| <td>INTEGER</td> |
| <td>The current version of the OS, as an integer in the format MMmmss, where |
| MM is a two-digit major version number, mm is a two-digit minor version number, |
| and ss is a two-digit sub-minor version number. For example, version 6.0.1 would |
| be represented as 060001</td> |
| </tr> |
| <tr> |
| <td><code>patchMonthYear</code></td> |
| <td>INTEGER</td> |
| <td>The month and year of the last patch, as an integer in the format YYYYMM, |
| where YYYY is a four-digit year and MM is a two-digit month. For example, April |
| 2016 would be represented as 201604.</td> |
| </tr> |
| </table> |
| <h3 id="verifiedbootstate-values">VerifiedBootState values</h3> |
| <p> |
| The values of <code>verifiedBootState</code> have the following meanings: |
| </p> |
| <table> |
| <tr> |
| <th>Value</th> |
| <th>Meaning</th> |
| </tr> |
| <tr> |
| <td><code>Verified</code></td> |
| <td>Indicates a full chain of trust extending from the bootloader to verified |
| partitions, including the bootloader, boot partition, and all verified |
| partitions.<br /> |
| In this state, the verifiedBootKey value is the hash of the embedded certificate, |
| meaning the unchangeable certificate burned into ROM.</td> |
| </tr> |
| <tr> |
| <td><code>SelfSigned</code></td> |
| <td>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. |
| <br /> |
| In this state, the verifiedBootKey value is the hash of the self-signing |
| certificate.</td> |
| </tr> |
| <tr> |
| <td><code>Unverified</code></td> |
| <td>Indicates a device may 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.<br /> |
| In this state the verifiedBootKey value is empty.</td> |
| </tr> |
| <tr> |
| <td><code>Failed</code></td> |
| <td>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.</td> |
| </tr> |
| </table> |
| |
| <h3 id="securitylevel-values">SecurityLevel values</h3> |
| <p> |
| The values of securityLevel have the following meanings: |
| </p> |
| <table> |
| <tr> |
| <th>Value</th> |
| <th>Meaning</th> |
| </tr> |
| <tr> |
| <td><code>Software</code></td> |
| <td>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.</td> |
| </tr> |
| <tr> |
| <td><code>TrustedEnvironment</code></td> |
| <td>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.</td> |
| </tr> |
| </table> |
| <h2 id="unique-id">Unique ID</h2> |
| <p> |
| 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: |
| </p> |
| |
| <pre class="prettyprint"> |
| HMAC_SHA256(T || C || R, HBK) |
| </pre> |
| |
| <p> |
| Where: |
| </p> |
| |
| <ul> |
| <li><code>T</code> is the "temporal counter value", computed by dividing the |
| value of <code>KM_TAG_CREATION_DATETIME</code> by 2592000000, dropping any |
| remainder. <code>T</code> changes every 30 days (2592000000 = 30 * 24 * 60 * 60 |
| * 1000).</li> |
| <li><code>C</code> is the value of <code>KM_TAG_APPLICATION_ID</code></li> |
| <li><code>R</code> is 1 if <code>KM_TAG_RESET_SINCE_ID_ROTATION</code> is |
| present in the attest_params parameter to the attest_key call, or 0 if the tag |
| is not present.</li> |
| <li><code>HBK</code> 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.</li> |
| </ul> |
| <p> |
| Truncate the HMAC_SHA256 output to 128 bits. |
| </p> |
| |
| <h2 id="attestation-keys-and-certificates">Attestation keys and |
| certificates</h2> |
| <p> |
| Two keys, one RSA and one ECDSA, and the corresponding certificate chains, are |
| securely provisioned into the device. |
| </p> |
| </body> |
| </html> |