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 serem confirmados no disco, e todas as leituras descriptografam os dados automaticamente antes de serem retornados ao processo de chamada.

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

  • Criou uma criptografia rápida, que criptografa apenas os blocos usados na partição de dados. 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.
  • Adição de forceencrypt flag fstab para criptografar na primeira inicialização.
  • Inclusão de suporte a padrões e criptografia sem senha.
  • Adição de armazenamento protegido por hardware da chave de criptografia usando Confiável Capacidade de assinatura do ambiente de execução (TEE), como em um TrustZone. Consulte Como armazenar a chave criptografada para mais informações detalhes.

Cuidado:dispositivos que fizeram upgrade para o Android 5.0 e, em seguida, criptografados podem ser devolvidos a um estado não criptografado ao redefinir para a configuração original. Novo Android 5.0 dispositivos 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 kernel que funciona na camada de dispositivos de blocos. Devido ao isso, a criptografia funciona com o Embedded MultiMediaCard (eMMC) e dispositivos flash semelhantes que se apresentam ao kernel como blocos dispositivos. 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. Você deve usar 128 bits ou mais para a chave (com 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 um PIN/senha ou senha no dispositivo, apenas a chave de 128 bits são recriptografados e armazenados. Por exemplo, mudanças de PIN/senha/padrão do usuário NÃO causam a recriptografia dos dados do usuário. Observe que dispositivo gerenciado podem estar sujeitos 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 recursos de criptografia em vold, o sistema usa a ferramenta de linha de comando Comandos cryptfs de vdc: checkpw, restart, enablecrypto, changepw, cryptocomplete, verifypw e setfield, getfield, mountdefaultencrypted, getpwtype getpw e clearpw.

Para criptografar, descriptografar ou excluir permanentemente /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 dados se 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 precisa estar em um destes três grupos: core, main e late_start

  • core: nunca é encerrado após a inicialização.
  • main: encerre e reinicie após inserir a senha do disco.
  • 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 sinalização SVC_DISABLED. Os serviços interrompidos não respondem a class_start.

Fluxos

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

  • Criptografe um dispositivo não criptografado anteriormente:
    • 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).
  • Inicialize um dispositivo criptografado:
    • Inicializar um dispositivo criptografado sem senha: inicializar um dispositivo criptografado que não tenha uma senha definida (relevante para dispositivos com Android 5.0 ou superior).
    • 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 ao criptografar /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.

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

    O /data não está criptografado, mas precisa ser porque o forceencrypt exige isso. Desconecte /data.

  2. Começar a criptografar /data

    vold.decrypt = "trigger_encryption" aciona init.rc, o que faz com que vold criptografe /data sem senha. Nenhum é definido porque este deve ser um novo dispositivo.

  3. Montar tmpfs

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

  4. Mostrar o framework para mostrar o progresso

    Como o dispositivo praticamente não tem dados para criptografar, a barra de progresso não aparecem com frequência porque a criptografia acontece muito rapidamente. Consulte Criptografar um dispositivo existente para mais detalhes sobre a interface de progresso.

  5. Quando /data estiver criptografado, remova o framework

    vold define vold.decrypt como trigger_default_encryption, que inicia o serviço defaultcrypto. Isso inicia o fluxo abaixo para a montagem de os dados do usuário criptografados 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.

  6. Montar /data

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

  7. Iniciar framework

    vold define vold.decrypt como trigger_restart_framework, que continua a inicialização normal de desenvolvimento de software.

Criptografar um dispositivo existente

Isso é o que acontece quando você criptografa um dispositivo Android K ou anterior que foi migrado para L.

Esse processo é iniciado pelo usuário e é chamado de "criptografia no local" o 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 durante a criptografia, os dados dos arquivos são deixados em um estado parcialmente criptografado. O dispositivo deve para a configuração original e todos os dados serão perdidos.

Para ativar a criptografia no local, o vold inicia uma repetição para ler cada específico do dispositivo em bloco real e gravá-lo ao dispositivo de bloqueio de criptografia. O vold verifica se um setor está em antes de ler e gravar, o que facilita a criptografia de dados muito mais rápido em um novo dispositivo com pouco ou nenhum dado.

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

  1. Verificar senha

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

  2. 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 propriedade vold.decrypt será definida como trigger_shutdown_framework. Isso faz com que init.rc interrompa os serviços nas classes late_start e main.

  3. Criar um rodapé de criptografia
  4. Criar um arquivo de migas de pão
  5. Reinicializar
  6. Detectar arquivo de navegação estrutural
  7. 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. O vold cria e grava os metadados de criptografia.

  8. Durante a criptografia, ative o tmpfs

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

  9. Exibir a estrutura para mostrar o progresso

    trigger_restart_min_framework faz com que init.rc iniciar a classe de serviços main. Quando o framework percebe que vold.encrypt_progress é definido como 0, e a barra de progresso é mostrada. UI, que consulta essa propriedade a cada cinco segundos e atualiza uma barra de progresso. O loop de criptografia atualiza o vold.encrypt_progress sempre que ele criptografa outro percentual da partição.

  10. Atualize o rodapé de criptografia quando o /data for criptografado

    Quando /data for criptografado, o vold será apagado a flag ENCRYPTION_IN_PROGRESS nos metadados.

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

    Se a reinicialização falhar por algum motivo, vold vai definir a propriedade vold.encrypt_progress como error_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 em nenhum momento.

