Keystore protegido por hardware

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:

Acesso ao KeyMint

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 e system.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.