Criptografia baseada em arquivos

O Android 7.0 e versões mais recentes oferecem suporte à criptografia baseada em arquivos (FBE, na sigla em inglês). A criptografia baseada em arquivos permite que arquivos diferentes sejam criptografados com chaves diferentes que podem ser desbloqueadas de forma independente.

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

Todos os dispositivos lançados com o Android 10 e versões mais recentes precisam usar a criptografia baseada em arquivos.

Inicialização direta

A criptografia baseada em arquivos ativa um novo recurso introduzido no Android 7.0 chamado Inicialização direta. A inicialização direta permite que dispositivos criptografados sejam inicializados direto na tela de bloqueio. Antes, em dispositivos criptografados que usavam criptografia de disco completo (FDE, na sigla em inglês), os usuários precisavam fornecer credenciais antes que qualquer dado pudesse ser acessado, impedindo que o smartphone realizasse todas as operações, exceto as mais básicas. Por exemplo, os alarmes não funcionavam, os serviços de acessibilidade não estavam disponíveis, e os smartphones não podiam receber chamadas, mas eram limitados apenas a operações básicas de discagem de emergência.

Com a introdução da criptografia baseada em arquivos (FBE, na sigla em inglês) e de novas APIs para que os apps fiquem cientes da criptografia, é possível que eles operem em um contexto limitado. Isso pode acontecer antes que os usuários forneçam as credenciais, mas as informações particulares deles ainda ficam protegidas.

Em um dispositivo com FBE, cada usuário tem dois locais de armazenamento disponíveis para apps:

  • O armazenamento criptografado por credenciais (CE, na sigla em inglês), que é o local de armazenamento padrão e só é disponibilizado depois que o usuário desbloqueia o dispositivo.
  • O armazenamento criptografado pelo dispositivo (DE, na sigla em inglês), que é um local de armazenamento disponibilizado durante o modo de inicialização direta e depois que o usuário desbloqueia o dispositivo.

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

A API Direct Boot permite que apps compatíveis com criptografia acessem cada uma dessas áreas. Há mudanças no ciclo de vida do app para atender à necessidade de notificar os apps quando o armazenamento de CE de um usuário é desbloqueado em resposta a inserção inicial de credenciais na tela de bloqueio ou, no caso do perfil de trabalho, fornecendo um desafio de trabalho. Os dispositivos com o Android 7.0 precisam oferecer suporte a essas novas APIs e ciclos de vida, independentemente de implementarem ou não a FBE. No entanto, sem FBE, o armazenamento DE e CE estão sempre no estado desbloqueado.

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

Todos os pacotes necessários no AOSP foram atualizados para serem compatíveis com a inicialização direta. No entanto, quando os fabricantes de dispositivos usam versões personalizadas desses apps, eles querem garantir que, no mínimo, haja pacotes compatíveis com inicialização direta que ofereçam os seguintes serviços:

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

Exemplos e origem

O Android oferece uma implementação de referência da criptografia baseada em arquivos, em que o vold (system/vold) fornece a funcionalidade para gerenciar dispositivos de armazenamento e volumes no Android. A adição do FBE fornece ao vold vários comandos novos para oferecer suporte ao gerenciamento de chaves CE e DE de vários usuários. Além das mudanças principais para usar os recursos de criptografia baseada em arquivos no kernel, muitos pacotes do sistema, incluindo a tela de bloqueio e a SystemUI, foram modificados para oferecer suporte aos recursos de criptografia baseada em arquivos e inicialização direta. São eles:

  • Discador do AOSP (packages/apps/Dialer)
  • Relógio de mesa (packages/apps/DeskClock)
  • LatinIME (packages/inputmethods/LatinIME)*
  • App Configurações (packages/apps/Settings)*
  • SystemUI (frameworks/base/packages/SystemUI)*

* Apps do sistema que usam o atributo de manifesto defaultToDeviceProtectedStorage

Para mais exemplos de apps e serviços compatíveis com criptografia, execute o comando mangrep directBootAware no diretório de frameworks ou pacotes da árvore de origem do AOSP.

Dependências

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

  • Suporte do kernel para criptografia Ext4 ou F2FS.
  • Suporte ao KeyMint (ou Keymaster 1.0 ou mais recente). Não há suporte para Keymaster 0.3, porque ele não oferece os recursos necessários nem garante proteção suficiente para chaves de criptografia.
  • O KeyMint/Keymaster e o Gatekeeper precisam ser implementados em um ambiente de execução confiável (TEE, na sigla em inglês) para proteger as chaves DE, de modo que um SO não autorizado (SO personalizado instalado no dispositivo) não possa simplesmente solicitar as chaves DE.
  • A raiz de confiança de hardware e a inicialização verificada vinculadas à inicialização do KeyMint são necessárias para garantir que as chaves DE não sejam acessíveis por um sistema operacional não autorizado.

