Criptografia de disco completo

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 enviá-los para o disco e todas as leituras descriptografam os dados automaticamente antes de devolvê-los ao processo de chamada.

A criptografia de disco completo foi introduzida no Android na versão 4.4, mas o Android 5.0 introduziu esses novos recursos:

  • Criou criptografia rápida, que criptografa apenas blocos usados ​​na partição de dados para evitar que a primeira inicialização demore muito. Apenas os sistemas de arquivos ext4 e f2fs atualmente suportam criptografia rápida.
  • Adicionado o forceencrypt fstab para criptografar na primeira inicialização.
  • Adicionado suporte para padrões e criptografia sem senha.
  • Adicionado armazenamento com suporte de hardware da chave de criptografia usando o recurso de assinatura do Trusted Execution Environment (TEE) (como em uma TrustZone). Consulte Armazenando a chave criptografada para obter mais detalhes.

Cuidado: os dispositivos atualizados para o Android 5.0 e, em seguida, criptografados podem retornar a um estado não criptografado pela redefinição de dados de fábrica. Novos dispositivos Android 5.0 criptografados na primeira inicialização não podem retornar 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 causa disso, a criptografia funciona com o 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 é 128 Advanced Encryption Standard (AES) com encadeamento de blocos de cifra (CBC) e ESSIV:SHA256. A chave mestra é criptografada com AES de 128 bits por meio de chamadas para a biblioteca OpenSSL. Você deve usar 128 bits ou mais para a chave (sendo 256 opcionais).

Observação: os OEMs podem usar 128 bits ou superior para criptografar a chave mestra.

Na versão Android 5.0, existem quatro tipos de estados de criptografia:

  • predefinição
  • ALFINETE
  • senha
  • padronizar

Na primeira inicialização, o dispositivo cria uma chave mestra de 128 bits gerada aleatoriamente e, em seguida, faz 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 meio de um TEE (como TrustZone), que usa um hash da assinatura para criptografar a chave mestra.

Você pode encontrar 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 é criptografada e armazenada novamente. (ou seja, as alterações do PIN/pass/padrão do usuário NÃO causam a recriptografia dos dados do usuário.) Observe que 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 em init. Outras partes do sistema também analisam as propriedades para realizar tarefas como relatar o status, solicitar uma senha ou solicitar a redefinição de fábrica no caso de um erro fatal. Para invocar recursos de criptografia em vold , o sistema usa os comandos checkpw da ferramenta de linha de comando vdc : cryptfs , restart , enablecrypto , changepw , cryptocomplete , verifypw , setfield , getfield , mountdefaultencrypted , getpwtype , getpw e clearpw .

Para criptografar, descriptografar ou limpar /data , /data não deve ser montado. No entanto, para mostrar qualquer interface do usuário (UI), a estrutura deve ser iniciada e a estrutura requer que /data seja executado. Para resolver esse enigma, 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. Ele impõe a limitação de que, para alternar do sistema de arquivos temporário para o sistema de arquivos /data verdadeiro, o sistema deve interromper todos os processos com arquivos abertos no sistema de arquivos temporário e reiniciar esses processos no sistema de arquivos /data real. Para fazer isso, todos os serviços devem estar em um dos três grupos: core , main e late_start .

  • core : Nunca desligue depois de iniciar.
  • main : Desligue e reinicie depois que a senha do disco for inserida.
  • late_start : Não inicia até que /data tenha sido descriptografado e montado.

Para acionar essas ações, a propriedade vold.decrypt é configurada para várias strings . Para matar 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 um sinalizador SVC_DISABLED . Os serviços interrompidos não respondem a class_start .

Fluxos

Há quatro fluxos para um dispositivo criptografado. Um dispositivo é criptografado apenas uma vez e segue um fluxo de inicialização normal.

  • Criptografe um dispositivo não criptografado anteriormente:
    • Criptografe um novo dispositivo com forceencrypt : Criptografia obrigatória na primeira inicialização (começando no Android L).
    • Criptografe um dispositivo existente: criptografia iniciada pelo usuário (Android K e versões anteriores).
  • Inicialize um dispositivo criptografado:
    • Iniciando um dispositivo criptografado sem senha: Inicializando um dispositivo criptografado sem senha definida (relevante para dispositivos que executam o Android 5.0 e posterior).
    • Iniciando um dispositivo criptografado com uma senha: Inicializando um dispositivo criptografado com uma senha definida.

