O subsistema Gatekeeper executa a autenticação de padrão/senha do dispositivo em um Trusted Execution Environment (TEE). O Gatekeeper registra e verifica as senhas por meio de um HMAC com uma chave secreta suportada por hardware. Além disso, o Gatekeeper limita tentativas consecutivas de verificação com falha e deve se recusar a atender solicitações com base em um determinado tempo limite e um determinado número de tentativas consecutivas com falha.
Quando os usuários verificam suas senhas, o Gatekeeper usa o segredo compartilhado derivado de TEE para assinar um atestado de autenticação para enviar ao Keystore com suporte de hardware . Ou seja, um atestado de Gatekeeper notifica o Keystore que as chaves vinculadas à autenticação (por exemplo, as chaves que os aplicativos criaram) podem ser liberadas para uso pelos aplicativos.
Arquitetura
O Gatekeeper envolve três componentes principais:
-
gatekeeperd
(daemon de gatekeeper). Um serviço de binder C++ contendo lógica independente de plataforma e correspondente à interface JavaGateKeeperService
. - Camada de abstração de hardware do gatekeeper (HAL) . A interface HAL em
hardware/libhardware/include/hardware/gatekeeper.h
e o módulo de implementação. - Porteiro (TEE) . A contraparte TEE do
gatekeeperd
. Uma implementação do Gatekeeper baseada em TEE.
O Gatekeeper requer a implementação do Gatekeeper HAL (especificamente as funções em hardware/libhardware/include/hardware/gatekeeper.h
) e o componente 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 assinaturas de computação).
O LockSettingsService
faz uma solicitação (via Binder) que atinge o daemon do gatekeeperd
no sistema operacional Android. O daemon gatekeeperd
faz então uma solicitação que alcança sua contraparte (Gatekeeper) no TEE:
O daemon gatekeeperd
dá às APIs da estrutura do Android acesso à HAL e participa do relatório de autenticações de dispositivos para o Keystore. O daemon gatekeeperd
é executado em seu próprio processo e é separado do servidor do sistema.
Implementação de HAL
O daemon gatekeeperd
usa o HAL para interagir com a contraparte TEE do daemon gatekeeperd
para autenticação de senha. A implementação de HAL deve ser capaz de assinar (inscrever-se) e verificar blobs. Todas as implementações devem aderir ao formato padrão para o token de autenticação (AuthToken) gerado em cada verificação de senha bem-sucedida. Para obter 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
devem implementar as funções de enroll
e verify
:
- A função de
enroll
pega um blob de senha, o assina e retorna a assinatura como um identificador. O blob retornado (de uma chamada paraenroll
) deve ter a estrutura mostrada emsystem/gatekeeper/include/gatekeeper/password_handle.h
. - A função de
verify
deve comparar a assinatura produzida pela senha fornecida e garantir que ela corresponda ao identificador de senha registrado.
A chave usada para registrar e verificar nunca deve ser alterada e deve ser re-derivada a 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, você pode usar qualquer sistema operacional TEE para implementar o Gatekeeper, desde que o TEE tenha acesso a uma chave suportada por hardware e um relógio monotônico seguro que tiquetaque em suspender .
O Trusty usa um sistema IPC interno para comunicar um segredo compartilhado 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 ou armazena o valor em cache. As implementações são livres para compartilhar esse segredo 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 fornece uma implementação C++ genérica do GateKeeper que requer apenas a adição de rotinas específicas do dispositivo para ser concluída. Para implementar um TEE Gatekeeper com código específico do dispositivo para seu TEE, consulte as funções e comentários em system/gatekeeper/include/gatekeeper/gatekeeper.h
. Para o TEE GateKeeper, as principais responsabilidades de uma implementação compatível incluem:
- Adesão ao Gatekeeper HAL.
- Os AuthTokens retornados devem ser formatados de acordo com a especificação AuthToken (descrita em Autenticação ).
- O TEE Gatekeeper deve ser capaz de compartilhar uma chave HMAC com o Keymaster, solicitando a chave por meio de um TEE IPC sob demanda ou mantendo um cache válido do valor o tempo todo.
IDs seguras do usuário (SIDs)
Um SID de usuário é a representação TEE de um usuário (sem conexão forte com um ID de usuário do Android). O SID é gerado com um gerador de números pseudoaleatórios criptográficos (PRNG) sempre que um usuário cadastra uma nova senha sem fornecer uma anterior. Isso é conhecido como uma nova inscrição não confiável e não é permitido pela estrutura do Android em circunstâncias normais. Uma nova inscrição confiável ocorre quando um usuário fornece uma senha anterior válida; neste caso, o SID do Usuário é migrado para o novo handle de senha, conservando as chaves que estavam vinculadas a ele.
O SID do usuário é HMAC junto 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 de verify
e associados a todas as chaves do Keystore vinculadas à autenticação (para obter detalhes sobre o formato AuthToken e o Keystore, consulte Autenticação ). Como uma chamada não confiável para a função de enroll
alterará o SID do usuário, a chamada tornará inúteis as chaves vinculadas a essa senha. Os invasores podem alterar a senha do dispositivo se controlarem o sistema operacional Android, mas destruirão chaves confidenciais protegidas pela raiz no processo.
Solicitar limitação
O GateKeeper deve 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 fornece retorno de 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 solicitações se houver um tempo limite pendente.
O GateKeeper deve escrever um contador de falhas antes de verificar uma senha de usuário. Se a verificação de senha for bem-sucedida, o contador de falhas deverá ser apagado. Isso evita ataques que impedem a limitação desabilitando o MMC incorporado (eMMC) após emitir uma chamada de verify
. A enroll
de registro também verifica a senha do usuário (se fornecida) e deve ser limitada da mesma forma.
Se suportado pelo dispositivo, é altamente recomendável que o contador de falhas seja gravado no armazenamento seguro. Se o dispositivo não suportar criptografia baseada em arquivo ou se o armazenamento seguro for muito lento, as implementações poderão usar o Replay Protected Memory Block (RPMB) diretamente.