Archivio chiavi supportato da hardware

La disponibilità di un ambiente di esecuzione attendibile in un sistema su un chip (SoC) offre ai dispositivi Android l'opportunità di fornire servizi di sicurezza efficaci e basati su hardware al sistema operativo Android, ai servizi di piattaforma e persino alle app di terze parti (sotto forma di estensioni specifiche per Android all'architettura di crittografia Java standard, consulta KeyGenParameterSpec).

Glossario

Ecco una breve panoramica dei componenti del Keystore e delle relative relazioni.

AndroidKeyStore
L'API e il componente del framework Android utilizzati dalle app per accedere alla funzionalità Keystore. Si tratta di un'implementazione delle API Java Cryptography Architecture standard, ma aggiunge anche estensioni specifiche per Android e consiste in codice Java eseguito nello spazio di processo dell'app. AndroidKeyStore soddisfa le richieste dell'app relative al comportamento dell'archivio chiavi forwardingle al demone dell'archivio chiavi.
Daemon keystore
Un daemon di sistema Android che fornisce l'accesso a tutte le funzionalità di Keystore tramite un'API Binder. Questo demone è responsabile della memorizzazione dei keyblob creati dall'implementazione di KeyMint (o Keymaster) sottostante, che contengono il materiale della chiave segreta, criptato in modo che il Keystore possa memorizzarli, ma non utilizzarli o rivelarli.
Servizio HAL KeyMint
Un server AIDL che implementa l'HAL IKeyMintDevice fornendo l'accesso al TA KeyMint sottostante.
App attendibile (TA) KeyMint
Software in esecuzione in un contesto sicuro, il più delle volte in TrustZone su un SoC ARM, che fornisce tutte le operazioni di crittografia sicura. Questa app ha accesso al materiale chiave non elaborato e convalida tutte le condizioni di controllo dell'accesso alle chiavi prima di consentirne l'utilizzo.
LockSettingsService
Il componente di sistema Android responsabile dell'autenticazione dell'utente, sia con password che con impronta. Non fa parte di Keystore, ma è pertinente perché Keystore supporta il concetto di chiavi legate all'autenticazione: chiavi che possono essere utilizzate solo se l'utente si è autenticato. LockSettingsService interagisce con il TA Gatekeeper e con il TA Fingerprint per ottenere token di autenticazione, che fornisce al daemon del keystore e che vengono utilizzati dal TA KeyMint.
Gatekeeper TA
Il componente in esecuzione nell'ambiente sicuro responsabile dell'autenticazione delle password degli utenti e della generazione di token di autenticazione utilizzati per dimostrare al TA KeyMint che è stata eseguita un'autenticazione per un determinato utente in un determinato momento.
TA impronte digitali
Il componente in esecuzione nell'ambiente sicuro che è responsabile dell'autenticazione delle impronte degli utenti e della generazione di token di autenticazione utilizzati per dimostrare al TA KeyMint che è stata eseguita un'autenticazione per un determinato utente in un determinato momento.

Architettura

L'API Android Keystore e l'HAL KeyMint di base forniscono un insieme di primitive di crittografia di base, ma adeguate, per consentire l'implementazione di protocolli che utilizzano chiavi con controllo dell'accesso e basate su hardware.

L'HAL KeyMint è un servizio fornito dall'OEM utilizzato dal servizio Keystore per fornire servizi di crittografia basati su hardware. Per mantenere al sicuro il materiale della chiave privata, le implementazioni HAL non eseguono operazioni sensibili nello spazio utente o nello spazio del kernel. Il servizio HAL KeyMint in esecuzione in Android delega invece le operazioni sensibili a un TA in esecuzione in un qualche tipo di ambiente sicuro, in genere tramite il marshalling e lo smarshalling delle richieste in un formato di trasmissione definito dall'implementazione.

L'architettura risultante ha il seguente aspetto:

Accesso a KeyMint

Figura 1. Accesso a KeyMint.

