La crittografia dell'intero disco è il processo di codifica di tutti i dati utente su un dispositivo Android mediante una chiave criptata. Una volta criptato un dispositivo, tutti i dati creati dall'utente vengono criptati automaticamente prima di essere confermati su disco e tutte le letture decriptano automaticamente i dati prima di restituirli al processo di chiamata.
La crittografia completa del disco è stata introdotta in Android 4.4, ma Android 5.0 ha introdotto queste nuove funzionalità:
- È stata creata la crittografia rapida, che cripta solo i blocchi utilizzati nella partizione dei dati per evitare che il primo avvio richieda molto tempo. Al momento, solo i file system ext4 e f2fs supportano la crittografia rapida.
- È stato aggiunto il
forceencrypt
flag fstab per la crittografia al primo avvio. - È stato aggiunto il supporto per le sequenze e la crittografia senza password.
- È stata aggiunta la memorizzazione basata su hardware della chiave di crittografia utilizzando la funzionalità di firma del Trusted Execution Environment (TEE), ad esempio in una TrustZone. Per ulteriori dettagli, consulta Archiviazione della chiave criptata.
Attenzione: i dispositivi di cui è stato eseguito l'upgrade ad Android 5.0 e poi la crittografia possono essere ripristinati a uno stato non criptato tramite il ripristino dei dati di fabbrica. I nuovi dispositivi Android 5.0 criptati al primo avvio non possono essere ripristinati a uno stato non criptato.
Come funziona la crittografia completa del disco di Android
La crittografia completa del disco di Android si basa su dm-crypt
, una funzionalità del kernel che funziona a livello di blocco del dispositivo. Per questo motivo, la crittografia funziona con Embedded MultiMediaCard (eMMC) e dispositivi flash simili che si presentano al kernel come dispositivi di blocco. La crittografia non è possibile con YAFFS, che comunica direttamente con un chip flash NAND non elaborato.
L'algoritmo di crittografia è Advanced Encryption Standard (AES) a 128 bit con chaining di blocchi di crittografia (CBC) ed ESSIV:SHA256. La chiave master viene criptata con AES a 128 bit tramite chiamate alla libreria OpenSSL. Devi utilizzare almeno 128 bit per la chiave (256 sono facoltativi).
Nota:gli OEM possono utilizzare 128 bit o più per criptare la chiave master.
In Android 5.0 esistono quattro tipi di stati della crittografia:
- predefinito
- PIN
- password
- pattern
Al primo avvio, il dispositivo crea una chiave master di 128 bit generata in modo casuale, quindi la sottopone ad hashing con una password predefinita e un valore salt memorizzato. La password predefinita è: "default_password" Tuttavia, l'hash risultante viene firmato anche tramite un TEE (come TrustZone), che utilizza un hash della firma per criptare la chiave master.
Puoi trovare la password predefinita definita nel file cryptfs.cpp del progetto Android Open Source.
Quando l'utente imposta il PIN/la pass o la password sul dispositivo, solo la chiave di 128 bit viene sottoposta a nuova crittografia e memorizzata. (ad es. le modifiche al PIN/alla password/al pattern dell'utente NON causano la nuova crittografia dei dati utente). Tieni presente che il dispositivo gestito potrebbe essere soggetto a limitazioni di PIN, sequenza o password.
La crittografia è gestita da init
e vold
.
init
chiama vold
e vold imposta le proprietà per attivare gli eventi in init. Altre parti del sistema esaminano anche le proprietà per svolgere attività come controllare lo stato dei report, chiedere una password o richiedere il ripristino dei dati di fabbrica in caso di errore fatale. Per richiamare
le funzionalità di crittografia in vold
, il sistema utilizza i comandi cryptfs
dello strumento da riga di comando
vdc
: checkpw
,
restart
, enablecrypto
, changepw
,
cryptocomplete
, verifypw
, setfield
,
getfield
, mountdefaultencrypted
, getpwtype
,
getpw
e clearpw
.
Per criptare, decriptare o cancellare i dati di /data
, /data
non deve essere montato. Tuttavia, per mostrare qualsiasi interfaccia utente (UI), il framework deve essere avviato e richiede l'esecuzione di /data
. Per risolvere questo problema, viene montato un file system temporaneo su /data
.
In questo modo Android può richiedere le password, mostrare l'avanzamento o suggerire un wipe dei dati, se necessario. Tuttavia, impone la limitazione che, per passare dal file system temporaneo al file system /data
reale, il sistema deve interrompere ogni processo con file aperti sul file system temporaneo e riavviare queste procedure sul file system /data
reale. Per farlo, tutti i servizi devono appartenere a uno dei tre gruppi: core
, main
e late_start
.
core
: non arrestarsi mai dopo l'avvio.main
: dopo aver inserito la password del disco, arresta e riavvia il sistema.late_start
: non si avvia finché/data
non è stato decriptato e montato.
Per attivare queste azioni, la proprietà vold.decrypt
è impostata su diverse stringhe.
Per uccidere e riavviare i servizi, i comandi init
sono:
class_reset
: arresta un servizio, ma ne consente il riavvio con class_start.class_start
: riavvia un servizio.class_stop
: arresta un servizio e aggiunge un flagSVC_DISABLED
. I servizi arrestati non rispondono aclass_start
.
Flussi
Esistono quattro flussi per un dispositivo criptato. Un dispositivo viene criptato una sola volta e poi segue un normale flusso di avvio.
- Criptare un dispositivo non criptato in precedenza:
- Crittografa un nuovo dispositivo con
forceencrypt
: crittografia obbligatoria al primo avvio (a partire da Android L). - Crittografare un dispositivo esistente: crittografia avviata dall'utente (Android K e versioni precedenti).
- Crittografa un nuovo dispositivo con
- Avvia un dispositivo criptato:
- Avvio di un dispositivo criptato senza password: avvio di un dispositivo criptato per il quale non è stata impostata una password (rilevante per i dispositivi con Android 5.0 e versioni successive).
- Avvio di un dispositivo criptato con una password: avvio di un dispositivo criptato con una password impostata.
Oltre a questi flussi, il dispositivo potrebbe anche non riuscire a criptare /data
.
Ciascun flusso è descritto in dettaglio di seguito.
Criptare un nuovo dispositivo con forceencrypt
Si tratta del normale primo avvio di un dispositivo con Android 5.0.
- Rileva il file system non criptato con il flag
forceencrypt
/data
non è criptato, ma deve esserlo perchéforceencrypt
lo richiede. Smonta/data
. - Avvia la crittografia
/data
vold.decrypt = "trigger_encryption"
attivainit.rc
, che fa sì chevold
cripta/data
senza password. Non è impostato alcun valore perché si tratta di un nuovo dispositivo. - Montare tmpfs
vold
monta un file system tmpfs/data
(utilizzando le opzioni tmpfs diro.crypto.tmpfs_options
) e imposta la proprietàvold.encrypt_progress
su 0.vold
prepara il file tmpfs/data
per l'avvio di un sistema criptato e imposta la proprietàvold.decrypt
su:trigger_restart_min_framework
- Mostrare il framework per mostrare l'avanzamento
Poiché il dispositivo non ha praticamente dati da criptare, la barra di avanzamento non viene visualizzata spesso perché la crittografia avviene molto rapidamente. Per ulteriori dettagli sull'interfaccia utente di avanzamento, consulta Eseguire la crittografia di un dispositivo esistente.
- Quando
/data
è criptato, rimuovi il frameworkvold
impostavold.decrypt
sutrigger_default_encryption
, che avvia il serviziodefaultcrypto
. (Questo avvia il flusso riportato di seguito per il montaggio di userdata criptato predefinito.)trigger_default_encryption
controlla il tipo di crittografia per verificare se/data
è criptato con o senza una password. Poiché i dispositivi Android 5.0 sono criptati al primo avvio, non dovrebbe essere impostata alcuna password. Pertanto, decrittografiamo e montiamo/data
. - Monta
/data
init
monta quindi/data
su un RAMDisk tmpfs utilizzando parametri acquisiti daro.crypto.tmpfs_options
, impostato ininit.rc
. - Framework di avvio
vold
impostavold.decrypt
sutrigger_restart_framework
, che continua il normale processo di avvio.
Criptare un dispositivo esistente
Questo accade quando esegui la crittografia di un dispositivo Android K o precedente non criptato di cui è stata eseguita la migrazione a L.
Questa procedura viene avviata dall'utente ed è indicata come "crittografia in situ" nel codice. Quando un utente seleziona l'opzione di crittografia di un dispositivo, l'interfaccia utente si assicura che la batteria sia completamente carica e che l'alimentatore CA sia collegato in modo che l'alimentazione sia sufficiente per completare la procedura di crittografia.
Avviso:se il dispositivo si scarica e si spegne prima del completamento della crittografia, i dati dei file rimangono in uno stato di crittografia parziale. Il dispositivo deve essere sottoposto a un ripristino dei dati di fabbrica e tutti i dati andranno persi.
Per attivare la crittografia in situ, vold
avvia un ciclo per leggere ogni settore del dispositivo di blocco reale e poi scriverlo nel dispositivo di blocco crittografico. vold
controlla se un settore è in uso prima di leggerlo e scriverlo, il che rende la crittografia molto più veloce su un nuovo dispositivo con pochi o nessun dato.
Stato del dispositivo: imposta ro.crypto.state = "unencrypted"
ed esegui l'attivatore on nonencrypted
init
per continuare l'avvio.
- Controlla password
L'interfaccia utente chiama
vold
con il comandocryptfs enablecrypto inplace
dovepasswd
è la password della schermata di blocco dell'utente. - Rimuovere il framework
vold
controlla la presenza di errori, restituisce -1 se non riesce a eseguire la crittografia e stampa un motivo nel log. Se può eseguire la crittografia, imposta la proprietàvold.decrypt
sutrigger_shutdown_framework
. Di conseguenza,init.rc
interrompe i servizi nelle classilate_start
emain
. - Creare un piè di pagina con crittografia
- Creare un file breadcrumb
- Riavvia
- Rileva file breadcrumb
- Avvia la crittografia
/data
vold
configura quindi la mappatura della crittografia, che crea un dispositivo di blocco della crittografia virtuale che si mappa sul dispositivo di blocco reale, ma cripta ogni settore durante la scrittura e decripta ogni settore durante la lettura.vold
crea e scrive poi i metadati della crittografia. - Durante l'operazione di crittografia, monta tmpfs
vold
monta un file tmpfs/data
(utilizzando le opzioni tmpfs daro.crypto.tmpfs_options
) e imposta la proprietàvold.encrypt_progress
su 0.vold
prepara il file system tmpfs/data
per l'avvio di un sistema criptato e imposta la proprietàvold.decrypt
su:trigger_restart_min_framework
- Mostrare il framework per mostrare l'avanzamento
trigger_restart_min_framework
induceinit.rc
a avviare la classe di servizimain
. Quando il framework rileva chevold.encrypt_progress
è impostato su 0, viene visualizzata l'interfaccia utente della barra di avanzamento, che esegue query sulla proprietà ogni cinque secondi e aggiorna una barra di avanzamento. Il loop di crittografia aggiornavold.encrypt_progress
ogni volta che cripta un'altra percentuale della partizione. - Quando
/data
è criptato, aggiorna il piè di pagina della crittografiaQuando
/data
viene criptato correttamente,vold
cancella l'indicatoreENCRYPTION_IN_PROGRESS
nei metadati.Una volta sbloccato il dispositivo, la password viene utilizzata per criptare la chiave principale e il piè di pagina della crittografia viene aggiornato.
Se il riavvio non riesce per qualche motivo,
vold
imposta la proprietàvold.encrypt_progress
suerror_reboot_failed
e l'interfaccia utente dovrebbe mostrare un messaggio che chiede all'utente di premere un pulsante per riavviare. Non è previsto che si verifichi.
Avviare un dispositivo criptato con la crittografia predefinita
Questo è ciò che accade quando avvii un dispositivo criptato senza password. Poiché i dispositivi Android 5.0 sono criptati al primo avvio, non dovrebbe essere impostata alcuna password e quindi questo è lo stato di crittografia predefinita.
- Rileva
/data
criptato senza passwordRileva che il dispositivo Android è criptato perché
/data
non può essere montato ed è impostato uno dei flagencryptable
oforceencrypt
.vold
impostavold.decrypt
sutrigger_default_encryption
, che avvia il serviziodefaultcrypto
.trigger_default_encryption
controlla il tipo di crittografia per verificare se/data
è criptato con o senza una password. - Decripta /data
Crea il dispositivo
dm-crypt
sul dispositivo di blocco in modo che sia pronto per l'uso. - Monta /data
vold
quindi monta la partizione/data
reale decriptata e prepara la nuova partizione. Imposta la proprietàvold.post_fs_data_done
su 0 e poivold.decrypt
sutrigger_post_fs_data
. In questo modo,init.rc
esegue i suoi comandipost-fs-data
. Creano le directory o i link necessari e impostanovold.post_fs_data_done
su 1.Quando
vold
vede il 1 in quella proprietà, imposta la proprietàvold.decrypt
su:trigger_restart_framework.
. Questo fa sì cheinit.rc
riavvii i servizi nel gruppomain
e avvii anche i servizi nel gruppolate_start
per la prima volta dall'avvio. - Framework di avvio
Ora il framework avvia tutti i suoi servizi utilizzando il file
/data
decriptato e il sistema è pronto per l'uso.
Avviare un dispositivo criptato senza crittografia predefinita
Questo accade quando avvii un dispositivo criptato con una password impostata. La password del dispositivo può essere un PIN, una sequenza o una password.
- Rilevare il dispositivo criptato con una password
Rileva che il dispositivo Android è criptato perché il flag
ro.crypto.state = "encrypted"
vold
impostavold.decrypt
sutrigger_restart_min_framework
perché/data
è criptato con una password. - Montare tmpfs
init
imposta cinque proprietà per salvare le opzioni di montaggio iniziali assegnate a/data
con i parametri passati dainit.rc
.vold
utilizza queste proprietà per configurare la mappatura della crittografia:ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(numero esadecimale ASCII di 8 cifre preceduto da 0x)
- Avvia il framework per richiedere la password
Il framework si avvia e rileva che
vold.decrypt
è impostato sutrigger_restart_min_framework
. Questo indica al framework che sta avviandosi su un disco/data
tmpfs e che deve recuperare la password dell'utente.Tuttavia, prima deve assicurarsi che il disco sia stato criptato correttamente. Invia il comando
cryptfs cryptocomplete
avold
.vold
restituisce 0 se la crittografia è stata completata correttamente, -1 in caso di errore interno o -2 se la crittografia non è stata completata correttamente.vold
lo determina cercando il flagCRYPTO_ENCRYPTION_IN_PROGRESS
nei metadati della crittografia. Se è impostato, significa che la procedura di crittografia è stata interrotta e non sono presenti dati utilizzabili sul dispositivo. Sevold
restituisce un errore, l'interfaccia utente deve mostrare un messaggio all'utente per riavviare e ripristinare i dati di fabbrica del dispositivo e fornire un pulsante da premere per farlo. - Decriptare i dati con la password
Una volta completata la procedura
cryptfs cryptocomplete
, il framework visualizza un'interfaccia utente che richiede la password del disco. L'interfaccia utente controlla la password inviando il comandocryptfs checkpw
avold
. Se la password è corretta (il che viene stabilito montando correttamente/data
decriptato in una posizione temporanea e poi smontandolo),vold
salva il nome del dispositivo di blocco decriptato nella proprietàro.crypto.fs_crypto_blkdev
e restituisce lo stato 0 all'interfaccia utente. Se la password non è corretta, viene restituito -1 all'interfaccia utente. - Framework di interruzione
L'interfaccia utente mostra un'immagine di avvio della criptovaluta e poi chiama
vold
con il comandocryptfs restart
.vold
imposta la proprietàvold.decrypt
sutrigger_reset_main
, il che fa eseguireinit.rc
l'operazioneclass_reset main
. In questo modo vengono interrotti tutti i servizi nella classe principale, il che consente di smontare il file system tmpfs/data
. - Monta
/data
vold
quindi monta la partizione/data
reale decriptata e prepara la nuova partizione (che potrebbe non essere mai stata preparata se è stata criptata con l'opzione di reset, che non è supportata nella prima release). Imposta la proprietàvold.post_fs_data_done
su 0 e poi impostavold.decrypt
sutrigger_post_fs_data
. In questo modo,init.rc
eseguirà i suoi comandipost-fs-data
. Questi agenti creano le eventuali directory o i link necessari e poi impostanovold.post_fs_data_done
su 1. Quandovold
vede il valore 1 in quella proprietà, imposta la proprietàvold.decrypt
sutrigger_restart_framework
. In questo modo,init.rc
avvia nuovamente i servizi nel corsomain
e avvia anche i servizi nel corsolate_start
per la prima volta dall'avvio. - Avvia il framework completo
Ora il framework avvia tutti i suoi servizi utilizzando il file system
/data
decriptato e il sistema è pronto per l'uso.
Errore
Un dispositivo che non riesce a decriptare potrebbe avere dei problemi per diversi motivi. Il dispositivo inizia con la normale serie di passaggi per l'avvio:
- Rilevare il dispositivo criptato con una password
- Montare tmpfs
- Avvia il framework per richiedere la password
Tuttavia, dopo l'apertura del framework, il dispositivo può riscontrare alcuni errori:
- La password corrisponde, ma non è possibile decriptare i dati
- L'utente inserisce la password errata 30 volte
Se questi errori non vengono risolti, chiedi all'utente di eseguire il ripristino dei dati di fabbrica:
Se vold
rileva un errore durante il processo di crittografia e se non sono stati ancora distrutti dati e il framework è attivo, vold
imposta la proprietà vold.encrypt_progress
su error_not_encrypted
.
L'interfaccia utente chiede all'utente di riavviare il dispositivo e lo avvisa che la procedura di crittografia non è mai stata avviata. Se l'errore si verifica dopo lo smantellamento del framework, ma prima dell'apertura dell'interfaccia utente della barra di avanzamento, vold
riavvia il sistema. Se il riavvio non va a buon fine, vold.encrypt_progress
viene impostato su error_shutting_down
e viene restituito -1, ma non verrà rilevato alcun errore. Questo problema non dovrebbe accadere di frequente.
Se vold
rileva un errore durante la procedura di crittografia, imposta vold.encrypt_progress
su error_partially_encrypted
e restituisce -1. L'interfaccia utente dovrebbe quindi mostrare un messaggio che indica che la crittografia
è fallita e fornire un pulsante per consentire all'utente di ripristinare i dati di fabbrica del dispositivo.
Memorizza la chiave criptata
La chiave criptata viene archiviata nei metadati della crittografia. Il supporto hardware viene implementato utilizzando la funzionalità di firma del Trusted Execution Environment (TEE). In precedenza, criptavamo la chiave principale con una chiave generata applicando scrypt alla password dell'utente e al sale memorizzato. Per rendere la chiave resiliente agli attacchi off-box, estendiamo questo algoritmo firmando la chiave risultante con una chiave TEE memorizzata. La firma risultante viene poi trasformata in una chiave di lunghezza appropriata con un'altra applicazione di scrypt. Questa chiave viene poi utilizzata per criptare e decriptare la chiave master. Per memorizzare questa chiave:
- Genera una chiave di crittografia del disco (DEK) casuale di 16 byte e un valore di salt di 16 byte.
- Applica scrypt alla password dell'utente e al sale per produrre la chiave intermedia 1 (IK1) di 32 byte.
- Inserisci zero byte in IK1 per ottenere le dimensioni della chiave privata legata all'hardware (HBK). Nello specifico, il padding è: 00 || IK1 || 00..00; un byte zero, 32 byte IK1, 223 zero byte.
- Firma IK1 con padding con HBK per produrre IK2 di 256 byte.
- Applica scrypt a IK2 e al sale (lo stesso sale del passaggio 2) per produrre IK3 di 32 byte.
- Utilizza i primi 16 byte di IK3 come KEK e gli ultimi 16 byte come IV.
- Cripta la DEK con AES_CBC, con la chiave KEK e il vettore di inizializzazione IV.
Cambiare la password
Quando un utente sceglie di cambiare o rimuovere la password nelle impostazioni, l'interfaccia utente invia il comando cryptfs changepw
a vold
e vold
cripta di nuovo la chiave principale del disco con la nuova password.
Proprietà di crittografia
vold
e init
comunicano tra loro impostando le proprietà. Di seguito è riportato un elenco delle proprietà disponibili per la crittografia.
Proprietà Vold
Proprietà | Descrizione |
---|---|
vold.decrypt trigger_encryption |
Criptare il disco senza una password. |
vold.decrypt trigger_default_encryption |
Controlla se l'unità è criptata senza password.
Se è così, decriptalo e montalo,
altrimenti imposta vold.decrypt su trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
Impostato da vold per arrestare l'interfaccia utente che richiede la password del disco. |
vold.decrypt trigger_post_fs_data |
Impostato da vold per preparare /data con le directory necessarie e così via. |
vold.decrypt trigger_restart_framework |
Impostato da vold per avviare il framework reale e tutti i servizi. |
vold.decrypt trigger_shutdown_framework |
Impostato da vold per arrestare il framework completo e avviare la crittografia. |
vold.decrypt trigger_restart_min_framework |
Impostato da vold per avviare la UI della barra di avanzamento per la crittografia o richiedere la password, a seconda del valore di ro.crypto.state . |
vold.encrypt_progress |
Quando il framework si avvia, se questa proprietà è impostata, viene attivata la modalità UI della barra di avanzamento. |
vold.encrypt_progress 0 to 100 |
L'interfaccia utente della barra di avanzamento deve mostrare il valore percentuale impostato. |
vold.encrypt_progress error_partially_encrypted |
L'interfaccia utente della barra di avanzamento dovrebbe mostrare un messaggio che indica che la crittografia non è riuscita e offrire all'utente la possibilità di eseguire il ripristino dei dati di fabbrica del dispositivo. |
vold.encrypt_progress error_reboot_failed |
L'interfaccia utente della barra di avanzamento dovrebbe mostrare un messaggio che indica che la crittografia è stata completata e fornire all'utente un pulsante per riavviare il dispositivo. Questo errore non dovrebbe verificarsi. |
vold.encrypt_progress error_not_encrypted |
L'interfaccia utente della barra di avanzamento dovrebbe mostrare un messaggio che indica che si è verificato un errore, che non sono stati criptati o persi dati e fornire all'utente un pulsante per riavviare il sistema. |
vold.encrypt_progress error_shutting_down |
L'interfaccia utente della barra di avanzamento non è in esecuzione, pertanto non è chiaro chi risponda a questo errore. E non dovrebbe mai accadere. |
vold.post_fs_data_done 0 |
Impostato da vold poco prima di impostare vold.decrypt su trigger_post_fs_data . |
vold.post_fs_data_done 1 |
Imposta init.rc o
init.rc subito dopo aver completato l'attività post-fs-data . |
Proprietà init
Proprietà | Descrizione |
---|---|
ro.crypto.fs_crypto_blkdev |
Impostato dal comando vold checkpw per un uso successivo
dal comando vold restart . |
ro.crypto.state unencrypted |
Impostato da init per indicare che questo sistema è in esecuzione con un /data ro.crypto.state encrypted non criptato. Impostato da init per indicare
che questo sistema è in esecuzione con un /data criptato. |
|
Queste cinque proprietà vengono impostate da
init quando tenta di montare /data con i parametri passati da
init.rc . vold li utilizza per configurare la mappatura della crittografia. |
ro.crypto.tmpfs_options |
Impostato da init.rc con le opzioni che init deve utilizzare per montare il file system tmpfs /data . |
azioni init
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