Estou citando o Manual do Android aqui , mas:
NOTA:
A fonte que usei não é diretamente relevante para o Marshmallow, mas é relevante para o Lollipop e superior.
TL: DR
Vou abordar as perguntas do OP agora. Detalhes técnicos seguirão.
A chave de criptografia padrão vem de uma fonte de hardware (um chip semelhante a um TPM) e a senha padrão do AOSP definida como default_password
no cryptfs.c
arquivo de origem, veja abaixo.
Sim, não apenas o padrão, mas qualquer senha é transformada em uma chave e armazenada em um chip semelhante ao TPM, chamado TEE (abreviação de "Trusted Execution Environment", veja abaixo para obter mais detalhes).
Um hacker com acesso UART / JTAG aos chips no SoC do dispositivo pode tecnicamente obter acesso à chave TEE, ou um kernel personalizado pode vazar essas informações para um hacker. Algumas agências de três letras em teorias da conspiração podem, possivelmente, formar uma parceria com o OEM para obter esses núcleos inseguros usados em dispositivos de produção, mas eu não colocaria muitas lojas nele. Mais uma vez, consulte a última seção desta resposta para obter mais detalhes.
A única coisa que impede um hacker de acessar a chave é a enorme quantidade de esforço necessária para isso.
- A verificação do hash do (checksumming) do firmware (chamado "Inicialização Verificada" do Google) é feita de fato no Lollipop e acima dele por padrão (e está disponível no JellyBean 4.3 em diante), por um módulo do kernel chamado
dm-verity
. No entanto, isso é independente do status de criptografia.
Fonte: Guia de segurança AOSP aqui .
- Sobre o processo envolvido na descriptografia do sistema com uma senha personalizada, veja abaixo. Vou apenas dizer aqui que a senha do usuário está envolvida na criação e no uso da chave de criptografia.
Visão geral
Na primeira inicialização, o dispositivo cria uma chave mestra de 128 bits gerada aleatoriamente e a hash com uma senha padrão e sal armazenado. A senha padrão é: "default_password" No entanto, o hash resultante também é assinado por meio de um TEE (como o TrustZone), que usa um hash da assinatura para criptografar a chave mestra.
Você pode encontrar a senha padrão definida no arquivo cryptfs.c 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, alterações de PIN / senha / padrão do usuário NÃO causam re-criptografia da partição de dados do usuário.)
Iniciando um dispositivo criptografado com criptografia padrão
É 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 definida e, portanto, este é o estado de criptografia padrão.
- Detectar dados criptografados / sem senha
Detecte 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 defaultcrypto
serviço. trigger_default_encryption
verifica o tipo de criptografia para ver se / data está criptografado com ou sem uma senha.
- Descriptografar / dados
Cria o dm-crypt
dispositivo sobre o dispositivo de bloco para que ele esteja pronto para uso.
- Montagem / dados
vold
monta a partição real / de dados descriptografada e 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 init.rc
com que seus post-fs-data
comandos sejam executados . Eles criarão os diretórios ou links necessários e depois serão definidos vold.post_fs_data_done
como 1
.
Uma vez que vold
vê a 1 em que a propriedade, ele define a propriedade vold.decrypt
de: trigger_restart_framework
. Isso faz init.rc
com que iniciar serviços na classe main
novamente e também iniciar serviços na classe late_start pela primeira vez desde a inicialização.
- Iniciar estrutura
Agora, a estrutura inicializa todos os seus serviços usando os dados descriptografados / e o sistema está pronto para uso.
Iniciando um dispositivo criptografado sem criptografia padrão
É o que acontece quando você inicializa um dispositivo criptografado com uma senha definida. A senha do dispositivo pode ser um alfinete, padrão ou senha.
- Detectar dispositivo criptografado com uma senha
Detecte que o dispositivo Android está criptografado porque o sinalizador ro.crypto.state = "encrypted"
vold
conjuntos vold.decrypt
para trigger_restart_min_framework
porque os dados / é criptografado com uma senha.
- Mount tmpfs
init
define cinco propriedades para salvar as opções de montagem inicial fornecidas para / data com parâmetros passados de init.rc
. vold
usa essas propriedades para configurar o mapeamento criptográfico:
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 ASCII de 8 dígitos, precedido por 0x)
- Iniciar estrutura para solicitar senha
A estrutura inicia e vê que vold.decrypt
está definido como trigger_restart_min_framework
. Isso informa à estrutura que ele está inicializando em um tmpfs /data
disco e precisa obter a senha do usuário.
Primeiro, no entanto, ele precisa garantir que o disco esteja criptografado corretamente. Ele envia o comando cryptfs cryptocomplete
para vold
. vold
retorna 0 se a criptografia foi concluída com êxito, -1 em erro interno ou -2 se a criptografia não foi concluída com êxito. vold
determina isso procurando nos metadados criptográficos do CRYPTO_ENCRYPTION_IN_PROGRESS
sinalizador. 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 deverá exibir uma mensagem para o usuário reiniciar e redefinir o dispositivo de fábrica e dar ao usuário um botão para pressionar.
- Descriptografar dados com senha
Uma vez cryptfs cryptocomplete
bem-sucedido, a estrutura exibe 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 (que é determinada montando com êxito o descriptografado /data
em um local temporário e desmontando-o), o 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 à interface do usuário.
- Parar estrutura
Os puts UI até um gráfico de boot de criptografia e depois chama vold com o comando cryptfs restart
. vold
define a propriedade vold.decrypt
como trigger_reset_main
, o que causa init.rc
isso class_reset main
. Isso interrompe todos os serviços da main
classe, o que permite tmpfs /data
que seja desmontado.
- Montagem / dados
vold
depois monta a /data
partição real descriptografada e prepara a nova partição (que talvez nunca tenha sido preparada se foi criptografada com a opção de limpeza, que não é suportada no primeiro release). Ele define a propriedade vold.post_fs_data_done
como 0
e, em seguida, define vold.decrypt
como trigger_post_fs_data
. Isso faz init.rc
com que seja executado post-fs-data commands
. Eles criarão os diretórios ou links necessários e depois serão definidos vold.post_fs_data_done
como 1
. Depois de vold
ver o 1
nessa propriedade, ele define a propriedade vold.decrypt
como trigger_restart_framework
. Isso faz init.rc
com que os serviços em classe sejam iniciados main
novamente e também os serviços em classe late_start
pela primeira vez desde a inicialização.
- Iniciar estrutura completa
Agora, a estrutura inicializa todos os seus serviços usando o sistema de arquivos descriptografado / de dados e o sistema está pronto para uso.
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 aplicando scrypt
a senha do usuário e o sal armazenado.
Para tornar a chave resiliente contra ataques externos, estendemos esse algoritmo assinando a chave resultante com uma chave TEE armazenada. A assinatura resultante é então transformada em uma chave de tamanho apropriada por mais uma aplicação de scrypt
. Essa chave é usada para criptografar e descriptografar a chave mestra. Para armazenar esta chave:
- Gere chave de criptografia de disco (DEK) aleatória de 16 bytes e sal de 16 bytes.
- Aplique
scrypt
à senha do usuário e ao salt para produzir a chave intermediária 1 de 32 bytes (IK1).
- Almofada IK1 com zero bytes para o tamanho da chave privada ligada ao hardware (HBK). Especificamente, preenchemos como: 00 || IK1 || 00..00; um byte zero, 32 bytes IK1, 223 bytes zero.
- Assine IK1 acolchoado com HBK para produzir IK2 de 256 bytes.
- Aplique
scrypt
no IK2 e no sal (o mesmo sal que na 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 DEK com AES_CBC, com chave KEK e vetor de inicialização IV.