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 por meio de um HMAC com uma chave secreta protegida por hardware. Além disso, o Gatekeeper limita as tentativas de verificação com falhas consecutivas e precisa recusar as solicitações com base em um determinado tempo limite e um determinado número de tentativas consecutivas.
Quando os usuários verificam as senhas, o Gatekeeper usa o segredo compartilhado derivados do TEE para assinar um atestado de autenticação a ser enviado ao keystore com suporte de hardware. Ou seja, um atestado do gatekeeper notifica o keystore de que as chaves vinculadas à autenticação (por exemplo, chaves criadas por apps) podem ser liberadas para uso por apps.
Arquitetura
O Gatekeeper envolve três componentes principais:
gatekeeperd
(daemon do Gatekeeper). Um serviço de vinculação C++ contendo lógica independente da plataforma e correspondente à interface JavaGateKeeperService
.- Camada de abstração de hardware (HAL) do gatekeeper. A interface
HAL em
hardware/libhardware/include/hardware/gatekeeper.h
e o módulo de implementação. - Gatekeeper (TEE). A contraparte do TEE de
gatekeeperd
. Uma implementação do Gatekeeper baseada em TEE.
O Gatekeeper exige a implementação do
HAL do Gatekeeper (especificamente as funções em
hardware/libhardware/include/hardware/gatekeeper.h
) e o
componente do Gatekeeper específico do TEE (baseado em parte no
arquivo de cabeçalho system/gatekeeper/include/gatekeeper/gatekeeper.h
que
inclui funções virtuais puras para criar/acessar chaves e computar
assinaturas).
O LockSettingsService
faz uma solicitação (via Binder) que
alcança o daemon gatekeeperd
no SO Android. O
daemon gatekeeperd
faz uma solicitação que chega à
contraparte (Gatekeeper) no TEE:

O daemon gatekeeperd
dá às APIs do framework do 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 para interagir
com a contraparte TEE do daemon gatekeeperd
para
autenticação de senha. A implementação da HAL 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 (AuthToken) gerado em cada verificação
de senha bem-sucedida. Para detalhes sobre o conteúdo e a semântica do AuthToken,
consulte Formato
AuthToken.
As implementações do
arquivo de cabeçalho hardware/libhardware/include/hardware/gatekeeper.h
precisam implementar as funções enroll
e verify
:
- A função
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 gerada 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, é possível usar qualquer SO TEE para implementar o Gatekeeper, desde que o TEE tenha acesso a uma chave com suporte de hardware e um relógio monótono e seguro que marque em suspensão.
O Trusty usa um sistema IPC interno para comunicar uma chave secreta compartilhada diretamente entre o Keymaster e a implementação do Trusty do Gatekeeper (o Trusty Gatekeeper). Esse segredo compartilhado é usado para assinar AuthTokens enviados ao Keystore para fornecer atestados de verificação de senha. O Trusty Gatekeeper solicita a chave do Keymaster 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 em C++ do GateKeeper que exige
apenas a adição de rotinas específicas do dispositivo para ser concluída. Para implementar um
controlador de acesso 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
.
Para o TEE GateKeeper, as principais responsabilidades de uma implementação
em conformidade incluem:
- Adesão à HAL do gatekeeper.
- Os AuthTokens retornados precisam ser formatados de acordo com a especificação do AuthToken (descrita em Autenticação).
- O gatekeeper do TEE precisa compartilhar uma chave HMAC com o Keymaster, solicitando a chave por um IPC do TEE sob demanda ou mantendo um cache válido do valor o tempo todo.
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) 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 não é permitida pelo framework do Android em circunstâncias normais. Uma nova inscrição confiável ocorre quando um usuário fornece uma senha anterior válida. Nesse caso, o SID do usuário é migrado para o novo identificador de senha, mantendo as chaves vinculadas a ele.
O SID do usuário é HMAC com a senha no identificador de senha quando a senha é registrada.
Os SIDs do usuário são gravados no AuthToken retornado pela função
verify
e associados a todas as chaves do Keystore vinculadas à autenticação. Para saber mais
sobre o formato AuthToken e o Keystore, consulte
Autenticação. Como uma
chamada não confiável para a função enroll
vai mudar o SID do usuário, a
chamada vai tornar as chaves vinculadas a essa senha inúteis. Os invasores podem mudar
a senha do dispositivo se controlarem o SO Android, mas eles
destruirão 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. Conforme mostrado em
hardware/libhardware/include/hardware/gatekeeper.h
, o HAL
permite retornar um tempo limite em milissegundos. O tempo limite informa ao cliente
para não chamar o GateKeeper novamente até que o tempo limite tenha decorrido. 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.