Full-Disk Encryption

Full-disk encryption è il processo di codifica di tutti i dati dell’utente su un dispositivo Android usando una chiave cifrata. Una volta che un dispositivo è crittografato, tutti i dati creati dall’utente vengono automaticamente crittografati prima di impegnarli sul disco e tutti i dati letti vengono automaticamente decrittati prima di restituirli al processo chiamante.

La crittografia a disco intero è stata introdotta in Android nella 4.4, ma Android 5.0 ha introdotto queste nuove caratteristiche:

  • Crittografia veloce creata, che cripta solo i blocchi usati sulla partizione dati per evitare che il primo avvio richieda molto tempo. Attualmente solo i filesystem ext4 e f2fs supportano la crittografia veloce.
  • Aggiunto il flag forceencrypt fstab per criptare al primo avvio.
  • Aggiunto il supporto per i modelli e la crittografia senza password.
  • Aggiunta la memorizzazione con supporto hardware della chiave di crittografia utilizzando la capacità di firma del Trusted Execution Environment (TEE) (come in una TrustZone). Vedere Memorizzazione della chiave crittografata per maggiori dettagli.

Attenzione: I dispositivi aggiornati ad Android 5.0 e poi crittografati possono essere riportati a uno stato non crittografato mediante un reset dei dati di fabbrica. I nuovi dispositivi Android 5.0 crittografati al primo avvio non possono essere riportati allo stato non crittografato.

Come funziona la crittografia full-disk di Android

La crittografia full-disk di Android si basa su dm-crypt, che è una caratteristica del kernel che funziona al livello del dispositivo a blocchi. A causa di questo, 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 parla direttamente con un chip rawNAND flash.

L’algoritmo di crittografia è 128 Advanced Encryption Standard (AES) con cifratura a blocchi (CBC) e ESSIV:SHA256. La chiave principale è criptata con AES a 128 bit tramite chiamate alla libreria OpenSSL. Devi usare 128 bit o più per la chiave (256 è opzionale).

Nota: gli OEM possono usare 128 bit o più per crittografare la chiave principale.

Nella versione Android 5.0, ci sono quattro tipi di stati di crittografia:

  • default
  • PIN
  • password
  • pattern

Al primo avvio, il dispositivo crea una master key a 128 bit generata in modo casuale e poi la codifica con una password predefinita e un sale memorizzato. La password predefinita è: “default_password “Tuttavia, l’hash risultante è anche firmato attraverso un TEE (come TrustZone), che utilizza un hash della firma per crittografare la chiave principale.

È possibile trovare la password predefinita definita nell’Android Open Source Project cryptfs.cppfile.

Quando l’utente imposta il PIN/pass o la password sul dispositivo, solo la chiave a 128 bit viene nuovamente criptata e memorizzata. (Si noti che i dispositivi gestiti possono essere soggetti a restrizioni di PIN, modello o password.

La crittografia è gestita da init e vold.init chiama vold, e vold imposta le proprietà per attivare gli eventi init. Altre parti del sistema guardano anche alle proprietà per svolgere compiti come riferire lo stato, chiedere una password, o richiedere un reset di fabbrica nel caso di un errore fatale. Per invocare le funzioni di cifratura in vold, il sistema usa i comandi cryptfs dello strumento a riga di comandovdc: checkpw,restart, enablecrypto, changepw,cryptocomplete, verifypw, setfield,getfield, mountdefaultencrypted, getpwtype,getpw, e clearpw.

Per criptare, decriptare o cancellare /data, /data non deve essere montato. Tuttavia, per mostrare qualsiasi interfaccia utente (UI), il framework deve essere avviato e il framework richiede che /data venga eseguito. Per risolvere questo enigma, viene montato un filesystem temporaneo su /data, il che permette ad Android di richiedere la password, mostrare il progresso o suggerire una cancellazione dei dati secondo necessità. Impone la limitazione che per passare dal filesystem temporaneo al vero filesystem /data, il sistema deve fermare ogni processo con file aperti sul filesystem temporaneo e riavviare quei processi sul vero filesystem /data. Per fare questo, tutti i servizi devono essere in uno dei tre gruppi: core, main, elate_start.

  • core: Mai spento dopo l’avvio.
  • main: Si spegne e poi si riavvia dopo aver inserito la password del disco.
  • late_start: Non si avvia fino a quando /data non è stato decriptato e montato.

Per innescare queste azioni, la proprietà vold.decrypt è impostata su varie stringhe.Per uccidere e riavviare i servizi, i comandi init sono:

  • class_reset: Ferma un servizio ma ne permette il riavvio con class_start.
  • class_start: Riavvia un servizio.
  • class_stop: Ferma un servizio e aggiunge un flag SVC_DISABLED. I servizi fermati non rispondono a class_start.

Flows

Ci sono quattro flussi per un dispositivo criptato. Un dispositivo viene criptato solo una volta e poi segue un normale flusso di avvio.

  • Cifra un dispositivo precedentemente non cifrato:
    • Codifica 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 precedenti).
  • Avviare un dispositivo crittografato:
    • Avviare un dispositivo crittografato senza password: avvio di un dispositivo crittografato che non ha una password impostata (rilevante per i dispositivi con Android 5.0 e successivi).
    • Avvio di un dispositivo crittografato con password: avvio di un dispositivo crittografato che ha una password impostata.

