Atestado de chave e ID

O Keystore fornece um local mais seguro para criar, armazenar e usar chaves criptográficas de maneira controlada. Quando o armazenamento de chaves com suporte de hardware está disponível e é usado, o material da chave fica mais seguro contra a extração do dispositivo, e o Keymaster impõe restrições difíceis de subverter.

No entanto, isso só é verdade se as chaves do keystore estiverem em armazenamento com suporte de hardware. No Keymaster 1, não havia como os aplicativos ou servidores remotos verificarem de forma confiável se esse era o caso. O daemon keystore carregou o HAL do keymaster disponível e acreditou no que o HAL disse com relação ao suporte de hardware das chaves.

Para remediar isso, a Keymaster introduziuo atestado de chave no Android 7.0 (Keymaster 2) e o atestado de ID no Android 8.0 (Keymaster 3).

O atestado de chave visa fornecer uma maneira de determinar fortemente se um par de chaves assimétricas é suportado por hardware, quais são as propriedades da chave e quais restrições são aplicadas ao seu uso.

O atestado de ID permite que o dispositivo forneça prova de seus identificadores de hardware, como número de série ou IMEI.

Atestado de chave

Para oferecer suporte ao atestado de chave, o Android 7.1 introduziu um conjunto de tags, tipo e método para o HAL.

Tag

  • Tag::ATTESTATION_CHALLENGE
  • Tag::INCLUDE_UNIQUE_ID
  • Tag::RESET_SINCE_ID_ROTATION

Tipo

Keymaster 2 e abaixo

typedef struct {
    keymaster_blob_t* entries;
    size_t entry_count;
} keymaster_cert_chain_t;

Método AttestKey

Keymaster 3

    attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
        generates(ErrorCode error, vec<vec<uint8_t>> certChain);

Keymaster 2 e abaixo

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 é a estrutura do dispositivo keymaster.
  • keyToAttest é o blob de chaves retornado de generateKey para o qual o atestado será criado.
  • attestParams é uma lista de quaisquer parâmetros necessários para atestado. Isso inclui Tag::ATTESTATION_CHALLENGE e possivelmente Tag::RESET_SINCE_ID_ROTATION , bem como Tag::APPLICATION_ID e Tag::APPLICATION_DATA . Os dois últimos são necessários para descriptografar o blob de chaves se tiverem sido especificados durante a geração da chave.
  • certChain é o parâmetro de saída, que retorna uma matriz de certificados. A entrada 0 é o certificado de atestado, o que significa que certifica a chave de keyToAttest e contém a extensão de atestado.

O método attestKey é considerado uma operação de chave pública na chave atestada, pois pode ser chamado a qualquer momento e não precisa atender às restrições de autorização. Por exemplo, se a chave atestada precisar de autenticação de usuário para uso, um atestado pode ser gerado sem autenticação de usuário.

Certificado de atestado

O certificado de atestado é um certificado X.509 padrão, com uma extensão de atestado opcional que contém uma descrição da chave atestada. O certificado é assinado com uma chave de atestado fornecida pela fábrica que usa o mesmo algoritmo da chave que está sendo atestado (RSA para RSA, EC para EC).

O certificado de atestado contém os campos da tabela abaixo e não pode conter campos adicionais. Alguns campos especificam um valor de campo fixo. Os testes CTS validam que o conteúdo do certificado é exatamente como definido.

Certificado SEQUÊNCIA

Nome do campo (consulte RFC 5280 ) Valor
tbsCertificado SEQUÊNCIA DE CERTIFICADO TBS
algoritmo de assinatura AlgorithmIdentifier do algoritmo usado para assinar a chave:
ECDSA para chaves EC, RSA para chaves RSA.
valorAssinatura BIT STRING, assinatura calculada em tbsCertificate codificado em DER ASN.1.

SEQUÊNCIA DE CERTIFICADO TBS

