Il sottosistema Gatekeeper esegue l'autenticazione del pattern/password del dispositivo in un Trusted Execution Environment (TEE). Gatekeeper registra e verifica le password tramite un HMAC con una chiave segreta supportata da hardware. Inoltre, Gatekeeper limita i tentativi di verifica consecutivi non riusciti e deve rifiutarsi di soddisfare le richieste in base a un determinato timeout e a un determinato numero di tentativi consecutivi falliti.
Quando gli utenti verificano le proprie password, Gatekeeper utilizza il segreto condiviso derivato da TEE per firmare un attestato di autenticazione da inviare al Keystore supportato da hardware . Vale a dire, un'attestazione Gatekeeper notifica al Keystore che le chiavi legate all'autenticazione (ad esempio, le chiavi create dalle app) possono essere rilasciate per l'utilizzo da parte delle app.
Architettura
Gatekeeper coinvolge tre componenti principali:
-
gatekeeperd
(demone del gatekeeper). Un servizio di associazione C++ contenente logica indipendente dalla piattaforma e corrispondente all'interfaccia JavaGateKeeperService
. - Livello di astrazione hardware (HAL) di Gatekeeper . L'interfaccia HAL in
hardware/libhardware/include/hardware/gatekeeper.h
e il modulo di implementazione. - Portiere (TEE) . La controparte TEE di
gatekeeperd
. Un'implementazione di Gatekeeper basata su TEE.
Gatekeeper richiede l'implementazione del Gatekeeper HAL (in particolare le funzioni in hardware/libhardware/include/hardware/gatekeeper.h
) e il componente Gatekeeper specifico per TEE (basato in parte sul file di intestazione system/gatekeeper/include/gatekeeper/gatekeeper.h
che include pure funzioni virtuali per la creazione/l'accesso a chiavi e il calcolo delle firme).
Il LockSettingsService
effettua una richiesta (tramite Binder) che raggiunge il daemon gatekeeperd
nel sistema operativo Android. Il demone gatekeeperd
effettua quindi una richiesta che raggiunge la sua controparte (Gatekeeper) nel TEE:
Il daemon gatekeeperd
fornisce alle API del framework Android l'accesso all'HAL e partecipa alla segnalazione delle autenticazioni del dispositivo a Keystore. Il demone gatekeeperd
viene eseguito nel proprio processo ed è separato dal server di sistema.
Implementazione dell'HAL
Il demone gatekeeperd
utilizza l'HAL per interagire con la controparte TEE del demone gatekeeperd
per l'autenticazione della password. L'implementazione dell'HAL deve essere in grado di firmare (registrare) e verificare i BLOB. Si prevede che tutte le implementazioni aderiscano al formato standard per il token di autenticazione (AuthToken) generato a ogni verifica della password riuscita. Per dettagli sul contenuto e sulla semantica dell'AuthToken, vedere Formato AuthToken .
Le implementazioni del file di intestazione hardware/libhardware/include/hardware/gatekeeper.h
devono implementare le funzioni enroll
e verify
:
- La funzione
enroll
accetta un BLOB di password, lo firma e restituisce la firma come handle. Il BLOB restituito (da una chiamata aenroll
) deve avere la struttura mostrata insystem/gatekeeper/include/gatekeeper/password_handle.h
. - La funzione
verify
deve confrontare la firma prodotta dalla password fornita e garantire che corrisponda all'handle della password registrata.
La chiave utilizzata per la registrazione e la verifica non deve mai cambiare e deve essere nuovamente derivabile a ogni avvio del dispositivo.
Trusty e altre implementazioni
Il sistema operativo Trusty è il sistema operativo affidabile open source di Google per ambienti TEE e contiene un'implementazione approvata di GateKeeper. Tuttavia, è possibile utilizzare qualsiasi sistema operativo TEE per implementare Gatekeeper purché TEE abbia accesso a una chiave supportata da hardware e a un orologio sicuro e monotono che ticchetta in modalità suspend .
Trusty utilizza un sistema IPC interno per comunicare un segreto condiviso direttamente tra Keymaster e l'implementazione Trusty di Gatekeeper (il Trusty Gatekeeper ). Questo segreto condiviso viene utilizzato per firmare AuthToken inviati a Keystore per fornire attestazioni di verifica della password. Trusty Gatekeeper richiede la chiave da Keymaster per ogni utilizzo e non persiste né memorizza nella cache il valore. Le implementazioni sono libere di condividere questo segreto in qualsiasi modo che non comprometta la sicurezza.
La chiave HMAC utilizzata per registrare e verificare le password viene derivata e conservata esclusivamente in GateKeeper.
Android fornisce un'implementazione C++ generica di GateKeeper che richiede solo l'aggiunta di routine specifiche del dispositivo per essere completata. Per implementare un TEE Gatekeeper con codice specifico del dispositivo per il tuo TEE, fai riferimento alle funzioni e ai commenti in system/gatekeeper/include/gatekeeper/gatekeeper.h
. Per TEE GateKeeper, le responsabilità principali di un'implementazione conforme includono:
- Adesione al Gatekeeper HAL.
- Gli AuthToken restituiti devono essere formattati secondo la specifica AuthToken (descritta in Autenticazione ).
- Il TEE Gatekeeper deve essere in grado di condividere una chiave HMAC con Keymaster, richiedendo la chiave tramite un TEE IPC su richiesta o mantenendo sempre una cache valida del valore.
ID sicuri dell'utente (SID)
Un SID utente è la rappresentazione TEE di un utente (senza una connessione forte con un ID utente Android). Il SID viene generato con un generatore di numeri pseudocasuali crittografici (PRNG) ogni volta che un utente registra una nuova password senza fornirne una precedente. Questa operazione è nota come nuova registrazione non attendibile e non è consentita dal framework Android in circostanze normali. Una nuova registrazione attendibile si verifica quando un utente fornisce una password precedente valida; in questo caso il SID Utente viene migrato sul nuovo handle di password, conservando le chiavi ad esso legate.
Il SID utente viene inserito in HMAC insieme alla password nell'handle della password quando la password viene registrata.
I SID utente vengono scritti nell'AuthToken restituito dalla funzione verify
e associati a tutte le chiavi del Keystore legate all'autenticazione (per dettagli sul formato AuthToken e sul Keystore, vedere Authentication ). Poiché una chiamata non attendibile alla funzione enroll
modificherà il SID utente, la chiamata renderà inutilizzabili le chiavi associate a tale password. Gli aggressori possono modificare la password del dispositivo se controllano il sistema operativo Android, ma nel processo distruggeranno le chiavi sensibili protette da root.
Richiedi la limitazione
GateKeeper deve essere in grado di limitare in modo sicuro i tentativi di forza bruta sulle credenziali di un utente. Come mostrato in hardware/libhardware/include/hardware/gatekeeper.h
, l'HAL prevede la restituzione di un timeout in millisecondi. Il timeout informa il client di non chiamare nuovamente GateKeeper fino allo scadere del timeout; GateKeeper non dovrebbe soddisfare le richieste se è presente un timeout in sospeso.
GateKeeper deve scrivere un contatore di errori prima di verificare la password di un utente. Se la verifica della password ha esito positivo, il contatore degli errori dovrebbe essere azzerato. Ciò impedisce attacchi che impediscono la limitazione disabilitando l'MMC incorporato (eMMC) dopo aver emesso una chiamata verify
. La funzione enroll
verifica anche la password dell'utente (se fornita) e deve essere limitata allo stesso modo.
Se supportato dal dispositivo, si consiglia vivamente di scrivere il contatore degli errori in un archivio protetto. Se il dispositivo non supporta la crittografia basata su file o se l'archiviazione sicura è troppo lenta, le implementazioni possono utilizzare direttamente Replay Protected Memory Block (RPMB).