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 na versão 4.4, mas o Android 5.0 introduziu estes novos recursos:
- Criou a criptografia rápida, em que apenas os blocos usados na partição de dados são criptografados para evitar que a primeira inicialização demore muito tempo. No momento, apenas os sistemas de arquivos ext4 e f2fs oferecem suporte à criptografia rápida.
- Foi adicionada a sinalização fstab
forceencrypt
para criptografar na primeira inicialização. - Inclusão de suporte a padrões e criptografia sem senha.
- Inclusão de armazenamento protegido por hardware da chave de criptografia usando o recurso de assinatura do ambiente de execução confiável (TEE), como em um TrustZone. Consulte Como armazenar a chave criptografada para mais detalhes.
Cuidado:dispositivos atualizados para o Android 5.0 e depois criptografados podem ser retornados para um estado não criptografado após uma redefinição para a configuração original. 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 do 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 para a biblioteca OpenSSL. Você precisa usar 128 bits ou mais para a chave, sendo 256 opcionais.
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 gera um hash com uma senha padrão e um sal 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.
Encontre a senha padrão definida no arquivo cryptfs.cpp do Android Open Source Project.
Quando o usuário define o PIN/senha ou senha no dispositivo, apenas a chave de 128 bits é recriptografada 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 vold define propriedades para acionar
eventos no init. 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 permanentemente /data
, o /data
não pode ser ativado. No entanto, para mostrar qualquer interface do usuário (interface), o
framework precisa ser iniciado e /data
para ser 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 exclusão
de dados conforme necessário. Ele impõe a limitação de que, para alternar do
sistema de arquivos temporário para o verdadeiro sistema de arquivos /data
, 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 ativado.
Para acionar essas ações, a propriedade vold.decrypt
é definida como
várias strings.
Para encerrar e reiniciar os 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 segue um fluxo de inicialização normal.
- Criptografar um dispositivo que não estava criptografado:
- Criptografe 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).
- Criptografe um novo dispositivo com
- Inicialize um dispositivo criptografado:
- Iniciar um dispositivo criptografado sem senha: inicializar um dispositivo criptografado que não tem uma senha definida (relevante para dispositivos com 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
Esta é a primeira inicialização normal de um dispositivo Android 5.0.
- Detectar o sistema de arquivos não criptografado com a flag
forceencrypt
O
/data
não está criptografado, mas precisa ser porque oforceencrypt
exige isso. Desconecte/data
. - Começar a criptografar
/data
vold.decrypt = "trigger_encryption"
acionainit.rc
, o que faz com quevold
criptografe/data
sem senha. Nenhum é definido porque este deve ser 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 Como criptografar um dispositivo existente para mais detalhes sobre a interface de progresso.
- Quando
/data
estiver criptografado, remova o frameworkvold
definevold.decrypt
comotrigger_default_encryption
, o 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 é necessário definir uma senha. Portanto, descriptografamos e ativamos/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
. - Iniciar framework
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 no local, vold
inicia uma repetição para ler cada
setor do dispositivo de bloco real e gravá-lo
no dispositivo de bloco de criptografia. 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 on nonencrypted
init
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. - Durante a criptografia, ative o tmpfs
vold
monta um/data
de tmpfs (usando as opções de tmpfs dero.crypto.tmpfs_options
e define a propriedadevold.encrypt_progress
como 0.vold
prepara os tmpfs/data
para inicializar um sistema criptografado e define a propriedadevold.decrypt
como:trigger_restart_min_framework
- Mostrar o progresso do framework
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. - Quando
/data
estiver criptografado, atualize o rodapé de criptografiaQuando
/data
for criptografado,vold
limpará 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 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 pode 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
, o que inicia o serviçodefaultcrypto
. Otrigger_default_encryption
verifica o tipo de criptografia para conferir se/data
está criptografado com ou sem uma senha. - Descriptografar /data
Cria o dispositivo
dm-crypt
no dispositivo de transferência por blocos 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
. Ele cria todos os diretórios ou links necessários e, em seguida, definevold.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. - Iniciar framework
Agora o framework inicializa todos os serviços usando o
/data
descriptografado, e o sistema está pronto para uso.
Iniciar um dispositivo criptografado sem a 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
Detecte se o dispositivo Android está criptografado porque a flag
ro.crypto.state = "encrypted"
vold
definevold.decrypt
comotrigger_restart_min_framework
porque/data
é criptografado 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 senha
O framework é iniciado e percebe 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 ela estiver definida, o processo de criptografia será interrompido e não haverá 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 IU verifica a senha enviando o comandocryptfs checkpw
paravold
. Se a senha estiver correta, o que é determinado pela ativação e desativação do/data
descriptografado em um local temporário,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
Em seguida,
vold
monta a partição/data
real descriptografada e prepara a nova partição, que pode nunca ter sido preparada se ela tivesse sido criptografada com a opção de exclusão permanente, que não é compatível com a primeira versão. Ele define a propriedadevold.post_fs_data_done
como 0 e, em seguida,vold.decrypt
comotrigger_post_fs_data
. Isso faz com queinit.rc
execute os comandospost-fs-data
. Ele cria todos os diretórios ou links necessários e definevold.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 serviços na classemain
novamente e também inicie serviços na classelate_start
pela primeira vez desde a inicialização. - Iniciar o 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 dispositivo criptografado com uma senha
- Montar tmpfs
- Iniciar framework para solicitar 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 incorreta 30 vezes
Se esses erros não forem resolvidos, solicite que o usuário faça a exclusão permanente para a configuração original:
Se vold
detectar um erro durante o processo de criptografia e se nenhum dado tiver sido destruído ainda 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 informa que o processo de criptografia
nunca foi iniciado. Se o erro ocorrer depois que o framework for removido, mas
antes que a interface da barra de progresso esteja ativa, vold
vai reinicializar 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 vai 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 o sal para produzir a chave intermediária 1 de 32 bytes (IK1).
- Preencha o IK1 com zero bytes para o tamanho da chave privada vinculada a hardware (HBK). Especificamente, preenchemos como: 00 || IK1 || 00..00; um byte zero, 32 IK1 bytes, 223 zero bytes.
- Assine o IK1 preenchido com HBK para produzir o IK2 de 256 bytes.
- Aplique o scrypt ao IK2 e um sal (o mesmo sal da etapa 2) para produzir o IK3 de 32 bytes.
- Usar 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 do 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-o.
Caso contrário, defina vold.decrypt como trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
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 por 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 por vold para iniciar a
interface da barra de progresso para criptografia ou
solicitar 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 exibir 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 a configuração original. |
vold.encrypt_progress error_reboot_failed |
A interface da barra de progresso vai mostrar uma mensagem informando que a criptografia foi concluída e oferecer ao usuário um botão para reinicializar o dispositivo. Esse erro não deve acontecer. |
vold.encrypt_progress error_not_encrypted |
A interface da barra de progresso precisa exibir 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, então não está claro quem responde a esse erro. E isso nunca deveria acontecer de qualquer maneira. |
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 init
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 este sistema está sendo executado com um /data ro.crypto.state encrypted
não criptografado. Definido por init para informar
que este sistema está sendo executado com um /data criptografado. |
|
Essas cinco propriedades são definidas por init quando ele tenta ativar /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 ativar o sistema de arquivos /data 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