Implementação

Primeiro, apps como despertadores, telefone e recursos de acessibilidade precisam ser android:directBootAware de acordo com a documentação para desenvolvedores do Direct Boot.

Suporte do kernel

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

CONFIG_FS_ENCRYPTION=y

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

Se o 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 a 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 precisam ativar a aceleração criptográfica para acelerar a criptografia baseada em arquivos e melhorar a experiência do usuário. Por exemplo, em dispositivos baseados em ARM64, a aceleração ARMv8 CE (extensões de criptografia) pode ser ativada 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 consumo de energia, os fabricantes de dispositivos também podem considerar a implementação de hardware de criptografia inline, que criptografa/descriptografa os dados enquanto eles estão a caminho do/para o dispositivo de armazenamento. Os kernels comuns do Android (versão 4.14 e mais recentes) contêm um framework que permite o uso da criptografia inline quando há suporte para hardware e driver do fornecedor. Para ativar a criptografia inline, defina 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 dispositivo usar armazenamento baseado em UFS, ative também:

CONFIG_SCSI_UFS_CRYPTO=y

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

CONFIG_MMC_CRYPTO=y

Ativar a criptografia baseada em arquivos

Para ativar a FBE em um dispositivo, é necessário ativá-la no armazenamento interno (userdata). Isso também ativa automaticamente a FBE no armazenamento adaptável. No entanto, o formato de criptografia no armazenamento adaptável pode ser substituído se necessário.

Armazenamento interno

A FBE é ativada adicionando a opção fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] à coluna fs_mgr_flags da linha fstab para userdata. Essa 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, adiantum ou aes-256-hctr2. 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 flags separadas pelo caractere +. As seguintes flags são compatíveis:
    • A flag v1 seleciona políticas de criptografia da versão 1, e a flag v2 seleciona 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 lançado com o Android 11 ou mais recente (conforme determinado por ro.product.first_api_level) ou v1 se o dispositivo foi lançado com o Android 10 ou anterior.
    • A flag inlinecrypt_optimized seleciona um formato de criptografia otimizado para hardware de criptografia inline que não processa grandes números de chaves de maneira eficiente. Para isso, ela deriva 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.
    • A flag emmc_optimized é semelhante a inlinecrypt_optimized, mas também seleciona um método de geração de IV que limita os IVs a 32 bits. Essa flag só deve ser usada em hardware de criptografia inline que esteja em conformidade com a especificação JEDEC eMMC v5.2 e, portanto, seja compatível apenas com IVs de 32 bits. Em outros hardwares de criptografia inline, use inlinecrypt_optimized. Essa flag nunca deve ser usada em armazenamento baseado em UFS. A especificação UFS permite o uso de IVs de 64 bits.
    • Em dispositivos compatíveis com chaves de criptografia inline encapsuladas por hardware, as chaves de FBE podem ser encapsuladas por hardware adicionando a flag wrappedkey ou wrappedkey_v0. wrappedkey é a versão moderna. wrappedkey_v0 só deve ser usado em dispositivos que não são compatíveis com wrappedkey ou que já foram lançados com wrappedkey_v0. Para mais informações, consulte Ativar chaves encapsuladas.
    • A flag dusize_4k força o tamanho da unidade de dados de criptografia a ser de 4.096 bytes, mesmo quando o tamanho do bloco do sistema de arquivos não é de 4.096 bytes. O tamanho da unidade de dados de criptografia é a granularidade da criptografia do conteúdo do arquivo. Essa flag está disponível desde o Android 15. Essa flag só deve ser usada para ativar o uso de hardware de criptografia inline que não oferece suporte a unidades de dados maiores que 4.096 bytes em um dispositivo que usa um tamanho de página maior que 4.096 bytes e que usa o sistema de arquivos f2fs.

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

Desde o Android 14, o AES-HCTR2 é o modo de preferência da criptografia de nomes de arquivos para dispositivos com instruções de criptografia acelerada. No entanto, apenas os kernels mais recentes do Android oferecem suporte a AES-HCTR2. Em uma versão futura do Android, ele será o modo padrão para criptografia de nomes de arquivos. Se o kernel tiver suporte para AES-HCTR2, ele poderá ser ativado para criptografia de nomes de arquivos definindo filenames_encryption_mode como aes-256-hctr2. No caso mais simples, isso seria feito com fileencryption=aes-256-xts:aes-256-hctr2.