Além desses fluxos, o dispositivo também pode falhar ao criptografar /data . Cada um dos fluxos é explicado em detalhes a seguir.

Criptografe um novo dispositivo com forceencrypt

Esta é a primeira inicialização normal para um dispositivo Android 5.0.

  1. Detectar sistema de arquivos não criptografado com sinalizador forceencrypt

    /data não é criptografado, mas precisa ser porque forceencrypt o exige. Desmontar /data .

  2. Comece a criptografar /data

    vold.decrypt = "trigger_encryption" aciona init.rc , que fará com que vold criptografe /data sem senha. (Nenhum está definido porque este deve ser um novo dispositivo.)

  3. Monte tmpfs

    vold monta um tmpfs /data (usando as opções tmpfs de ro.crypto.tmpfs_options ) e define a propriedade vold.encrypt_progress como 0. vold prepara o tmpfs /data para inicializar um sistema criptografado e define a propriedade vold.decrypt como: trigger_restart_min_framework

  4. Traga a estrutura para mostrar o progresso

    Como o dispositivo praticamente não tem dados para criptografar, a barra de progresso geralmente não aparece porque a criptografia acontece muito rapidamente. Consulte Criptografar um dispositivo existente para obter mais detalhes sobre a interface do usuário de progresso.

  5. Quando /data é criptografado, desative a estrutura

    vold define vold.decrypt para trigger_default_encryption que inicia o serviço defaultcrypto . (Isso inicia o fluxo abaixo para montar um userdata criptografado padrão.) trigger_default_encryption verifica o tipo de criptografia para ver 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 nenhuma senha definida; portanto, descriptografamos e montamos /data .

  6. Montar /data

    init então monta /data em um tmpfs RAMDisk usando parâmetros que ele pega de ro.crypto.tmpfs_options , que é definido em init.rc .

  7. Iniciar estrutura

    Defina vold como trigger_restart_framework , que continua o processo de inicialização usual.

Criptografar um dispositivo existente

Isso é o que 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 local” no código. Quando um usuário opta por criptografar um dispositivo, a interface do usuário garante que a bateria esteja totalmente carregada e que o adaptador 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 deve ser redefinido de fábrica e todos os dados são perdidos.

Para habilitar a criptografia inplace, o vold inicia um loop para ler cada setor do dispositivo de bloco real e, em seguida, gravá-lo no dispositivo de bloco de criptografia. vold verifica se um setor está em uso antes de lê-lo e gravá-lo, o que torna a criptografia muito mais rápida em um novo dispositivo que possui pouco ou nenhum dado.

