A disponibilidade de um ambiente de execução confiável em um sistema em um chip
(SoC, na sigla em inglês) oferece uma oportunidade para que os dispositivos Android forneçam serviços de segurança
robustos com suporte de hardware para o SO Android, para serviços de plataforma e até mesmo para
apps de terceiros (na forma de extensões específicas do Android para a
arquitetura de criptografia Java padrão. Consulte
KeyGenParameterSpec
).
Glossário
Confira uma visão geral rápida dos componentes do Keystore e as relações entre eles.
AndroidKeyStore
- A API e o componente do Android Framework usados
por apps para acessar a funcionalidade do Keystore. É uma implementação das
APIs padrão da Java Cryptography Architecture, mas também adiciona extensões específicas
do Android e consiste em código Java executado no próprio espaço
do processo do app. O
AndroidKeyStore
atende às solicitações do app para o comportamento do keystore encaminhando-as para o daemon do keystore. - daemon do keystore
- Um daemon do sistema Android que fornece acesso a todas as funcionalidades do Keystore por uma API Binder. Esse daemon é responsável por armazenar keyblobs criados pela implementação de KeyMint (ou Keymaster) subjacente, que contêm o material de chave secreta, criptografado para que o Keystore possa armazená-los, mas não usá-los ou revelá-los.
- Serviço HAL do KeyMint
- Um servidor AIDL que implementa
a HAL
IKeyMintDevice
, fornecendo acesso à TA KeyMint subjacente. - App confiável KeyMint (TA)
- Software executado em um contexto seguro, geralmente na TrustZone em um SoC ARM, que fornece todas as operações criptográficas seguras. Esse app tem acesso ao material bruto da chave e valida todas as condições de controle de acesso nas chaves antes de permitir o uso delas.
LockSettingsService
- O componente do sistema Android responsável pela autenticação do usuário, tanto por senha quanto
por impressão digital. Ele não faz parte do Keystore, mas é relevante porque o Keystore oferece suporte ao conceito
de chaves vinculadas à autenticação: chaves que só podem ser usadas se o usuário tiver feito a autenticação.
O
LockSettingsService
interage com a TA do Gatekeeper e a TA de impressão digital para receber tokens de autenticação, que são fornecidos ao daemon do keystore e consumidos pela TA do KeyMint. - Gatekeeper TA
- O componente executado no ambiente seguro que é responsável por autenticar as senhas do usuário e gerar tokens de autenticação usados para provar ao TA do KeyMint que uma autenticação foi feita para um usuário específico em um determinado momento.
- TA de impressão digital
- O componente executado no ambiente seguro que é responsável por autenticar as impressões digitais do usuário e gerar tokens de autenticação usados para provar ao TA do KeyMint que uma autenticação foi feita para um usuário específico em um determinado momento.
Arquitetura
A API Keystore do Android e o HAL do KeyMint fornecem um conjunto básico, mas adequado, de primitivas criptográficas para permitir a implementação de protocolos usando chaves controladas por hardware.
O HAL do KeyMint é um serviço fornecido pelo OEM usado pelo serviço de keystore para fornecer serviços criptográficos com suporte de hardware. Para manter o material da chave privada seguro, as implementações do HAL não executam operações sensíveis no espaço do usuário ou mesmo no espaço do kernel. Em vez disso, o serviço HAL Keymint em execução no Android delega operações sensíveis a um TA em execução em algum tipo de ambiente seguro, normalmente agrupando e desempacotando solicitações em algum formato de transmissão definido pela implementação.
A arquitetura resultante é esta:

Figura 1. Acesso ao KeyMint.
A API KeyMint HAL é de baixo nível, usada por componentes internos da plataforma e não exposta a desenvolvedores de apps. A API Java de nível superior disponível para apps é descrita no site para desenvolvedores Android.
Controle de acesso
O Android Keystore fornece um componente central para o armazenamento e o uso de chaves criptográficas com suporte de hardware, tanto para apps quanto para outros componentes do sistema. Por isso, o acesso a qualquer chave individual normalmente é limitado ao app ou componente do sistema que criou a chave.
Domínios do keystore
Para oferecer suporte a esse controle de acesso, as chaves são identificadas no Keystore com um descritor de chave. Esse descritor de chave indica um domínio ao qual o descritor pertence, junto com uma identidade nesse domínio.
Os apps Android acessam o Keystore usando a arquitetura padrão de criptografia
do Java, que identifica chaves com um alias de string. Esse método de
identificação é mapeado internamente para o domínio APP
do Keystore. O
UID do autor da chamada também é incluído para eliminar o conflito de chaves de apps
diferentes, impedindo que um app acesse as chaves de outro.
Internamente, o código do framework também recebe um ID de chave
numérica exclusivo depois que uma chave é carregada. Esse ID numérico é usado como identificador
para descritores de chaves no domínio KEY_ID
. No entanto, o controle
de acesso ainda é realizado: mesmo que um app descubra um ID de chave para a chave de outro
app, ele não poderá usá-la em circunstâncias normais.
No entanto, é possível que um app conceda o uso de uma chave a outro app
(identificado pelo UID). Essa operação de concessão retorna um identificador de concessão exclusivo,
que é usado como o identificador de descritores de chave no
domínio GRANT
. Novamente, o controle de acesso ainda é realizado: mesmo
se um terceiro app descobrir o ID de concessão para a chave de um beneficiário, ele não poderá usá-lo.
O keystore também oferece suporte a dois outros domínios para descritores de chave, que são usados para outros componentes do sistema e não estão disponíveis para chaves criadas por apps:
- O domínio
BLOB
indica que não há um identificador para a chave no descritor de chave. Em vez disso, o descritor de chave contém o keyblob e o cliente processa o armazenamento do keyblob. Ele é usado por clientes (por exemplo,vold
) que precisam acessar o Keystore antes que a partição de dados seja montada. - O domínio
SELINUX
permite que os componentes do sistema compartilhem chaves, com o acesso governado por um identificador numérico que corresponde a um rótulo do SELinux (consulte Política do SELinux para keystore_key).
Política do SELinux para keystore_key
Os valores de identificador usados para descritores de chave Domain::SELINUX
são configurados no arquivo de política SELinux keystore2_key_context
.
Cada linha nesses arquivos mapeia um número para um rótulo SELinux, por exemplo:
# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and # Settings to share keystore keys. 102 u:object_r:wifi_key:s0
Um componente que precisa acessar a chave com o ID 102 no
domínio SELINUX
precisa ter a política SELinux correspondente. Por
exemplo, para permitir que wpa_supplicant
receba e use essas chaves,
adicione a seguinte linha a hal_wifi_supplicant.te
:
allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };
Os identificadores numéricos das chaves Domain::SELINUX
são divididos
em intervalos para oferecer suporte a diferentes partições sem colisões:
Partição | Intervalo | Arquivos de configuração |
---|---|---|
Sistema | 0 a 9.999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
|
Sistema estendido | 10.000 ... 19.999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
|
Produto | 20.000 ... 29.999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
|
Fornecedor | 30.000 ... 39.999 | /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts
|
Os seguintes valores específicos foram definidos para a partição do sistema:
ID do namespace | Rótulo SEPolicy | UID | Descrição |
---|---|---|---|
0 | su_key |
N/A | Chave de superusuário. Usado apenas para testes em builds userdebug e eng. Não é relevante em builds de usuários. |
1 | shell_key |
N/A | Namespace disponível para o shell. Usado principalmente para testes, mas também pode ser usado em builds do usuário na linha de comando. |
100 | vold_key |
N/A | Destinado ao uso pelo vold. |
101 | odsign_key |
N/A | Usado pelo daemon de assinatura no dispositivo. |
102 | wifi_key |
AID_WIFI(1010) |
Usado pelo subsistema de Wi-Fi do Android, incluindo wpa_supplicant . |
103 | locksettings_key |
N/A | Usado por LockSettingsService |
120 | resume_on_reboot_key |
AID_SYSTEM(1000) |
Usado pelo servidor do sistema do Android para oferecer suporte à retomada na reinicialização. |
Vetores de acesso
O keystore permite controlar quais operações podem ser realizadas em uma chave, além de controlar o acesso geral a uma chave. As permissões keystore2_key
são descritas no
arquivo KeyPermission.aidl
.
Permissões do sistema
Além dos controles de acesso por chave descritos na política do SELinux para keystore_key, a tabela a seguir descreve outras permissões do SELinux que são necessárias para realizar várias operações de sistema e manutenção:
Permissão | Significado |
---|---|
add_auth
|
Obrigatório para adicionar tokens de autenticação ao Keystore. É usado por provedores de autenticação, como o Gatekeeper
ou BiometricManager . |
clear_ns
|
Obrigatório para excluir todas as chaves em um namespace específico. É usado como uma operação de manutenção quando os apps são desinstalados. |
list
|
Necessário para que o sistema enumere chaves por várias propriedades, como
propriedade ou se elas estão vinculadas à autenticação. Essa permissão não é necessária para autores de chamadas
que enumeram os próprios namespaces (abrangidos pela
permissão get_info ). |
lock
|
É necessário para notificar o keystore de que o dispositivo foi bloqueado, o que, por sua vez, remove as superchaves para garantir que as chaves vinculadas à autenticação não estejam disponíveis. |
unlock
|
Necessário para notificar o keystore de que o dispositivo foi desbloqueado, restaurando o acesso às superchaves que protegem as chaves vinculadas à autenticação. |
reset
|
Necessário para redefinir o Keystore para a configuração original, excluindo todas as chaves que não são vitais para o funcionamento do SO Android. |
Histórico
No Android 5 e versões anteriores, o Android tinha uma API de serviços criptográficos simples e com suporte a hardware, fornecida pelas versões 0.2 e 0.3 da camada de abstração de hardware (HAL) do Keymaster. O keystore fornece operações de assinatura e verificação digitais, além de geração e importação de pares de chaves de assinatura assimétricas. Isso já está implementado em muitos dispositivos, mas há muitos objetivos de segurança que não podem ser alcançados facilmente com apenas uma API de assinatura. O Android 6.0 estendeu a API Keystore para oferecer uma gama mais ampla de recursos.
Android 6.0
No Android 6.0, o Keymaster 1.0 adicionou primitivas criptográficas simétricas, AES e HMAC, além de um sistema de controle de acesso para chaves com suporte de hardware. Os controles de acesso são especificados durante a geração de chaves e aplicados durante o ciclo de vida da chave. As chaves podem ser restringidas para uso somente após a autenticação do usuário e apenas para fins específicos ou com parâmetros criptográficos específicos.
Além de expandir o intervalo de primitivas criptográficas, o Keystore no Android 6.0 adicionou o seguinte:
- Um esquema de controle de uso para permitir que o uso de chaves seja limitado, reduzindo o risco de comprometimento da segurança devido ao uso indevido de chaves
- Um esquema de controle de acesso para permitir a restrição de chaves a usuários e clientes especificados e um período definido
Android 7.0
No Android 7.0, o Keymaster 2 adicionou suporte para atestado de chaves e vinculação de versão.
O atestado de chave fornece certificados de chave pública que contêm uma descrição detalhada da chave e dos controles de acesso para verificar remotamente a existência da chave em hardware seguro e a configuração.
A vinculação de versão vincula as chaves ao sistema operacional e à versão do nível do patch. Isso garante que um invasor que descubra uma vulnerabilidade em uma versão antiga do sistema ou do software TEE não possa reverter um dispositivo para a versão vulnerável e usar chaves criadas com a versão mais recente. Além disso, quando uma chave com uma determinada versão e nível de patch é usada em um dispositivo que foi atualizado para uma versão ou nível de patch mais recente, a chave é atualizada antes de ser usada, e a versão anterior da chave é invalidada. À medida que o dispositivo é atualizado, as chaves avançam com ele, mas qualquer reversão do dispositivo para uma versão anterior faz com que as chaves fiquem inutilizáveis.
Android 8.0
No Android 8.0, o Keymaster 3 fez a transição do HAL de estrutura C antigo para a interface HAL C++ gerada a partir de uma definição na nova linguagem de definição de interface de hardware (HIDL). Como parte da mudança, muitos dos tipos de argumentos foram alterados, embora os tipos e métodos tenham uma correspondência um a um com os tipos antigos e os métodos de estrutura HAL.
Além dessa revisão da interface, o Android 8.0 estendeu o recurso de atestado do Keymaster 2 para oferecer suporte ao atestado de ID. O atestado de identidade oferece um mecanismo limitado e opcional para atestados fortes de identificadores de hardware, como número de série do dispositivo, nome do produto e ID do smartphone (IMEI ou MEID). Para implementar essa adição, o Android 8.0 mudou o esquema de atestado ASN.1 para adicionar atestado de identidade. As implementações do Keymaster precisam encontrar uma maneira segura de extrair os itens de dados relevantes e definir um mecanismo para desativar o recurso de forma segura e permanente.
Android 9
No Android 9, as atualizações incluíam:
- Atualize para Keymaster 4.
- Suporte para elementos Secure incorporados
- Suporte para importação de chave segura
- Suporte para criptografia 3DES
- Mudanças na vinculação de versões para que
boot.img
esystem.img
tenham versões definidas separadamente para permitir atualizações independentes
Android 10
O Android 10 introduziu a versão 4.1 da HAL do Keymaster, que adicionou:
- Suporte a chaves que só podem ser usadas quando o dispositivo está desbloqueado
- Suporte a chaves que só podem ser usadas nos estágios iniciais de inicialização
- Suporte opcional para chaves de armazenamento envoltas em hardware
- Suporte opcional para atestado exclusivo do dispositivo no StrongBox
Android 12
O Android 12 introduziu a nova HAL KeyMint, que substitui a HAL Keymaster mas oferece uma funcionalidade semelhante. Além de todos os recursos acima, o HAL do KeyMint também inclui:
- Suporte para o contrato de chaves ECDH
- Suporte para chaves de atestado especificadas pelo usuário
- Suporte a chaves com um número limitado de usos
O Android 12 também inclui uma nova versão do daemon do sistema do keystore,
reescrito em Rust e conhecido como keystore2
.
Android 13
O Android 13 adicionou a v2 da HAL KeyMint, que adiciona suporte a Curve25519 para assinatura e acordo de chaves.