Criptografia baseada em arquivo

O Android 7.0 e superior oferece suporte à criptografia baseada em arquivo (FBE). A criptografia baseada em arquivo permite que arquivos diferentes sejam criptografados com chaves diferentes que podem ser desbloqueadas independentemente.

Este artigo descreve como habilitar a criptografia baseada em arquivo em novos dispositivos e como os aplicativos do sistema podem usar as APIs de inicialização direta para oferecer aos usuários a melhor e mais segura experiência possível.

Inicialização direta

A criptografia baseada em arquivo permite um novo recurso introduzido no Android 7.0 chamado Direct Boot . A inicialização direta permite que os dispositivos criptografados sejam inicializados diretamente na tela de bloqueio. Anteriormente, em dispositivos criptografados usando criptografia de disco completo (FDE), os usuários precisavam fornecer credenciais antes que qualquer dado pudesse ser acessado, impedindo que o telefone executasse todas as operações, exceto as mais básicas. Por exemplo, os alarmes não podiam funcionar, os serviços de acessibilidade não estavam disponíveis e os telefones não podiam receber chamadas, limitando-se apenas a operações básicas de discagem de emergência.

Com a introdução da criptografia baseada em arquivo (FBE) e novas APIs para tornar os aplicativos cientes da criptografia, é possível que esses aplicativos operem dentro de um contexto limitado. Isso pode acontecer antes que os usuários forneçam suas credenciais enquanto ainda protegem as informações privadas do usuário.

Em um dispositivo habilitado para FBE, cada usuário do dispositivo tem dois locais de armazenamento disponíveis para aplicativos:

  • Armazenamento criptografado por credencial (CE), que é o local de armazenamento padrão e disponível somente após o usuário desbloquear o dispositivo.
  • Armazenamento criptografado por dispositivo (DE), que é um local de armazenamento disponível durante o modo de inicialização direta e após o usuário ter desbloqueado o dispositivo.

Essa separação torna os perfis de trabalho mais seguros porque permite que mais de um usuário seja protegido por vez, pois a criptografia não é mais baseada apenas em uma senha de inicialização.

A API de inicialização direta permite que aplicativos com reconhecimento de criptografia acessem cada uma dessas áreas. Há mudanças no ciclo de vida do aplicativo para acomodar a necessidade de notificar os aplicativos quando o armazenamento CE de um usuário é desbloqueado em resposta à primeira inserção de credenciais na tela de bloqueio ou no caso de um perfil de trabalho fornecer um desafio de trabalho . Os dispositivos que executam o Android 7.0 devem ser compatíveis com essas novas APIs e ciclos de vida, independentemente de implementarem ou não o FBE. Embora, sem FBE, o armazenamento DE e CE estará sempre no estado desbloqueado.

Uma implementação completa de criptografia baseada em arquivo nos sistemas de arquivos Ext4 e F2FS é fornecida no Android Open Source Project (AOSP) e só precisa ser habilitada em dispositivos que atendam aos requisitos. Os fabricantes que optam por usar o FBE podem explorar maneiras de otimizar o recurso com base no sistema no chip (SoC) usado.

Todos os pacotes necessários no AOSP foram atualizados para reconhecimento de inicialização direta. No entanto, quando os fabricantes de dispositivos usarem versões personalizadas desses aplicativos, eles desejarão garantir, no mínimo, que haja pacotes com reconhecimento de inicialização direta que forneçam os seguintes serviços:

  • Serviços de telefonia e discador
  • Método de entrada para inserir senhas na tela de bloqueio

Exemplos e fonte