In aggiunta a questi flussi, il dispositivo può anche fallire la crittografia /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.

  1. Rileva il filesystem non criptato con forceencrypt flag

    /data non è criptato ma deve esserlo perché forceencrypt lo impone.Smonta /data.

  2. Iniziare la crittografia di /data

    vold.decrypt = "trigger_encryption" innesca init.rc, che causerà vold per crittografare /data senza password.(Nessuna è impostata perché questo dovrebbe essere un nuovo dispositivo.)

  3. Mount tmpfs

    vold monta un tmpfs /data (usando le opzioni tmpfs daro.crypto.tmpfs_options) e imposta la proprietà vold.encrypt_progress a 0.vold prepara il tmpfs /data per avviare un sistema criptato e imposta la proprietà vold.decrypt a: trigger_restart_min_framework

  4. Porta in alto il quadro per mostrare il progresso

    Perché il dispositivo non ha praticamente nessun dato da criptare, la barra di progresso spesso non apparirà perché la criptazione avviene così rapidamente. VedereCodificare un dispositivo esistente per maggiori dettagli sull’interfaccia utente di progresso.

  5. Quando /data è criptato, porta giù il framework

    vold imposta vold.decrypt sutrigger_default_encryption che avvia il serviziodefaultcrypto. (Questo avvia il flusso sottostante per il montaggio di dati utente crittografati adefault.) trigger_default_encryption controlla il tipo di crittografia per vedere se /data è crittografato con o senza apassword. Poiché i dispositivi Android 5.0 sono crittografati al primo avvio, non dovrebbe essere impostata alcuna password; quindi decifriamo e montiamo /data.

  6. Mount /data

    init quindi monta /data su un RAMDisk tmpfs usando parametri che prende da ro.crypto.tmpfs_options, che è impostato in init.rc.

  7. Avvia framework

    Imposta vold a trigger_restart_framework, che continua il solito processo di avvio.

Criptare un dispositivo esistente

Questo è ciò che accade quando si cripta un dispositivo Android K o precedente non crittografato che è stato migrato a L.

Questo processo è avviato dall’utente e si riferisce al codice come “inplace encryption”. Quando un utente seleziona di crittografare un dispositivo, l’UI si assicura che la batteria sia completamente carica e che l’adattatore AC sia collegato in modo che ci sia abbastanza potenza per finire il processo di crittografia.

Attenzione: Se il dispositivo esaurisce l’alimentazione e si spegne prima che abbia finito la crittografia, i dati dei file vengono lasciati in uno stato parzialmente crittografato. Il dispositivo deve essere resettato di fabbrica e tutti i dati sono persi.