Nome do campo (consulte RFC 5280 ) Valor
version INTEIRO 2 (significa certificado v3)
serialNumber INTEGER 1 (valor fixo: igual em todos os certificados)
signature AlgorithmIdentificador do algoritmo usado para assinar a chave: ECDSA para chaves EC, RSA para chaves RSA.
issuer Igual ao campo de assunto da chave de atestado de lote.
validity SEQUENCE de duas datas, contendo os valores de Tag::ACTIVE_DATETIME e Tag::USAGE_EXPIRE_DATETIME . Esses valores estão em milissegundos desde 1º de janeiro de 1970. Consulte RFC 5280 para representações de data corretas em certificados.
Se Tag::ACTIVE_DATETIME não estiver presente, use o valor de Tag::CREATION_DATETIME . Se Tag::USAGE_EXPIRE_DATETIME não estiver presente, use a data de expiração do certificado de chave de atestado de lote.
subject CN = "Android Keystore Key" (valor fixo: mesmo em todos os certificados)
subjectPublicKeyInfo SubjectPublicKeyInfo contendo chave pública atestada.
extensions/Key Usage digitalSignature: define se a chave tem propósito KeyPurpose::SIGN ou KeyPurpose::VERIFY . Todos os outros bits desabilitados.
extensions/CRL Distribution Points Valor a definir
extensions/"attestation" O OID é 1.3.6.1.4.1.11129.2.1.17; o conteúdo é definido na seção Extensão de Atestado abaixo. Tal como acontece com todas as extensões de certificado X.509, o conteúdo é representado como um OCTET_STRING contendo uma codificação DER da SEQUÊNCIA de atestado.

Extensão de atestado

A extensão de attestation contém uma descrição completa das autorizações do keymaster associadas à chave, em uma estrutura que corresponde diretamente às listas de autorização usadas no Android e no HAL do keymaster. Cada tag em uma lista de autorização é representada por uma entrada ASN.1 SEQUENCE , explicitamente marcada com o número da tag keymaster, mas com o descritor de tipo (quatro bits de alta ordem) mascarado.

Por exemplo, no Keymaster 3, Tag::PURPOSE PURPOSE é definido em types.hal como ENUM_REP | 1 . Para a extensão de atestado, o valor ENUM_REP é removido, deixando a tag 1 . (Para Keymaster 2 e abaixo, KM_TAG_PURPOSE é definido em keymaster_defs.h.)

Os valores são traduzidos de forma direta para os tipos ASN.1, conforme esta tabela:

Tipo de chave-mestre Tipo ASN.1
ENUM INTEIRO
ENUM_REP CONJUNTO de INTEIRO
UINT INTEIRO
UINT_REP CONJUNTO de INTEIRO
ULONG INTEIRO
ULONG_REP CONJUNTO de INTEIRO
DATE INTEGER (milissegundos desde 1º de janeiro de 1970 00:00:00 GMT)
BOOL NULL (no keymaster, tag presente significa verdadeiro, ausente significa falso.
A mesma semântica se aplica à codificação ASN.1)
BIGNUM Não é usado atualmente, portanto, nenhum mapeamento é definido
BYTES OCTET_STRING

Esquema

O conteúdo da extensão de atestado é descrito pelo esquema ASN.1 a seguir.

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,
  applicationId               [601] EXPLICIT OCTET_STRING 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),
}

Campos de descrição da chave

Os campos keymasterVersion e attestationChallenge são identificados posicionalmente, em vez de por tag, portanto, as tags no formulário codificado especificam apenas o tipo de campo. Os campos restantes são marcados implicitamente conforme especificado no esquema.

Nome do campo Tipo Valor
attestationVersion INTEIRO Versão do esquema de atestado: 1, 2 ou 3.
attestationSecurity Nível de segurança O nível de segurança deste atestado. É possível obter atestados de software de chaves suportadas por hardware. Esses atestados não são confiáveis ​​se o sistema Android estiver comprometido.
keymasterVersion INTEIRO Versão do dispositivo keymaster: 0, 1, 2, 3 ou 4.
keymasterSecurity Nível de segurança O nível de segurança da implementação do keymaster.
attestationChallenge OCTET_STRING Valor do Tag::ATTESTATION_CHALLENGE , especificado para solicitação de atestado.
uniqueId OCTET_STRING ID exclusivo opcional, presente se a chave tiver Tag::INCLUDE_UNIQUE_ID
softwareEnforced Lista de autorizações Opcional, autorizações de keymaster que não são impostas pelo TEE, se houver.
teeEnforced Lista de autorizações Opcional, autorizações do Keymaster que são impostas pelo TEE, se houver.

Campos da lista de autorizações

Os campos AuthorizationList são todos opcionais e são identificados pelo valor da tag keymaster, com os bits de tipo mascarados. A marcação explícita é usada para que os campos também contenham uma marca indicando seu tipo ASN.1, para facilitar a análise.