Em dispositivos lançados com o Android 10 e versões anteriores, fileencryption=ice também é aceito para especificar o uso do modo de criptografia de conteúdo de arquivos 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 no disco produzido por esse modo era específico do fornecedor. Em dispositivos lançados com o Android 11 ou versões mais recentes, esse modo não é mais permitido, e um formato de criptografia padrão precisa 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 o hardware de criptografia inline, adicione também a opção de montagem inlinecrypt. Por exemplo, uma linha completa de fstab pode ter esta aparência:

/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, a FBE e o armazenamento adotável podem ser usados juntos.

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

Em dispositivos lançados com o Android 11 ou versões mais recentes, use as seguintes propriedades:

  • ro.crypto.volume.options (novo no Android 11) seleciona o formato de criptografia FBE no armazenamento adotável. Ela tem a mesma sintaxe do argumento da opção fileencryption fstab e usa os mesmos padrões. Consulte as recomendações para fileencryption acima para saber o que usar aqui.
  • O 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 o Android 10 e versões anteriores, 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 equivale ao segundo campo separado por dois pontos de ro.crypto.volume.options, exceto que o padrão em dispositivos lançados com o Android 10 e versões anteriores é 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.

Integrar com o KeyMint

A HAL do KeyMint precisa ser iniciada como parte da classe early_hal. Isso ocorre porque a FBE exige que o KeyMint esteja pronto para processar solicitações na fase de inicialização post-fs-data, que é quando o vold configura as chaves iniciais.

Excluir diretórios

O init aplica a chave DE do sistema a todos os diretórios de nível superior de /data, exceto os diretórios que precisam ser descriptografados, como o diretório que contém a própria chave DE do sistema e os diretórios que contêm diretórios CE ou DE do usuário. As chaves de criptografia são aplicadas de forma recursiva e não podem ser substituídas por subdiretórios.

No Android 11 e versões mais recentes, a chave que init aplica aos diretórios pode ser controlada pelo argumento encryption=<action> para o comando mkdir em scripts de inicialização. Os valores possíveis de <action> estão documentados no README da linguagem de inicialização do Android.

No Android 10, as ações de criptografia init foram fixadas no seguinte local:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

No Android 9 e em versões anteriores, o local era:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

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

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

Suporte à inicialização direta em apps do sistema

Fazer com que os apps reconheçam a inicialização direta

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

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

O atributo directBootAware no nível do app é uma forma abreviada de marcar todos os componentes do app como tendo reconhecimento de criptografia.

O atributo defaultToDeviceProtectedStorage redireciona o local de armazenamento padrão do app para o armazenamento DE, em vez de apontar para o armazenamento CE. Os apps do sistema que usam essa flag precisam auditar cuidadosamente todos os dados armazenados no local padrão e mudar os caminhos de dados sensíveis para usar o armazenamento CE. Os fabricantes de dispositivos que usam essa opção precisam inspecionar cuidadosamente os dados que estão armazenando para garantir que não contenham informações pessoais.

Ao executar nesse modo, as seguintes APIs do sistema ficam disponíveis para gerenciar explicitamente um contexto apoiado pelo armazenamento de CE quando necessário, que são equivalentes às contrapartes protegidas por dispositivo.

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

Suporte para dispositivo compartilhado

Cada usuário em um ambiente multiusuário recebe uma chave de criptografia separada. Cada usuário recebe duas chaves: uma DE e uma CE. O usuário 0 precisa fazer login no dispositivo primeiro, porque é um usuário especial. Isso é pertinente para usos de administração de dispositivos.

Os apps compatíveis com criptomoedas interagem entre os usuários da seguinte maneira: INTERACT_ACROSS_USERS e INTERACT_ACROSS_USERS_FULL permitem que um app funcione para todos os usuários do dispositivo. No entanto, esses apps só podem acessar diretórios criptografados com CE de usuários que já estão desbloqueados.

Um app pode interagir livremente nas áreas de DE, mas o desbloqueio de um usuário não significa que todos os usuários no dispositivo estão desbloqueados. O app precisa verificar esse status antes de tentar acessar essas áreas.

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

Gerenciar atualizações

A partição de recuperação não consegue acessar o armazenamento protegido por DE na partição userdata. É altamente recomendável que os dispositivos que implementam o FBE ofereçam suporte a OTA usando atualizações do sistema A/B. Como a OTA pode ser aplicada durante a operação normal, não é necessário que a recuperação acesse dados na unidade criptografada.