Per abilitare la crittografia sul posto, vold inizia un ciclo per leggere ogni settore del dispositivo di blocco reale e poi scriverlo nel dispositivo di blocco crittografico. vold controlla per vedere 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 esegue il trigger on nonencrypted init per continuare l’avvio.

  1. Controlla la password

    L’UI chiama vold con il comando cryptfs enablecrypto inplacedove passwd è la password del lock screen dell’utente.

  2. Disattiva il framework

    vold controlla gli errori, restituisce -1 se non può criptare e stampa una ragione nel log. Se può criptare, imposta la proprietà vold.decrypta trigger_shutdown_framework. Questo fa sì che init.rc fermi i servizi nelle classi late_start e main.

  3. Crea un crypto footer
  4. Crea un file breadcrumb
  5. Riavvia
  6. Rileva il file breadcrumb
  7. Inizia a criptare /data

    vold poi imposta il crypto mapping, che crea un dispositivo virtuale di blocco crittografico che mappa sul dispositivo di blocco reale, ma cripta ogni settore quando viene scritto, e decripta ogni settore quando viene letto. vold quindi crea e scrive i metadati di crittografia.

  8. Mentre sta criptando, mount tmpfs

    vold monta un tmpfs /data (usando le opzioni tmpfs di ro.crypto.tmpfs_options) e imposta la proprietàvold.encrypt_progress a 0. vold prepara il tmpfs/data per l’avvio di un sistema criptato e imposta la proprietàvold.decrypt a: trigger_restart_min_framework

  9. Porta il framework a mostrare il progresso

    trigger_restart_min_framework causa init.rc l’avvio della classe di servizi main. Quando il framework vede chevold.encrypt_progress è impostato a 0, porta in primo piano la barra di progresso, che interroga quella proprietà ogni cinque secondi e aggiorna una barra di progresso.Il ciclo di crittografia aggiorna vold.encrypt_progress ogni volta che cripta un’altra percentuale della partizione.

  10. Quando /data è criptato, aggiorna il piè di pagina crittografico

    Quando /data è criptato con successo, vold cancella il flag ENCRYPTION_IN_PROGRESS nei metadati.

    Quando il dispositivo viene sbloccato con successo, la password viene usata per criptare la chiave principale e il piè di pagina crittografico viene aggiornato.

    Se il riavvio fallisce per qualche motivo, vold imposta la proprietàvold.encrypt_progress su error_reboot_failed e l’interfaccia utente dovrebbe mostrare un messaggio che chiede all’utente di premere un pulsante per riavviare. Questo non dovrebbe mai accadere.

Avvio di un dispositivo criptato con crittografia di default

Questo è ciò che accade quando si avvia un dispositivo criptato senza password.Poiché i dispositivi Android 5.0 sono criptati al primo avvio, non ci dovrebbe essere alcuna setpassword e quindi questo è lo stato di crittografia di default.

  1. Rileva /data criptato senza password

    Rileva che il dispositivo Android è criptato perché /datanon può essere montato e uno dei flag encryptable oforceencrypt è impostato.

    vold imposta vold.decrypt sutrigger_default_encryption, che avvia il serviziodefaultcrypto. trigger_default_encryptioncontrolla il tipo di crittografia per vedere se /data è criptato con o senza password.

  2. Decrypt /data

    Crea il dispositivo dm-crypt sopra il dispositivo a blocchi in modo che il dispositivo sia pronto all’uso.

  3. Mount /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 poi imposta vold.decrypt su trigger_post_fs_data. Questo fa sì che init.rc esegua i suoi comandi post-fs-data. Essi creeranno qualsiasi directory o link necessario e poi imposteranno vold.post_fs_data_done a 1.

    Una volta che vold vede l’1 in quella proprietà, imposta la proprietà vold.decrypt a: trigger_restart_framework. Questo fa sì che init.rc avvii nuovamente i servizi nella classe maine anche i servizi nella classe late_start per la prima volta dall’avvio.

  4. Avvia il framework

    Ora il framework avvia tutti i suoi servizi usando il /data decriptato, e il sistema è pronto all’uso.

Avviare un dispositivo criptato senza crittografia predefinita

