Crittografia dell'intero disco

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

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 crittografati automaticamente prima di eseguirne il commit su disco e tutte le letture decrittografano automaticamente i dati prima di restituirli al processo di chiamata.

La crittografia dell'intero disco è stata introdotta in Android in 4.4, ma Android 5.0 ha introdotto queste nuove funzionalità:

  • Crittografia rapida 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 veloce.
  • Aggiunto il flag fstab forceencrypt per crittografare al primo avvio.
  • Aggiunto supporto per modelli e crittografia senza password.
  • Aggiunta l'archiviazione supportata dall'hardware della chiave di crittografia utilizzando la funzionalità di firma di Trusted Execution Environment (TEE) (ad esempio in una TrustZone). Per ulteriori dettagli, vedere Memorizzazione della chiave crittografata .

Attenzione: i dispositivi aggiornati ad Android 5.0 e quindi crittografati possono 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 di 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) ed 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 opzionale).

Nota: gli OEM possono utilizzare 128 bit o versioni successive per crittografare la chiave principale.

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 esegue l'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 di Android Open Source Project.

Quando l'utente imposta il PIN/pass o la password sul dispositivo, solo la chiave a 128 bit viene nuovamente crittografata e memorizzata. (ad es. le modifiche al PIN/pass/modello utente NON causano la ricrittografia 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 gli eventi in init. Altre parti del sistema esaminano anche 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 cryptfs di vdc dello strumento a riga di comando : checkpw , 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 progressi o suggerire una cancellazione dei dati secondo necessità. Impone la limitazione che per passare dal filesystem temporaneo al vero filesystem /data , il sistema deve interrompere ogni processo con file aperti sul filesystem temporaneo e riavviare quei processi sul filesystem /data reale. Per fare ciò, tutti i servizi devono essere in uno dei tre gruppi: core , main e late_start .

  • core : non si spegne mai dopo l'avvio.
  • main : Spegnere e riavviare dopo aver immesso 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 : interrompe un servizio e aggiunge un flag SVC_DISABLED . I servizi interrotti non rispondono a class_start .

Flussi

Esistono quattro flussi per un dispositivo crittografato. Un dispositivo viene crittografato solo una volta e quindi segue un normale flusso di avvio.

  • Crittografa 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 precedenti).
  • 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 . 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.

  1. Rileva filesystem non crittografato con flag forceencrypt

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

  2. Inizia a crittografare /data

    vold.decrypt = "trigger_encryption" attiva init.rc , che farà crittografare vold /data senza password. (Nessuno è impostato perché questo dovrebbe essere un nuovo dispositivo.)

  3. Monta tmpfs

    vold monta un tmpfs /data (usando le opzioni tmpfs da ro.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

  4. Visualizza il quadro 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 così rapidamente. Per ulteriori dettagli sull'interfaccia utente di avanzamento, vedere Crittografare un dispositivo esistente .

  5. Quando /data è crittografato, rimuovere il framework

    vold imposta vold.decrypt su trigger_default_encryption che avvia il servizio defaultcrypto . (Ciò avvia il flusso seguente per il montaggio di dati utente crittografati predefiniti.) 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 decidiamo e montiamo /data .

  6. Monta /data

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

  7. Avvia quadro

    Imposta vold su trigger_restart_framework , che continua il normale processo di avvio.

Crittografa un dispositivo esistente

Questo è ciò che accade quando si crittografa un dispositivo Android K o precedente non crittografato di cui è stata eseguita la migrazione 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 energia sufficiente per completare il processo di crittografia.

Avvertenza: se il dispositivo si scarica e si spegne prima che la crittografia sia terminata, i dati dei file vengono lasciati 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 sul dispositivo a blocchi crittografici. 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.

  1. Controlla la password

    L'interfaccia utente chiama vold con il comando cryptfs enablecrypto inplace dove passwd è la password della schermata di blocco dell'utente.

  2. Abbattere la struttura

    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 su trigger_shutdown_framework . Questo fa sì che init.rc arresti i servizi nelle classi late_start e main .

  3. Crea un piè di pagina crittografico
  4. Crea un file breadcrumb
  5. Riavviare
  6. Rileva file breadcrumb
  7. Inizia a crittografare /data

    vold quindi imposta la mappatura crittografica, che crea un dispositivo a blocchi crittografici virtuale che esegue la mappatura 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.

  8. Mentre sta crittografando, monta tmpfs

    vold monta un tmpfs /data (usando le opzioni tmpfs da ro.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

  9. Visualizza il quadro per mostrare i progressi

    trigger_restart_min_framework fa sì che init.rc avvii la classe main di servizi. Quando il framework vede che vold.encrypt_progress è impostato su 0, fa apparire l'interfaccia utente della barra di avanzamento, che interroga tale proprietà ogni cinque secondi e aggiorna una barra di avanzamento. Il ciclo di crittografia aggiorna vold.encrypt_progress ogni volta che crittografa un'altra percentuale della partizione.

  10. Quando /data è crittografato, aggiorna il piè di pagina della crittografia

    Quando /data viene crittografato correttamente, vold cancella il flag ENCRYPTION_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 su error_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 quindi questo è lo stato di crittografia predefinito .

  1. Rileva /data crittografati senza password

    Rileva che il dispositivo Android è crittografato perché /data non può essere montato ed è impostato uno dei flag encryptable o forceencrypt .

    vold imposta vold.decrypt su trigger_default_encryption , che avvia il servizio defaultcrypto . trigger_default_encryption controlla il tipo di crittografia per vedere se /data è crittografato con o senza password.

  2. Decrittografa /dati

    Crea il dispositivo dm-crypt sul dispositivo a blocchi in modo che il dispositivo sia pronto per l'uso.

  3. Monta /dati

    vold quindi monta la partizione reale /data decrittografata e quindi prepara la nuova partizione. Imposta la proprietà vold.post_fs_data_done su 0 e quindi imposta vold.decrypt su trigger_post_fs_data . Questo fa sì che init.rc esegua i suoi comandi post-fs-data . Creeranno tutte le directory o i collegamenti necessari e quindi imposteranno vold.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ì 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.

  4. Avvia quadro

    Ora il framework avvia tutti i suoi servizi usando il decrypted /data 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.

  1. Rileva dispositivo crittografato con una password

    Rileva che il dispositivo Android è crittografato perché il flag ro.crypto.state = "encrypted"

    vold imposta vold.decrypt su trigger_restart_min_framework perché /data è crittografato con una password.

  2. Monta tmpfs

    init imposta cinque proprietà per salvare le opzioni di montaggio iniziali fornite per /data con parametri passati da init.rc . vold utilizza 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 di 8 cifre ASCII preceduto da 0x)
  3. Avvia il framework per richiedere la password

    Il framework si avvia e vede che vold.decrypt è impostato su trigger_restart_min_framework . Questo dice al framework che si sta avviando su un disco tmpfs /data e deve ottenere la password dell'utente.

    Innanzitutto, tuttavia, deve assicurarsi che il disco sia stato crittografato correttamente. Invia il comando cryptfs cryptocomplete a vold . 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 flag CRYPTO_ENCRYPTION_IN_PROGRESS . Se è impostato, il processo di crittografia è stato interrotto e sul dispositivo non sono presenti dati utilizzabili. Se vold 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.

  4. Decrittografare i dati con password

    Una volta cryptfs cryptocomplete ha esito positivo, il framework visualizza un'interfaccia utente che richiede la password del disco. L'interfaccia utente verifica la password inviando il comando cryptfs checkpw a vold . Se la password è corretta (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.

  5. Arresta il quadro

    L'interfaccia utente crea un grafico di avvio crittografico e quindi chiama vold con il comando cryptfs restart . vold imposta la proprietà vold.decrypt su trigger_reset_main , che fa in modo che init.rc class_reset main . Ciò interrompe tutti i servizi nella classe principale, il che consente di smontare tmpfs /data .

  6. Monta /data

    vold quindi monta la partizione reale /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 imposta vold.decrypt su trigger_post_fs_data . Questo fa sì che init.rc esegua i suoi comandi post-fs-data . Creeranno tutte le directory o i collegamenti necessari e quindi imposteranno vold.post_fs_data_done su 1. Una volta che vold vede 1 in quella proprietà, imposta la proprietà vold.decrypt su trigger_restart_framework . Ciò 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 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:

  1. Rileva dispositivo crittografato con una password
  2. Monta tmpfs
  3. 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 avverte che il processo di crittografia non è mai stato avviato. 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 non riesce, 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 informa che la crittografia non è riuscita e fornire un pulsante per consentire all'utente di ripristinare le impostazioni di fabbrica del dispositivo.

Memorizzazione della chiave crittografata

La chiave crittografata viene archiviata nei metadati crittografici. Il supporto hardware viene implementato utilizzando la funzionalità di firma di Trusted Execution Environment (TEE). In precedenza, abbiamo crittografato la chiave master con una chiave generata applicando scrypt alla password dell'utente e al salt 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 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:

  1. Genera chiave di crittografia del disco (DEK) casuale a 16 byte e salt a 16 byte.
  2. Applicare scrypt alla password dell'utente e al salt per produrre la chiave intermedia 1 (IK1) a 32 byte.
  3. Riempire IK1 con zero byte alla dimensione della chiave privata associata all'hardware (HBK). In particolare, riempiamo come: 00 || IK1 || 00..00; uno zero byte, 32 IK1 byte, 223 zero byte.
  4. Firma IK1 riempito con HBK per produrre IK2 a 256 byte.
  5. Applicare scrypt a IK2 e salt (lo stesso salt del passaggio 2) per produrre IK3 a 32 byte.
  6. Utilizzare i primi 16 byte di IK3 come KEK e gli ultimi 16 byte come IV.
  7. 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 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à Vold

Proprietà Descrizione
vold.decrypt trigger_encryption Crittografa l'unità senza password.
vold.decrypt trigger_default_encryption Controllare l'unità per vedere se è crittografata senza password. Se lo è, decifralo 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 il framework completo 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 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 L'interfaccia utente della barra di avanzamento dovrebbe visualizzare un messaggio che informa 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 informa 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 accadere.
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 un uso successivo dal comando vold restart .
ro.crypto.state unencrypted Impostato da init per dire che questo sistema è in esecuzione con un /data ro.crypto.state encrypted . Impostato da init per dire che questo sistema è in esecuzione con un /data crittografato.

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 tenta di montare /data con 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 usare durante il montaggio del filesystem tmpfs /data .

Inizia le 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