O subsistema Gatekeeper realiza a autenticação de padrão/senha do dispositivo em um ambiente de execução confiável (TEE). O gatekeeper registra e verifica senhas usando uma chave secreta protegida por hardware. Além disso, o Gatekeeper limita as tentativas de verificação falhadas consecutivas e precisa recusar as solicitações de serviço com base em um tempo limite e um número de tentativas falhadas consecutivas.
Quando os usuários verificam as senhas, o Gatekeeper emite um token de autenticação assinado com uma chave HMAC por inicialização que está disponível apenas para componentes seguros. Esse token é enviado para o Keystore com suporte a hardware. Ou seja, um token de autenticação do Gatekeeper notifica o Keystore de que chaves vinculadas à autenticação (por exemplo, chaves criadas por apps) podem ser usadas por apps.
Arquitetura
O Gatekeeper envolve três componentes principais:
gatekeeperd
(daemon gatekeeper) — um serviço de vinculação C++ no Android que contém uma lógica independente de plataforma que implementa a interface AIDLIGateKeeperService
, com base em uma implementação específica do fornecedor deIGatekeeper
.- Serviço da camada de abstração de hardware (HAL) do gatekeeper: uma
implementação específica do fornecedor da
interface AIDL
IGatekeeper
. Esse serviço HAL é executado no Android, mas a funcionalidade principal do Gatekeeper precisa ser executada em um ambiente seguro. Por isso, ele normalmente se comunica com o TA do Gatekeeper. - Aplicativo de confiança do gatekeeper (TA): uma implementação específica do fornecedor que é executada no TEE e realiza a verificação real de senha ou padrão.
O LockSettingsService
faz uma solicitação (por meio do Binder) que
alcança o daemon gatekeeperd
no SO Android. O
daemon gatekeeperd
faz uma solicitação do
serviço HAL IGatekeeper
, que, por sua vez, alcança a
TA Gatekeeper correspondente no TEE:

Figura 1. Fluxo de dados de alto nível para autenticação pelo GateKeeper.
O daemon gatekeeperd
dá às APIs do framework Android acesso
ao HAL e participa do envio de relatórios de
autenticações do dispositivo para o keystore.
O daemon gatekeeperd
é executado no próprio processo e é separado do
servidor do sistema.
Implementação da HAL
O daemon gatekeeperd
usa o HAL IGatekeeper
para
interagir com o TA do Gatekeeper subjacente para autenticação de senha. A
implementação da TA do gatekeeper precisa ser capaz de assinar (inscrição) e verificar blobs. Todas
as implementações precisam aderir ao formato padrão do
token de autenticação (HardwareAuthToken
) gerado em cada verificação
de senha bem-sucedida. Para detalhes sobre o conteúdo e a semântica do HardwareAuthToken
, consulte a
definição de
HardwareAuthToken.aidl
.
As implementações do fornecedor do HAL IGatekeeper
precisam implementar
as funções enroll
e verify
:
- O método
enroll
recebe um blob de senha, o assina e retorna a assinatura como um identificador. O blob retornado (de uma chamada paraenroll
) precisa ter a estrutura mostrada emsystem/gatekeeper/include/gatekeeper/password_handle.h
. - A função
verify
precisa comparar a assinatura produzida pela senha fornecida e garantir que ela corresponda ao identificador de senha registrado.
A chave usada para registro e verificação nunca pode mudar e precisa ser rederivável em cada inicialização do dispositivo.
Trusty e outras implementações
O sistema operacional Trusty é o sistema operacional confiável de código aberto do Google para ambientes TEE e contém uma implementação aprovada do Gatekeeper. No entanto, qualquer SO TEE pode implementar o Gatekeeper, desde que o TEE tenha acesso a uma chave persistente com suporte de hardware e um relógio monótono e seguro que marque na suspensão.
O Trusty usa um sistema IPC interno para comunicar uma chave secreta compartilhada diretamente entre o KeyMint e a implementação do Trusty do Gatekeeper (o Trusty Gatekeeper). Esse segredo compartilhado é usado para assinar tokens de autenticação enviados ao Keystore para fornecer atestados de verificação de senha. O Trusty Gatekeeper solicita a chave do KeyMint para cada uso e não persiste nem armazena em cache o valor. As implementações podem compartilhar esse secret de qualquer maneira que não comprometa a segurança.
A chave HMAC usada para registrar e verificar senhas é derivada e mantida exclusivamente no Gatekeeper.
O Android oferece uma implementação genérica do Gatekeeper em C++, que exige
apenas a adição de rotinas específicas do dispositivo para ser concluída. A implementação
do Trusty é baseada nisso. Para implementar um gatekeeper do TEE com
código específico do dispositivo para o TEE, consulte as funções e os comentários
em system/gatekeeper/include/gatekeeper/gatekeeper.h
. As principais
responsabilidades de uma implementação em conformidade incluem:
- Adesão ao HAL
IGatekeeper
. - Os tokens de autenticação retornados precisam ser formatados de acordo com a especificação
HardwareAuthToken
(descrita emHardwareAuthToken.aidl
). - O gatekeeper do TEE precisa compartilhar uma chave HMAC com o KeyMint usando uma das seguintes opções:
- Acordo secreto compartilhado:o gatekeeper pode participar da
negociação por inicialização da chave HMAC implementando o
HAL
ISharedSecret
. Isso exige que o Gatekeeper e o KeyMint tenham acesso a um segredo compartilhado comum. - Acesso direto:o Gatekeeper pode recuperar a chave HMAC do KeyMint usando um mecanismo de comunicação interprocesso interno do TEE, sob demanda ou no primeiro uso (armazenado em cache depois).
- Acordo secreto compartilhado:o gatekeeper pode participar da
negociação por inicialização da chave HMAC implementando o
HAL
IDs seguros do usuário (SIDs)
Um SID do usuário é a representação do TEE de um usuário (sem conexão forte com um ID do usuário do Android). O SID é gerado com um gerador de números pseudoaleatórios criptográficos (PRNG, na sigla em inglês) sempre que um usuário registra uma nova senha sem fornecer uma anterior. Isso é conhecido como uma nova inscrição não confiável e normalmente acontece apenas quando um usuário define uma senha ou um padrão pela primeira vez.
Uma rematrícula confiável ocorre quando um usuário fornece uma senha anterior válida, como ao mudar a senha. Nesse caso, o SID do usuário é migrado para o novo identificador de senha, conservando as chaves vinculadas a ele.
O SID do usuário é incluído na autenticação HMAC com a senha no identificador de senha quando a senha é registrada.
Os SIDs do usuário são incluídos na HardwareAuthToken
retornada pela função
verify()
e associadas a todas as chaves do Keystore vinculadas à autenticação. Para detalhes
sobre o formato HardwareAuthToken
e o Keystore, consulte
Autenticação.
Como uma chamada não confiável para a função enroll()
muda o SID do usuário, a chamada torna as chaves vinculadas a essa senha
inúteis. Os invasores podem mudar a senha do dispositivo se controlarem o
SO Android, mas eles destroem chaves sensíveis protegidas por raiz no
processo.
Limitação de solicitações
O gatekeeper precisa ser capaz de limitar com segurança as tentativas de força bruta em uma credencial
de usuário. Como mostrado
em GatekeeperVerifyResponse.aidl
,
o HAL fornece um tempo limite em milissegundos. O tempo limite informa
ao cliente para não chamar o Gatekeeper novamente até que o tempo limite expire.
O Gatekeeper não deve atender às solicitações se houver um tempo limite pendente.
O gatekeeper precisa gravar um contador de falhas antes de verificar a senha de um usuário. Se
a verificação de senha for bem-sucedida, o contador de falhas será limpo. Isso
impede ataques que impedem o estrangulamento desativando o MMC (eMMC)
integrado após emitir uma chamada verify
. A função enroll
também
verifica a senha do usuário (se fornecida) e precisa ser limitada da mesma forma.
Se o dispositivo oferecer suporte, é altamente recomendável que o contador de falhas seja gravado no armazenamento seguro. Se o dispositivo não oferecer suporte à criptografia baseada em arquivos ou se o armazenamento seguro for muito lento, as implementações poderão usar o bloco de memória protegida contra repetição (RPMB, na sigla em inglês) diretamente.