Il kernel GKI include un modulo kernel Linux chiamato fips140.ko
conforme ai requisiti FIPS 140-3 per i moduli software crittografici. Questo modulo può essere inviato per la certificazione FIPS se il prodotto che esegue il kernel GKI lo richiede.
I seguenti requisiti FIPS 140-3 in particolare devono essere soddisfatti prima che le routine crittografiche possano essere utilizzate:
- Il modulo deve verificare la propria integrità prima di rendere disponibili gli algoritmi crittografici.
- Il modulo deve esercitare e verificare i suoi algoritmi crittografici approvati utilizzando autotest con risposta nota prima di renderli disponibili.
Perché un modulo kernel separato
La convalida FIPS 140-3 si basa sull'idea che una volta che un modulo basato su software o hardware è stato certificato, non viene mai modificato. Se modificato, deve essere ricertificato. Ciò non corrisponde facilmente ai processi di sviluppo software in uso oggi e, come risultato di questo requisito, i moduli software FIPS sono generalmente progettati per essere il più strettamente focalizzati possibile sui componenti crittografici, per garantire che le modifiche non correlate alla crittografia non richiedono una rivalutazione della crittografia.
Il kernel GKI è progettato per essere aggiornato regolarmente durante l'intero ciclo di vita supportato. Ciò rende impossibile che l'intero kernel si trovi all'interno del limite del modulo FIPS, poiché tale modulo deve essere ricertificato ad ogni aggiornamento del kernel. Inoltre, GKI è compilato con LTO (Link Time Optimization) abilitato, poiché LTO è un prerequisito per CFI che è un'importante caratteristica di sicurezza. Ciò rende impossibile tracciare il confine del modulo FIPS solo attorno al codice crittografico del kernel, poiché tale codice non si trova in una posizione chiaramente definita nel binario risultante. Gli aggiornamenti del kernel possono anche modificare il codice crittografico.
Pertanto, tutto il codice coperto dai requisiti FIPS 140-3 è impacchettato in un modulo kernel separato fips140.ko
che si basa solo su interfacce stabili esposte dalla sorgente del kernel GKI da cui è stato creato. Ciò garantisce che il modulo può essere utilizzato con diverse versioni GKI della stessa generazione e che deve essere aggiornato e inviato nuovamente per la certificazione solo se sono stati risolti eventuali problemi nel codice trasportato dal modulo stesso.
Quando utilizzare il modulo
Il kernel GKI stesso contiene codice che dipende dalle routine crittografiche che sono anche impacchettate nel modulo kernel FIPS 140-3. Pertanto, le routine di crittografia integrate non vengono effettivamente spostate fuori dal kernel GKI, ma piuttosto vengono copiate nel modulo. Quando il modulo viene caricato, le routine di crittografia integrate vengono cancellate dalla Linux CryptoAPI e sostituite da quelle trasportate dal modulo.
Ciò significa che il modulo fips140.ko
è completamente facoltativo e ha senso implementarlo solo se la certificazione FIPS 140-3 è un requisito. Oltre a ciò, il modulo non fornisce alcuna funzionalità aggiuntiva e caricarlo inutilmente può solo influire sul tempo di avvio, senza fornire alcun vantaggio.
Come distribuire il modulo
Il modulo può essere incorporato nella build Android utilizzando i seguenti passaggi:
- Aggiungi il nome del modulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
. Questo fa sì che il modulo venga copiato nel ramdisk del fornitore. - Aggiungi il nome del modulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
. Questo fa sì che il nome del modulo venga aggiunto amodules.load
sulla destinazione.modules.load
contiene l'elenco dei moduli caricati dainit
all'avvio del dispositivo.
L'autocontrollo di integrità
Il modulo del kernel FIPS 140-3 prende il digest HMAC-SHA256 delle proprie sezioni .code
e .rodata
al momento del caricamento del modulo e lo confronta con il digest registrato nel modulo. Ciò avviene dopo che il caricatore di moduli Linux ha già apportato le solite modifiche come l'elaborazione del riposizionamento ELF e l'applicazione di patch alternative per gli errori della CPU a quelle sezioni. Vengono eseguiti i seguenti passaggi aggiuntivi per garantire che il digest possa essere riprodotto correttamente:
- Le rilocazioni ELF sono conservate all'interno del modulo in modo che possano essere applicate in senso inverso all'ingresso dell'HMAC.
- Tutte le altre patch del codice sono disabilitate per il modulo, comprese le chiavi statiche e quindi i tracepoint e i vendor hook.
Gli autotest a risposta nota
Tutti gli algoritmi implementati coperti dai requisiti FIPS 140-3 devono eseguire un autotest con risposta nota prima di essere utilizzati. Secondo FIPS 140-3 Implementation Guidance 10.3.A , un singolo vettore di test per algoritmo che utilizza una qualsiasi delle lunghezze di chiave supportate è sufficiente per le crittografie, a condizione che vengano testate sia la crittografia che la decrittografia.
La Linux CryptoAPI ha una nozione di priorità dell'algoritmo, in cui possono coesistere diverse implementazioni (come una che utilizza speciali istruzioni crittografiche e un fallback per le CPU che non implementano tali istruzioni) dello stesso algoritmo. Pertanto, è necessario testare tutte le implementazioni dello stesso algoritmo. Ciò è necessario perché Linux CryptoAPI consente di eludere la selezione basata sulla priorità e di selezionare invece un algoritmo con priorità inferiore.
Algoritmi inclusi nel modulo
Tutti gli algoritmi inclusi nel modulo FIPS 140-3 quando compilati dalle fonti android13-5.10 sono elencati di seguito.
Algoritmo | Implementazioni | Approvabile | Definizione |
---|---|---|---|
aes | aes-generic , aes-arm64 , aes-ce , libreria AES | sì | Cifratura a blocchi AES semplice, senza modalità operativa: sono supportate tutte le dimensioni delle chiavi (128 bit, 192 bit e 256 bit). Tutte le implementazioni diverse dall'implementazione della libreria possono essere composte con una modalità operativa tramite un modello. |
cmac(aes) | cmac (modello), cmac-aes-neon , cmac-aes-ce | sì | AES-CMAC: sono supportate tutte le dimensioni delle chiavi AES. Il modello cmac può essere composto con qualsiasi implementazione di aes utilizzando cmac(<aes-impl>) . Le altre implementazioni sono autonome. |
ecb(aes) | ecb (modello), ecb-aes-neon , ecb-aes-neonbs , ecb-aes-ce | sì | AES-ECB: sono supportate tutte le dimensioni delle chiavi AES. Il modello ecb può essere composto con qualsiasi implementazione di aes utilizzando ecb(<aes-impl>) . Le altre implementazioni sono autonome. |
cbc(aes) | cbc (modello), cbc-aes-neon , cbc-aes-neonbs , cbc-aes-ce | sì | AES-CBC: sono supportate tutte le dimensioni delle chiavi AES. Il modello cbc può essere composto con qualsiasi implementazione di aes utilizzando ctr(<aes-impl>) . Le altre implementazioni sono autonome. |
cts(cbc(aes)) | cts (modello), cts-cbc-aes-neon , cts-cbc-aes-ce | sì | AES-CBC-CTS o AES-CBC con furto di testo cifrato: la convenzione utilizzata è CS3 ; gli ultimi due blocchi di testo cifrato vengono scambiati incondizionatamente. Sono supportate tutte le dimensioni delle chiavi AES. Il modello cts può essere composto con qualsiasi implementazione di cbc utilizzando cts(<cbc(aes)-impl>) . Le altre implementazioni sono autonome. |
ctr(aes) | ctr (modello), ctr-aes-neon , ctr-aes-neonbs , ctr-aes-ce | sì | AES-CTR: sono supportate tutte le dimensioni delle chiavi AES. Il modello ctr può essere composto con qualsiasi implementazione di aes utilizzando ctr(<aes-impl>) . Le altre implementazioni sono autonome. |
xts(aes) | xts (modello), xts-aes-neon , xts-aes-neonbs , xts-aes-ce | sì | AES-XTS: sono supportate tutte le dimensioni delle chiavi AES. Il modello xts può essere composto con qualsiasi implementazione di ecb(aes) utilizzando xts(<ecb(aes)-impl>) . Le altre implementazioni sono autonome. Tutte le implementazioni implementano il controllo della chiave debole richiesto da FIPS; ovvero, le chiavi XTS la cui prima e seconda metà sono uguali vengono rifiutate. |
gcm(aes) | gcm (modello), gcm-aes-ce | N. 1 | AES-GCM: sono supportate tutte le dimensioni delle chiavi AES. Sono supportati solo IV a 96 bit. Come per tutte le altre modalità AES in questo modulo, il chiamante è responsabile della fornitura degli IV. Il modello gcm può essere composto con qualsiasi implementazione di ctr(aes) e ghash usando gcm_base(<ctr(aes)-impl>,<ghash-impl>) . Le altre implementazioni sono autonome. |
sha1 | sha1-generic , sha1-ce | sì | Funzione hash crittografica SHA-1 |
sha224 | sha224-generic , sha224-arm64 , sha224-ce | sì | Funzione hash crittografica SHA-224: il codice è condiviso con SHA-256. |
sha256 | sha256-generic , sha256-arm64 , sha256-ce , libreria SHA-256 | sì | Funzione hash crittografica SHA-256: un'interfaccia di libreria viene fornita a SHA-256 oltre alla tradizionale interfaccia CryptoAPI. Questa interfaccia della libreria utilizza un'implementazione diversa. |
sha384 | sha384-generic , sha384-arm64 , sha384-ce | sì | Funzione hash crittografica SHA-384: il codice è condiviso con SHA-512. |
sha512 | sha512-generic , sha512-arm64 , sha512-ce | sì | Funzione hash crittografica SHA-512 |
hmac | hmac (modello) | sì | HMAC (Keyed-Hash Message Authentication Code): il modello hmac può essere composto con qualsiasi algoritmo o implementazione SHA utilizzando hmac(<sha-alg>) o hmac(<sha-impl>) . |
stdrng | drbg_pr_hmac_sha1 , drbg_pr_hmac_sha256 , drbg_pr_hmac_sha384 , drbg_pr_hmac_sha512 | sì | HMAC_DRBG istanziato con la funzione hash denominata e con la resistenza alla previsione abilitata: i controlli di integrità sono inclusi. Gli utenti di questa interfaccia ottengono le proprie istanze DRBG. |
stdrng | drbg_nopr_hmac_sha1 , drbg_nopr_hmac_sha256 , drbg_nopr_hmac_sha384 , drbg_nopr_hmac_sha512 | sì | Uguale agli algoritmi drbg_pr_* , ma con la resistenza alla previsione disabilitata. Il codice è condiviso con la variante resistente alla previsione. Il DRBG con priorità più alta è drbg_nopr_hmac_sha256 . |
jitterentropy_rng | jitterentropy_rng | No | Versione 2.2.0 di Jitter RNG : gli utenti di questa interfaccia ottengono le proprie istanze di Jitter RNG. Non riutilizzano le istanze utilizzate dai DRBG. |
xcbc(aes) | xcbc-aes-neon , xcbc-aes-ce | No | |
cbcmac(aes) | cbcmac-aes-neon , cbcmac-aes-ce | No | |
essiv(cbc(aes),sha256) | essiv-cbc-aes-sha256-neon , essiv-cbc-aes-sha256-ce | No |
Costruire il modulo dal sorgente
Il modulo fips140.ko
può essere compilato dai sorgenti del kernel GKI utilizzando il seguente comando:
BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
Questo esegue la compilazione completa con il kernel e il modulo fips140.ko
, con il digest HMAC-SHA256 corretto del suo contenuto incorporato.
In Android 14 (AOSP sperimentale) e versioni successive, compila con Bazel anziché build/build.sh
utilizzando il seguente comando:
tools/bazel run //common:fips140_dist
Guida per l'utente finale
Guida dell'ufficiale crittografico
Per far funzionare il modulo kernel, il sistema operativo deve essere limitato a una modalità operativa a singolo operatore. Questo viene gestito automaticamente da Android utilizzando l'hardware di gestione della memoria nel processore.
Il modulo del kernel non può essere installato separatamente; è incluso come parte del firmware del dispositivo e viene caricato automaticamente all'avvio. Funziona solo in una modalità operativa approvata.
Il Crypto Officer può eseguire gli autotest in qualsiasi momento riavviando il dispositivo.
Guida per l'utente
L'utente del modulo del kernel sono altri componenti del kernel che devono utilizzare algoritmi crittografici. Il modulo kernel non fornisce logica aggiuntiva nell'uso degli algoritmi e non memorizza alcun parametro oltre il tempo necessario per eseguire un'operazione crittografica.
L'uso degli algoritmi ai fini della conformità FIPS è limitato agli algoritmi approvati. Per soddisfare il requisito "indicatore di servizio" FIPS 140-3, il modulo fornisce una funzione fips140_is_approved_service
che indica se un algoritmo è approvato.
Errori di autotest
In caso di errore dell'autotest, il modulo del kernel provoca il panico del kernel e il dispositivo non continua l'avvio. Se un riavvio del dispositivo non risolve il problema, il dispositivo deve avviarsi in modalità di ripristino per correggere il problema eseguendo nuovamente il flashing del dispositivo.
Si prevede che le implementazioni AES-GCM del modulo possano essere "approvate dall'algoritmo" ma non "approvate dal modulo". Possono essere convalidati, ma AES-GCM non può essere considerato un algoritmo approvato dal punto di vista del modulo FIPS. Questo perché i requisiti del modulo FIPS per GCM sono incompatibili con le implementazioni GCM che non generano i propri IV. ↩