Estado do dispositivo : Defina ro.crypto.state = "unencrypted" e execute o gatilho on nonencrypted init não criptografado para continuar a inicialização.

  1. Verifique a senha

    A interface do usuário chama vold com o comando cryptfs enablecrypto inplace onde passwd é a senha da tela de bloqueio do usuário.

  2. Derrube o quadro

    vold verifica se há erros, retorna -1 se não puder criptografar e imprime um motivo no log. Se puder criptografar, definirá a propriedade vold.decrypt como trigger_shutdown_framework . Isso faz com que o init.rc pare os serviços nas classes late_start e main .

  3. Criar um rodapé de criptografia
  4. Criar um arquivo breadcrumb
  5. Reinício
  6. Detectar arquivo breadcrumb
  7. Comece a criptografar /data

    vold então configura o mapeamento de criptografia, que cria um dispositivo de bloco de criptografia virtual que mapeia para o dispositivo de bloco real, mas criptografa cada setor à medida que é gravado e descriptografa cada setor à medida que é lido. vold então cria e grava os metadados de criptografia.

  8. Enquanto estiver criptografando, monte tmpfs

    vold monta um tmpfs /data (usando as opções tmpfs de ro.crypto.tmpfs_options ) e define a propriedade vold.encrypt_progress como 0. vold prepara o tmpfs /data para inicializar um sistema criptografado e define a propriedade vold.decrypt como: trigger_restart_min_framework

  9. Traga a estrutura para mostrar o progresso

    trigger_restart_min_framework faz com que o init.rc inicie a classe main de serviços. Quando a estrutura vê que vold.encrypt_progress está definido como 0, ela exibe a interface do usuário da barra de progresso, que consulta essa propriedade a cada cinco segundos e atualiza uma barra de progresso. O loop de criptografia atualiza vold.encrypt_progress toda vez que criptografa outra porcentagem da partição.

  10. Quando /data é criptografado, atualize o rodapé de criptografia

    Quando /data é criptografado com sucesso, vold limpa o sinalizador ENCRYPTION_IN_PROGRESS nos metadados.

    Quando o dispositivo é desbloqueado com sucesso, a senha é usada para criptografar a chave mestra e o rodapé de criptografia é atualizado.

    Se a reinicialização falhar por algum motivo, vold define a propriedade vold.encrypt_progress como error_reboot_failed e a interface do usuário deve exibir uma mensagem solicitando que o usuário pressione um botão para reinicializar. Não se espera que isso ocorra.

Iniciando um dispositivo criptografado com criptografia padrão

Isso é o que 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 e, portanto, esse é o estado de criptografia padrão .

  1. Detectar /data criptografados sem senha

    Detecta que o dispositivo Android está criptografado porque /data não pode ser montado e um dos sinalizadores encryptable ou forceencrypt está definido.

    vold define vold.decrypt como trigger_default_encryption , que inicia o serviço defaultcrypto . trigger_default_encryption verifica o tipo de criptografia para ver se /data está criptografado com ou sem senha.

  2. Descriptografar /dados

    Cria o dispositivo dm-crypt sobre o dispositivo de bloco para que o dispositivo esteja pronto para uso.

  3. Montar/dados

    vold então monta a partição real /data descriptografada e então prepara a nova partição. Ele define a propriedade vold.post_fs_data_done como 0 e, em seguida, define vold.decrypt como trigger_post_fs_data . Isso faz com que o init.rc execute seus comandos post-fs-data . Eles criarão todos os diretórios ou links necessários e, em seguida, vold.post_fs_data_done como 1.

    Uma vez que vold vê o 1 nessa propriedade, ele define a propriedade vold.decrypt como: trigger_restart_framework. Isso faz com que o init.rc inicie os serviços na classe main novamente e também inicie os serviços na classe late_start pela primeira vez desde a inicialização.

  4. Iniciar estrutura

    Agora o framework inicializa todos os seus serviços usando o /data descriptografado e o sistema está pronto para uso.

Iniciando um dispositivo criptografado sem criptografia padrão