Questo è ciò che accade quando si avvia un dispositivo criptato che ha una password impostata. La password del dispositivo può essere un pin, un modello o una password.

  1. Rileva dispositivo criptato con password

    Rileva che il dispositivo Android è criptato perché il flagro.crypto.state = "encrypted"

    vold imposta vold.decrypt atrigger_restart_min_framework perché /data è criptato con password.

  2. Monta tmpfs

    init imposta cinque proprietà per salvare le opzioni di montaggio iniziali date per /data con parametri passati da init.rc.vold usa queste proprietà per impostare la mappatura crittografica:

    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 (numero esadecimale ASCII di 8 cifre preceduto da 0x)
  3. 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 ha bisogno di ottenere la password dell’utente.

    Prima, però, ha bisogno di assicurarsi che il disco sia stato correttamente criptato. Invia il comando cryptfs cryptocomplete a vold.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 di crittografia il flag CRYPTO_ENCRYPTION_IN_PROGRESS. Se è impostato, il processo di crittografia è stato interrotto, e ci sono dati nousable sul dispositivo. Se vold restituisce un errore, l’UI dovrebbe mostrare un messaggio all’utente per riavviare e resettare il dispositivo, e dare all’utente un pulsante da premere per farlo.

  4. Decifrare i dati con password

    Una volta che cryptfs cryptocomplete ha successo, il framework mostra un’UI che chiede la password del disco. L’UI controlla la password inviando il comando cryptfs checkpw a vold. Se la password è corretta (il che è determinato montando con successo il /data decriptato in una posizione temporanea, poi smontandolo), vold salva il nome del dispositivo a blocchi decriptato nella proprietà ro.crypto.fs_crypto_blkdev e restituisce lo stato 0 all’interfaccia utente. Se la password non è corretta, restituisce -1 all’UI.

  5. Stop framework

    L’UI mette un grafico di avvio crittografico e poi chiama vold con il comando cryptfs restart. vold imposta la proprietàvold.decrypt su trigger_reset_main, che fa sì cheinit.rc faccia class_reset main. Questo ferma tutti i servizi nella classe principale, il che permette di smontare il tmpfs /data.

  6. Mount /data

    vold monta quindi la partizione reale /data decriptata e prepara la nuova partizione (che potrebbe non essere mai stata preparata se è stata criptata con l’opzione wipe, che non è supportata nella prima release). Imposta la proprietà vold.post_fs_data_done su 0 e imposta vold.decrypt su trigger_post_fs_data. Questo fa sì cheinit.rc esegua i suoi comandi post-fs-data. Questi creeranno qualsiasi directory o link necessario e poi imposteranno vold.post_fs_data_done a 1. Una volta che vold vede l’1 in quella proprietà, imposta la proprietà vold.decrypt a trigger_restart_framework. Questo fa sì che init.rc avvii nuovamente i servizi nella classe main e avvii anche i servizi nella classe late_start per la prima volta dall’avvio.

  7. Avvia il framework completo

    Ora il framework avvia tutti i suoi servizi usando il filesystem /data decriptato, e il sistema è pronto all’uso.

Failure

Un dispositivo che non riesce a decifrare potrebbe essere sbagliato per alcune ragioni. Il dispositivo inizia con la normale serie di passi per il boot:

  1. Rileva il dispositivo criptato con una password
  2. Monta tmpfs
  3. Avvia il framework per richiedere la password

Ma dopo che il framework si apre, il dispositivo può incontrare alcuni errori:

  • La password corrisponde ma non può decifrare i dati
  • L’utente inserisce la password sbagliata 30 volte

Se questi errori non sono risolti, invita l’utente a fare un factory wipe:

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 a error_not_encrypted.L’UI chiede all’utente di riavviare e lo avverte che il processo di crittografia non è mai iniziato. Se l’errore si verifica dopo che il framework è stato abbattuto, ma prima che la barra di avanzamento UI sia su, vold riavvierà il sistema. Se il riavvio non riesce, imposta vold.encrypt_progress aerror_shutting_down e restituisce -1; ma non ci sarà nulla per catturare l’errore. Non ci si aspetta che questo accada.

Se vold rileva un errore durante il processo di crittografia, impostavold.encrypt_progress a error_partially_encryptede restituisce -1. L’UI dovrebbe quindi visualizzare un messaggio che dice che la crittografia è fallita e fornire un pulsante per l’utente per resettare il dispositivo.

Memorizzazione della chiave crittografata

