Questa pagina contiene informazioni sulle funzionalità di crittografia di Android Keystore, come fornite dall'implementazione di KeyMint (o Keymaster) sottostante.
Primitivi di crittografia
Keystore fornisce le seguenti categorie di operazioni:
- Creazione di chiavi, che genera materiale di chiavi private o segrete accessibile solo all'ambiente sicuro. I client possono creare chiavi nei seguenti modi:
- Generazione di nuove chiavi
- Importazione di materiale della chiave non criptato
- Importazione di materiale della chiave criptato
- Attestazione della chiave: la creazione di una chiave asimmetrica genera un certificato contenente la parte della chiave pubblica della coppia di chiavi. Facoltativamente, questo certificato contiene anche informazioni sui metadati della chiave e sullo stato del dispositivo, il tutto firmato da una catena di chiavi che rimanda a una radice attendibile.
- Operazioni crittografiche:
- Crittografia e decrittografia simmetrica (AES, 3DES)
- Decriptazione asimmetrica (RSA)
- Firma asimmetrica (ECDSA, RSA)
- Firma e verifica simmetriche (HMAC)
- Accordo su chiavi asimmetriche (ECDH)
Tieni presente che Keystore e KeyMint non gestiscono le operazioni con le chiavi pubbliche per le chiavi asimmetriche.
Gli elementi del protocollo, come scopo, modalità e riempimento, nonché i vincoli di controllo dell'accesso, vengono specificati quando le chiavi vengono generate o importate e sono legati in modo permanente alla chiave, garantendo che non possano essere utilizzate in nessun altro modo.
Le primitive e le modalità che devono essere supportate dall'implementazione di KeyMint sono descritte nella specifica dell'interfaccia HAL IKeyMintDevice
.
L'implementazione di KeyMint sottostante deve eseguire la generazione di numeri casuali per supportare la generazione di chiavi e la creazione di padding o vettori di inizializzazione (IV) casuali. Per supportare questa funzionalità, il sistema Android fornisce periodicamente un'entropia aggiuntiva all'implementazione di KeyMint.
Controllo di accesso alle chiavi
Le chiavi basate su hardware che non possono mai essere estratte dal dispositivo non forniscono molta sicurezza se un malintenzionato può utilizzarle a piacimento (anche se sono più sicure delle chiavi che possono essere esfiltrate). Pertanto, è fondamentale che Keystore applichi i controlli di accesso.
I controlli di accesso sono definiti come un "elenco di autorizzazioni" di coppie di tag/valori. I tag di autorizzazione sono numeri interi a 32 bit e i valori sono di vari tipi. Alcuni tag possono essere ripetuti per specificare più valori. La possibilità di ripetere un tag è specificata nell'interfaccia HAL di KeyMint (in precedenza Keymaster).
I valori dei tag supportati sono definiti nel
file
Tag.aidl
e ciascuno è associato a un
TagType
che indica il tipo di valore associato (ad esempio, intero o byte) e se può essere ripetuto per specificare più valori supportati.
Quando KeyMint crea una chiave, l'utente chiamante specifica un elenco di autorizzazioni per la chiave. Questo elenco viene modificato da Keystore e KeyMint per aggiungere vincoli aggiuntivi e l'implementazione di KeyMint sottostante codifica l'elenco di autorizzazioni finale nel keyblob restituito. L'elenco di autorizzazioni codificato è vincolato in modo criptato al keyblob, in modo che qualsiasi tentativo di modificarlo (incluso l'ordinamento) generi un keyblob non valido che non può essere utilizzato per le operazioni di crittografia.
Applicazione tramite hardware o software
Non tutte le implementazioni hardware sicure contengono le stesse funzionalità. Per supportare una serie di approcci, KeyMint distingue tra applicazione di controlli di accesso sicuri e non sicuri o, rispettivamente, applicazione hardware e software.
Questo valore è esposto nell'API KeyMint con il campo securityLevel
del
tipo KeyCharacteristics
. L'hardware sicuro è responsabile del posizionamento delle autorizzazioni in KeyCharacteristics
con il livello di sicurezza appropriato, in base a ciò che può applicare. Queste informazioni sono esposte anche nei record di attestazione per le chiavi asimmetriche: le caratteristiche chiave per SecurityLevel::TRUSTED_ENVIRONMENT
o SecurityLevel::STRONGBOX
appaiono nell'elenco hardwareEnforced
e le caratteristiche per SecurityLevel::SOFTWARE
o SecurityLevel::KEYSTORE
appaiono nell'elenco softwareEnforced
.
Ad esempio, i vincoli relativi all'intervallo di data e ora in cui è possibile utilizzare una chiave solitamente non vengono applicati dall'ambiente sicuro perché non ha accesso attendibile alle informazioni su data e ora. Di conseguenza, le autorizzazioni come
Tag::ORIGINATION_EXPIRE_DATETIME
vengono applicate dall'archivio chiavi in
Android e avranno SecurityLevel::KEYSTORE
.
Per saperne di più su come determinare se le chiavi e le relative autorizzazioni sono supportate dall'hardware, consulta Attestazione delle chiavi.
Autorizzazioni per la costruzione di messaggi criptati
I seguenti tag vengono utilizzati per definire le caratteristiche di crittografia delle operazioni che utilizzano la chiave associata:
Tag::ALGORITHM
Tag::KEY_SIZE
Tag::BLOCK_MODE
Tag::PADDING
Tag::CALLER_NONCE
Tag::DIGEST
Tag::MGF_DIGEST
I seguenti tag sono ripetibili, il che significa che è possibile associare più valori a una singola chiave:
Tag::BLOCK_MODE
Tag::PADDING
Tag::DIGEST
Tag::MGF_DIGEST
Il valore da utilizzare viene specificato al momento dell'operazione.
Finalità
Le chiavi hanno un insieme di finalità associate, espresse come una o più voci di autorizzazione con il tag Tag::PURPOSE
, che definisce come possono essere utilizzate. Le finalità sono definite in
KeyPurpose.aidl
.
Tieni presente che alcune combinazioni di valori dello scopo creano problemi di sicurezza. Ad esempio, una chiave RSA che può essere utilizzata sia per la crittografia sia per la firma consente a un malintenzionato di convincere il sistema a decriptare dati arbitrari per generare firme.
Importazione di una chiave
KeyMint supporta l'importazione di:
- Coppie di chiavi asimmetriche in formato PKCS#8 con codifica DER (senza crittografia basata su password)
- Chiavi simmetriche come byte non elaborati
Per garantire che le chiavi importate possano essere distinte da quelle generate in modo sicuro, Tag::ORIGIN
è inclusa nell'elenco di autorizzazione delle chiavi appropriato. Ad esempio, se una chiave è stata generata in hardware sicuro, Tag::ORIGIN
con valore KeyOrigin::GENERATED
si trova nell'elenco hw_enforced
delle caratteristiche della chiave, mentre una chiave importata in hardware sicuro ha il valore KeyOrigin::IMPORTED
.
Autenticazione utente
Le implementazioni di KeyMint sicure non implementano l'autenticazione utente, ma dipendono da altre app attendibili che lo fanno. Per l'interfaccia implementata da queste app, consulta la pagina Gatekeeper.
I requisiti di autenticazione utente vengono specificati tramite due insiemi di tag. Il primo insieme indica quali metodi di autenticazione consentono l'utilizzo della chiave:
Tag::USER_SECURE_ID
ha un valore numerico di 64 bit che specifica l'ID utente sicuro fornito in un token di autenticazione sicuro per sbloccare l'utilizzo della chiave. Se ripetuta, la chiave può essere utilizzata se uno dei valori viene fornito in un token di autenticazione sicuro.
Il secondo set indica se e quando l'utente deve essere autenticato.
Se non è presente nessuno di questi tag, ma è presente Tag::USER_SECURE_ID
,
l'autenticazione è obbligatoria per ogni utilizzo della chiave.
Tag::NO_AUTHENTICATION_REQUIRED
indica che non è richiesta l'autenticazione dell'utente, anche se l'accesso alla chiave è comunque limitato all'app proprietaria (e a eventuali app a cui concede l'accesso).Tag::AUTH_TIMEOUT
è un valore numerico che specifica, in secondi, quanto deve essere recente l'autenticazione utente per autorizzare l'utilizzo della chiave. I timeout non si applicano ai riavvii; dopo un riavvio, tutte le autenticazioni vengono invalidate. Il timeout può essere impostato su un valore elevato per indicare che l'autenticazione è richiesta una volta per avvio (2^32 secondi sono circa 136 anni; presumibilmente i dispositivi Android vengono riavviati più spesso).
Richiedi un dispositivo sbloccato
Le chiavi con Tag::UNLOCKED_DEVICE_REQUIRED
sono utilizzabili solo quando il dispositivo è sbloccato. Per la semantica dettagliata, consulta
KeyProtection.Builder#setUnlockedDeviceRequired(boolean)
.
UNLOCKED_DEVICE_REQUIRED
viene applicato da Keystore, non da
KeyMint. Tuttavia, in Android 12 e versioni successive, Keystore protegge in modo criptato le chiavi UNLOCKED_DEVICE_REQUIRED
quando il dispositivo è bloccato per garantire che, nella maggior parte dei casi, non possano essere utilizzate anche se Keystore è compromesso quando il dispositivo è bloccato.
Per farlo, Keystore "supercripta" tutte le chiaviUNLOCKED_DEVICE_REQUIRED
prima di archiviarle nel proprio database e, se possibile, protegge le chiavi di supercrittografia (super chiavi) mentre il dispositivo è bloccato in modo che possano essere recuperate solo sbloccando il dispositivo. Il termine "supercrittografia" viene utilizzato perché questo livello di crittografia viene applicato oltre a quello che KeyMint applica già a tutte le chiavi.
Ogni utente (inclusi i profili)
ha due super chiavi associate a UNLOCKED_DEVICE_REQUIRED
:
- La superchiave simmetrica UnlockedDeviceRequired. Si tratta di una
chiave AES‑256‑GCM. Crittografa
le chiavi
UNLOCKED_DEVICE_REQUIRED
importate o generate mentre il dispositivo è sbloccato per l'utente. - La superchiave asimmetrica UnlockedDeviceRequired. Si tratta di una coppia di chiavi ECDH
P-521. Crittografa le chiavi
UNLOCKED_DEVICE_REQUIRED
importate o generate mentre il dispositivo è bloccato per l'utente. Le chiavi criptate con questa chiave asimmetrica vengono sottoposte nuovamente a crittografia con la chiave simmetrica al primo utilizzo (che può avvenire solo quando il dispositivo è sbloccato).
Keystore genera queste super chiavi al momento della creazione dell'utente e le memorizza nel suo database, criptate dalla password sintetica dell'utente. In questo modo possono essere recuperati utilizzando un PIN, una sequenza o una password equivalente.
Il Keystore memorizza nella cache anche queste super chiavi in memoria, il che gli consente di operare sulle chiavi UNLOCKED_DEVICE_REQUIRED
. Tuttavia, tenta di memorizzare nella cache le parti segrete di queste chiavi solo quando il dispositivo è sbloccato per l'utente. Quando il dispositivo è bloccato per l'utente, Keystore azzera la copia memorizzata nella cache delle parti segrete di queste super chiavi, se possibile. Nello specifico, quando il dispositivo è bloccato per l'utente, Keystore seleziona e applica uno dei tre livelli di protezione per le super chiavi UnlockedDeviceRequired dell'utente:
- Se l'utente ha attivato solo il PIN, la sequenza o la password, Keystore imposta su zero le parti segrete delle super chiavi memorizzate nella cache. In questo modo, le chiavi super sono recuperabili solo tramite la copia criptata nel database che può essere decriptata solo tramite PIN, sequenza o password equivalente.
- Se l'utente ha solo dati biometrici di 3a classe ("sicuri") e ha attivato PIN, sequenza o password, il Keystore organizza le super chiavi in modo che siano recuperabili da qualsiasi dato biometrico di 3a classe registrato dall'utente (in genere l'impronta), come alternativa a PIN, sequenza o password. Per farlo, genera una nuova chiave AES‑256‑GCM, cripta con essa le parti segrete delle super chiavi, importa la chiave AES‑256‑GCM in KeyMint come chiave legata alla biometria che richiede l'autenticazione biometrica per essere andata a buon fine negli ultimi 15 secondi e azzera le copie in testo non criptato di tutte queste chiavi.
- Se l'utente ha un dato biometrico di classe 1 ("di praticità"), di classe 2 ("debole") o un agente di attendibilità di sblocco attivo, Keystore conserva le super chiavi in cache in testo non cifrato. In questo caso, la sicurezza crittografica per le chiavi
UNLOCKED_DEVICE_REQUIRED
non è fornita. Gli utenti possono evitare questo metodo alternativo meno sicuro disattivando questi metodi di sblocco. I metodi di sblocco più comuni che rientrano in queste categorie sono lo sblocco con il volto su molti dispositivi e lo sblocco con uno smartwatch accoppiato.
Quando il dispositivo viene sbloccato per l'utente, Keystore recupera le super chiavi UnlockedDeviceRequired dell'utente, se possibile. Per lo sblocco tramite PIN, sequenza o password, decripta la copia di queste chiavi memorizzata nel database. In caso contrario, controlla se ha salvato una copia di queste chiavi criptate con una chiave associata alla biometria e, in questo caso, tenta di decriptarla. L'operazione riesce solo se l'utente si è autenticato correttamente con un dato biometrico di classe 3 negli ultimi 15 secondi, applicato da KeyMint (non Keystore).
Association client
Il binding del client, ovvero l'associazione di una chiave a una determinata app client, viene eseguito tramite un ID client facoltativo e alcuni dati del client facoltativi (Tag::APPLICATION_ID
e Tag::APPLICATION_DATA
, rispettivamente). Il keystore tratta questi valori come blob opachi, garantendo solo che gli stessi blob presentati durante la generazione/l'importazione delle chiavi vengano presentati per ogni utilizzo e siano identici byte per byte. I dati di associazione del client non vengono restituiti da
KeyMint. Il chiamante deve conoscerla per poter utilizzare la chiave.
Questa funzionalità non è esposta alle app.
Scadenza
Il keystore supporta la limitazione dell'utilizzo delle chiavi in base alla data. La data/ora di inizio e di scadenza della chiave possono essere associate a una chiave e il Keystore si rifiuta di eseguire operazioni con la chiave se la data/ora corrente non rientra nell'intervallo valido. L'intervallo di validità della chiave è specificato con i tag
Tag::ACTIVE_DATETIME
,
Tag::ORIGINATION_EXPIRE_DATETIME
e
Tag::USAGE_EXPIRE_DATETIME
. La distinzione tra "origine" e "utilizzo" si basa sul fatto che la chiave venga utilizzata per "generare" una nuova crittografia/firma/ecc. o per "utilizzare" una crittografia/firma/ecc. esistente. Tieni presente che questa distinzione non è esposta alle app.
I tag Tag::ACTIVE_DATETIME
,
Tag::ORIGINATION_EXPIRE_DATETIME
,
e Tag::USAGE_EXPIRE_DATETIME
sono facoltativi. Se i tag
non sono presenti, si presume che la chiave in discussione possa essere sempre utilizzata per decriptare/verificare i messaggi.
Poiché l'ora del sistema è fornita dal mondo non sicuro, i tag relativi alla scadenza sono nell'elenco applicato dal software.
Collegamento della radice di attendibilità
Il keystore richiede che le chiavi siano associate a una radice di attendibilità, ovvero una stringa di bit fornita all'hardware sicuro KeyMint durante l'avvio, preferibilmente dal bootloader. Questa stringa di bit è legata in modo crittografico a ogni chiave gestita da KeyMint.
La radice di attendibilità è costituita dall'hash della chiave pubblica utilizzata per verificare la firma sull'immagine di avvio e lo stato di blocco del dispositivo. Se la chiave pubblica viene modificata per consentire l'utilizzo di un'immagine di sistema diversa o se viene modificato lo stato della serratura, nessuna delle chiavi protette da KeyMint create dal sistema precedente è utilizzabile a meno che non venga ripristinata la radice di attendibilità precedente e venga avviato un sistema firmato da quella chiave. L'obiettivo è aumentare il valore dei controlli di accesso alle chiavi applicati tramite software impedendo a un sistema operativo installato dall'attaccante di utilizzare le chiavi KeyMint.
Nuova generazione di seed per il generatore di numeri casuali
Poiché l'hardware sicuro genera numeri casuali per il materiale della chiave e per i vettori di inizializzazione (IV) e poiché i generatori di numeri casuali hardware potrebbero non essere sempre completamente attendibili, l'HAL KeyMint fornisce un'interfaccia per consentire a Keystore di fornire entropia aggiuntiva, che viene aggiunta ai numeri casuali generati.
Utilizza un generatore di numeri casuali hardware come sorgente principale del seed. I dati iniziali forniti tramite l'API esterna non possono essere l'unica fonte di casualità utilizzata per la generazione di numeri. Inoltre, l'operazione di miscelazione utilizzata deve garantire che l'output casuale sia imprevedibile se una delle fonti di seed è imprevedibile.