O Android fornece uma implementação de referência de criptografia baseada em arquivo, na qual vold ( system/vold ) fornece a funcionalidade para gerenciar dispositivos e volumes de armazenamento no Android. A adição do FBE fornece ao vold vários novos comandos para suportar o gerenciamento de chaves para as chaves CE e DE de vários usuários. Além das principais alterações para usar os recursos de criptografia baseados em arquivo no kernel, muitos pacotes do sistema, incluindo a tela de bloqueio e o SystemUI, foram modificados para oferecer suporte aos recursos FBE e Direct Boot. Esses incluem:

  • Discador AOSP (pacotes/aplicativos/Discador)
  • Relógio de mesa (pacotes/aplicativos/DeskClock)
  • LatinIME (pacotes/métodos de entrada/LatinIME)*
  • Aplicativo de Configurações (pacotes/aplicativos/Configurações)*
  • SystemUI (frameworks/base/packages/SystemUI)*

* Aplicativos do sistema que usam o atributo de manifesto defaultToDeviceProtectedStorage

Mais exemplos de aplicativos e serviços que reconhecem criptografia podem ser encontrados executando o comando mangrep directBootAware no diretório de estruturas ou pacotes da árvore de origem do AOSP.

Dependências

Para usar a implementação AOSP do FBE com segurança, um dispositivo precisa atender às seguintes dependências:

  • Suporte de kernel para criptografia Ext4 ou criptografia F2FS.
  • Suporte Keymaster com HAL versão 1.0 ou 2.0. Não há suporte para o Keymaster 0.3, pois ele não fornece os recursos necessários nem garante proteção suficiente para chaves de criptografia.
  • Keymaster/ Keystore e Gatekeeper devem ser implementados em um Trusted Execution Environment (TEE) para fornecer proteção para as chaves DE para que um sistema operacional não autorizado (SO personalizado instalado no dispositivo) não possa simplesmente solicitar as chaves DE.
  • A Raiz de Confiança do Hardware e a Inicialização Verificada vinculada à inicialização do keymaster são necessárias para garantir que as credenciais do Device Encryption não sejam acessíveis por um sistema operacional não autorizado.

Observação : as políticas de armazenamento são aplicadas a uma pasta e a todas as suas subpastas. Os fabricantes devem limitar o conteúdo não criptografado à pasta OTA e à pasta que contém a chave que descriptografa o sistema. A maioria dos conteúdos deve residir em armazenamento criptografado por credencial em vez de armazenamento criptografado por dispositivo.

Implementação

Em primeiro lugar, aplicativos como despertadores, telefone, recursos de acessibilidade devem ser feitos android:directBootAware de acordo com a documentação do desenvolvedor do Direct Boot .

Suporte do kernel

O suporte de kernel para criptografia Ext4 e F2FS está disponível nos kernels comuns do Android, versão 3.18 e superior. Para habilitá-lo em um kernel da versão 5.1 ou superior, use:

CONFIG_FS_ENCRYPTION=y

Para kernels mais antigos, use CONFIG_EXT4_ENCRYPTION=y se o sistema de arquivos userdata do seu dispositivo for Ext4, ou use CONFIG_F2FS_FS_ENCRYPTION=y se o sistema de arquivos userdata do seu dispositivo for F2FS.

Se o seu dispositivo for compatível com armazenamento adotável ou usar criptografia de metadados no armazenamento interno, ative também as opções de configuração do kernel necessárias para criptografia de metadados conforme descrito na documentação de criptografia de metadados .

Além do suporte funcional para criptografia Ext4 ou F2FS, os fabricantes de dispositivos também devem habilitar a aceleração criptográfica para acelerar a criptografia baseada em arquivo e melhorar a experiência do usuário. Por exemplo, em dispositivos baseados em ARM64, a aceleração ARMv8 CE (Cryptography Extensions) pode ser habilitada definindo as seguintes opções de configuração do kernel:

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

Para melhorar ainda mais o desempenho e reduzir o uso de energia, os fabricantes de dispositivos também podem considerar a implementação de hardware de criptografia em linha , que criptografa/descriptografa os dados enquanto estão no caminho de/para o dispositivo de armazenamento. Os kernels comuns do Android (versão 4.14 e superior) contêm uma estrutura que permite que a criptografia em linha seja usada quando o suporte de hardware e driver do fornecedor estiver disponível. A estrutura de criptografia em linha pode ser habilitada definindo as seguintes opções de configuração do kernel:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