L'API HAL KeyMint è di basso livello, utilizzata dai componenti interni alla piattaforma e non esposta agli sviluppatori di app. L'API Java di livello superiore disponibile per le app è descritta sul sito Android for Developers.

Controllo dell'accesso

Android Keystore fornisce un componente centrale per lo stoccaggio e l'utilizzo di chiavi di crittografia basate su hardware, sia per le app sia per altri componenti di sistema. Di conseguenza, l'accesso a ogni singola chiave è in genere limitato all'app o al componente di sistema che ha creato la chiave.

Domini dell'archivio chiavi

Per supportare questo controllo dell'accesso, le chiavi vengono identificate nel Keystore con un descrittore della chiave. Questo descrittore della chiave indica un dominio a cui appartiene il descrittore, insieme a un'identità all'interno di quel dominio.

Le app per Android accedono all'archivio chiavi utilizzando l'architettura di crittografia Java standard, che identifica le chiavi con un alias di stringa. Questo metodo di identificazione viene mappato internamente al dominio Keystore APP; viene incluso anche l'UID del chiamante per distinguere le chiavi di diverse app, impedendo a un'app di accedere alle chiavi di un'altra.

Internamente, il codice del framework riceve anche un ID chiave numerico univoco dopo il caricamento di una chiave. Questo ID numerico viene utilizzato come identificatore per i descrittori delle chiavi all'interno del dominio KEY_ID. Tuttavia, il controllo accessi viene comunque eseguito: anche se un'app rileva un ID chiave per la chiave di un'altra app, non può utilizzarla in circostanze normali.

Tuttavia, è possibile che un'app conceda l'utilizzo di una chiave a un'altra app (identificata dall'UID). Questa operazione di concessione restituisce un identificatore univoco della concessione, che viene utilizzato come identificatore per i descrittori delle chiavi all'interno del dominio GRANT. Anche in questo caso, il controllo dell'accesso viene comunque eseguito: anche se un'app di terze parti scopre l'ID concessione per la chiave di un concesso, non può utilizzarlo.

Il keystore supporta anche altri due domini per i descrittori delle chiavi, che vengono utilizzati per altri componenti di sistema e non sono disponibili per le chiavi create dall'app:

  • Il dominio BLOB indica che non esiste un identificatore per la chiave nel descrittore della chiave. Il descrittore della chiave contiene invece il keyblob stesso e il client gestisce lo spazio di archiviazione del keyblob. Viene utilizzato dai client (ad esempio vold) che devono accedere al Keystore prima del montaggio della partizione dei dati.
  • Il dominio SELINUX consente ai componenti di sistema di condividere le chiavi, con accesso regolato da un identificatore numerico che corrisponde a un'etichetta SELinux (vedi Criterio SELinux per keystore_key).

Criterio SELinux per keystore_key

I valori degli identificatori utilizzati per i descrittori delle chiavi Domain::SELINUX sono configurati nel file del criterio SELinux keystore2_key_context. Ogni riga di questi file mappa un valore numerico a un'etichetta SELinux, ad esempio:

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share keystore keys.
102            u:object_r:wifi_key:s0

Un componente che ha bisogno di accedere alla chiave con ID 102 nel dominio SELINUX deve avere il criterio SELinux corrispondente. Ad esempio, per consentire a wpa_supplicant di ottenere e utilizzare queste chiavi, aggiungi la seguente riga a wpa_supplicant:hal_wifi_supplicant.te

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

Gli identificatori numerici per le chiavi Domain::SELINUX sono suddivisi in intervalli per supportare partizioni diverse senza collisioni:

Partizione Intervallo File di configurazione
Sistema 0 ... 9999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
Sistema esteso 10.000-19.999 /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
Prodotto 20.000 ... 29.999 /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
Fornitore 30.000 ... 39.999 /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

Per la partizione di sistema sono stati definiti i seguenti valori specifici:

ID spazio dei nomi Etichetta SEPolicy UID Descrizione
0 su_key N/D Chiave superutente. Utilizzato solo per i test sulle build userdebug ed eng. Non pertinente per le build utente.
1 shell_key N/D Spazio dei nomi disponibile per la shell. Utilizzato principalmente per i test, ma può essere utilizzato anche per le compilazioni utente dalla riga di comando.
100 vold_key N/D Da utilizzare da vold.
101 odsign_key N/D Utilizzato dal daemon di firma on-device.
102 wifi_key AID_WIFI(1010) Utilizzato dal sottosistema Wi-Fi di Android, incluso wpa_supplicant.
103 locksettings_key N/D Utilizzato da LockSettingsService
120 resume_on_reboot_key AID_SYSTEM(1000) Utilizzato dal server di sistema di Android per supportare la ripresa al riavvio.

Vettori di accesso

Il keystore consente di controllare le operazioni che possono essere eseguite su una chiave, oltre a controllare l'accesso complessivo a una chiave. Le autorizzazioni keystore2_key sono descritte nel file KeyPermission.aidl.

Autorizzazioni di sistema

Oltre ai controlli di accesso per chiave descritti in Norme SELinux per keystore_key, la tabella seguente descrive altre autorizzazioni SELinux necessarie per eseguire varie operazioni di sistema e manutenzione:

Autorizzazione Significato
add_auth Obbligatorio per aggiungere token di autenticazione al Keystore; utilizzato da provider di autenticazione come Gatekeeper o BiometricManager.
clear_ns Obbligatorio per eliminare tutte le chiavi in uno spazio dei nomi specifico; utilizzato come operazione di manutenzione quando le app vengono disinstallate.
list Obbligatorio per il sistema per l'enumerazione delle chiavi in base a varie proprietà, ad esempio la proprietà o se sono associate all'autenticazione. Questa autorizzazione non è richiesta dagli utenti che enumerano i propri spazi dei nomi (coperti dall'autorizzazione get_info).
lock Obbligatorio per notificare al keystore che il dispositivo è stato bloccato, il che a sua volta elimina le super chiavi per garantire che le chiavi legate all'autenticazione non siano disponibili.
unlock Obbligatorio per notificare al keystore che il dispositivo è stato sbloccato, ripristinando l'accesso alle superchiavi che proteggono le chiavi legate all'autenticazione.
reset Obbligatorio per reimpostare il Keystore sui valori predefiniti di fabbrica, eliminando tutte le chiavi che non sono vitali per il funzionamento del sistema operativo Android.

Cronologia

In Android 5 e versioni precedenti, Android aveva un'API di servizi criptati semplice basata su hardware, fornita dalle versioni 0.2 e 0.3 del livello di astrazione hardware (HAL) Keymaster. Il keystore forniva operazioni di firma e verifica digitale, oltre alla generazione e all'importazione di coppie di chiavi di firma asimmetrica. Questa funzionalità è già implementata su molti dispositivi, ma esistono molti scopi di sicurezza che non possono essere raggiunti facilmente solo con un'API di firma. Android 6.0 ha esteso l'API Keystore per fornire una gamma più ampia di funzionalità.

Android 6.0

In Android 6.0, Keymaster 1.0 ha aggiunto primitive crittografiche simmetriche, AES e HMAC, nonché un sistema di controllo dell'accesso per le chiavi con supporto hardware. I controlli di accesso vengono specificati durante la generazione della chiave e applicati per tutta la sua durata. Le chiavi possono essere limitate in modo da essere utilizzabili solo dopo l'autenticazione dell'utente e solo per finalità specifiche o con parametri criptici specifici.

Oltre ad ampliare la gamma di primitive crittografiche, Keystore in Android 6.0 ha aggiunto quanto segue:

  • Uno schema di controllo dell'utilizzo per consentire di limitare l'utilizzo delle chiavi, in modo da ridurre il rischio di compromissione della sicurezza a causa dell'uso improprio delle chiavi
  • Uno schema di controllo dell'accesso per consentire la limitazione delle chiavi a utenti, clienti e a un intervallo di tempo specificati

Android 7.0

In Android 7.0, Keymaster 2 ha aggiunto il supporto per l'attestazione delle chiavi e il binding della versione.

L'attestazione della chiave fornisce certificati di chiavi pubbliche che contengono una descrizione dettagliata della chiave e dei relativi controlli di accesso, per rendere verificabile da remoto l'esistenza della chiave in hardware sicuro e la relativa configurazione.

La associazione alla versione associa le chiavi al sistema operativo e alla versione del livello di patch. In questo modo, un malintenzionato che scopre una vulnerabilità in una versione precedente del sistema o del software TEE non può eseguire il rollback di un dispositivo alla versione vulnerabile e utilizzare le chiavi create con la versione più recente. Inoltre, quando una chiave con una determinata versione e un determinato livello patch viene utilizzata su un dispositivo di cui è stato eseguito l'upgrade a una versione o a un livello patch più recenti, viene eseguito l'upgrade della chiave prima che possa essere utilizzata e la versione precedente della chiave viene invalidata. Durante l'upgrade del dispositivo, le chiavi avanzano insieme al dispositivo, ma qualsiasi ripristino di una release precedente del dispositivo rende le chiavi inutilizzabili.

Android 8.0

In Android 8.0, Keymaster 3 è passato dall'HAL con struttura C di vecchio stile all'interfaccia HAL C++ generata da una definizione nel nuovo linguaggio di definizione dell'interfaccia hardware (HIDL). Nell'ambito della modifica, molti dei tipi di argomenti sono cambiati, anche se i tipi e i metodi hanno una corrispondenza uno a uno con i vecchi tipi e i metodi delle strutture HAL.

Oltre a questa revisione dell'interfaccia, Android 8.0 ha esteso la funzionalità di attestazione di Keymaster 2 per supportare la attestazione dell'identità. L'attestazione dell'identità fornisce un meccanismo limitato e facoltativo per attestare in modo affidabile gli identificatori hardware, come il numero di serie del dispositivo, il nome del prodotto e l'ID telefono (IMEI o MEID). Per implementare questa aggiunta, Android 8.0 ha modificato lo schema di attestazione ASN.1 per aggiungere l'attestazione dell'identità. Le implementazioni di Keymaster devono trovare un modo sicuro per recuperare gli elementi di dati pertinenti, nonché definire un meccanismo per disattivare la funzionalità in modo sicuro e permanente.

Android 9

In Android 9, gli aggiornamenti includevano:

  • Eseguire l'aggiornamento a Keymaster 4
  • Supporto per Secure Elements incorporati
  • Supporto per l'importazione di chiavi sicure
  • Supporto della crittografia 3DES
  • Modifiche all'associazione delle versioni in modo che boot.img e system.img abbiano versioni impostate separatamente per consentire aggiornamenti indipendenti

Android 10

Android 10 ha introdotto la versione 4.1 dell'HAL Keymaster, che ha aggiunto:

  • Supporto per le chiavi utilizzabili solo quando il dispositivo è sbloccato
  • Supporto per le chiavi che possono essere utilizzate solo nelle fasi iniziali dell'avvio
  • Supporto facoltativo per le chiavi di archiviazione con protezione hardware
  • Supporto facoltativo per l'attestazione univoca del dispositivo in StrongBox

Android 12

Android 12 ha introdotto il nuovo HAL KeyMint, che sostituisce l'HAL Keymaster, ma offre funzionalità simili. Oltre a tutte le funzionalità sopra descritte, la HAL KeyMint include anche:

  • Supporto per l'accordo sulle chiavi ECDH
  • Supporto per le chiavi di attestazione specificate dall'utente
  • Supporto per chiavi con un numero limitato di utilizzi

Android 12 include anche una nuova versione del daemon di sistema del keystore, riscritto in Rust e noto come keystore2

Android 13

Android 13 ha aggiunto la versione 2 dell'HAL KeyMint, che aggiunge il supporto per Curve25519 sia per la firma sia per il protocollo di scambio delle chiavi.