Ao usar uma solução OTA legada, 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. Configure esse diretório de nível superior para não ser criptografado (consulte Como excluir diretórios).
  3. Crie um diretório no diretório de nível superior para armazenar pacotes OTA.
  4. Adicione uma regra do SELinux e contextos de arquivo para controlar o acesso a esse diretório e ao conteúdo dele. Somente o processo ou os apps que recebem atualizações OTA podem ler e gravar nesse diretório. Nenhum outro app ou processo deve ter acesso a esse diretório.

Validação

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

Se o dispositivo estiver executando o Android 11 ou uma versão mais recente, 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 testes manuais a seguir. Em um dispositivo com FBE ativada:

  • Verifique se ro.crypto.state existe
    • Verificar se ro.crypto.state está criptografado
  • Verifique se ro.crypto.type existe
    • Verifique se ro.crypto.type está definido como file.

Além disso, os testadores podem verificar se o armazenamento CE está bloqueado antes que o dispositivo seja desbloqueado pela primeira vez desde a inicialização. Para fazer isso, use um build userdebug ou eng, defina um PIN, padrão ou senha no usuário principal e reinicie o dispositivo. Antes de desbloquear o dispositivo, execute o seguinte comando para verificar o armazenamento de CE do usuário principal. Se o dispositivo usar o Modo de usuário do sistema sem interface (a maioria dos dispositivos automotivos), o usuário principal será o 10. Portanto, execute:

adb root; adb shell ls /data/user/10

Em outros dispositivos (a maioria dos dispositivos não automotivos), o usuário principal é o usuário 0. Portanto, execute:

adb root; adb shell ls /data/user/0

Verifique se os nomes de arquivo listados estão codificados em Base64, indicando que eles estão criptografados e que a chave para descriptografá-los ainda não está disponível. Se os nomes de arquivo estiverem listados em texto simples, algo está errado.

Os fabricantes de dispositivos também são incentivados a executar os testes upstream do Linux para fscrypt nos dispositivos ou kernels. Esses testes fazem parte do pacote de testes do sistema de arquivos xfstests. No entanto, esses testes upstream não são oficialmente compatíveis com o Android.

Detalhes da implementação do AOSP

Esta seção fornece detalhes sobre a implementação do AOSP e descreve como a criptografia baseada em arquivos funciona. Não é necessário que os fabricantes de dispositivos façam mudanças aqui para usar o FBE e a inicialização direta nos aparelhos.

Criptografia fscrypt

A implementação do AOSP usa a criptografia "fscrypt" (com suporte de ext4 e f2fs) no kernel e normalmente é configurada para:

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

A criptografia Adiantum também é compatível. Quando a criptografia Adiantum está ativada, o conteúdo e os nomes dos arquivos são criptografados com Adiantum.

O fscrypt oferece suporte a duas versões de políticas de criptografia: versão 1 e versão 2. A versão 1 foi descontinuada, e os requisitos do CDD para dispositivos lançados com o Android 11 e versões mais recentes são compatíveis apenas com a versão 2. As políticas de criptografia da versão 2 usam HKDF-SHA512 para derivar as chaves de criptografia reais das chaves fornecidas pelo espaço do usuário.

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

Classes de armazenamento

A tabela a seguir lista as chaves de FBE e os diretórios que elas protegem em mais detalhes:

Classe de armazenamento Descrição Diretórios
Não criptografado Diretórios em /data que não podem ou não precisam ser protegidos pela FBE. Em dispositivos que usam criptografia de metadados, esses diretórios não são realmente não criptografados, mas protegidos pela chave de criptografia de metadados, que é equivalente à criptografia de disco do sistema.
  • /data/apex, exceto /data/apex/decompressed e /data/apex/ota_reserved, que são DE do sistema
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • Todos os diretórios cujos subdiretórios usam chaves FBE diferentes. Por exemplo, como cada diretório /data/user/${user_id} usa uma chave por usuário, o /data/user não usa nenhuma chave.
DE do sistema Dados criptografados por dispositivo não vinculados a um usuário específico
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • Todos os outros subdiretórios de /data que esta tabela não menciona como tendo uma classe diferente
Por inicialização Arquivos de sistema temporários que não precisam sobreviver a uma reinicialização /data/per_boot
CE do usuário (interno) Dados criptografados por credencial de cada usuário no armazenamento interno
  • /data/data (alias de /data/user/0)
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
Usuário da Alemanha (interno) Dados criptografados por dispositivo e por usuário no armazenamento interno
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
CE do usuário (adotável) Dados criptografados com credenciais por usuário no armazenamento adaptável
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
DE do usuário (adotável) Dados criptografados por dispositivo por usuário no armazenamento adotável
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