Se o seu dispositivo usa armazenamento baseado em UFS, ative também:

CONFIG_SCSI_UFS_CRYPTO=y

Se o seu dispositivo usa armazenamento baseado em eMMC, ative também:

CONFIG_MMC_CRYPTO=y

Ativando a criptografia baseada em arquivo

Habilitar o FBE em um dispositivo requer habilitá-lo no armazenamento interno ( userdata ). Isso também habilita automaticamente o FBE no armazenamento adotável; no entanto, o formato de criptografia no armazenamento adotável pode ser substituído, se necessário.

Armazenamento interno

O FBE é habilitado adicionando a opção fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] à coluna fs_mgr_flags da linha fstab para userdata . Esta opção define o formato de criptografia no armazenamento interno. Ele contém até três parâmetros separados por dois pontos:

  • O parâmetro contents_encryption_mode define qual algoritmo criptográfico é usado para criptografar o conteúdo do arquivo. Pode ser aes-256-xts ou adiantum . Desde o Android 11, ele também pode ser deixado em branco para especificar o algoritmo padrão, que é aes-256-xts .
  • O parâmetro filenames_encryption_mode define qual algoritmo criptográfico é usado para criptografar nomes de arquivos. Pode ser aes-256-cts , aes-256-heh ou adiantum . Se não for especificado, o padrão será aes-256-cts se contents_encryption_mode for aes-256-xts , ou adiantum se contents_encryption_mode for adiantum .
  • O parâmetro flags , novo no Android 11, é uma lista de sinalizadores separados pelo caractere + . Os seguintes sinalizadores são suportados:
    • O sinalizador v1 seleciona as políticas de criptografia da versão 1; o sinalizador v2 seleciona as políticas de criptografia da versão 2. As políticas de criptografia da versão 2 usam uma função de derivação de chave mais segura e flexível. O padrão é v2 se o dispositivo foi iniciado no Android 11 ou superior (conforme determinado por ro.product.first_api_level ), ou v1 se o dispositivo foi iniciado no Android 10 ou inferior.
    • O sinalizador inlinecrypt_optimized seleciona um formato de criptografia otimizado para hardware de criptografia em linha que não lida com um grande número de chaves com eficiência. Ele faz isso derivando apenas uma chave de criptografia de conteúdo de arquivo por chave CE ou DE, em vez de uma por arquivo. A geração de IVs (vetores de inicialização) é ajustada de acordo.
    • O sinalizador emmc_optimized é semelhante ao inlinecrypt_optimized , mas também seleciona um método de geração de IV que limita os IVs a 32 bits. Esse sinalizador deve ser usado apenas em hardware de criptografia em linha compatível com a especificação JEDEC eMMC v5.2 e, portanto, suporta apenas IVs de 32 bits. Em outro hardware de criptografia em linha, use inlinecrypt_optimized em vez disso. Esse sinalizador nunca deve ser usado em armazenamento baseado em UFS; a especificação UFS permite o uso de IVs de 64 bits.
    • Em dispositivos que suportam chaves encapsuladas em hardware , o sinalizador wrappedkey_v0 permite o uso de chaves encapsuladas em hardware para FBE. Isso só pode ser usado em combinação com a opção de montagem inlinecrypt e o inlinecrypt_optimized ou emmc_optimized .

Se você não estiver usando hardware de criptografia em linha, a configuração recomendada para a maioria dos dispositivos é fileencryption=aes-256-xts . Se você estiver usando hardware de criptografia em linha, a configuração recomendada para a maioria dos dispositivos é fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (ou equivalentemente fileencryption=::inlinecrypt_optimized ). Em dispositivos sem qualquer forma de aceleração AES, Adiantum pode ser usado em vez de AES definindo fileencryption=adiantum .

Em dispositivos iniciados com Android 10 ou inferior, fileencryption=ice também é aceito para especificar o uso do modo de criptografia de conteúdo de arquivo FSCRYPT_MODE_PRIVATE . Esse modo não é implementado pelos kernels comuns do Android, mas pode ser implementado por fornecedores usando patches de kernel personalizados. O formato em disco produzido por este modo era específico do fornecedor. Em dispositivos iniciados com Android 11 ou superior, esse modo não é mais permitido e um formato de criptografia padrão deve ser usado.