Isso é o que acontece quando você inicializa um dispositivo criptografado que tem uma senha definida. A senha do dispositivo pode ser um pino, padrão ou senha.

  1. Detectar dispositivo criptografado com uma senha

    Detectar que o dispositivo Android está criptografado porque o sinalizador ro.crypto.state = "encrypted"

    vold define vold.decrypt como trigger_restart_min_framework porque /data é criptografado com uma senha.

  2. Monte tmpfs

    init define cinco propriedades para salvar as opções de montagem iniciais fornecidas para /data com parâmetros passados ​​de init.rc . vold usa estas propriedades para configurar o mapeamento de criptografia:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (número hexadecimal ASCII de 8 dígitos precedido por 0x)
  3. Iniciar estrutura para solicitar senha

    A estrutura inicializa e vê que vold.decrypt está definido como trigger_restart_min_framework . Isso informa ao framework que ele está inicializando em um disco tmpfs /data e precisa obter a senha do usuário.

    Primeiro, no entanto, ele precisa ter certeza de que o disco foi criptografado corretamente. Ele envia o comando cryptfs cryptocomplete para vold . vold retorna 0 se a criptografia foi concluída com sucesso, -1 em caso de erro interno ou -2 se a criptografia não foi concluída com sucesso. vold determina isso procurando nos metadados de criptografia pelo sinalizador CRYPTO_ENCRYPTION_IN_PROGRESS . Se estiver definido, o processo de criptografia foi interrompido e não há dados utilizáveis ​​no dispositivo. Se vold retornar um erro, a interface do usuário deve exibir uma mensagem ao usuário para reinicializar e redefinir o dispositivo de fábrica e fornecer ao usuário um botão para pressionar para fazer isso.

  4. Descriptografar dados com senha

    Depois que cryptfs cryptocomplete for bem-sucedido, a estrutura exibirá uma interface do usuário solicitando a senha do disco. A interface do usuário verifica a senha enviando o comando cryptfs checkpw para vold . Se a senha estiver correta (o que é determinado pela montagem bem-sucedida do /data descriptografado em um local temporário e depois desmontado), vold salva o nome do dispositivo de bloco descriptografado na propriedade ro.crypto.fs_crypto_blkdev e retorna o status 0 para a interface do usuário . Se a senha estiver incorreta, ela retornará -1 para a interface do usuário.

  5. Parar estrutura

    A interface do usuário coloca um gráfico de inicialização de criptografia e, em seguida, chama vold com o comando cryptfs restart . vold configura a propriedade vold.decrypt para trigger_reset_main , o que faz com que init.rc faça class_reset main . Isso interrompe todos os serviços na classe principal, o que permite que o tmpfs /data seja desmontado.

  6. Montar /data

    vold então monta a partição real /data descriptografada e prepara a nova partição (que pode nunca ter sido preparada se foi criptografada com a opção de limpeza, que não é suportada na primeira versão). Ele define a propriedade vold.post_fs_data_done como 0 e, em seguida, define vold.decrypt como trigger_post_fs_data . Isso faz com que o init.rc execute seus comandos post-fs-data . Eles irão criar quaisquer diretórios ou links necessários e então definir vold.post_fs_data_done como 1. Uma vez que vold vê o 1 naquela propriedade, ele define a propriedade vold.decrypt como trigger_restart_framework . Isso faz com que o init.rc inicie os serviços na classe main novamente e também inicie os serviços na classe late_start pela primeira vez desde a inicialização.

  7. Iniciar estrutura completa

    Agora, o framework inicializa todos os seus 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 errado por alguns motivos. O dispositivo inicia com a série normal de etapas para inicializar:

  1. Detectar dispositivo criptografado com uma senha
  2. Monte tmpfs
  3. Iniciar estrutura para solicitar senha

Mas depois que a estrutura é aberta, o dispositivo pode encontrar alguns erros:

  • A senha corresponde, mas não pode descriptografar os dados
  • O usuário digita a senha errada 30 vezes

Se esses erros não forem resolvidos, solicite ao usuário que limpe de fábrica :

Se vold detectar um erro durante o processo de criptografia e se nenhum dado tiver sido destruído ainda e a estrutura estiver ativa, vold definirá a propriedade vold.encrypt_progress como error_not_encrypted . A interface do usuário solicita que o usuário reinicialize e os alerta de que o processo de criptografia nunca foi iniciado. Se o erro ocorrer depois que a estrutura for desativada, mas antes que a interface do usuário da barra de progresso esteja ativa, o vold reinicializará o sistema. Se a reinicialização falhar, ele definirá vold.encrypt_progress como error_shutting_down e retornará -1; mas não haverá nada para pegar o erro. Não se espera que isso aconteça.

Se vold detectar um erro durante o processo de criptografia, ele definirá vold.encrypt_progress como error_partially_encrypted e retornará -1. A interface do usuário deve exibir uma mensagem informando que a criptografia falhou e fornecer um botão para o usuário redefinir o dispositivo de fábrica.

Armazenando a chave criptografada