Para obter detalhes sobre os valores de cada campo, consulte types.hal para Keymaster 3 e keymaster_defs.h para Keymaster 2 e abaixo. Os nomes de tags Keymaster foram transformados em nomes de campo omitindo o prefixo KM_TAG e alterando o restante para camel case, então Tag::KEY_SIZE tornou-se keySize .

Campos RootOfTrust

Os campos RootOfTrust são identificados posicionalmente.

Nome do campo Tipo Valor
verifiedBootKey OCTET_STRING Um hash seguro da chave usada para verificar a imagem do sistema. SHA-256 recomendado.
deviceLocked BOLEANO True se o carregador de inicialização estiver bloqueado, o que significa que apenas imagens assinadas podem ser exibidas e que a verificação de inicialização verificada é feita.
verifiedBootState Estado de inicialização verificado Estado de inicialização verificada.
verifiedBootHash OCTET_STRING Um resumo de todos os dados protegidos pela inicialização verificada. Para dispositivos que usam a implementação do Android Verified Boot de Verified Boot, esse valor contém o resumo da estrutura VBMeta ou a estrutura de metadados de inicialização verificada. Para saber mais sobre como calcular esse valor, consulte The VBMeta Digest

Valores de VerifiedBootState

Os valores de verifiedBootState têm os seguintes significados:

Valor Significado
Verified Indica uma cadeia completa de confiança que se estende do carregador de inicialização às partições verificadas, incluindo o carregador de inicialização, partição de inicialização e todas as partições verificadas.
Nesse estado, o valor verifiedBootKey é o hash do certificado incorporado, ou seja, o certificado imutável gravado na ROM.
SelfSigned Indica que a partição de inicialização foi verificada usando o certificado incorporado e a assinatura é válida. O bootloader exibe um aviso e a impressão digital da chave pública antes de permitir que o processo de inicialização continue.
Nesse estado, o valor verifiedBootKey é o hash do certificado autoassinado.
Unverified Indica que um dispositivo pode ser modificado livremente. A integridade do dispositivo é deixada para o usuário verificar fora de banda. O carregador de inicialização exibe um aviso ao usuário antes de permitir que o processo de inicialização continue.
Nesse estado, o valor verifiedBootKey está vazio.
Failed Indica que o dispositivo falhou na verificação. Nenhum certificado de atestado realmente contém esse valor, porque nesse estado o carregador de inicialização é interrompido. Ele está incluído aqui para completar.

Valores de nível de segurança

Os valores de securityLevel têm os seguintes significados:

Valor Significado
Software O código que cria ou gerencia o elemento relevante (atestado ou chave) é implementado no sistema Android e pode ser alterado se esse sistema for comprometido.
TrustedEnvironment O código que cria ou gerencia o elemento relevante (atestado ou chave) é implementado em um Trusted Execution Environment (TEE). Ele pode ser alterado se o TEE for comprometido, mas o TEE é altamente resistente ao comprometimento remoto e moderadamente resistente ao comprometimento por ataque direto ao hardware.
StrongBox O código que cria ou gerencia o elemento relevante (atestado ou chave) é implementado em um módulo de segurança de hardware dedicado. Ele pode ser alterado se o módulo de segurança de hardware for comprometido, mas é altamente resistente ao comprometimento remoto e altamente resistente ao comprometimento por ataque direto ao hardware.

ID único

O ID exclusivo é um valor de 128 bits que identifica o dispositivo, mas apenas por um período limitado de tempo. O valor é calculado com:

HMAC_SHA256(T || C || R, HBK)

Onde:

  • T é o "valor do contador temporal", calculado dividindo o valor de Tag::CREATION_DATETIME por 2592000000, descartando qualquer resto. T muda a cada 30 dias (2592000000 = 30 * 24 * 60 * 60 * 1000).
  • C é o valor da Tag::APPLICATION_ID
  • R é 1 se Tag::RESET_SINCE_ID_ROTATION estiver presente no parâmetro attest_params para a chamada attest_key, ou 0 se o tag não estiver presente.
  • HBK é um segredo exclusivo de hardware conhecido pelo Trusted Execution Environment e nunca revelado por ele. O segredo contém pelo menos 128 bits de entropia e é exclusivo para o dispositivo individual (a singularidade probabilística é aceitável, considerando os 128 bits de entropia). HBK deve ser derivado de material de chave fundida via HMAC ou AES_CMAC.