Por padrão, a criptografia do conteúdo do arquivo é feita usando a API de criptografia do kernel do Linux. Se você quiser usar hardware de criptografia inline, adicione também a opção de montagem inlinecrypt . Por exemplo, uma linha fstab completa pode se parecer com:

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

Armazenamento adotável

Desde o Android 9, o FBE e o armazenamento adotável podem ser usados ​​juntos.

Especificar a opção fileencryption fstab para userdata também habilita automaticamente o FBE e a criptografia de metadados no armazenamento adotável. No entanto, você pode substituir os formatos de criptografia FBE e/ou metadados no armazenamento adotável, definindo propriedades em PRODUCT_PROPERTY_OVERRIDES .

Em dispositivos lançados com Android 11 ou superior, use as seguintes propriedades:

  • ro.crypto.volume.options (novo no Android 11) seleciona o formato de criptografia FBE no armazenamento adotável. Ele tem a mesma sintaxe que o argumento para a opção fstab fileencryption e usa os mesmos padrões. Consulte as recomendações para fileencryption de arquivos acima para saber o que usar aqui.
  • ro.crypto.volume.metadata.encryption seleciona o formato de criptografia de metadados no armazenamento adotável. Consulte a documentação de criptografia de metadados .

Em dispositivos lançados com Android 10 ou inferior, use as seguintes propriedades:

  • ro.crypto.volume.contents_mode seleciona o modo de criptografia de conteúdo. Isso é equivalente ao primeiro campo separado por dois pontos de ro.crypto.volume.options .
  • ro.crypto.volume.filenames_mode seleciona o modo de criptografia de nomes de arquivos. Isso é equivalente ao segundo campo separado por dois pontos de ro.crypto.volume.options , exceto que o padrão em dispositivos iniciados com Android 10 ou inferior é aes-256-heh . Na maioria dos dispositivos, isso precisa ser substituído explicitamente por aes-256-cts .
  • ro.crypto.fde_algorithm e ro.crypto.fde_sector_size selecionam o formato de criptografia de metadados no armazenamento adotável. Consulte a documentação de criptografia de metadados .

Integração com Keymaster

A geração de chaves e o gerenciamento do chaveiro do kernel são feitos pelo vold . A implementação AOSP do FBE requer que o dispositivo suporte o Keymaster HAL versão 1.0 ou posterior. Não há suporte para versões anteriores do Keymaster HAL.

Na primeira inicialização, as chaves do usuário 0 são geradas e instaladas no início do processo de inicialização. Quando a fase on-post-fs do init for concluída, o Keymaster deverá estar pronto para lidar com as solicitações. Em dispositivos Pixel, isso é tratado com um bloco de script para garantir que o Keymaster seja iniciado antes /data seja montado.

Política de criptografia

