Questa pagina fornisce ulteriori dettagli e linee guida per aiutare gli implementatori del livello di astrazione hardware (HAL) di KeyMint. La documentazione principale per la HAL è la specifica dell'interfaccia AIDL.
Uso improprio dell'API
I chiamanti possono creare chiavi KeyMint con autorizzazioni valide come parametri API, ma che rendono le chiavi risultanti non sicure o inutilizzabili. In questi casi, le implementazioni di KeyMint non sono obbligatoriamente destinate a non riuscire o a generare 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 scopo (quindi inutili) e simili non deve essere diagnosticato dalle implementazioni.
È responsabilità delle app, del framework e di Android Keystore assicurarsi che le chiamate ai moduli KeyMint siano sensate e utili.
Punto di contatto addRngEntropy
Il punto di contatto addRngEntropy
aggiunge l'entropia fornita dall'utente chiamante al pool utilizzato dall'implementazione di KeyMint per generare numeri casuali, per le chiavi e gli IV.
Le implementazioni di KeyMint devono combinare in modo sicuro l'entropia fornita nel loro pool, che deve contenere anche l'entropia generata internamente da un generatore di numeri casuali hardware. L'unione deve essere gestita in modo che un malintenzionato che ha il controllo completo dei bit forniti da addRngEntropy
o dei bit 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 le 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 relativi valori esaminando il keyblob restituito. Tuttavia, sono legati in modo criptato al keyblob, pertanto se i valori corretti non vengono forniti quando la chiave viene utilizzata, l'utilizzo non va a buon fine. Analogamente,
Tag::ROOT_OF_TRUST
è
legato in modo criptato 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 il modo in cui è stata creata la chiave (KeyOrigin::GENERATED
,
KeyOrigin::IMPORTED
o KeyOrigin::SECURELY_IMPORTED
).
Resistenza al rollback
La resistenza al rollback è indicata da Tag::ROLLBACK_RESISTANCE
e indica che, una volta eliminata una chiave con deleteKey
o deleteAllKeys
, l'hardware sicuro garantisce che non potrà mai essere utilizzata di nuovo.
Le implementazioni di KeyMint restituiscono all'chiamante il materiale della chiave generato o importato come keyblob, un modulo criptato e autenticato. Quando Keystore elimina il keyblob, la chiave non è più presente, ma un malintenzionato che è riuscito in precedenza a recuperare il materiale della chiave potrebbe potenzialmente ripristinarla 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, questo viene fatto memorizzando metadati aggiuntivi delle chiavi in una posizione attendibile che non può essere manipolata da un malintenzionato. Sui dispositivi mobili, il meccanismo utilizzato per questo è solitamente RPMB (Replay Protected Memory Blocks). 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 contatto begin()
avvia un'operazione di crittografia utilizzando la chiave specificata, per lo scopo specificato, con i parametri specificati (se opportuno). Restituisce un nuovo oggetto IKeyMintOperation
Binder
utilizzato per completare l'operazione. Inoltre, viene restituito un valore della sfida che viene utilizzato come parte del token di autenticazione nelle operazioni autenticate.
Un'implementazione di KeyMint supporta almeno 16 operazioni contemporaneamente. Il keystore ne utilizza fino a 15, lasciandone uno 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 di avviarne una sedicesima, chiama abort()
sull'operazione utilizzata meno di recente per ridurre il numero di operazioni attive a 14 prima di chiamare begin()
per avviare l'operazione appena 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 i tag con i valori specificati in origine 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 operationBinder viene invalidato. Qualsiasi utilizzo futuro dell'oggetto
restituisce ErrorCode::INVALID_OPERATION_HANDLE
.
Applicazione delle autorizzazioni
L'applicazione dell'autorizzazione delle chiavi viene eseguita principalmente in begin()
. L'unica eccezione è il caso in cui la chiave abbia uno o più valori Tag::USER_SECURE_ID
e non abbia 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 la validità del token, l'implementazione di KeyMint:
- Verifica la firma HMAC sul token di autenticazione.
- Controlla che il token contenga un ID utente sicuro corrispondente a quello associato alla chiave.
- Verifica che il tipo di autenticazione del token corrisponda a
Tag::USER_AUTH_TYPE
della chiave. - Controlla che il token contenga il valore della verifica per l'operazione corrente nel campo della verifica.
Se queste condizioni non sono soddisfatte, KeyMint
restituisce ErrorCode::KEY_USER_NOT_AUTHENTICATED
.
L'utente che effettua la chiamata fornisce il token di autenticazione a ogni chiamata a update()
e
finish()
. L'implementazione può convalidare il token una sola volta.