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 degenerateKey
para o qual o atestado será criado. -
attestParams
é uma lista de quaisquer parâmetros necessários para atestado. Isso incluiTag::ATTESTATION_CHALLENGE
e possivelmenteTag::RESET_SINCE_ID_ROTATION
, bem comoTag::APPLICATION_ID
eTag::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 dekeyToAttest
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 deTag::CREATION_DATETIME
por 2592000000, descartando qualquer resto.T
muda a cada 30 dias (2592000000 = 30 * 24 * 60 * 60 * 1000). -
C
é o valor daTag::APPLICATION_ID
-
R
é 1 seTag::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:
- Nome da marca, conforme retornado por
Build.BRAND
no Android - Nome do dispositivo, conforme retornado por
Build.DEVICE
no Android - Nome do produto, conforme retornado por
Build.PRODUCT
no Android - Nome do fabricante, conforme retornado por
Build.MANUFACTURER
no Android - Nome do modelo, conforme retornado por
Build.MODEL
no Android - Número de série
- IMEIs de todos os rádios
- 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.