A criptografia baseada em arquivo aplica a política de criptografia no nível do diretório. Quando a partição userdata de um dispositivo é criada pela primeira vez, as estruturas e políticas básicas são aplicadas pelos scripts de init . Esses scripts acionarão a criação das chaves CE e DE do primeiro usuário (usuário 0's), bem como definirão quais diretórios devem ser criptografados com essas chaves. Quando usuários e perfis adicionais são criados, as chaves adicionais necessárias são geradas e armazenadas no keystore; seus locais de armazenamento de credenciais e dispositivos são criados e a política de criptografia vincula essas chaves a esses diretórios.

No Android 11 e superior, a política de criptografia não é mais codificada em um local centralizado, mas é definida por argumentos para os comandos mkdir nos scripts de inicialização. Os diretórios criptografados com a chave DE do sistema usam encryption=Require , enquanto os diretórios não criptografados (ou diretórios cujos subdiretórios são criptografados com chaves por usuário) usam encryption=None .

No Android 10, a política de criptografia foi codificada neste local:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

No Android 9 e anteriores, o local era:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

É possível adicionar exceções para evitar que certos diretórios sejam criptografados. Se forem feitas modificações desse tipo, o fabricante do dispositivo deve incluir políticas SELinux que concedam acesso apenas aos aplicativos que precisam usar o diretório não criptografado. Isso deve excluir todos os aplicativos não confiáveis.

O único caso de uso aceitável conhecido para isso é o suporte a recursos OTA legados.

Suporte a inicialização direta em aplicativos do sistema

Tornando os aplicativos com reconhecimento de inicialização direta

Para facilitar a migração rápida de aplicativos do sistema, há dois novos atributos que podem ser definidos no nível do aplicativo. O atributo defaultToDeviceProtectedStorage está disponível apenas para aplicativos do sistema. O atributo directBootAware está disponível para todos.

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

O atributo directBootAware no nível do aplicativo é uma abreviação para marcar todos os componentes no aplicativo como tendo reconhecimento de criptografia.

O atributo defaultToDeviceProtectedStorage redireciona o local de armazenamento do aplicativo padrão para apontar para o armazenamento DE em vez de apontar para o armazenamento CE. Os aplicativos do sistema que usam esse sinalizador devem auditar cuidadosamente todos os dados armazenados no local padrão e alterar os caminhos dos dados confidenciais para usar o armazenamento CE. Os fabricantes de dispositivos que usam essa opção devem inspecionar cuidadosamente os dados que estão armazenando para garantir que não contenham informações pessoais.

Ao executar neste modo, as seguintes APIs do sistema estão disponíveis para gerenciar explicitamente um Contexto apoiado pelo armazenamento CE quando necessário, que são equivalentes às suas contrapartes Protegidas por Dispositivo.

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

Suporte a vários usuários

Cada usuário em um ambiente multiusuário obtém uma chave de criptografia separada. Cada usuário recebe duas chaves: uma chave DE e uma chave CE. O usuário 0 deve fazer login no dispositivo primeiro, pois é um usuário especial. Isso é pertinente para usos de Administração de Dispositivos .

Os aplicativos com reconhecimento de criptografia interagem entre os usuários desta maneira: INTERACT_ACROSS_USERS e INTERACT_ACROSS_USERS_FULL permitem que um aplicativo atue em todos os usuários do dispositivo. No entanto, esses aplicativos poderão acessar apenas diretórios criptografados por CE para usuários que já estão desbloqueados.

Um aplicativo pode interagir livremente nas áreas DE, mas um usuário desbloqueado não significa que todos os usuários do dispositivo estejam desbloqueados. O aplicativo deve verificar esse status antes de tentar acessar essas áreas.

Cada ID de usuário de perfil de trabalho também recebe duas chaves: DE e CE. Quando o desafio de trabalho é cumprido, o usuário do perfil é desbloqueado e o Keymaster (em TEE) pode fornecer a chave TEE do perfil.

Como lidar com atualizações

A partição de recuperação não consegue acessar o armazenamento protegido por DE na partição userdata. Os dispositivos que implementam o FBE são altamente recomendados para oferecer suporte ao OTA usando atualizações do sistema A/B . Como o OTA pode ser aplicado durante a operação normal, não há necessidade de recuperação para acessar os dados na unidade criptografada.

Ao usar uma solução OTA herdada, que requer recuperação para acessar o arquivo OTA na partição userdata :

  1. Crie um diretório de nível superior (por exemplo misc_ne ) na partição userdata .
  2. Adicione este diretório de nível superior à exceção da política de criptografia (consulte Política de criptografia acima).
  3. Crie um diretório dentro do diretório de nível superior para armazenar pacotes OTA.
  4. Adicione uma regra SELinux e contextos de arquivo para controlar o acesso a esta pasta e seu conteúdo. Somente o processo ou os aplicativos que recebem atualizações OTA devem poder ler e gravar nessa pasta. Nenhum outro aplicativo ou processo deve ter acesso a esta pasta.

Validação

Para garantir que a versão implementada do recurso funcione conforme o esperado, primeiro execute os vários testes de criptografia CTS, como DirectBootHostTest e EncryptionTest .

Se o dispositivo estiver executando o Android 11 ou superior, execute também vts_kernel_encryption_test :

atest vts_kernel_encryption_test

ou:

vts-tradefed run vts -m vts_kernel_encryption_test

Além disso, os fabricantes de dispositivos podem realizar os seguintes testes manuais. Em um dispositivo com FBE ativado:

  • Verifique se o ro.crypto.state existe
    • Certifique-se de que o ro.crypto.state esteja criptografado
  • Verifique se o ro.crypto.type existe
    • Certifique-se de que ro.crypto.type esteja definido como file

Além disso, os testadores podem inicializar uma instância userdebug com uma tela de bloqueio definida no usuário principal. Em seguida, adb shell no dispositivo e use su para se tornar root. Certifique-se de que /data/data contém nomes de arquivos criptografados; se isso não acontecer, algo está errado.

Os fabricantes de dispositivos também são incentivados a explorar a execução dos testes upstream do Linux para fscrypt em seus dispositivos ou kernels. Esses testes fazem parte do conjunto de testes do sistema de arquivos xfstests. No entanto, esses testes upstream não são oficialmente suportados pelo Android.

Detalhes da implementação do AOSP

Esta seção fornece detalhes sobre a implementação do AOSP e descreve como funciona a criptografia baseada em arquivo. Não deve ser necessário que os fabricantes de dispositivos façam alterações aqui para usar o FBE e o Direct Boot em seus dispositivos.

criptografia fscrypt

A implementação AOSP usa criptografia "fscrypt" (suportada por ext4 e f2fs) no kernel e normalmente é configurada para:

  • Criptografe o conteúdo do arquivo com AES-256 no modo XTS
  • Criptografe nomes de arquivos com AES-256 no modo CBC-CTS

A criptografia Adiantum também é suportada. Quando a criptografia Adiantum está habilitada, tanto o conteúdo dos arquivos quanto os nomes dos arquivos são criptografados com Adiantum.

Para obter mais informações sobre fscrypt, consulte a documentação do kernel upstream .

Derivação de chave

As chaves de criptografia baseadas em arquivo, que são chaves de 512 bits, são armazenadas criptografadas por outra chave (uma chave AES-GCM de 256 bits) mantida no TEE. Para usar esta chave TEE, três requisitos devem ser atendidos:

  • O token de autenticação
  • A credencial estendida
  • O "hash secdiscardable"

O token de autenticação é um token autenticado criptograficamente gerado pelo Gatekeeper quando um usuário efetua login com êxito. O TEE se recusará a usar a chave a menos que o token de autenticação correto seja fornecido. Se o usuário não tiver credencial, nenhum token de autenticação será usado nem necessário.

A credencial estendida é a credencial do usuário após salgar e estender com o algoritmo scrypt . A credencial é realmente hash uma vez no serviço de configurações de bloqueio antes de ser passada para vold para passar para scrypt . Isso é criptograficamente vinculado à chave no TEE com todas as garantias que se aplicam a KM_TAG_APPLICATION_ID . Se o usuário não tiver credencial, nenhuma credencial estendida será usada nem necessária.

O secdiscardable hash é um hash de 512 bits de um arquivo aleatório de 16 KB armazenado junto com outras informações usadas para reconstruir a chave, como a semente. Esse arquivo é excluído com segurança quando a chave é excluída ou é criptografada de uma nova maneira; essa proteção adicional garante que um invasor recupere cada bit desse arquivo excluído com segurança para recuperar a chave. Isso é criptograficamente vinculado à chave no TEE com todas as garantias que se aplicam a KM_TAG_APPLICATION_ID .

Na maioria dos casos, as chaves FBE também passam por uma etapa de derivação de chave adicional no kernel para gerar as subchaves realmente usadas para fazer a criptografia, por exemplo, chaves por arquivo ou por modo. Para políticas de criptografia da versão 2, o HKDF-SHA512 é usado para isso.