Gatekeeper

Das Gatekeeper-Subsystem führt die Authentifizierung von Gerätemuster/Passwort in einer Trusted Execution Environment (TEE) durch. Gatekeeper registriert und überprüft Passwörter mithilfe eines hardwaregestützten geheimen Schlüssels. Außerdem drosselt Gatekeeper aufeinanderfolgende fehlgeschlagene Überprüfungsversuche und muss Anfragen basierend auf einem bestimmten Zeitlimit und einer bestimmten Anzahl aufeinanderfolgender fehlgeschlagener Versuche ablehnen.

Wenn Nutzer ihre Passwörter bestätigen, gibt Gatekeeper ein Authentifizierungstoken aus, das mit einem HMAC-Schlüssel pro Bootvorgang signiert ist, der nur für sichere Komponenten verfügbar ist. Dieses Token wird an den hardwarebasierten Keystore gesendet. Ein Gatekeeper-Authentifizierungstoken teilt dem Schlüsselspeicher mit, dass Authentifizierungsgebundene Schlüssel (z. B. von Apps erstellte Schlüssel) von Apps verwendet werden können.

Architektur

Gatekeeper umfasst drei Hauptkomponenten:

  • gatekeeperd (Gatekeeper-Daemon): Ein C++-Binder-Dienst in Android, der plattformunabhängige Logik zur Implementierung der IGateKeeperService-AIDL-Schnittstelle enthält, basierend auf einer zugrunde liegenden anbieterspezifischen Implementierung von IGatekeeper.
  • Gatekeeper-HAL-Dienst (Hardware Abstraction Layer): Eine anbieterspezifische Implementierung der IGatekeeper-AIDL-Schnittstelle. Dieser HAL-Dienst wird in Android ausgeführt, die Gatekeeper-Kernfunktionen müssen jedoch in einer sicheren Umgebung ausgeführt werden. Daher kommuniziert er in der Regel mit dem Gatekeeper TA.
  • Gatekeeper Trusted Application (TA): Eine anbieterspezifische Implementierung, die in der TEE ausgeführt wird und die eigentliche Passwort- oder Musterüberprüfung durchführt.

Die LockSettingsService stellt eine Anfrage (über Binder) an den gatekeeperd-Daemon im Android-Betriebssystem. Der gatekeeperd-Daemon sendet dann eine Anfrage an den IGatekeeper-HAL-Dienst, die wiederum das Gatekeeper-TA-Gegenstück im TEE erreicht:

Ablauf für Gatekeeper

Abbildung 1: Allgemeiner Datenfluss für die Authentifizierung durch GateKeeper.

Der gatekeeperd-Daemon ermöglicht den Android-Framework-APIs den Zugriff auf die HAL und ist an der Meldung von Geräteauthentifizierungen an Keystore beteiligt. Der gatekeeperd-Daemon wird in einem eigenen Prozess ausgeführt und ist vom Systemserver getrennt.

HAL-Implementierung

Der gatekeeperd-Daemon verwendet das IGatekeeper-HAL, um für die Passwortauthentifizierung mit der zugrunde liegenden Gatekeeper-TA zu interagieren. Die Gatekeeper-TA-Implementierung muss in der Lage sein, Blobs zu signieren (registrieren) und zu überprüfen. Alle Implementierungen müssen dem Standardformat für das Authentifizierungstoken (HardwareAuthToken) entsprechen, das bei jeder erfolgreichen Passwortbestätigung generiert wird. Weitere Informationen zum Inhalt und zur Semantik von HardwareAuthToken finden Sie in der Definition von HardwareAuthToken.aidl.

Anbieterimplementierungen des IGatekeeper HAL müssen die Funktionen enroll und verify implementieren:

  • Die Methode enroll nimmt einen Passwort-Blob entgegen, signiert ihn und gibt die Signatur als Handle zurück. Das zurückgegebene Blob (aus einem Aufruf von enroll) muss die in system/gatekeeper/include/gatekeeper/password_handle.h gezeigte Struktur haben.
  • Die verify-Funktion muss die mit dem angegebenen Passwort erstellte Signatur vergleichen und dafür sorgen, dass sie mit dem registrierten Passwort-Handle übereinstimmt.

Der Schlüssel, der für die Registrierung und Bestätigung verwendet wird, darf sich niemals ändern und sollte bei jedem Gerätestart neu abgeleitet werden können.

Trusty und andere Implementierungen

Das Betriebssystem Trusty ist das vertrauenswürdige Open-Source-Betriebssystem von Google für TEE-Umgebungen und enthält eine genehmigte Implementierung von Gatekeeper. Jedes TEE-Betriebssystem kann Gatekeeper implementieren, sofern die TEE Zugriff auf einen persistenten, hardwaregestützten Schlüssel und eine sichere, monotone Uhr hat, die im Ruhezustand tickt.

