La crittografia dell'intero disco è il processo di codifica di tutti i dati utente su un dispositivo Android utilizzando una chiave crittografata. Una volta crittografato un dispositivo, tutti i dati creati dall'utente vengono automaticamente crittografati prima di salvarli su disco e tutte le letture decrittografano automaticamente i dati prima di restituirli al processo chiamante.
La crittografia dell'intero disco è stata introdotta in Android nella versione 4.4, ma Android 5.0 ha introdotto queste nuove funzionalità:
- Creata la crittografia veloce, che crittografa solo i blocchi utilizzati sulla partizione dati per evitare che il primo avvio richieda molto tempo. Solo i filesystem ext4 e f2fs attualmente supportano la crittografia veloce.
- Aggiunto il flag fstab
forceencrypt
per crittografare al primo avvio. - Aggiunto supporto per pattern e crittografia senza password.
- Aggiunta archiviazione supportata da hardware della chiave di crittografia utilizzando la funzionalità di firma TEE (Trusted Execution Environment) (come in TrustZone). Vedi Memorizzazione della chiave crittografata per maggiori dettagli.
Attenzione: i dispositivi aggiornati ad Android 5.0 e poi crittografati potrebbero tornare allo stato non crittografato tramite il ripristino dei dati di fabbrica. I nuovi dispositivi Android 5.0 crittografati al primo avvio non possono essere riportati a uno stato non crittografato.
Come funziona la crittografia dell'intero disco Android
La crittografia dell'intero disco Android si basa su dm-crypt
, una funzionalità del kernel che funziona a livello del dispositivo a blocchi. Per questo motivo, la crittografia funziona con Embedded MultiMediaCard ( eMMC) e dispositivi flash simili che si presentano al kernel come dispositivi a blocchi. La crittografia non è possibile con YAFFS, che comunica direttamente con un chip flash NAND grezzo.
L'algoritmo di crittografia è 128 Advanced Encryption Standard (AES) con cipher-block chaining (CBC) ed ESSIV:SHA256. La chiave principale viene crittografata con AES a 128 bit tramite chiamate alla libreria OpenSSL. È necessario utilizzare 128 bit o più per la chiave (256 sono facoltativi).
Nota: gli OEM possono utilizzare 128 bit o versioni successive per crittografare la chiave master.
Nella versione Android 5.0 sono disponibili quattro tipi di stati di crittografia:
- predefinito
- SPILLO
- parola d'ordine
- modello
Al primo avvio, il dispositivo crea una chiave master a 128 bit generata casualmente e quindi la sottopone ad hashing con una password predefinita e sale 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 crittografare la chiave principale.
Puoi trovare la password predefinita definita nel file cryptfs.cpp del progetto Android Open Source.
Quando l'utente imposta il PIN/pass o la password sul dispositivo, solo la chiave a 128 bit viene nuovamente crittografata e archiviata. (ovvero, le modifiche al PIN/pass/sequenza utente NON causano la nuova crittografia dei dati utente.) Tieni presente che il dispositivo gestito può essere soggetto a restrizioni relative a PIN, sequenza o password.
La crittografia è gestita da init
e vold
. init
chiama vold
e vold imposta le proprietà per attivare eventi in init. Anche altre parti del sistema esaminano le proprietà per svolgere attività come segnalare lo stato, richiedere una password o richiedere il ripristino delle impostazioni di fabbrica in caso di errore irreversibile. 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 crittografare, decrittografare o cancellare /data
, /data
non deve essere montato. Tuttavia, per mostrare qualsiasi interfaccia utente (UI), il framework deve essere avviato e richiede l'esecuzione /data
. Per risolvere questo enigma, viene montato un filesystem temporaneo su /data
. Ciò consente ad Android di richiedere password, mostrare progressi o suggerire la cancellazione dei dati secondo necessità. Impone la limitazione che per passare dal filesystem temporaneo al filesystem true /data
, il sistema deve arrestare ogni processo con file aperti sul filesystem temporaneo e riavviare tali processi sul filesystem /data
reale. Per fare ciò, tutti i servizi devono trovarsi in uno dei tre gruppi: core
, main
e late_start
.
-
core
: non spegnere mai dopo l'avvio. -
main
: arresta e riavvia dopo aver immesso la password del disco. -
late_start
: non si avvia finché/data
non è stato decrittografato e montato.
Per attivare queste azioni, la proprietà vold.decrypt
è impostata su varie stringhe . Per terminare 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 crittografato. Un dispositivo viene crittografato solo una volta e quindi segue un normale flusso di avvio.
- Crittografare un dispositivo precedentemente non crittografato:
- Crittografa un nuovo dispositivo con
forceencrypt
: crittografia obbligatoria al primo avvio (a partire da Android L). - Crittografa un dispositivo esistente: crittografia avviata dall'utente (Android K e versioni precedenti).
- Crittografa un nuovo dispositivo con
- Avvia un dispositivo crittografato:
- Avvio di un dispositivo crittografato senza password: avvio di un dispositivo crittografato per cui non è stata impostata una password (rilevante per i dispositivi con Android 5.0 e versioni successive).
- Avvio di un dispositivo crittografato con una password: avvio di un dispositivo crittografato con una password impostata.
Oltre a questi flussi, il dispositivo può anche non riuscire a crittografare /data
. Ciascuno dei flussi è spiegato in dettaglio di seguito.
Crittografa un nuovo dispositivo con forceencrypt
Questo è il normale primo avvio per un dispositivo Android 5.0.
- Rileva il file system non crittografato con il flag
forceencrypt
/data
non è crittografato ma deve esserlo perchéforceencrypt
lo impone. Smonta/data
. - Inizia a crittografare
/data
vold.decrypt = "trigger_encryption"
attivainit.rc
, che farà sìvold
crittografi/data
senza password. (Nessuno è impostato perché dovrebbe trattarsi di un nuovo dispositivo.) - Montare tmpfs
vold
monta un tmpfs/data
(usando le opzioni tmpfs daro.crypto.tmpfs_options
) e imposta la proprietàvold.encrypt_progress
su 0.vold
prepara tmpfs/data
per l'avvio di un sistema crittografato e imposta la proprietàvold.decrypt
su:trigger_restart_min_framework
- Visualizza la struttura per mostrare i progressi
Poiché il dispositivo non ha praticamente dati da crittografare, la barra di avanzamento spesso non viene effettivamente visualizzata perché la crittografia avviene molto rapidamente. Vedi Crittografare un dispositivo esistente per ulteriori dettagli sull'interfaccia utente di avanzamento.
- Quando
/data
viene crittografato, rimuovi il frameworkvold
impostavold.decrypt
sutrigger_default_encryption
che avvia il serviziodefaultcrypto
. (In questo modo viene avviato il flusso riportato di seguito per il montaggio di un dato utente crittografato predefinito.)trigger_default_encryption
controlla il tipo di crittografia per vedere se/data
è crittografato con o senza password. Poiché i dispositivi Android 5.0 vengono crittografati al primo avvio, non dovrebbe essere impostata alcuna password; quindi decodifichiamo e montiamo/data
. - Monta
/data
init
quindi monta/data
su un RAMDisk tmpfs utilizzando i parametri che prende daro.crypto.tmpfs_options
, che è impostato ininit.rc
. - Avvia quadro
vold
impostavold.decrypt
sutrigger_restart_framework
, che continua il consueto processo di avvio.
Crittografa un dispositivo esistente
Questo è ciò che accade quando crittografi un dispositivo Android K o precedente non crittografato che è stato migrato a L.
Questo processo viene avviato dall'utente e nel codice viene denominato "crittografia interna". Quando un utente sceglie di crittografare un dispositivo, l'interfaccia utente si assicura che la batteria sia completamente carica e che l'adattatore CA sia collegato in modo che ci sia energia sufficiente per completare il processo di crittografia.
Avviso: se il dispositivo si esaurisce e si spegne prima di aver terminato la crittografia, i dati del file vengono lasciati in uno stato parzialmente crittografato. Il dispositivo deve essere ripristinato alle impostazioni di fabbrica e tutti i dati andranno persi.
Per abilitare la crittografia sul posto, vold
avvia un ciclo per leggere ogni settore del dispositivo a blocchi reale e quindi scriverlo sul dispositivo a blocchi 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 che ha pochi o nessun dato.
Stato del dispositivo : imposta ro.crypto.state = "unencrypted"
ed esegui il trigger init
on nonencrypted
per continuare l'avvio.
- Controlla la password
L'interfaccia utente chiama
vold
con il comandocryptfs enablecrypto inplace
dovepasswd
è la password della schermata di blocco dell'utente. - Togli il quadro
vold
controlla gli errori, restituisce -1 se non può crittografare e stampa un motivo nel registro. Se può crittografare, imposta la proprietàvold.decrypt
sutrigger_shutdown_framework
. Ciò fa sì cheinit.rc
interrompa i servizi nelle classilate_start
emain
. - Crea un piè di pagina crittografico
- Crea un file breadcrumb
- Riavviare
- Rileva il file breadcrumb
- Inizia a crittografare
/data
vold
quindi imposta la mappatura crittografica, che crea un dispositivo a blocchi crittografico virtuale che si mappa sul dispositivo a blocchi reale ma crittografa ogni settore mentre viene scritto e decrittografa ogni settore mentre viene letto.vold
quindi crea e scrive i metadati crittografici. - Durante la crittografia, monta tmpfs
vold
monta un tmpfs/data
(usando le opzioni tmpfs daro.crypto.tmpfs_options
) e imposta la proprietàvold.encrypt_progress
su 0.vold
prepara tmpfs/data
per l'avvio di un sistema crittografato e imposta la proprietàvold.decrypt
su:trigger_restart_min_framework
- Visualizza la struttura per mostrare i progressi
trigger_restart_min_framework
fa sì cheinit.rc
avvii la classemain
di servizi. Quando il framework rileva chevold.encrypt_progress
è impostato su 0, visualizza l'interfaccia utente della barra di avanzamento, che interroga tale proprietà ogni cinque secondi e aggiorna una barra di avanzamento. Il ciclo di crittografia aggiornavold.encrypt_progress
ogni volta che crittografa un'altra percentuale della partizione. - Quando
/data
è crittografato, aggiorna il footer crittograficoQuando
/data
viene crittografato con successo,vold
cancella il flagENCRYPTION_IN_PROGRESS
nei metadati.Quando il dispositivo viene sbloccato con successo, la password viene quindi utilizzata per crittografare la chiave principale e il footer crittografico viene aggiornato.
Se il riavvio fallisce per qualche motivo,
vold
imposta la proprietàvold.encrypt_progress
suerror_reboot_failed
e l'interfaccia utente dovrebbe visualizzare un messaggio che chiede all'utente di premere un pulsante per riavviare. Non si prevede che ciò accada mai.
Avvio di un dispositivo crittografato con crittografia predefinita
Questo è ciò che accade quando si avvia un dispositivo crittografato senza password. Poiché i dispositivi Android 5.0 vengono crittografati al primo avvio, non dovrebbe essere impostata alcuna password e pertanto questo è lo stato di crittografia predefinito .
- Rileva
/data
crittografati senza passwordRileva che il dispositivo Android è crittografato perché
/data
non può essere montato e uno dei flagencryptable
oforceencrypt
è impostato.vold
impostavold.decrypt
sutrigger_default_encryption
, che avvia il serviziodefaultcrypto
.trigger_default_encryption
controlla il tipo di crittografia per vedere se/data
è crittografato con o senza password. - Decifra /data
Crea il dispositivo
dm-crypt
sul dispositivo a blocchi in modo che il dispositivo sia pronto per l'uso. - Monta /dati
vold
quindi monta la partizione reale/data
decodificata e quindi prepara la nuova partizione. Imposta la proprietàvold.post_fs_data_done
su 0 e quindi impostavold.decrypt
sutrigger_post_fs_data
. Ciò fa sì cheinit.rc
esegua i suoi comandipost-fs-data
. Creeranno tutte le directory o i collegamenti necessari e quindi imposterannovold.post_fs_data_done
su 1.Una volta che
vold
vede l'1 in quella proprietà, imposta la proprietàvold.decrypt
su:trigger_restart_framework.
Ciò fa sì cheinit.rc
avvii nuovamente i servizi nella classemain
e avvii anche i servizi nella classelate_start
per la prima volta dall'avvio. - Avvia quadro
Ora il framework avvia tutti i suoi servizi utilizzando il
/data
decrittografato e il sistema è pronto per l'uso.
Avvio di un dispositivo crittografato senza crittografia predefinita
Questo è ciò che accade quando si avvia un dispositivo crittografato con una password impostata. La password del dispositivo può essere un PIN, una sequenza o una password.
- Rileva dispositivo crittografato con una password
Rileva che il dispositivo Android è crittografato perché il flag
ro.crypto.state = "encrypted"
vold
impostavold.decrypt
sutrigger_restart_min_framework
perché/data
è crittografato con una password. - Montare tmpfs
init
imposta cinque proprietà per salvare le opzioni di montaggio iniziali fornite per/data
con i parametri passati dainit.rc
.vold
utilizza queste proprietà per impostare la mappatura crittografica:-
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 vede che
vold.decrypt
è impostato sutrigger_restart_min_framework
. Questo indica al framework che si sta avviando su un disco tmpfs/data
e che deve ottenere la password dell'utente.Innanzitutto, però, è necessario assicurarsi che il disco sia stato crittografato correttamente. Invia il comando
cryptfs cryptocomplete
avold
.vold
restituisce 0 se la crittografia è stata completata con successo, -1 in caso di errore interno o -2 se la crittografia non è stata completata con successo.vold
lo determina cercando nei metadati crittografici il flagCRYPTO_ENCRYPTION_IN_PROGRESS
. Se è impostato, il processo di crittografia è stato interrotto e sul dispositivo non sono presenti dati utilizzabili. Sevold
restituisce un errore, l'interfaccia utente dovrebbe visualizzare un messaggio all'utente per riavviare e ripristinare le impostazioni di fabbrica del dispositivo e fornire all'utente un pulsante da premere per farlo. - Decrittografare i dati con password
Una volta che
cryptfs cryptocomplete
ha esito positivo, 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 (che viene determinata montando con successo il/data
decrittografato in una posizione temporanea, quindi smontandolo),vold
salva il nome del dispositivo a blocchi decrittografato nella proprietàro.crypto.fs_crypto_blkdev
e restituisce lo stato 0 all'interfaccia utente . Se la password non è corretta, restituisce -1 all'interfaccia utente. - Smettere di quadro
L'interfaccia utente visualizza un'immagine di avvio crittografato e quindi chiama
vold
con il comandocryptfs restart
.vold
imposta la proprietàvold.decrypt
sutrigger_reset_main
, che fa sì cheinit.rc
eseguaclass_reset main
. Ciò arresta tutti i servizi nella classe principale, consentendo di smontare tmpfs/data
. - Monta
/data
vold
quindi monta la partizione reale/data
decriptata e prepara la nuova partizione (che potrebbe non essere mai stata preparata se fosse stata crittografata con l'opzione di cancellazione, che non è supportata al primo rilascio). Imposta la proprietàvold.post_fs_data_done
su 0 e quindi impostavold.decrypt
sutrigger_post_fs_data
. Ciò fa sì cheinit.rc
esegua i suoi comandipost-fs-data
. Creeranno tutte le directory o i collegamenti necessari e quindi imposterannovold.post_fs_data_done
su 1. Una volta chevold
vede 1 in quella proprietà, imposta la proprietàvold.decrypt
sutrigger_restart_framework
. Ciò fa sì cheinit.rc
avvii nuovamente i servizi nella classemain
e avvii anche i servizi nella classelate_start
per la prima volta dall'avvio. - Avvia il quadro completo
Ora il framework avvia tutti i suoi servizi utilizzando il filesystem
/data
decrittografato e il sistema è pronto per l'uso.
Fallimento
Un dispositivo che non riesce a decrittografare potrebbe essere errato per alcuni motivi. Il dispositivo si avvia con la normale serie di passaggi per l'avvio:
- Rileva dispositivo crittografato con una password
- Montare tmpfs
- Avvia il framework per richiedere la password
Ma dopo l'apertura del framework, il dispositivo può riscontrare alcuni errori:
- La password corrisponde ma non può decrittografare i dati
- L'utente inserisce una password errata 30 volte
Se questi errori non vengono risolti, chiedi all'utente di cancellare le impostazioni di fabbrica :
Se vold
rileva un errore durante il processo di crittografia e se nessun dato è stato ancora distrutto e il framework è attivo, vold
imposta la proprietà vold.encrypt_progress
su error_not_encrypted
. L'interfaccia utente richiede all'utente di riavviare e avvisa che il processo di crittografia non è mai stato avviato. Se l'errore si verifica dopo che il framework è stato smontato, ma prima che la barra di avanzamento dell'interfaccia utente sia attiva, vold
riavvierà il sistema. Se il riavvio fallisce, imposta vold.encrypt_progress
su error_shutting_down
e restituisce -1; ma non ci sarà nulla per rilevare l'errore. Non è previsto che ciò accada.
Se vold
rileva un errore durante il processo di crittografia, imposta vold.encrypt_progress
su error_partially_encrypted
e restituisce -1. L'interfaccia utente dovrebbe quindi visualizzare un messaggio che indica che la crittografia non è riuscita e fornire all'utente un pulsante per ripristinare le impostazioni di fabbrica del dispositivo.
Memorizzazione della chiave crittografata
La chiave crittografata è archiviata nei metadati crittografici. Il supporto hardware viene implementato utilizzando la funzionalità di firma TEE (Trusted Execution Environment). In precedenza, abbiamo crittografato la chiave master con una chiave generata applicando scrypt alla password dell'utente e al salt archiviato. Per rendere la chiave resistente agli attacchi off-box, estendiamo questo algoritmo firmando la chiave risultante con una chiave TEE memorizzata. La firma risultante viene quindi trasformata in una chiave di lunghezza appropriata mediante un'ulteriore applicazione di scrypt. Questa chiave viene quindi utilizzata per crittografare e decrittografare la chiave principale. Per memorizzare questa chiave:
- Genera una chiave di crittografia del disco (DEK) casuale da 16 byte e salt da 16 byte.
- Applicare scrypt alla password dell'utente e al salt per produrre la chiave intermedia 1 (IK1) a 32 byte.
- Riempi IK1 con zero byte fino alla dimensione della chiave privata associata all'hardware (HBK). Nello specifico, inseriamo come: 00 || IK1 || 00..00; un byte zero, 32 byte IK1, 223 byte zero.
- Segno riempito IK1 con HBK per produrre IK2 da 256 byte.
- Applicare scrypt a IK2 e salt (stesso sale del passaggio 2) per produrre IK3 a 32 byte.
- Utilizza i primi 16 byte di IK3 come KEK e gli ultimi 16 byte come IV.
- Crittografa DEK con AES_CBC, con chiave KEK e vettore di inizializzazione IV.
Modifica della password
Quando un utente sceglie di modificare o rimuovere la propria password nelle impostazioni, l'interfaccia utente invia il comando cryptfs changepw
a vold
e vold
crittografa nuovamente la chiave master 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à di Vold
Proprietà | Descrizione |
---|---|
vold.decrypt trigger_encryption | Crittografa l'unità senza password. |
vold.decrypt trigger_default_encryption | Controlla l'unità per vedere se è crittografata senza password. Se lo è, 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, et al. |
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 l'intero framework per avviare la crittografia. |
vold.decrypt trigger_restart_min_framework | Impostato da vold per avviare la barra di avanzamento dell'interfaccia utente per la crittografia o la richiesta di password, a seconda del valore di ro.crypto.state . |
vold.encrypt_progress | All'avvio del framework, se questa proprietà è impostata, entra nella modalità UI della barra di avanzamento. |
vold.encrypt_progress 0 to 100 | L'interfaccia utente della barra di avanzamento dovrebbe visualizzare il valore percentuale impostato. |
vold.encrypt_progress error_partially_encrypted | La barra di avanzamento dell'interfaccia utente dovrebbe visualizzare un messaggio indicante che la crittografia non è riuscita e offrire all'utente un'opzione per ripristinare le impostazioni di fabbrica del dispositivo. |
vold.encrypt_progress error_reboot_failed | La barra di avanzamento dell'interfaccia utente dovrebbe visualizzare un messaggio che indica che la crittografia è stata completata e fornire all'utente un pulsante per riavviare il dispositivo. Non è previsto che si verifichi questo errore. |
vold.encrypt_progress error_not_encrypted | L'interfaccia utente della barra di avanzamento dovrebbe visualizzare un messaggio che indica che si è verificato un errore, che nessun dato è stato crittografato o perso 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, quindi non è chiaro chi risponderà a questo errore. E comunque non dovrebbe mai succedere. |
vold.post_fs_data_done 0 | Impostato da vold appena prima di impostare vold.decrypt su trigger_post_fs_data . |
vold.post_fs_data_done 1 | Impostato da init.rc o init.rc subito dopo aver terminato l'attività post-fs-data . |
proprietà iniziali
Proprietà | Descrizione |
---|---|
ro.crypto.fs_crypto_blkdev | Impostato dal comando vold checkpw per un utilizzo successivo da parte del comando vold restart . |
ro.crypto.state unencrypted | Impostato da init per indicare che questo sistema è in esecuzione con un file /data ro.crypto.state encrypted non crittografato. Impostato da init per indicare che questo sistema è in esecuzione con un file /data crittografato. |
| Queste cinque proprietà vengono impostate da init quando tenta di montare /data con i parametri passati da init.rc . vold li usa per impostare la mappatura crittografica. |
ro.crypto.tmpfs_options | Impostato da init.rc con le opzioni che init dovrebbe utilizzare durante il montaggio del filesystem tmpfs /data . |
Azioni iniziali
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