La chiave crittografata è memorizzata nei metadati di crittografia. Il supporto hardware è implementato utilizzando la capacità di firma del Trusted Execution Environment (TEE).In precedenza, abbiamo criptato la chiave principale con una chiave generata applicando scrypt alla password dell’utente e al sale memorizzato. 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 poi trasformata in una chiave di lunghezza appropriata da un’altra applicazione di scrypt. Questa chiave viene poi usata per criptare e decriptare la chiave principale. Per memorizzare questa chiave:

  1. Genera una chiave di cifratura del disco (DEK) casuale a 16 byte e un sale a 16 byte.
  2. Applica scrypt alla password utente e al sale per produrre la chiave intermedia 1 (IK1) a 32 byte.
  3. Pad IK1 con zero byte per la dimensione della chiave privata legata all’hardware (HBK): 00 || IK1 || 00..00; un byte zero, 32 byte IK1, 223 byte zero.
  4. Segnamo IK1 imbottito con HBK per produrre 256 byte IK2.
  5. Applica scrypt a IK2 e sale (stesso sale del passo 2) per produrre 32 byte IK3.
  6. Utilizzare i primi 16 byte di IK3 come KEK e gli ultimi 16 byte come IV.
  7. Codifica DEK con AES_CBC, con chiave KEK e vettore di inizializzazione IV.

Modifica della password

Quando un utente sceglie di cambiare o rimuovere la propria password nelle impostazioni, l’UI invia il comando cryptfs changepw a vold, evold ricodifica la chiave master del disco con la nuova password.

Proprietà di crittografia

vold e init comunicano tra loro impostando delle proprietà. Ecco una lista delle proprietà disponibili per la crittografia.

Proprietà di crittografia

Proprietà Descrizione
vold.decrypt trigger_encryption Codifica l’unità senza password.
vold.decrypt trigger_default_encryption Controlla l’unità per vedere se è criptata senza password; se lo è, decriptala e montala, altrimenti imposta vold.decrypt su trigger_restart_min_framework.
vold.decrypt trigger_reset_main Imposta da vold per spegnere l’UI che chiede la password del disco.
vold.decrypt trigger_post_fs_data Imposta da vold per preparare /data con le directory necessarie, ecc.
vold.decrypt trigger_restart_framework Imposta da vold per avviare il vero framework e tutti i servizi.
vold.decrypt trigger_shutdown_framework Imposta da vold per spegnere il framework completo per avviare la crittografia.
vold.decrypt trigger_restart_min_framework Imposta da vold per avviare la barra di avanzamento UI 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, entra in modalità progress bar UI.
vold.encrypt_progress 0 to 100 La progress bar UI dovrebbe visualizzare il valore percentuale impostato.
vold.encrypt_progress error_partially_encrypted La barra di avanzamento UI dovrebbe visualizzare un messaggio che la crittografia è fallita, e dare all’utente un’opzione per resettare il dispositivo.
vold.encrypt_progress error_reboot_failed La barra di avanzamento UI dovrebbe visualizzare un messaggio che dice crittografia completata, e dare all’utente un pulsante per riavviare il dispositivo. Questo errore non dovrebbe accadere.
vold.encrypt_progress error_not_encrypted La barra di avanzamento UI dovrebbe visualizzare un messaggio che dice che si è verificato un errore, nessun dato è stato criptato o perso, e dare all’utente un pulsante per riavviare il sistema.
vold.encrypt_progress error_shutting_down La barra di avanzamento UI non è in esecuzione, quindi non è chiaro chi risponderà a questo errore. E comunque non dovrebbe mai accadere.
vold.post_fs_data_done 0 Imposta da vold appena prima di impostare vold.decrypt a trigger_post_fs_data.
vold.post_fs_data_done 1 Imposta da init.rc o init.rc appena dopo aver finito il compito post-fs-data.

init proprietà

Proprietà Descrizione
ro.crypto.fs_crypto_blkdev Imposta dal comando vold checkpw per essere usata successivamente dal comando vold restart.
ro.crypto.state unencrypted Imposta da init per dire che questo sistema sta funzionando con un /data ro.crypto.state encrypted non criptato. Impostato da init per dire che questo sistema è in esecuzione con un /data criptato.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

Queste cinque proprietà sono impostate da init quando prova a montare /data con parametri passati da init.rc. vold le usa per impostare la mappatura crittografica.
ro.crypto.tmpfs_options Imposta da init.rc con le opzioni che init dovrebbe usare quando monta il filesystem tmpfs /data.

Azioni di init

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.