Armazenamento e proteção de chaves

Todas as chaves FBE são gerenciadas pelo vold e armazenadas criptografadas no disco, exceto a chave por inicialização, que não é armazenada. A tabela a seguir lista os locais em que as várias chaves de FBE são armazenadas:

Tipo de chave Local da chave Classe de armazenamento do local da chave
Chave DE do sistema /data/unencrypted Não criptografado
Chaves CE (internas) do usuário /data/misc/vold/user_keys/ce/${user_id} DE do sistema
Chaves de DE do usuário (internas) /data/misc/vold/user_keys/de/${user_id} DE do sistema
Chaves CE do usuário (adotáveis) /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} CE do usuário (interno)
Chaves DE do usuário (adotáveis) /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} Usuário da Alemanha (interno)

Como mostrado na tabela anterior, a maioria das chaves de FBE é armazenada em diretórios criptografados por outra chave de FBE. As chaves não podem ser desbloqueadas até que a classe de armazenamento que as contém seja desbloqueada.

O vold também aplica uma camada de criptografia a todas as chaves FBE. Todas as chaves, exceto as de CE para armazenamento interno, são criptografadas com AES-256-GCM usando a própria chave do Keystore, que não é exposta fora do TEE. Isso garante que as chaves de FBE não possam ser desbloqueadas, a menos que um sistema operacional confiável tenha sido inicializado, conforme exigido pela Inicialização verificada. A resistência à reversão também é solicitada na chave do Keystore, o que permite que as chaves de FBE sejam excluídas com segurança em dispositivos em que o KeyMint oferece suporte à resistência à reversão. Como um fallback de melhor esforço para quando a resistência a rollbacks não está disponível, o hash SHA-512 de 16.384 bytes aleatórios armazenados no arquivo secdiscardable armazenado junto com a chave é usado como o Tag::APPLICATION_ID da chave do Keystore. Todos esses bytes precisam ser recuperados para recuperar uma chave FBE.

As chaves CE para armazenamento interno recebem um nível de proteção mais forte que garante que elas não possam ser desbloqueadas sem o fator de conhecimento da tela de bloqueio (LSKF) (PIN, padrão ou senha) do usuário, um token de redefinição de senha segura ou as chaves do lado do cliente e do servidor para uma operação de retomada na reinicialização. Os tokens de redefinição de senha só podem ser criados para perfis de trabalho e dispositivos totalmente gerenciados.

Para isso, o vold criptografa cada chave CE para armazenamento interno usando uma chave AES-256-GCM derivada da senha sintética do usuário. A senha sintética é um secret criptográfico imutável de alta entropia gerado aleatoriamente para cada usuário. LockSettingsService em system_server gerencia a senha sintética e as formas como ela é protegida.

Para proteger a senha sintética com o LSKF, o LockSettingsService primeiro estende o LSKF passando-o por scrypt, visando um tempo de cerca de 25 ms e um uso da memória de cerca de 2 MiB. Como as LSKFs geralmente são curtas, essa etapa não oferece muita segurança. A principal camada de segurança é o Elemento de segurança (SE) ou a limitação de taxa aplicada pelo TEE descrita abaixo.

Se o dispositivo implementar a HAL do Weaver, o LockSettingsService vai mapear o LSKF estendido para um secret aleatório de alta entropia armazenado no SE ou no TEE usando o Weaver. Em seguida, o LockSettingsService criptografa a senha sintética duas vezes: primeiro com uma chave de software derivada do LSKF estendido e do segredo do Weaver e, depois, com uma chave do Keystore não vinculada à autenticação. Isso fornece limitação de taxa de palpites de LSKF imposta por SE ou TEE.

Se o dispositivo não implementar o Weaver, o LockSettingsService vai usar o LSKF estendido como uma senha do Gatekeeper. Em seguida, o LockSettingsService criptografa a senha sintética duas vezes: primeiro com uma chave de software derivada do LSKF estendido e do hash de um arquivo secdiscardable e, em seguida, com uma chave do Keystore que está vinculada à autenticação do registro do Gatekeeper. Isso fornece uma limitação de taxa de tentativas de LSKF aplicada pelo TEE.

Quando a LSKF é alterada, o LockSettingsService exclui todas as informações associadas à vinculação da senha sintética à LSKF antiga. Em dispositivos compatíveis com o Weaver ou com chaves do Keystore resistentes à reversão, isso garante a exclusão segura da vinculação antiga. Por esse motivo, as proteções descritas aqui são aplicadas mesmo quando o usuário não tem uma LSKF.