Iniciar 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 senha. Portanto, esse é o estado de criptografia padrão.

  1. Detectar /data criptografado sem senha

    Detectar se o dispositivo Android está criptografado porque /data não pode ser montado e uma das sinalizações encryptable ou forceencrypt foi definido.

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

  2. Descriptografar /data

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

  3. Montar /dados

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

    Quando vold encontra o 1 nessa propriedade, ele define a propriedade vold.decrypt como: trigger_restart_framework.. Isso faz com que 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 framework

    Agora, o framework inicializa todos os serviços usando a /data descriptografada. 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.

  1. Detectar dispositivo criptografado com uma senha

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

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

  2. Montar tmpfs

    init define cinco propriedades para salvar as opções de montagem iniciais. dado para /data com parâmetros transmitidos de init.rc. O 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 de 8 dígitos ASCII precedido por 0x)
  3. Iniciar framework para solicitar senha

    O framework é iniciado e verifica que vold.decrypt está definido como trigger_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 para vold. vold retorna 0 se a criptografia tiver sido concluída, -1 em caso de erro interno ou -2 se a criptografia não for concluída. O vold determina isso procurando a flag CRYPTO_ENCRYPTION_IN_PROGRESS nos metadados de criptografia. Se ela estiver definida, o processo de criptografia foi interrompido, e não dados utilizáveis no dispositivo. Se vold retornar um erro, a interface deverá exibirá uma mensagem ao usuário para reinicializar e redefinir o dispositivo para a configuração original e conceder ao usuário um botão para pressionar.

  4. Descriptografar dados com senha

    Quando cryptfs cryptocomplete for bem-sucedido, o framework exibe uma IU solicitando a senha do disco. A interface 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 a desmontagem), vold vai salvar o nome do dispositivo de bloco descriptografado na propriedade ro.crypto.fs_crypto_blkdev e retornar o status 0 para a interface. Se o a senha estiver incorreta, ele retornará -1 para a interface.

  5. Framework de interrupção

    A interface mostra um gráfico de inicialização criptográfica e chama vold com o comando cryptfs restart. vold define a propriedade. vold.decrypt para trigger_reset_main, o que faz init.rc para class_reset main. Esta ação interrompe todos os serviços na classe principal, o que permite que o /data de tmpfs seja desconectado.

  6. 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 foi criptografada com a opção "Limpar", que não é aceita nas lançamento). Ele define a propriedade vold.post_fs_data_done como 0 e depois define vold.decrypt como trigger_post_fs_data. Isso faz com que init.rc para executar os comandos post-fs-data. Eles criar quaisquer diretórios ou links necessários e, em seguida, definir vold.post_fs_data_done para 1. Quando vold encontra o 1 nessa propriedade, ele define a propriedade vold.decrypt como trigger_restart_framework. Isso faz com que o init.rc seja iniciado serviços na classe main novamente e também iniciam serviços na classe late_start pela primeira vez desde a inicialização.

  7. Iniciar o framework completo

    Agora, o framework inicializa todos os serviços usando a /data descriptografada. do sistema e ele 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 de inicialização:

  1. Detectar dispositivo criptografado com uma senha
  2. Montar tmpfs
  3. 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 ao usuário que faça uma redefinição de fábrica:

Se o vold detectar um erro durante o processo de criptografia e se nenhum dado foi destruído ainda e o framework está ativo, vold define a propriedade vold.encrypt_progress para 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 a estrutura for desativada, mas antes que a interface da barra de progresso fique ativa, o vold reinicializa o sistema. Se a reinicialização falhar, ela definirá vold.encrypt_progress como error_shutting_down e retorna -1; mas não haverá nada para detectar o erro. Isso não é esperado.

Se o vold detectar um erro durante o processo de criptografia, ele definirá De vold.encrypt_progress a error_partially_encrypted e retorna -1. A interface vai mostrar uma mensagem informando que a criptografia falhou e forneça 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 a capacidade de assinatura do ambiente de execução confiável (TEE). Antes, criptografamos a chave mestra com uma chave gerada aplicando scrypt à senha do usuário e ao sal armazenado. Para tornar a chave resiliente contra ataques prontos para uso, 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:

  1. Gere uma chave de criptografia de disco (DEK, na sigla em inglês) aleatória e com um sal de 16 bytes.
  2. Aplique o scrypt à senha do usuário e o sal para produzir um intermediário de 32 bytes chave 1 (IK1).
  3. 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 IK1 bytes, 223 de zero bytes.
  4. Assine o IK1 preenchido com HBK para produzir o IK2 de 256 bytes.
  5. Aplique o scrypt ao IK2 e um sal (o mesmo sal da etapa 2) para produzir o IK3 de 32 bytes.
  6. Usar os primeiros 16 bytes de IK3 como KEK e os últimos 16 bytes como IV.
  7. 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 alterar ou remover a senha nas configurações, a interface envia do comando cryptfs changepw para vold; vold recriptografa a chave mestra do disco com a nova senha.

Propriedades de criptografia

vold e init se comunicam entre si pela de configuração do Terraform. 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. 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 iniciar, Se esta propriedade estiver definida, insira o 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, então não está claro quem responde para este 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 uma /data ro.crypto.state encrypted. Definido por init para informar que o sistema está em execução 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 init quando tenta montar /data com parâmetros transmitidos da init.rc O vold usa isso 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