Trusty verwendet ein internes IPC-System, um ein gemeinsames Secret direkt zwischen KeyMint (früher Keymaster) und der Trusty-Implementierung von Gatekeeper (dem Trusty Gatekeeper) zu übertragen. Dieses gemeinsame Secret wird zum Signieren von AuthTokens verwendet, die an Keystore gesendet werden, um Attestierungen der Passwortüberprüfung bereitzustellen. Trusty Gatekeeper fordert den Schlüssel für jede Verwendung von KeyMint an und speichert oder speichert den Wert nicht im Cache. Implementierungen können dieses Secret auf beliebige Weise weitergeben, solange die Sicherheit nicht beeinträchtigt wird.

Der HMAC-Schlüssel, der zum Registrieren und Überprüfen von Passwörtern verwendet wird, wird abgeleitet und ausschließlich in Gatekeeper gespeichert.

Android bietet eine generische C++-Gatekeeper-Implementierung, die nur durch das Hinzufügen gerätespezifischer Routinen vervollständigt werden muss. Die Trusty-Implementierung basiert darauf. Wenn Sie einen TEE-Gatekeeper mit gerätespezifischem Code für Ihr TEE implementieren möchten, sehen Sie sich die Funktionen und Kommentare in system/gatekeeper/include/gatekeeper/gatekeeper.h an. Zu den primären Aufgaben einer konformen Implementierung gehören:

  • Einhaltung der IGatekeeper-HAL.
  • Zurückgegebene Authentifizierungstokens müssen gemäß der HardwareAuthToken-Spezifikation formatiert sein (siehe Authentifizierung).
  • Der TEE-Gatekeeper muss in der Lage sein, einen HMAC-Schlüssel mit KeyMint zu teilen. Dazu kann er den Schlüssel bei Bedarf über einen TEE-IPC anfordern oder jederzeit einen gültigen Cache des Werts verwalten.

Sichere Nutzer-IDs (SIDs)

Eine Nutzer-SID ist die TEE-Darstellung eines Nutzers (ohne starke Verbindung zu einer Android-Nutzer-ID). Die Sitzungs-ID wird mit einem kryptografischen Pseudozufallszahlengenerator (PRNG) generiert, wenn ein Nutzer ein neues Passwort registriert, ohne ein vorheriges anzugeben. Dies wird als nicht vertrauenswürdige erneute Registrierung bezeichnet und erfolgt normalerweise nur, wenn ein Nutzer zum ersten Mal ein Passwort oder Muster festlegt.

Eine vertrauenswürdige erneute Registrierung erfolgt, wenn ein Nutzer ein gültiges, vorheriges Passwort angibt, z. B. beim Ändern des Passworts. In diesem Fall wird die Nutzer-SID zum neuen Passwort-Handle migriert und die daran gebundenen Schlüssel werden beibehalten.

Die Nutzer-SID ist zusammen mit dem Passwort im Passwort-Handle in der HMAC-Authentifizierung enthalten, wenn das Passwort registriert ist.

Nutzer-SIDs sind im HardwareAuthToken enthalten, das von der Funktion verify() zurückgegeben wird, und sind allen authentifizierungsgebundenen Keystore-Schlüsseln zugeordnet. Weitere Informationen zum HardwareAuthToken-Format und zum Keystore finden Sie unter Authentifizierung.

Da ein nicht vertrauenswürdiger Aufruf der Funktion enroll() die Nutzer-SID ändert, werden die an dieses Passwort gebundenen Schlüssel durch den Aufruf unbrauchbar. Angreifer können das Passwort für das Gerät ändern, wenn sie das Android-Betriebssystem kontrollieren. Dabei werden jedoch sensible, durch Root geschützte Schlüssel zerstört.

Anfragedrosselung

Gatekeeper muss Brute-Force-Angriffe auf Nutzeranmeldedaten sicher drosseln können. Wie in GatekeeperVerifyResponse.aidl dargestellt, kann das HAL ein Zeitlimit in Millisekunden zurückgeben. Das Zeitlimit informiert den Client darüber, dass Gatekeeper erst nach Ablauf des Zeitlimits wieder aufgerufen werden soll. Gatekeeper sollte keine Anfragen bearbeiten, wenn ein Timeout aussteht.

Gatekeeper muss einen Fehlerzähler schreiben, bevor ein Nutzerpasswort überprüft wird. Wenn die Passwortüberprüfung erfolgreich ist, sollte der Fehlerzähler zurückgesetzt werden. Dadurch werden Angriffe verhindert, die eine Drosselung verhindern, indem die eingebettete MMC (eMMC) nach einem verify-Aufruf deaktiviert wird. Die Funktion enroll überprüft auch das Nutzerpasswort (falls angegeben) und muss auf dieselbe Weise gedrosselt werden.

Wenn das Gerät dies unterstützt, wird dringend empfohlen, den Fehlerzähler in einem sicheren Speicher zu speichern. Wenn das Gerät keine dateibasierte Verschlüsselung unterstützt oder der sichere Speicher zu langsam ist, können Implementierungen den Replay Protected Memory Block (RPMB) direkt verwenden.