A criptografia de disco completo é o processo de codificação de todos os dados do usuário em um dispositivo Android usando uma chave criptografada. Depois que um dispositivo é criptografado, todos os dados criados pelo usuário são criptografados automaticamente antes de serem confirmados no disco, e todas as leituras descriptografam automaticamente os dados antes de serem retornados ao processo de chamada.
A criptografia de disco completo foi introduzida no Android 4.4, mas o Android 5.0 apresentou estes novos recursos:
- Criação de criptografia rápida, que criptografa apenas blocos usados na partição de dados para evitar que a primeira inicialização demore muito. No momento, apenas os sistemas de arquivos ext4 e f2fs oferecem suporte à criptografia rápida.
- Adicionamos a flag fstab
forceencrypt
para criptografar na primeira inicialização. - Inclusão de suporte a padrões e criptografia sem senha.
- Foi adicionado armazenamento com suporte de hardware da chave de criptografia usando o recurso de assinatura do ambiente de execução confiável (TEE), como em uma TrustZone. Consulte Como armazenar a chave criptografada para mais detalhes.
Atenção:os dispositivos que foram atualizados para o Android 5.0 e criptografados podem ser retornados a um estado não criptografado com a redefinição de dados de fábrica. Os novos dispositivos Android 5.0 criptografados na primeira inicialização não podem ser retornados a um estado não criptografado.
Como funciona a criptografia de disco completo do Android
A criptografia de disco completo do Android é baseada em dm-crypt
, que é um recurso
do kernel que funciona na camada de dispositivo de bloco. Por
isso, a criptografia funciona com Embedded MultiMediaCard (eMMC) e
dispositivos flash semelhantes que se apresentam ao kernel como dispositivos
de bloco. A criptografia não é possível com o YAFFS, que se comunica diretamente com um chip flash NAND
bruto.
O algoritmo de criptografia é o padrão de criptografia avançada (AES) de 128 bits com cadeamento de blocos de cifras (CBC) e ESSIV:SHA256. A chave mestra é criptografada com AES de 128 bits por chamadas à biblioteca OpenSSL. É necessário usar 128 bits ou mais para a chave (256 é opcional).
Observação:os OEMs podem usar 128 bits ou mais para criptografar a chave mestra.
Na versão Android 5.0, há quatro tipos de estados de criptografia:
- padrão
- PIN
- senha
- padrão
Na primeira inicialização, o dispositivo cria uma chave mestra de 128 bits gerada aleatoriamente e a converte em hash com uma senha padrão e um salt armazenado. A senha padrão é: "default_password". No entanto, o hash resultante também é assinado por um TEE (como o TrustZone), que usa um hash da assinatura para criptografar a chave mestra.
A senha padrão definida no projeto do Android Open Source cryptfs.cpp pode ser encontrada aqui.
Quando o usuário define o PIN/senha ou a senha no dispositivo, apenas a chave de 128 bits é criptografada novamente e armazenada. Por exemplo, mudanças de PIN/senha/padrão do usuário NÃO causam a recriptografia dos dados do usuário. O dispositivo gerenciado pode estar sujeito a restrições de PIN, padrão ou senha.
A criptografia é gerenciada por init
e vold
.
init
chama vold
, e o vold define propriedades para acionar
eventos na inicialização. Outras partes do sistema
também analisam as propriedades para realizar tarefas como informar o status, solicitar uma
senha ou solicitar a redefinição de fábrica no caso de um erro fatal. Para invocar
os recursos de criptografia em vold
, o sistema usa os comandos cryptfs
da ferramenta de linha de comando
vdc
: checkpw
,
restart
, enablecrypto
, changepw
,
cryptocomplete
, verifypw
, setfield
,
getfield
, mountdefaultencrypted
, getpwtype
,
getpw
e clearpw
.
Para criptografar, descriptografar ou excluir /data
, /data
não pode ser montado. No entanto, para mostrar qualquer interface do usuário (IU), o
framework precisa ser iniciado e requer que /data
seja executado. Para
resolver esse problema, um sistema de arquivos temporário é montado em /data
.
Isso permite que o Android solicite senhas, mostre o progresso ou sugira uma limpeza
de dados, conforme necessário. Isso impõe a limitação de que, para alternar do
sistema de arquivos temporário para o sistema de arquivos /data
real, o sistema precisa
interromper todos os processos com arquivos abertos no sistema de arquivos temporário e reiniciar esses
processos no sistema de arquivos /data
real. Para isso, todos os serviços
precisam estar em um dos três grupos: core
, main
e
late_start
.
core
: nunca é encerrado após a inicialização.main
: desligue e reinicie após a senha do disco ser inserida.late_start
: não é iniciado até que/data
seja descriptografado e montado.
Para acionar essas ações, a propriedade vold.decrypt
é definida como
várias strings.
Para encerrar e reiniciar serviços, os comandos init
são:
class_reset
: interrompe um serviço, mas permite que ele seja reiniciado com class_start.class_start
: reinicia um serviço.class_stop
: interrompe um serviço e adiciona uma flagSVC_DISABLED
. Os serviços interrompidos não respondem aclass_start
.
Fluxos
Há quatro fluxos para um dispositivo criptografado. Um dispositivo é criptografado apenas uma vez e depois segue um fluxo de inicialização normal.
- Criptografar um dispositivo que não estava criptografado:
- Criptografar um novo dispositivo com
forceencrypt
: criptografia obrigatória na primeira inicialização (a partir do Android L). - Criptografar um dispositivo existente: criptografia iniciada pelo usuário (Android K e versões anteriores).
- Criptografar um novo dispositivo com
- Inicialize um dispositivo criptografado:
- Inicialização de um dispositivo criptografado sem senha: inicialização de um dispositivo criptografado que não tem uma senha definida (relevante para dispositivos com o Android 5.0 e versões mais recentes).
- Como iniciar um dispositivo criptografado com uma senha: inicializar um dispositivo criptografado que tenha uma senha definida.
Além desses fluxos, o dispositivo também pode falhar na criptografia de /data
.
Cada um dos fluxos é explicado em detalhes abaixo.
Criptografar um novo dispositivo com forceencrypt
Essa é a primeira inicialização normal de um dispositivo com Android 5.0.
- Detectar o sistema de arquivos não criptografado com a flag
forceencrypt
/data
não está criptografado, mas precisa ser porqueforceencrypt
exige isso. Desconecte/data
. - Começar a criptografar
/data
vold.decrypt = "trigger_encryption"
acionainit.rc
, o que faz com quevold
criptografe/data
sem senha. Nenhuma está definida porque este é um novo dispositivo. - Montar tmpfs
vold
monta um/data
tmpfs (usando as opções tmpfs dero.crypto.tmpfs_options
) e define a propriedadevold.encrypt_progress
como 0.vold
prepara o tmpfs/data
para inicializar um sistema criptografado e define a propriedadevold.decrypt
como:trigger_restart_min_framework
- Mostrar o framework para mostrar o progresso
Como o dispositivo não tem dados para criptografia, a barra de progresso não aparece com frequência porque a criptografia acontece muito rápido. Consulte Criptografar um dispositivo existente para mais detalhes sobre a interface de progresso.
- Quando
/data
estiver criptografado, remova o frameworkvold
definevold.decrypt
comotrigger_default_encryption
, que inicia o serviçodefaultcrypto
. Isso inicia o fluxo abaixo para montar um userdata criptografado padrão.trigger_default_encryption
verifica o tipo de criptografia para saber se/data
está criptografado com ou sem uma senha. Como os dispositivos Android 5.0 são criptografados na primeira inicialização, não deve haver uma senha definida. Portanto, descriptografamos e montamos/data
. - Montar
/data
Em seguida,
init
monta/data
em um RAMDisk tmpfs usando parâmetros que ele coleta dero.crypto.tmpfs_options
, que é definido eminit.rc
. - Framework de início
vold
definevold.decrypt
comotrigger_restart_framework
, que continua o processo de inicialização normal.
Criptografar um dispositivo
Isso acontece quando você criptografa um dispositivo Android K ou anterior não criptografado que foi migrado para L.
Esse processo é iniciado pelo usuário e é chamado de "criptografia in-place" no código. Quando um usuário seleciona a criptografia de um dispositivo, a interface garante que a bateria esteja totalmente carregada e que o adaptador de CA esteja conectado para que haja energia suficiente para concluir o processo de criptografia.
Aviso:se o dispositivo ficar sem energia e for desligado antes de terminar a criptografia, os dados do arquivo serão deixados em um estado parcialmente criptografado. O dispositivo precisa ser redefinido para a configuração original, e todos os dados são perdidos.
Para ativar a criptografia in-place, vold
inicia um loop para ler cada
setor do dispositivo de bloco real e, em seguida, gravar
no dispositivo de bloco criptográfico. O vold
verifica se um setor está em
uso antes de ler e gravar nele, o que torna
a criptografia muito mais rápida em um novo dispositivo que tem poucos ou nenhum dado.
Estado do dispositivo: defina ro.crypto.state = "unencrypted"
e execute o gatilho init
on nonencrypted
para continuar a inicialização.
- Verificar senha
A interface chama
vold
com o comandocryptfs enablecrypto inplace
, em quepasswd
é a senha da tela de bloqueio do usuário. - Remover a estrutura
vold
verifica erros, retorna -1 se não puder criptografar e imprime um motivo no registro. Se a criptografia for possível, a propriedadevold.decrypt
será definida comotrigger_shutdown_framework
. Isso faz com queinit.rc
interrompa os serviços nas classeslate_start
emain
. - Criar um rodapé de criptografia
- Criar um arquivo de migas de pão
- Reiniciar
- Detectar arquivo de navegação estrutural
- Começar a criptografar
/data
Em seguida,
vold
configura o mapeamento de criptografia, que cria um dispositivo de bloco de criptografia virtual que é mapeado para o dispositivo de bloco real, mas criptografa cada setor conforme é gravado e descriptografa cada setor conforme é lido. Em seguida,vold
cria e grava os metadados de criptografia. - Montar tmpfs durante a criptografia
vold
monta um/data
do tmpfs (usando as opções do tmpfs dero.crypto.tmpfs_options
) e define a propriedadevold.encrypt_progress
como 0. Ovold
prepara o tmpfs/data
para inicializar um sistema criptografado e define a propriedadevold.decrypt
como:trigger_restart_min_framework
- Mostrar o framework para mostrar o progresso
trigger_restart_min_framework
faz com queinit.rc
inicie a classe de serviçosmain
. Quando o framework detecta quevold.encrypt_progress
está definido como 0, ele mostra a interface da barra de progresso, que consulta essa propriedade a cada cinco segundos e atualiza uma barra de progresso. O loop de criptografia atualizavold.encrypt_progress
sempre que criptografa outra porcentagem da partição. - Atualize o rodapé de criptografia quando
/data
for criptografadoQuando
/data
é criptografado,vold
limpa a flagENCRYPTION_IN_PROGRESS
nos metadados.Quando o dispositivo é desbloqueado, a senha é usada para criptografar a chave mestra, e o rodapé criptográfico é atualizado.
Se a reinicialização falhar por algum motivo,
vold
vai definir a propriedadevold.encrypt_progress
comoerror_reboot_failed
, e a interface vai mostrar uma mensagem pedindo que o usuário pressione um botão para reiniciar. Isso não deve acontecer.
Iniciar um dispositivo criptografado com a criptografia padrão
Isso acontece quando você inicializa um dispositivo criptografado sem senha. Como os dispositivos Android 5.0 são criptografados na primeira inicialização, não deve haver uma senha definida. Portanto, esse é o estado de criptografia padrão.
- Detectar
/data
criptografados sem senhaDetecta que o dispositivo Android está criptografado porque
/data
não pode ser montado e uma das flagsencryptable
ouforceencrypt
está definida.vold
definevold.decrypt
comotrigger_default_encryption
, que inicia o serviçodefaultcrypto
.trigger_default_encryption
verifica o tipo de criptografia para saber se/data
está criptografado com ou sem uma senha. - Descriptografar /data
Cria o dispositivo
dm-crypt
sobre o dispositivo de bloco para que ele esteja pronto para uso. - Montar /data
O
vold
monta a partição/data
real descriptografada e prepara a nova partição. Ele define a propriedadevold.post_fs_data_done
como 0 e, em seguida, definevold.decrypt
comotrigger_post_fs_data
. Isso faz com queinit.rc
execute os comandospost-fs-data
. Eles criam os diretórios ou links necessários e definemvold.post_fs_data_done
como 1.Quando
vold
encontra o 1 nessa propriedade, ele define a propriedadevold.decrypt
como:trigger_restart_framework.
. Isso faz com queinit.rc
inicie os serviços na classemain
novamente e também inicie os serviços na classelate_start
pela primeira vez desde a inicialização. - Framework de início
Agora o framework inicializa todos os serviços usando o
/data
descriptografado, e o sistema está pronto para uso.
Iniciar um dispositivo criptografado sem criptografia padrão
Isso acontece quando você inicializa um dispositivo criptografado que tem uma senha definida. A senha do dispositivo pode ser um PIN, um padrão ou uma senha.
- Detectar dispositivo criptografado com uma senha
Detectar que o dispositivo Android está criptografado porque a flag
ro.crypto.state = "encrypted"
vold
definevold.decrypt
comotrigger_restart_min_framework
porque/data
é codificado com uma senha. - Montar tmpfs
init
define cinco propriedades para salvar as opções de montagem iniciais fornecidas para/data
com parâmetros transmitidos deinit.rc
. Ovold
usa estas propriedades para configurar o mapeamento de criptografia:ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(número hexadecimal de 8 dígitos ASCII precedido por 0x)
- Iniciar framework para solicitar a senha
O framework é iniciado e verifica que
vold.decrypt
está definido comotrigger_restart_min_framework
. Isso informa ao framework que ele está iniciando em um disco/data
do tmpfs e precisa receber a senha do usuário.No entanto, primeiro, ele precisa verificar se o disco foi criptografado corretamente. Ele envia o comando
cryptfs cryptocomplete
paravold
.vold
retorna 0 se a criptografia foi concluída, -1 em caso de erro interno ou -2 se a criptografia não foi concluída. Ovold
determina isso procurando a flagCRYPTO_ENCRYPTION_IN_PROGRESS
nos metadados de criptografia. Se estiver definido, o processo de criptografia foi interrompido e não há dados utilizáveis no dispositivo. Sevold
retornar um erro, a interface precisará mostrar uma mensagem para o usuário reiniciar e redefinir o dispositivo para a configuração original e fornecer um botão para que ele faça isso. - Descriptografar dados com senha
Quando
cryptfs cryptocomplete
for bem-sucedido, o framework vai mostrar uma interface que solicita a senha do disco. A interface verifica a senha enviando o comandocryptfs checkpw
paravold
. Se a senha estiver correta (determinada pela montagem bem-sucedida do/data
descriptografado em um local temporário e depois a desmontagem),vold
vai salvar o nome do dispositivo de bloco descriptografado na propriedadero.crypto.fs_crypto_blkdev
e retornar o status 0 para a interface. Se a senha estiver incorreta, ela retornará -1 para a interface. - Framework de interrupção
A interface mostra um gráfico de inicialização de criptografia e chama
vold
com o comandocryptfs restart
.vold
define a propriedadevold.decrypt
comotrigger_reset_main
, o que faz com queinit.rc
executeclass_reset main
. Isso interrompe todos os serviços na classe principal, o que permite que o/data
do tmpfs seja desmontado. - Montar
/data
O
vold
monta a partição/data
real descriptografada e prepara a nova partição, que pode nunca ter sido preparada se ela foi criptografada com a opção de limpeza, que não tem suporte na primeira versão. Ele define a propriedadevold.post_fs_data_done
como 0 e, em seguida, definevold.decrypt
comotrigger_post_fs_data
. Isso faz com queinit.rc
execute os comandospost-fs-data
. Eles criam os diretórios ou links necessários e definemvold.post_fs_data_done
como 1. Quandovold
encontra o 1 nessa propriedade, ele define a propriedadevold.decrypt
comotrigger_restart_framework
. Isso faz com queinit.rc
inicie os serviços na classemain
novamente e também inicie os serviços na classelate_start
pela primeira vez desde a inicialização. - Iniciar framework completo
Agora o framework inicializa todos os serviços usando o sistema de arquivos
/data
descriptografado, e o sistema está pronto para uso.
Falha
Um dispositivo que não consegue descriptografar pode estar com problemas por alguns motivos. O dispositivo começa com a série normal de etapas para inicialização:
- Detectar um dispositivo criptografado com uma senha
- Ativar o tmpfs
- Iniciar o framework para solicitar a senha
No entanto, depois que o framework é aberto, o dispositivo pode encontrar alguns erros:
- A senha corresponde, mas não consegue descriptografar os dados
- O usuário digita a senha errada 30 vezes
Se esses erros não forem resolvidos, solicite ao usuário que faça uma redefinição de fábrica:
Se vold
detectar um erro durante o processo de criptografia e se
nenhum dado tiver sido destruído e o framework estiver ativo, vold
definirá
a propriedade vold.encrypt_progress
como error_not_encrypted
.
A interface solicita que o usuário reinicie e alerta que o processo de criptografia
não foi iniciado. Se o erro ocorrer depois que o framework for removido, mas
antes que a IU da barra de progresso seja exibida, o vold
reinicia o sistema. Se
a reinicialização falhar, ela vai definir vold.encrypt_progress
como
error_shutting_down
e retornar -1. No entanto, não haverá nada
para detectar o erro. Isso não é esperado.
Se vold
detectar um erro durante o processo de criptografia, ele definirá
vold.encrypt_progress
como error_partially_encrypted
e retornará -1. A interface precisa mostrar uma mensagem informando que a criptografia
falhou e fornecer um botão para o usuário redefinir o dispositivo para a configuração original.
Armazenar a chave criptografada
A chave criptografada é armazenada nos metadados de criptografia. O suporte de hardware é implementado usando o recurso de assinatura do Ambiente de execução confiável (TEE). Anteriormente, criptografávamos a chave mestra com uma chave gerada aplicando o scrypt à senha do usuário e ao sal armazenado. Para tornar a chave resistente a ataques fora da caixa, estendemos esse algoritmo assinando a chave resultante com uma chave TEE armazenada. A assinatura resultante é transformada em uma chave de comprimento adequado por mais uma aplicação de scrypt. Essa chave é usada para criptografar e descriptografar a chave mestra. Para armazenar essa chave:
- Gere uma chave de criptografia de disco (DEK, na sigla em inglês) aleatória de 16 bytes e um sal de 16 bytes.
- Aplique o scrypt à senha do usuário e ao sal para produzir a chave intermediária de 32 bytes 1 (IK1).
- Preencha IK1 com zero bytes para o tamanho da chave privada vinculada ao hardware (HBK). Especificamente, preenchemos como: 00 || IK1 || 00..00; um byte zero, 32 bytes IK1, 223 bytes zero.
- Assine o IK1 com HBK para produzir o IK2 de 256 bytes.
- Aplique o scrypt em IK2 e no sal (o mesmo sal da etapa 2) para produzir IK3 de 32 bytes.
- Use os primeiros 16 bytes de IK3 como KEK e os últimos 16 bytes como IV.
- Criptografe a DEK com AES_CBC, com a chave KEK e o vetor de inicialização IV.
Mudar a senha
Quando um usuário decide mudar ou remover a senha nas configurações, a interface envia
o comando cryptfs changepw
para vold
, e
vold
criptografa novamente a chave mestra do disco com a nova senha.
Propriedades de criptografia
vold
e init
se comunicam entre si
definindo propriedades. Confira uma lista de propriedades disponíveis para criptografia.
Propriedades de Vold
Propriedade | Descrição |
---|---|
vold.decrypt trigger_encryption |
Criptografar a unidade sem senha. |
vold.decrypt trigger_default_encryption |
Verifique se a unidade está criptografada sem senha.
Se estiver, descriptografe e monte.
Caso contrário, defina vold.decrypt como trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
Foi definido pelo vold para encerrar a IU que solicita a senha do disco. |
vold.decrypt trigger_post_fs_data |
Foi definido pelo vold para preparar /data com os diretórios necessários, entre outros. |
vold.decrypt trigger_restart_framework |
Definido pelo vold para iniciar o framework real e todos os serviços. |
vold.decrypt trigger_shutdown_framework |
O Vold é definido para encerrar o framework completo e iniciar a criptografia. |
vold.decrypt trigger_restart_min_framework |
É definido pelo vold para iniciar a
interface da barra de progresso para criptografia ou
pedir a senha, dependendo do
valor de ro.crypto.state . |
vold.encrypt_progress |
Quando o framework for iniciado, se essa propriedade estiver definida, entre no modo de interface da barra de progresso. |
vold.encrypt_progress 0 to 100 |
A interface da barra de progresso precisa mostrar o valor percentual definido. |
vold.encrypt_progress error_partially_encrypted |
A interface da barra de progresso precisa mostrar uma mensagem informando que a criptografia falhou e oferecer ao usuário a opção de redefinir o dispositivo para as configurações de fábrica. |
vold.encrypt_progress error_reboot_failed |
A IU da barra de progresso precisa mostrar uma mensagem informando que a criptografia foi concluída e oferecer ao usuário um botão para reiniciar o dispositivo. Esse erro não deve acontecer. |
vold.encrypt_progress error_not_encrypted |
A interface da barra de progresso precisa mostrar uma mensagem informando que ocorreu um erro, nenhum dado foi criptografado ou perdido e fornecer ao usuário um botão para reiniciar o sistema. |
vold.encrypt_progress error_shutting_down |
A interface da barra de progresso não está em execução. Portanto, não está claro quem responde a esse erro. E isso não deveria acontecer. |
vold.post_fs_data_done 0 |
Defina por vold antes de definir vold.decrypt
como trigger_post_fs_data . |
vold.post_fs_data_done 1 |
Defina por init.rc ou
init.rc logo após concluir a tarefa post-fs-data . |
Propriedades de inicialização
Propriedade | Descrição |
---|---|
ro.crypto.fs_crypto_blkdev |
Definido pelo comando vold checkpw para uso posterior
pelo comando vold restart . |
ro.crypto.state unencrypted |
Definido por init para informar que o sistema está em execução com um
/data ro.crypto.state encrypted não criptografado. Definido por init para informar
que o sistema está em execução com um /data criptografado. |
|
Essas cinco propriedades são definidas por
init quando ele tenta montar /data com parâmetros transmitidos de
init.rc . O vold usa esses dados para configurar o mapeamento de criptografia. |
ro.crypto.tmpfs_options |
Definido por init.rc com as opções que o init precisa usar ao
montar o sistema de arquivos /data do tmpfs. |
ações de inicialização
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption