Come la maggior parte dei software per la crittografia di dischi e file, la crittografia dello spazio di archiviazione di Android tradizionalmente si basa sulle chiavi di crittografia non elaborate presenti nella memoria di sistema per eseguire la crittografia. Anche quando la crittografia viene eseguita da hardware dedicato anziché da software, in genere il software deve comunque e gestire le chiavi di crittografia non elaborate.
In genere questo non viene considerato come un problema perché le chiavi non sono presenti durante un attacco offline, che è il principale tipo di attacco che la crittografia ha lo scopo di proteggere. Tuttavia, c'è il desiderio di fornire Maggiore protezione contro altri tipi di attacchi, come l'avvio a freddo attacchi online e attacchi online nei quali un aggressore potrebbe riuscire a far trapelare il sistema senza compromettere completamente il dispositivo.
Per risolvere il problema, Android 11 ha introdotto il supporto per le chiavi con wrapping hardware, per le quali è presente il supporto hardware. Le chiavi con wrapping hardware sono chiavi di archiviazione note solo in forma non elaborata hardware dedicato; il software vede e utilizza queste chiavi solo nelle (criptato). Questo hardware deve essere in grado di generare e importare le chiavi di archiviazione, eseguendone il wrapping in forme temporanee e a lungo termine, generando le sottochiavi, programmando direttamente una sottochiave in un motore di crittografia in linea e restituendo al software una sottochiave separata.
Nota: un inline crypto Engine (oppure inline) l'hardware di crittografia) si riferisce all'hardware che cripta/decripta i dati mentre mentre è in viaggio verso/dal dispositivo di archiviazione. Di solito si tratta di un host UFS o eMMC che implementa le estensioni di crittografia definite dal specifica JEDEC.
Design
Questa sezione illustra il design della funzionalità dei tasti con wrapping hardware, tra cui: il supporto hardware necessario. Questa discussione si concentra sulla crittografia basata su file (FBE), ma gli si applica ai metadati crittografia.
Un modo per evitare di aver bisogno delle chiavi di crittografia non elaborate nella memoria di sistema è quello di e conservarli solo negli slot delle chiavi di un motore di crittografia in linea. Tuttavia, questo affronta alcuni problemi:
- Il numero di chiavi di crittografia può superare il numero di slot delle chiavi.
- I motori di crittografia in linea possono essere utilizzati solo per criptare/decriptare blocchi completi di i dati su disco. Tuttavia, nel caso di FBE, il software deve comunque essere in grado Eseguire altre operazioni crittografiche, ad esempio la crittografia dei nomi file e la ricavazione della chiave o identificatori univoci. Il software deve comunque accedere alle chiavi FBE non elaborate per fai quest'altro lavoro.
Per evitare questi problemi, le chiavi di archiviazione vengono trasformate in chiavi con wrapping hardware, che possono essere decriptate e utilizzate solo hardware dedicato. In questo modo è possibile supportare un numero illimitato di chiavi. Nella Inoltre, la gerarchia delle chiavi è stata modificata e spostata parzialmente in questo hardware, che consente di restituire al software una sottochiave per attività che non possono utilizzare di crittografia in linea.
Gerarchia delle chiavi
Le chiavi possono essere derivate da altre chiavi utilizzando una KDF (funzione di derivazione della chiave) come HKDF, generando una gerarchia di chiavi.
Il seguente diagramma illustra una tipica gerarchia delle chiavi per FBE quando le chiavi con wrapping hardware non vengono utilizzate:
La chiave di classe FBE è la chiave di crittografia non elaborata che Android passa a Linux. per sbloccare un particolare set di directory criptate, come con crittografia delle credenziali per un determinato utente Android. (Nel kernel, è denominata chiave master fscrypt.) Da questa chiave, il kernel deriva le seguenti sottochiavi:
- L'identificatore della chiave. Non viene utilizzato per la crittografia, ma è un valore utilizzata per identificare la chiave con cui un determinato file o directory viene protette.
- La chiave di crittografia dei contenuti del file
- La chiave di crittografia dei nomi file
Al contrario, il seguente diagramma illustra la gerarchia delle chiavi per FBE quando vengono usate chiavi con wrapping hardware:
Rispetto al caso precedente, è stato aggiunto un livello aggiuntivo alla chiave della gerarchia di contenuti e la chiave di crittografia dei contenuti dei file è stata riposizionata. La radice rappresenta ancora la chiave che Android passa a Linux per sbloccare crittografate con le directory crittografate. Tuttavia, ora la chiave è in forma con wrapping temporaneo e per poter essere utilizzato, deve essere passato all'hardware dedicato. Questo hardware deve implementare due interfacce che prendono una chiave con wrapping temporaneo:
- Un'interfaccia per ricavare
inline_encryption_key
e direttamente programmalo in un keyslot del motore di crittografia in linea. Ciò consente crittografare/decrittare i contenuti senza che il software abbia accesso ai file chiave. Nei kernel comuni di Android, questa interfaccia corrisponde dell'operazioneblk_crypto_ll_ops::keyslot_program
, che deve essere implementato dal driver di archiviazione. - Un'interfaccia per ricavare e restituire
sw_secret
("software segreto" - Chiamato anche "segreto grezzo" in alcuni punti), che è la chiave Linux ricava le sottochiavi per tutto ciò che non riguarda i contenuti dei file la crittografia. Nei kernel comuni di Android, questa interfaccia corrisponde dell'operazioneblk_crypto_ll_ops::derive_sw_secret
, che deve essere implementato dal driver di archiviazione.
per ricavare inline_encryption_key
e sw_secret
dal
chiave di archiviazione non elaborata, l'hardware deve utilizzare un KDF con una crittografia efficace. Questo KDF
Deve seguire le best practice in materia di crittografia. deve avere un livello di sicurezza pari a
almeno 256 bit, ovvero abbastanza per qualsiasi algoritmo utilizzato in seguito. Deve inoltre utilizzare un parametro
stringa di etichette, contesto e/o informazioni specifiche dell'applicazione distinte,
ricavando ciascun tipo di sottochiave per garantire che le sottochiavi risultanti
sono crittograficamente isolati, cioè la conoscenza di una di esse non rivela alcuna
e l'altro. Lo stretching della chiave non è obbligatorio, poiché la chiave di archiviazione non elaborata è già
in modo uniforme casuale.
Tecnicamente, è possibile utilizzare qualsiasi file KDF che soddisfi i requisiti di sicurezza.
Tuttavia, a scopo di test, è necessario reimplementare lo stesso KDF in
di eseguire il test. Attualmente, un KDF è stato esaminato e implementato; puoi trovare
nel codice sorgente di vts_kernel_encryption_test
.
È consigliabile che l'hardware utilizzi questo KDF, che usa NIST SP 800-108 "KDF in Counter Mode" con AES-256-CMAC come PRF. Tieni presente che, per essere compatibili,
parti dell'algoritmo devono essere identiche, inclusa la scelta dei contesti KDF
ed etichette per ogni sottochiave.
Wrapping delle chiavi
Per raggiungere gli obiettivi di sicurezza delle chiavi con wrapping hardware, sono disponibili due tipi di wrapping delle chiavi sono definiti:
- wrapping temporaneo: l'hardware cripta la chiave non elaborata utilizzando una chiave che viene generato casualmente a ogni avvio e non è esposto direttamente all'esterno dell'hardware.
- wrapping a lungo termine: l'hardware cripta la chiave non elaborata utilizzando una una chiave permanente univoca integrata nell'hardware che non è all'esterno dell'hardware.
Tutte le chiavi passate al kernel Linux per sbloccare lo spazio di archiviazione con wrapping temporaneo. Questo assicura che se un utente malintenzionato sia in grado di estrarre un chiave in uso dalla memoria di sistema, questa chiave sarà inutilizzabile non solo fuori dal dispositivo, ma anche sul dispositivo dopo un riavvio.
Allo stesso tempo, Android deve comunque poter archiviare una versione criptata delle chiavi sul disco, in modo da poter essere sbloccate in primo luogo. I dati non elaborati per questo scopo. Tuttavia, è preferibile non avere mai i dati non elaborati siano presenti nella memoria di sistema in modo che non possano mai essere estratte essere utilizzati al di fuori del dispositivo, anche se estratti al momento dell'avvio. Per questo motivo, il concetto del wrapping a lungo termine.
Per supportare la gestione delle chiavi con wrapping in questi due modi diversi, l'hardware deve implementare le seguenti interfacce:
- Interfacce per generare e importare chiavi di archiviazione, restituendole in
con wrapping di un modulo a lungo termine. Si accede a queste interfacce indirettamente
KeyMint e corrispondono al tag KeyMint
TAG_STORAGE_KEY
. Il pulsante "Genera" funzionalità utilizzata davold
per generare nuovo spazio di archiviazione per l'uso da parte di Android, mentre la chiave di "importazione" è utilizzatavts_kernel_encryption_test
per importare le chiavi di test. - Un'interfaccia per convertire una chiave di archiviazione con wrapping a lungo termine in una
chiave di archiviazione con wrapping temporaneo. Corrisponde alla
convertStorageKeyToEphemeral
metodo KeyMint. Questo metodo è utilizzato sia davold
che davts_kernel_encryption_test
nell'ordine per sbloccare lo spazio di archiviazione.
L'algoritmo del wrapping delle chiavi è un dettaglio di implementazione, ma deve utilizzare una AEAD potente come AES-256-GCM con IV casuali.
Modifiche software necessarie
AOSP dispone già di un framework di base per il supporto delle chiavi con wrapping hardware. Questo
include il supporto nei componenti dello spazio utente, come vold
, nonché
come il supporto kernel Linux in blk-crypto, fscrypt e
dm-default-key.
Tuttavia, sono necessarie alcune modifiche specifiche dell'implementazione.
Modifiche a KeyMint
L'implementazione KeyMint del dispositivo deve essere modificata per supportare
TAG_STORAGE_KEY
e implementare
Metodo convertStorageKeyToEphemeral
.
In Keymaster, è stato utilizzato exportKey
al posto di
convertStorageKeyToEphemeral
.
Modifiche al kernel Linux
Il driver del kernel Linux per il motore di crittografia in linea del dispositivo deve essere modificato per supportare chiavi con wrapping hardware.
Per android14
e kernel successivi,
imposta BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
tra blk_crypto_profile::key_types_supported
,
metti blk_crypto_ll_ops::keyslot_program
e blk_crypto_ll_ops::keyslot_evict
supportare la programmazione/la rimozione di chiavi con wrapping hardware,
e implementare blk_crypto_ll_ops::derive_sw_secret
.
Per i kernel android12
e android13
,
imposta BLK_CRYPTO_FEATURE_WRAPPED_KEYS
tra blk_keyslot_manager::features
,
rendi blk_ksm_ll_ops::keyslot_program
e blk_ksm_ll_ops::keyslot_evict
supportare la programmazione/la rimozione di chiavi con wrapping hardware,
e implementare blk_ksm_ll_ops::derive_raw_secret
.
Per android11
kernel,
imposta BLK_CRYPTO_FEATURE_WRAPPED_KEYS
tra keyslot_manager::features
,
metti keyslot_mgmt_ll_ops::keyslot_program
e keyslot_mgmt_ll_ops::keyslot_evict
supportare la programmazione/la rimozione di chiavi con wrapping hardware,
e implementare keyslot_mgmt_ll_ops::derive_raw_secret
.
Test
Sebbene sia più difficile testare la crittografia con chiavi con wrapping hardware rispetto alla crittografia
con le chiavi standard, è comunque possibile eseguire il test importando una chiave di test e
reimplementando la derivazione della chiave eseguita dall'hardware. Questo è implementato
in vts_kernel_encryption_test
. Per eseguire questo test,
esegui:
atest -v vts_kernel_encryption_test
Leggi il log di test e verifica che gli scenari di test delle chiavi con wrapping hardware (ad esempio,
FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
e
DmDefaultKeyTest.TestHwWrappedKey
) non sono state ignorate a causa dell'assistenza
per le chiavi con wrapping hardware che non vengono rilevate, in quanto i risultati del test saranno comunque
"superato" in quel caso.
Attivazione in corso
Quando il supporto della chiave con wrapping hardware del dispositivo funziona correttamente, puoi
apporta le seguenti modifiche al file fstab
del dispositivo per apportare
Android lo usa per il servizio FBE e la crittografia dei metadati:
- FBE: aggiungi il flag
wrappedkey_v0
allafileencryption
. Ad esempio, utilizzafileencryption=::inlinecrypt_optimized+wrappedkey_v0
. Per ulteriori dettagli, consulta FBE documentazione. - Crittografia dei metadati: aggiungi il flag
wrappedkey_v0
allametadata_encryption
. Ad esempio, utilizzametadata_encryption=:wrappedkey_v0
. Per ulteriori dettagli, consulta metadati documentazione sulla crittografia.