Trunque a saída HMAC_SHA256 para 128 bits.

Chaves de atestado e certificados

Duas chaves, uma RSA e uma ECDSA, e as cadeias de certificados correspondentes, são provisionadas com segurança no dispositivo.

atestado de identidade

O Android 8.0 inclui suporte opcional para atestado de ID para dispositivos com Keymaster 3. O atestado de ID permite que o dispositivo forneça prova de seus identificadores de hardware, como número de série ou IMEI. Embora seja um recurso opcional, é altamente recomendável que todas as implementações do Keymaster 3 forneçam suporte para ele, pois ser capaz de provar a identidade do dispositivo permite que casos de uso como configuração remota sem toque real sejam mais seguros (porque o lado remoto pode ter certeza de que está falando com o dispositivo certo, não com um dispositivo falsificando sua identidade).

O atestado de ID funciona criando cópias dos identificadores de hardware do dispositivo que somente o Trusted Execution Environment (TEE) pode acessar antes que o dispositivo saia da fábrica. Um usuário pode desbloquear o bootloader do dispositivo e alterar o software do sistema e os identificadores relatados pelas estruturas do Android. As cópias dos identificadores mantidos pelo TEE não podem ser manipuladas dessa maneira, garantindo que o atestado de ID do dispositivo só atestará os identificadores de hardware originais do dispositivo, frustrando assim as tentativas de falsificação.

A superfície da API principal para o atestado de ID se baseia no mecanismo de atestado de chave existente introduzido com o Keymaster 2. Ao solicitar um certificado de atestado para uma chave mantida pelo keymaster, o chamador pode solicitar que os identificadores de hardware do dispositivo sejam incluídos nos metadados do certificado de atestado. Se a chave for mantida no TEE, o certificado será encadeado de volta a uma raiz de confiança conhecida. O destinatário de tal certificado pode verificar se o certificado e seu conteúdo, incluindo os identificadores de hardware, foram escritos pelo TEE. Quando solicitado a incluir identificadores de hardware no certificado de atestado, o TEE atesta apenas os identificadores mantidos em seu armazenamento, conforme preenchidos no chão de fábrica.

Propriedades de armazenamento

O armazenamento que contém os identificadores do dispositivo precisa ter estas propriedades:

  • Os valores derivados dos identificadores originais do dispositivo são copiados para o armazenamento antes que o dispositivo saia da fábrica.
  • O método destroyAttestationIds() pode destruir permanentemente esta cópia dos dados derivados do identificador. Destruição permanente significa que os dados são completamente removidos para que nem uma redefinição de fábrica nem qualquer outro procedimento realizado no dispositivo possam restaurá-los. Isso é especialmente importante para dispositivos em que um usuário desbloqueou o carregador de inicialização e alterou o software do sistema e modificou os identificadores retornados pelas estruturas do Android.
  • As instalações de RMA devem ter a capacidade de gerar novas cópias dos dados derivados do identificador de hardware. Dessa forma, um dispositivo que passa pelo RMA pode realizar novamente a atestação de ID. O mecanismo usado pelos recursos de RMA deve ser protegido para que os usuários não possam invocá-lo, pois isso permitiria obter atestados de IDs falsificados.
  • Nenhum código que não seja o aplicativo confiável Keymaster no TEE é capaz de ler os dados derivados do identificador mantidos no armazenamento.
  • O armazenamento é inviolável: Se o conteúdo do armazenamento foi modificado, o TEE o trata como se as cópias do conteúdo tivessem sido destruídas e recusa todas as tentativas de atestado de identidade. Isso é implementado assinando ou MACing o armazenamento conforme descrito abaixo .
  • O armazenamento não contém os identificadores originais. Como o atestado de ID envolve um desafio, o chamador sempre fornece os identificadores a serem atestados. O TEE só precisa verificar se eles correspondem aos valores que tinham originalmente. Armazenar hashes seguros dos valores originais em vez dos valores permite essa verificação.

Construção

Para criar uma implementação que tenha as propriedades listadas acima, armazene os valores derivados de ID na seguinte construção S. Não armazene outras cópias dos valores de ID, exceto os locais normais do sistema, que um proprietário de dispositivo pode modificar fazendo root:

S = D || HMAC(HBK, D)

