Il kernel GKI include un
modulo del kernel Linux chiamato fips140.ko
che è 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.
Prima di poter utilizzare le routine crittografiche, devono essere soddisfatti i seguenti requisiti FIPS 140-3 in particolare:
- Il modulo deve verificare la propria integrità prima di rendere disponibili gli algoritmi crittografici.
- Il modulo deve esercitare e verificare i propri 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 certificato, un modulo basato su hardware o software non viene mai modificato. Se viene modificata, deve essere nuovamente certificata. Questo non corrisponde facilmente ai processi di sviluppo software attualmente in uso e, a causa di questo requisito, i moduli software FIPS sono generalmente progettati per essere il più possibile incentrati sui componenti crittografici, per garantire che le modifiche non correlate alla crittografia non richiedano una rivalutazione della crittografia.
Il kernel GKI è pensato per essere aggiornato regolarmente durante l'intero ciclo di vita supportato. Ciò rende impossibile che l'intero kernel rientri nei limiti del modulo FIPS, poiché un modulo di questo tipo deve essere ricertificato a ogni aggiornamento del kernel. Definire il "modulo FIPS" come un sottoinsieme dell'immagine del kernel attenuarebbe questo problema, ma non lo risolverebbe, poiché i contenuti binari del "modulo FIPS" cambierebbero comunque molto più di frequente del necessario.
Prima della versione 6.1 del kernel, occorreva considerare anche che GKI veniva compilato con LTO (Link Time Optimization) abilitato, dato che LTO era un prerequisito per l'Integrità del flusso di controllo, un'importante funzionalità di sicurezza.
Di conseguenza, tutto il codice coperto dai requisiti FIPS 140-3 viene pacchettizzato in un modulo kernel separato fips140.ko
che si basa solo su interfacce stabili esposte dal codice sorgente GKI da cui è stato creato. Ciò significa che il modulo può essere utilizzato con release GKI diverse della stessa generazione e che deve essere aggiornato e inviato nuovamente per la certificazione solo se sono stati corretti eventuali problemi nel codice del modulo stesso.
Quando utilizzare il modulo
Il kernel GKI stesso contiene codice che dipende dalle routine di crittografia che sono anche pacchettizzate nel modulo del kernel FIPS 140-3. Pertanto, le routine di crittografia predefinite non vengono rimosse dal kernel GKI, ma vengono copiate nel modulo. Quando il modulo viene caricato, le routine di crittografia integrate vengono ritirate da CryptoAPI di Linux e sostituite da quelle del 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 questo, il modulo non offre funzionalità aggiuntive e il suo caricamento non necessario potrebbe influire solo sul tempo di avvio, senza alcun vantaggio.
Come eseguire il deployment del modulo
Il modulo può essere incorporato nella build di Android seguendo i seguenti passaggi:
- Aggiungi il nome del modulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
. Il modulo viene quindi copiato nella ramdisk del fornitore. - Aggiungi il nome del modulo a
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
. In questo modo, il nome del modulo viene aggiunto amodules.load
nel target.modules.load
contiene l'elenco dei moduli caricati dainit
all'avvio del dispositivo.
Il controllo di integrità autonomo
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. Questo avviene dopo che il caricatore di moduli Linux ha già apportato le modifiche consuete, come l'elaborazione del ricollocamento ELF e le patch di alternative per gli errori della CPU a queste sezioni. Per garantire che il digest possa essere riprodotto correttamente, vengono eseguiti i seguenti passaggi aggiuntivi:
- Le rilocazioni ELF vengono conservate all'interno del modulo in modo che possano essere applicate in modo inverso all'input dell'HMAC.
- Il modulo annulla eventuali patch di codice apportate dal kernel per lo stack di chiamate dinamico ombra. Nello specifico, il modulo sostituisce tutte le istruzioni che push o pop dallo stack di chiamate shadow con le istruzioni del codice di autenticazione del puntatore (PAC) presenti inizialmente.
- Tutte le altre patch di codice sono disattivate per il modulo, incluse le chiavi statiche e quindi i tracepoint, nonché gli hook del fornitore.
I test di autovalutazione con risposta nota
Tutti gli algoritmi implementati che sono coperti dai requisiti FIPS 140-3 devono eseguire un autotest a risposta nota prima di essere utilizzati. In base alle Indicazioni per l'implementazione FIPS 140-3 10.3.A, un singolo vettore di test per algoritmo che utilizza una delle lunghezze della chiave supportate è sufficiente per le chiavi, a condizione che vengano testati sia la crittografia sia la decrittografia.
CryptoAPI di Linux ha un concetto di priorità dell'algoritmo, in cui possono coesistere diverse implementazioni (ad esempio una che utilizza istruzioni di crittografia speciali e una di riserva per le CPU che non le implementano) dello stesso algoritmo. Di conseguenza, è necessario testare tutte le implementazioni dello stesso algoritmo. Questo è necessario perché CryptoAPI di Linux consente di aggirare la selezione in base alla priorità e di selezionare un algoritmo con priorità inferiore.
Algoritmi inclusi nel modulo
Tutti gli algoritmi inclusi nel modulo FIPS 140-3 sono elencati di seguito.
Questo vale per i rami del kernel android12-5.10
, android13-5.10
, android13-5.15
,
android14-5.15
, android14-6.1
e android15-6.6
, anche se
le differenze tra le versioni del kernel sono indicate ove opportuno.
Algoritmo | Implementazioni | Approvabile | Definizione |
---|---|---|---|
aes |
aes-generic , aes-arm64 , aes-ce , libreria AES |
Sì | Cifratura a blocchi AES senza modalità di funzionamento: sono supportate tutte le dimensioni delle chiavi (128 bit, 192 bit e 256 bit). Tutte le implementazioni diverse da quella della libreria possono essere composte con una modalità di funzionamento 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 del testo crittografato: la convenzione utilizzata è CS3 ; gli ultimi due blocchi di testo crittografato 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: nella versione del kernel 6.1 e precedenti, sono supportate tutte le dimensioni delle chiavi AES; nella versione del kernel 6.6 e successive, sono supportati solo AES-128 e AES-256. 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 delle chiavi deboli richiesto da FIPS, ovvero le chiavi XTS la cui prima e seconda metà sono uguali vengono rifiutate. |
gcm(aes) |
gcm (modello), gcm-aes-ce |
No1 | 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, è compito dell'utente chiamante fornire gli IV. Il modello gcm può essere composto con qualsiasi implementazione di ctr(aes) e ghash utilizzando gcm_base(<ctr(aes)-impl>,<ghash-impl>) . Le altre implementazioni sono autonome. |
sha1 |
sha1-generic , sha1-ce |
Sì | Funzione di hash crittografica SHA-1 |
sha224 |
sha224-generic , sha224-arm64 e sha224-ce |
Sì | Funzione hash crittografica SHA-224: il codice viene condiviso con SHA-256. |
sha256 |
sha256-generic , sha256-arm64 , sha256-ce , libreria SHA-256 |
Sì | Funzione hash crittografica SHA-256: a SHA-256 viene fornita un'interfaccia della libreria oltre all'interfaccia CryptoAPI standard. L'interfaccia di questa libreria utilizza un'implementazione diversa. |
sha384 |
sha384-generic , sha384-arm64 e sha384-ce |
Sì | Funzione hash crittografica SHA-384: il codice viene condiviso con l'algoritmo SHA-512. |
sha512 |
sha512-generic , sha512-arm64 e sha512-ce |
Sì | Funzione di hash crittografica SHA-512 |
sha3-224 |
sha3-224-generic |
Sì | Funzione di hash crittografica SHA3-224. Presente solo nella versione del kernel 6.6 e successive. |
sha3-256 |
sha3-256-generic |
Sì | Uguale al precedente, ma con una lunghezza del digest di 256 bit (SHA3-256). Tutte le lunghezze del digest utilizzano la stessa implementazione di Keccak. |
sha3-384 |
sha3-384-generic |
Sì | Come sopra, ma con una lunghezza del digest di 384 bit (SHA3-384). Tutte le lunghezze del digest utilizzano la stessa implementazione di Keccak. |
sha3-512 |
sha3-512-generic |
Sì | Come sopra, ma con una lunghezza del digest di 512 bit (SHA3-512). Tutte le lunghezze del digest utilizzano la stessa implementazione di Keccak. |
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ì | Istanza HMAC_DRBG creata con la funzione hash denominata e con resistenza alle previsioni abilitata: sono inclusi i controlli di integrità. 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ì | Gli stessi algoritmi di drbg_pr_* , ma con la resistenza alla previsione disattivata. Il codice è condiviso con la variante resistente alle previsioni. Nella versione del kernel 5.10, la DRBG con la priorità più alta è drbg_nopr_hmac_sha256 . Nella versione del kernel 5.15 e successive, è drbg_pr_hmac_sha512 . |
jitterentropy_rng |
jitterentropy_rng |
No | Jitter RNG, versione 2.2.0 (kernel versione 6.1 e precedenti) o versione 3.4.0 (kernel versione 6.6 e successive). Gli utenti di questa interfaccia ricevono le proprie istanze Jitter RNG. Non riutilizzano le istanze utilizzate dai DRBG. |
xcbc(aes) |
xcbc-aes-neon , xcbc-aes-ce |
No | |
xctr(aes) |
xctr-aes-neon , xctr-aes-ce |
No | Presente solo nella versione del kernel 5.15 e successive. |
cbcmac(aes) |
cbcmac-aes-neon , cbcmac-aes-ce |
No | |
essiv(cbc(aes),sha256) |
essiv-cbc-aes-sha256-neon , essiv-cbc-aes-sha256-ce |
No |
Compila il modulo dal codice sorgente
Per Android 14 e versioni successive (incluso android-mainline
), crea il modulo fips140.ko
dal codice sorgente utilizzando i comandi seguenti.
Crea con Bazel:
tools/bazel run //common:fips140_dist
Crea con
build.sh
(precedente):BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
Questi comandi eseguono una compilazione completa che include il kernel e il fips140.ko
modulo con i contenuti del digest HMAC-SHA256 incorporati.
Guida per gli utenti finali
Indicazioni per l'ufficiale di crittografia
Per utilizzare il modulo del kernel, il sistema operativo deve essere limitato a una modalità di funzionamento con un solo operatore. Questa operazione viene gestita automaticamente da Android utilizzando l'hardware di gestione della memoria nel processore.
Il modulo del kernel non può essere installato separatamente; è incluso nel firmware del dispositivo e caricato automaticamente all'avvio. Funziona solo in una modalità di funzionamento approvata.
L'addetto alla crittografia può eseguire i test di autodiagnosi in qualsiasi momento riavviando il dispositivo.
Indicazioni per l'utente
Gli utenti del modulo kernel sono altri componenti del kernel che devono usare algoritmi di crittografia. Il modulo del kernel non fornisce logica aggiuntiva per l'utilizzo degli algoritmi e non memorizza parametri oltre il tempo necessario per eseguire un'operazione di crittografia.
L'utilizzo degli algoritmi ai fini della conformità FIPS è limitato agli algoritmi approvati. Per soddisfare il requisito di "indicatore di servizio" FIPS 140-3, il modulo fornisce una funzione fips140_is_approved_service
che indica se un algoritmo è approvato.
Errori di diagnostica automatica
In caso di errore di autotest, il modulo kernel fa "panic" il kernel e il dispositivo non continua ad avviarsi. Se il riavvio del dispositivo non risolve il problema, il dispositivo deve avviarsi in modalità di ripristino per correggere il problema eseguendo il riflash.
-
È previsto che le implementazioni AES-GCM del modulo possano essere "approvate da 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 non sono compatibili con le implementazioni GCM che non generano i propri IV. ↩