A chave criptografada é armazenada nos metadados de criptografia. O suporte de hardware é implementado usando o recurso de assinatura do Trusted Execution Environment (TEE). Anteriormente, criptografávamos a chave mestra com uma chave gerada pela aplicação de scrypt à senha do usuário e ao sal armazenado. Para tornar a chave resiliente contra ataques off-box, estendemos esse algoritmo assinando a chave resultante com uma chave TEE armazenada. A assinatura resultante é então transformada em uma chave de tamanho apropriado por mais uma aplicação de scrypt. Essa chave é então usada para criptografar e descriptografar a chave mestra. Para armazenar esta chave:

  1. Gere a chave de criptografia de disco (DEK) aleatória de 16 bytes e salt de 16 bytes.
  2. Aplique scrypt à senha do usuário e ao salt para produzir a chave intermediária 1 de 32 bytes (IK1).
  3. Preencher 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.
  4. Sinal acolchoado IK1 com HBK para produzir 256 bytes IK2.
  5. Aplique scrypt a IK2 e salt (mesmo salt da etapa 2) para produzir IK3 de 32 bytes.
  6. Use os primeiros 16 bytes de IK3 como KEK e os últimos 16 bytes como IV.
  7. Criptografe DEK com AES_CBC, com chave KEK e vetor de inicialização IV.

Alterando a senha

Quando um usuário opta por alterar ou remover sua senha nas configurações, a interface do usuário 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 definindo propriedades. Aqui está uma lista de propriedades disponíveis para criptografia.

Propriedades de Vold

Propriedade Descrição
vold.decrypt trigger_encryption Criptografe a unidade sem senha.
vold.decrypt trigger_default_encryption Verifique a unidade para ver se ela está criptografada sem senha. Se for, descriptografe e monte-o, senão defina vold.decrypt para trigger_restart_min_framework.
vold.decrypt trigger_reset_main Definido por vold para desligar a interface do usuário solicitando a senha do disco.
vold.decrypt trigger_post_fs_data Definido por vold para prep /data com os diretórios necessários, et al.
vold.decrypt trigger_restart_framework Definido por vold para iniciar o quadro real e todos os serviços.
vold.decrypt trigger_shutdown_framework Definido por vold para desligar a estrutura completa para iniciar a criptografia.
vold.decrypt trigger_restart_min_framework Definido por vold para iniciar a interface do usuário da barra de progresso para criptografia ou solicitar senha, dependendo do valor de ro.crypto.state .
vold.encrypt_progress Quando a estrutura for inicializada, se esta propriedade estiver configurada, entre no modo de interface do usuário da barra de progresso.
vold.encrypt_progress 0 to 100 A interface do usuário da barra de progresso deve exibir o valor percentual definido.
vold.encrypt_progress error_partially_encrypted A interface do usuário da barra de progresso deve exibir uma mensagem informando que a criptografia falhou e dar ao usuário a opção de redefinir o dispositivo de fábrica.
vold.encrypt_progress error_reboot_failed A interface do usuário da barra de progresso deve exibir uma mensagem informando que a criptografia foi concluída e fornecer ao usuário um botão para reinicializar o dispositivo. Este erro não é esperado para acontecer.
vold.encrypt_progress error_not_encrypted A interface do usuário da barra de progresso deve exibir uma mensagem informando que ocorreu um erro, nenhum dado foi criptografado ou perdido e fornecer ao usuário um botão para reinicializar o sistema.
vold.encrypt_progress error_shutting_down A interface do usuário da barra de progresso não está em execução, portanto, não está claro quem responderá a esse erro. E isso nunca deveria acontecer de qualquer maneira.
vold.post_fs_data_done 0 Definido por vold antes de definir vold.decrypt para trigger_post_fs_data .
vold.post_fs_data_done 1 Definido por init.rc ou init.rc logo após terminar 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 dizer que este sistema está sendo executado com um /data ro.crypto.state encrypted . Definido pelo init para dizer que este sistema está sendo executado com um /data criptografado.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

Essas cinco propriedades são definidas pelo init quando ele tenta montar /data com parâmetros passados ​​de init.rc . vold os usa para configurar o mapeamento de criptografia.
ro.crypto.tmpfs_options Definido pelo init.rc com as opções que o init deve usar ao montar o sistema de arquivos tmpfs /data .

Iniciar ações

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