La crittografia dell'intero disco è il processo di codifica di tutti i dati utente su un dispositivo Android utilizzando una chiave crittografata. Una volta che un dispositivo è crittografato, 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 in 4.4, ma Android 5.0 ha introdotto queste nuove funzionalità:
- Crittografia veloce creata, 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 rapida.
- Aggiunto il flag
forceencrypt
fstab per crittografare al primo avvio. - Aggiunto supporto per modelli e crittografia senza password.
- Aggiunta archiviazione supportata da hardware della chiave di crittografia utilizzando la funzionalità di firma TEE (Trusted Execution Environment) (come in una TrustZone). Vedere Memorizzazione della chiave crittografata per ulteriori dettagli.
Attenzione: i dispositivi aggiornati ad Android 5.0 e quindi crittografati potrebbero tornare a uno stato non crittografato mediante 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 di Android
La crittografia dell'intero disco Android si basa su dm-crypt
, che è una funzionalità del kernel che funziona a livello di 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) e ESSIV:SHA256. La chiave principale è crittografata con AES a 128 bit tramite chiamate alla libreria OpenSSL. È necessario utilizzare 128 bit o più per la chiave (con 256 facoltativi).
Nota: gli OEM possono utilizzare 128 bit o superiore 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 principale a 128 bit generata in modo casuale e quindi esegue l'hashing con una password predefinita e sale memorizzato. La password predefinita è: "default_password" Tuttavia, l'hash risultante è firmato anche tramite un TEE (come TrustZone), che utilizza un hash della firma per crittografare la chiave master.
È possibile 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. (ad es. le modifiche al PIN utente/passaggio/sequenza NON causano la nuova crittografia dei dati utente.) Si noti 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 eseguire 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 checkpw
dello strumento da riga di comando vdc
: cryptfs
, restart
, enablecrypto
, changepw
, cryptocomplete
, setfield
verifypw
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 il framework richiede /data
per essere eseguito. Per risolvere questo enigma, viene montato un filesystem temporaneo su /data
. Ciò consente ad Android di richiedere password, mostrare i progressi o suggerire una cancellazione dei dati, se necessario. Impone la limitazione che per passare dal filesystem temporaneo al filesystem /data
vero, il sistema deve arrestare ogni processo con file aperti sul filesystem temporaneo e riavviare quei 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 inserito la password del disco. -
late_start
: non si avvia fino a quando/data
è 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 senza password impostata (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
. Ognuno dei flussi è spiegato in dettaglio di seguito.
Crittografare 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à crittografarevold
/data
senza password. (Nessuno è impostato perché questo dovrebbe essere un nuovo dispositivo.) - Monta tmpfs
vold
monta un tmpfs/data
(utilizzando 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
- Apri 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. Vedere Crittografare un dispositivo esistente per ulteriori dettagli sull'interfaccia utente di avanzamento.
- Quando
/data
è crittografato, rimuovere il frameworkvold
impostavold.decrypt
sutrigger_default_encryption
che avvia il serviziodefaultcrypto
. (Questo avvia il flusso seguente 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 una password. Poiché i dispositivi Android 5.0 sono 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 usando i parametri che raccoglie daro.crypto.tmpfs_options
, che è impostato ininit.rc
. - Avvia quadro
vold
impostavold.decrypt
sutrigger_restart_framework
, che continua il normale processo di avvio.
Crittografare un dispositivo esistente
Questo è ciò che accade quando si crittografa un dispositivo Android K non crittografato o precedente che è stato migrato a L.
Questo processo è avviato dall'utente ed è indicato come "crittografia sul posto" nel codice. 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 vi sia alimentazione sufficiente per completare il processo di crittografia.
Avviso: se il dispositivo si esaurisce e si spegne prima di aver completato la crittografia, i dati del file rimangono in uno stato parzialmente crittografato. Il dispositivo deve essere ripristinato alle impostazioni di fabbrica e tutti i dati vengono persi.
Per abilitare la crittografia sul posto, vold
avvia un ciclo per leggere ogni settore del dispositivo a blocchi reale e quindi scriverlo nel 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 : impostare ro.crypto.state = "unencrypted"
ed eseguire 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. - Abbatti il quadro
vold
verifica la presenza di errori, restituisce -1 se non è in grado di 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 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
(utilizzando 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
- Apri 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 piè di pagina crittograficoQuando
/data
viene crittografato correttamente,vold
cancella il flagENCRYPTION_IN_PROGRESS
nei metadati.Quando il dispositivo viene sbloccato correttamente, la password viene quindi utilizzata per crittografare la chiave principale e il piè di pagina crittografico 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 visualizzare un messaggio che chiede all'utente di premere un pulsante per riavviare. Questo non dovrebbe mai accadere.
Avvio di un dispositivo crittografato con crittografia predefinita
Questo è ciò che accade quando avvii un dispositivo crittografato senza password. Poiché i dispositivi Android 5.0 sono crittografati al primo avvio, non dovrebbe esserci alcuna password impostata e pertanto questo è lo stato di crittografia predefinito .
- Rileva
/data
crittografati senza passwordRileva che il dispositivo Android è crittografato 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 vedere se/data
è crittografato con o senza password. - Decrittografare /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 real/data
decrittografata e quindi prepara la nuova partizione. Imposta la proprietàvold.post_fs_data_done
su 0 e quindi impostavold.decrypt
sutrigger_post_fs_data
. Questo 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 di nuovo 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
/data
decrittografato e il sistema è pronto per l'uso.
Avvio di un dispositivo crittografato senza crittografia predefinita
Questo è ciò che accade quando avvii un dispositivo crittografato con una password impostata. La password del dispositivo può essere un pin, una sequenza o una password.
- Rileva il 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. - Monta 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 a 8 cifre ASCII 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 dice al framework che si sta avviando su un disco tmpfs/data
e deve ottenere la password dell'utente.Prima, tuttavia, deve assicurarsi che il disco sia stato crittografato 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 nei metadati crittografici il flagCRYPTO_ENCRYPTION_IN_PROGRESS
. Se è impostato, il processo di crittografia è stato interrotto e non sono presenti dati utilizzabili sul dispositivo. 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 la password
Una volta
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 correttamente i/data
decrittografati in una posizione temporanea, quindi smontandoli),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. - Arresta il quadro
L'interfaccia utente crea un grafico di avvio crittografico e quindi chiama
vold
con il comandocryptfs restart
.vold
imposta la proprietàvold.decrypt
sutrigger_reset_main
, il che fa sì cheinit.rc
class_reset main
. Ciò arresta tutti i servizi nella classe principale, il che consente di smontare tmpfs/data
. - Monta
/data
vold
quindi monta la partizione real/data
decrittografata e prepara la nuova partizione (che potrebbe non essere mai stata preparata se fosse stata crittografata con l'opzione wipe, che non è supportata al primo rilascio). Imposta la proprietàvold.post_fs_data_done
su 0 e quindi impostavold.decrypt
sutrigger_post_fs_data
. Questo 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 l'1 in quella proprietà, imposta la proprietàvold.decrypt
sutrigger_restart_framework
. Ciò fa sì cheinit.rc
avvii di nuovo i servizi nella classemain
e avvii anche i servizi nella classelate_start
per la prima volta dall'avvio. - Avvia il framework 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 storto per alcuni motivi. Il dispositivo si avvia con la normale serie di passaggi per l'avvio:
- Rileva il dispositivo crittografato con una password
- Monta 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 i dati 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 lo avvisa che il processo di crittografia non è mai iniziato. Se l'errore si verifica dopo che il framework è stato demolito, ma prima che l'interfaccia utente della barra di avanzamento 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 catturare l'errore. Questo non dovrebbe accadere.
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 un pulsante per consentire all'utente di ripristinare le impostazioni di fabbrica del dispositivo.
Archiviazione della chiave crittografata
La chiave crittografata viene archiviata nei metadati crittografici. Il supporto hardware viene implementato utilizzando la funzionalità di firma TEE (Trusted Execution Environment). In precedenza, crittografavamo la chiave master con una chiave generata applicando scrypt alla password dell'utente e al salt memorizzato. Per rendere la chiave resiliente contro gli 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 da un'altra 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 casuale da 16 byte (DEK) e salt da 16 byte.
- Applicare scrypt alla password dell'utente e al salt per produrre la chiave intermedia 1 a 32 byte (IK1).
- Pad IK1 con zero byte fino alla dimensione della chiave privata associata all'hardware (HBK). Nello specifico, riempiamo come: 00 || CI1 || 00..00; uno zero byte, 32 IK1 byte, 223 zero byte.
- Firma IK1 imbottito con HBK per produrre IK2 da 256 byte.
- Applicare scrypt a IK2 e salt (stesso salt del passaggio 2) per produrre IK3 a 32 byte.
- Utilizzare i primi 16 byte di IK3 come KEK e gli ultimi 16 byte come IV.
- Crittografare DEK con AES_CBC, con chiave KEK e vettore di inizializzazione IV.
Modifica della parola d'ordine
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à vol
Proprietà | Descrizione |
---|---|
vold.decrypt trigger_encryption | Crittografare l'unità senza password. |
vold.decrypt trigger_default_encryption | Controlla l'unità per vedere se è crittografata senza password. Se lo è, decodificalo 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 l'interfaccia utente della barra di avanzamento per la crittografia o per richiedere la password, a seconda del valore di ro.crypto.state . |
vold.encrypt_progress | All'avvio del framework, se questa proprietà è impostata, accedere alla modalità dell'interfaccia utente 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 | L'interfaccia utente della barra di avanzamento dovrebbe visualizzare un messaggio indicante che la crittografia non è riuscita e offrire all'utente un'opzione per ripristinare i dati di fabbrica del dispositivo. |
vold.encrypt_progress error_reboot_failed | L'interfaccia utente della barra di avanzamento dovrebbe visualizzare 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 visualizzare un messaggio che indica che si è verificato un errore, 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à init
Proprietà | Descrizione |
---|---|
ro.crypto.fs_crypto_blkdev | Impostato dal comando vold checkpw per essere utilizzato successivamente 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 . Impostato da init per indicare che questo sistema è in esecuzione con un /data crittografato. |
| Queste cinque proprietà sono impostate da init quando tenta di montare /data con i parametri passati da init.rc . vold li utilizza per impostare la mappatura crittografica. |
ro.crypto.tmpfs_options | Impostato da init.rc con le opzioni che init dovrebbe usare durante il montaggio del filesystem tmpfs /data . |
Inizia azioni
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