Onde:

  • D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
  • HMAC é a construção HMAC com um hash seguro apropriado (recomenda-se SHA-256)
  • HBK é uma chave vinculada a hardware não usada para nenhum outro propósito
  • ID 1 ...ID n são os valores de ID originais; a associação de um valor específico a um índice específico depende da implementação, pois dispositivos diferentes terão números diferentes de identificadores
  • || representa concatenação

Como as saídas HMAC são de tamanho fixo, nenhum cabeçalho ou outra estrutura é necessário para encontrar hashes de ID individuais ou o HMAC de D. Além de verificar os valores fornecidos para realizar o atestado, as implementações precisam validar S extraindo D de S , computando HMAC(HBK, D) e comparando-o com o valor em S para verificar se nenhum ID individual foi modificado/corrompido. Além disso, as implementações devem usar comparações de tempo constante para todos os elementos de ID individuais e a validação de S. O tempo de comparação deve ser constante, independentemente do número de IDs fornecidos e da correspondência correta de qualquer parte do teste.

Identificadores de hardware

O atestado de ID é compatível com os seguintes identificadores de hardware:

  1. Nome da marca, conforme retornado por Build.BRAND no Android
  2. Nome do dispositivo, conforme retornado por Build.DEVICE no Android
  3. Nome do produto, conforme retornado por Build.PRODUCT no Android
  4. Nome do fabricante, conforme retornado por Build.MANUFACTURER no Android
  5. Nome do modelo, conforme retornado por Build.MODEL no Android
  6. Número de série
  7. IMEIs de todos os rádios
  8. MEIDs de todos os rádios

Para oferecer suporte ao atestado de ID do dispositivo, um dispositivo atesta esses identificadores. Todos os dispositivos que executam o Android têm os seis primeiros e são necessários para que esse recurso funcione. Se o dispositivo tiver rádios celulares integrados, o dispositivo também deve suportar atestado para os IMEIs e/ou MEIDs dos rádios.

O atestado de ID é solicitado realizando um atestado de chave e incluindo os identificadores de dispositivo para atestar na solicitação. Os identificadores são marcados como:

  • ATTESTATION_ID_BRAND
  • ATTESTATION_ID_DEVICE
  • ATTESTATION_ID_PRODUCT
  • ATTESTATION_ID_MANUFACTURER
  • ATTESTATION_ID_MODEL
  • ATTESTATION_ID_SERIAL
  • ATTESTATION_ID_IMEI
  • ATTESTATION_ID_MEID

O identificador a ser atestado é uma string de bytes codificada em UTF-8. Esse formato também se aplica a identificadores numéricos. Cada identificador para atestar é expresso como uma string codificada em UTF-8.

Se o dispositivo não suportar atestado de ID (ou destroyAttestationIds() foi chamado anteriormente e o dispositivo não puder mais atestar seus IDs), qualquer solicitação de atestado de chave que inclua uma ou mais dessas tags falhará com ErrorCode::CANNOT_ATTEST_IDS .

Se o dispositivo suportar atestado de ID e uma ou mais das tags acima foram incluídas em uma solicitação de atestado de chave, o TEE verifica se o identificador fornecido com cada uma das tags corresponde à sua cópia dos identificadores de hardware. Se um ou mais identificadores não corresponderem, todo o atestado falhará com ErrorCode::CANNOT_ATTEST_IDS . É válido que a mesma tag seja fornecida várias vezes. Isso pode ser útil, por exemplo, ao atestar IMEIs: Um dispositivo pode ter vários rádios com vários IMEIs. Uma solicitação de atestado é válida se o valor fornecido com cada ATTESTATION_ID_IMEI corresponder a um dos rádios do dispositivo. O mesmo se aplica a todas as outras tags.

Se o atestado for bem-sucedido, os IDs atestados serão adicionados à extensão de atestado (OID 1.3.6.1.4.1.11129.2.1.17) do certificado de atestado emitido, usando o esquema acima . As alterações do esquema de atestado do Keymaster 2 estão em negrito , com comentários.

API Java

Esta seção é apenas informativa. Os implementadores do Keymaster não implementam nem usam a API Java. Isso é fornecido para ajudar os implementadores a entender como o recurso é usado pelos aplicativos. Os componentes do sistema podem usá-lo de maneira diferente, por isso é crucial que esta seção não seja tratada como normativa.