MASTG-KNOW-0044: Key Attestation
Para aplicativos que dependem fortemente do Android Keystore para operações críticas de negócio, como autenticação multifator por meio de primitivas criptográficas, armazenamento seguro de dados sensíveis no lado do cliente, etc., o Android fornece o recurso de Atestado de Chave (Key Attestation), que ajuda a analisar a segurança do material criptográfico gerenciado por meio do Android Keystore. A partir do Android 8.0 (nível de API 26), o atestado de chave tornou-se obrigatório para todos os dispositivos novos (Android 7.0 ou superior) que precisam ter certificação de dispositivo para aplicativos do Google. Tais dispositivos usam chaves de atestado assinadas pelo certificado raiz de atestado de hardware do Google (Google Hardware Attestation Root certificate) e o mesmo pode ser verificado por meio do processo de atestado de chave.
Durante o atestado de chave, podemos especificar o alias de um par de chaves e, em troca, obter uma cadeia de certificados, que podemos usar para verificar as propriedades desse par de chaves. Se o certificado raiz da cadeia for o certificado raiz de atestado de hardware do Google (Google Hardware Attestation Root certificate), e as verificações relacionadas ao armazenamento do par de chaves em hardware forem feitas, isso dá a garantia de que o dispositivo suporta atestado de chave em nível de hardware e que a chave está no keystore com suporte de hardware que o Google considera seguro. Alternativamente, se a cadeia de atestado tiver qualquer outro certificado raiz, o Google não faz nenhuma afirmação sobre a segurança do hardware.
Embora o processo de atestado de chave possa ser implementado diretamente dentro do aplicativo, é recomendado que seja implementado no lado do servidor por razões de segurança. A seguir estão as diretrizes de alto nível para a implementação segura do Atestado de Chave:
- O servidor deve iniciar o processo de atestado de chave criando um número aleatório de forma segura usando CSPRNG (Gerador de Números Aleatórios Criptograficamente Seguro) e o mesmo deve ser enviado ao usuário como um desafio (challenge).
- O cliente deve chamar a API
setAttestationChallengecom o desafio recebido do servidor e, em seguida, recuperar a cadeia de certificados de atestado usando o métodoKeyStore.getCertificateChain. - A resposta de atestado deve ser enviada ao servidor para verificação e as seguintes verificações devem ser realizadas para a validação da resposta de atestado de chave:
- Verificar a cadeia de certificados, até a raiz, e realizar verificações de sanidade dos certificados, como validade, integridade e confiabilidade. Verificar a Lista de Status de Revogação de Certificado (Certificate Revocation Status List) mantida pelo Google, se nenhum dos certificados na cadeia foi revogado.
- Verificar se o certificado raiz está assinado com a chave raiz de atestado do Google, o que torna o processo de atestado confiável.
- Extrair os dados de extensão do certificado de atestado (certificate extension data), que aparecem dentro do primeiro elemento da cadeia de certificados, e realizar as seguintes verificações:
- Verificar se o desafio de atestado (attestation challenge) tem o mesmo valor que foi gerado no servidor ao iniciar o processo de atestado.
- Verificar a assinatura na resposta de atestado de chave.
- Verificar o nível de segurança do Keymaster, para determinar se o dispositivo possui um mecanismo de armazenamento seguro de chaves. Keymaster é um software que é executado no contexto de segurança e fornece todas as operações seguras do keystore. O nível de segurança será um entre
Software,TrustedEnvironmentouStrongBox. O cliente suporta atestado de chave em nível de hardware se o nível de segurança forTrustedEnvironmentouStrongBoxe a cadeia de certificados de atestado contiver um certificado raiz assinado com a chave raiz de atestado do Google. - Verificar o status do cliente para garantir uma cadeia de confiança completa - chave de inicialização verificada (verified boot key), bootloader bloqueado (locked bootloader) e estado de inicialização verificado (verified boot state).
- Adicionalmente, você pode verificar os atributos do par de chaves, como finalidade, tempo de acesso, requisito de autenticação, etc.
Nota: se por qualquer motivo esse processo falhar, significa que a chave não está em hardware de segurança. Isso não significa que a chave esteja comprometida.
O exemplo típico de resposta de atestado do Android Keystore é semelhante a este:
{
"fmt": "android-key",
"authData": "9569088f1ecee3232954035dbd10d7cae391305a2751b559bb8fd7cbb229bd...",
"attStmt": {
"alg": -7,
"sig": "304402202ca7a8cfb6299c4a073e7e022c57082a46c657e9e53...",
"x5c": [
"308202ca30820270a003020102020101300a06082a8648ce3d040302308188310b30090603550406130...",
"308202783082021ea00302010202021001300a06082a8648ce3d040302308198310b300906035504061...",
"3082028b30820232a003020102020900a2059ed10e435b57300a06082a8648ce3d040302308198310b3..."
]
}
}
No snippet JSON acima, as chaves têm o seguinte significado:
fmt: Identificador de formato de declaração de atestado (attestation statement format identifier)authData: Denota os dados do autenticador para o atestado (authenticator data for the attestation)alg: O algoritmo que é usado para a assinatura (Signature)sig: Assinatura (Signature)x5c: Cadeia de certificados de atestado (Attestation certificate chain)
Nota: O
sigé gerado concatenandoauthDataeclientDataHash(desafio enviado pelo servidor) e assinando por meio da chave privada da credencial usando o algoritmo de assinaturaalg. O mesmo é verificado no lado do servidor usando a chave pública no primeiro certificado.
Para maior compreensão sobre as diretrizes de implementação, você pode consultar o Código de Exemplo do Google (Google Sample Code).
Do ponto de vista da análise de segurança, os analistas podem realizar as seguintes verificações para a implementação segura do Atestado de Chave:
- Verificar se o atestado de chave está totalmente implementado no lado do cliente. Nesse caso, pode ser mais facilmente contornado por adulteração do aplicativo, hooking de métodos, etc.
- Verificar se o servidor usa um desafio aleatório ao iniciar o atestado de chave. A falha ao fazer isso levaria a uma implementação insegura, tornando-a vulnerável a ataques de replay. Além disso, devem ser realizadas verificações pertinentes à aleatoriedade do desafio.
- Verificar se o servidor verifica a integridade da resposta de atestado de chave.
- Verificar se o servidor realiza verificações básicas, como verificação de integridade, verificação de confiança, validade, etc., nos certificados da cadeia.