Questa pagina fornisce ulteriori dettagli e linee guida per aiutare gli implementatori dell'hardware abstraction layer (HAL) KeyMint. La documentazione principale per l'HAL è la specifica dell'interfaccia AIDL.
Utilizzo improprio delle API
I chiamanti possono creare chiavi KeyMint con autorizzazioni valide come parametri API, ma che rendono le chiavi risultanti non sicure o inutilizzabili. Le implementazioni di KeyMint non sono tenute a non riuscire in questi casi o a emettere una diagnostica. L'utilizzo di chiavi troppo piccole, la specifica di parametri di input irrilevanti, il riutilizzo di IV o nonce, la generazione di chiavi senza scopi (quindi inutili) e così via non devono essere diagnosticati dalle implementazioni.
È responsabilità delle app, del framework e di Android Keystore garantire che le chiamate ai moduli KeyMint siano sensate e utili.
addRngEntropy entry point
Il punto di ingresso addRngEntropy
aggiunge entropia fornita dal chiamante al pool utilizzato dall'implementazione di KeyMint per generare numeri casuali per chiavi e IV.
Le implementazioni di KeyMint devono combinare in modo sicuro l'entropia fornita nel pool, che deve contenere anche l'entropia generata internamente da un generatore di numeri casuali hardware. La combinazione deve essere gestita in modo che un malintenzionato che ha il controllo completo dei bit forniti da addRngEntropy
o di quelli generati dall'hardware (ma non di entrambi) non abbia un vantaggio significativo nella previsione dei bit generati dal pool di entropia.
Caratteristiche principali
Ciascuno dei meccanismi (generateKey
, importKey
e importWrappedKey
) che creano chiavi KeyMint restituisce le caratteristiche della chiave appena creata, suddivise in modo appropriato nei livelli di sicurezza che applicano ciascuna caratteristica. Le caratteristiche restituite includono tutti i parametri specificati per la creazione della chiave, tranne Tag::APPLICATION_ID
e Tag::APPLICATION_DATA
.
Se questi tag sono inclusi nei parametri chiave, vengono rimossi dalle caratteristiche restituite, in modo che non sia possibile trovare i loro valori esaminando il keyblob restituito. Tuttavia, sono associate crittograficamente
al keyblob, in modo che se non vengono forniti i valori corretti quando la chiave
viene utilizzata, l'utilizzo non va a buon fine. Analogamente,
Tag::ROOT_OF_TRUST
è
associato crittograficamente alla chiave, ma non può essere specificato durante
la creazione o l'importazione della chiave e non viene mai restituito.
Oltre ai tag forniti, l'implementazione di KeyMint aggiunge anche Tag::ORIGIN
, che indica la modalità di creazione della chiave (KeyOrigin::GENERATED
, KeyOrigin::IMPORTED
o KeyOrigin::SECURELY_IMPORTED
).
Resistenza al rollback
La resistenza al rollback è indicata da Tag::ROLLBACK_RESISTANCE
e significa che una volta eliminata una chiave con deleteKey
o deleteAllKeys
, l'hardware sicuro
garantisce che non sia più utilizzabile.
Le implementazioni di KeyMint restituiscono il materiale della chiave generato o importato al chiamante come keyblob, un modulo criptato e autenticato. Quando Keystore elimina il keyblob, la chiave non è più disponibile, ma un malintenzionato che in precedenza è riuscito a recuperare il materiale della chiave potrebbe potenzialmente ripristinarlo sul dispositivo.
Una chiave è resistente al rollback se l'hardware sicuro garantisce che le chiavi eliminate non possano essere ripristinate in un secondo momento. In genere, questa operazione viene eseguita memorizzando metadati aggiuntivi delle chiavi in una posizione attendibile che non può essere manipolata da un malintenzionato. Sui dispositivi mobili, il meccanismo utilizzato a questo scopo sono in genere i blocchi di memoria protetti da replay (RPMB). Poiché il numero di chiavi che possono essere create è essenzialmente illimitato e lo spazio di archiviazione attendibile utilizzato per la resistenza al rollback potrebbe essere limitato in termini di dimensioni, l'implementazione può non riuscire a creare chiavi resistenti al rollback quando lo spazio di archiviazione è pieno.
iniziale
Il punto di ingresso begin()
inizia un'operazione di crittografia utilizzando la chiave specificata, per lo scopo specificato, con i parametri specificati (a seconda dei casi). Restituisce un nuovo oggetto Binder IKeyMintOperation
utilizzato per completare l'operazione. Inoltre, viene restituito un valore di sfida
che viene utilizzato come parte del token di autenticazione nelle operazioni autenticate.
Un'implementazione di KeyMint supporta almeno 16 operazioni simultanee. Keystore ne utilizza fino a 15, lasciandone una per vold
da utilizzare per la crittografia
della password. Quando Keystore ha 15 operazioni in corso (begin()
è stato
chiamato, ma finish
o abort
non sono stati
chiamati) e riceve una richiesta per iniziare una sedicesima operazione, chiama
abort()
sull'operazione meno recente per ridurre il numero di
operazioni attive a 14 prima di chiamare begin()
per avviare
la nuova operazione richiesta.
Se Tag::APPLICATION_ID
o Tag::APPLICATION_DATA
sono stati specificati durante la generazione o l'importazione delle chiavi, le chiamate a begin()
devono
includere questi tag con i valori specificati originariamente
nell'argomento params
di questo metodo.
Gestione degli errori
Se un metodo su un IKeyMintOperation
restituisce un codice di errore diverso
da ErrorCode::OK
, l'operazione viene interrotta e l'oggetto
Binder dell'operazione viene invalidato. Qualsiasi utilizzo futuro dell'oggetto
restituisce ErrorCode::INVALID_OPERATION_HANDLE
.
Applicazione dell'autorizzazione
L'applicazione dell'autorizzazione delle chiavi viene eseguita principalmente
in begin()
. L'unica eccezione è il caso in cui la chiave
ha uno o più valori Tag::USER_SECURE_ID
e
non ha un valore Tag::AUTH_TIMEOUT
.
In questo caso, la chiave richiede un'autorizzazione per operazione e i metodi update()
o finish()
ricevono un token di autenticazione nell'argomento authToken
. Per garantire che il token sia valido, l'implementazione di KeyMint:
- Verifica la firma HMAC sul token di autenticazione.
- Verifica che il token contenga un ID utente sicuro corrispondente a uno associato alla chiave.
- Verifica che il tipo di autenticazione del token corrisponda a
Tag::USER_AUTH_TYPE
della chiave. - Verifica che il token contenga il valore della sfida per l'operazione corrente nel campo della sfida.
Se queste condizioni non vengono soddisfatte, KeyMint
restituisce ErrorCode::KEY_USER_NOT_AUTHENTICATED
.
Il chiamante fornisce il token di autenticazione a ogni chiamata a update()
e
finish()
. L'implementazione può convalidare il token una sola volta.