Gatekeeper

Das Gatekeeper-Subsystem führt die Authentifizierung des Gerätemusters/Passworts in einer vertrauenswürdigen Ausführungsumgebung (Trusted Execution Environment, TEE) durch. Gatekeeper registriert und überprüft Passwörter mit einem hardwaregestützten geheimen Schlüssel. Außerdem drosselt Gatekeeper aufeinanderfolgende fehlgeschlagene Bestätigungsversuche 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 Boot signiert ist, der nur für sichere Komponenten verfügbar ist. Dieses Token wird an den hardwaregestützten Schlüsselspeicher gesendet. Ein Gatekeeper-Authentifizierungstoken benachrichtigt den Schlüsselspeicher also, 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 enthält, die die IGateKeeperService-AIDL-Schnittstelle implementiert, 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 Hauptfunktionen des Gatekeepers 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 im TEE ausgeführt wird und die eigentliche Passwort- oder Musterüberprüfung durchführt.

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

Gatekeeper-Ablauf

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

Der gatekeeperd-Daemon gewährt den Android-Framework-APIs Zugriff auf die HAL und trägt zur Meldung von Geräte-Authentifizierungen an den Schlüsselspeicher bei. Der gatekeeperd-Daemon wird in einem eigenen Prozess ausgeführt und ist unabhängig vom Systemserver.

HAL-Implementierung

Der gatekeeperd-Daemon verwendet die IGatekeeper HAL, um für die Passwortauthentifizierung mit der zugrunde liegenden Gatekeeper-TA zu interagieren. Die Gatekeeper-TA-Implementierung muss Blobs signieren (registrieren) und verifizieren können. 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 der 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. Der zurückgegebene Blob (von einem Aufruf von enroll) muss die in system/gatekeeper/include/gatekeeper/password_handle.h gezeigte Struktur haben.
  • Die verify-Funktion muss die vom angegebenen Passwort generierte Signatur mit dem registrierten Passwort-Handle vergleichen und dafür sorgen, dass sie übereinstimmt.

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

Trusty und andere Implementierungen

Das Betriebssystem Trusty ist das Open-Source-Vertrauenswürdige Betriebssystem von Google für TEE-Umgebungen und enthält eine genehmigte Implementierung von Gatekeeper. Jedes TEE-Betriebssystem kann Gatekeeper jedoch implementieren, solange die TEE Zugriff auf einen persistenten, hardwaregestützten Schlüssel und eine sichere, monotone Uhr hat, die auch im Ruhemodus weiterläuft.

Trusty verwendet ein internes IPC-System, um einen geheimen Schlüssel direkt zwischen KeyMint und der Trusty-Implementierung von Gatekeeper (Trusty Gatekeeper) auszutauschen. Dieses freigegebene Secret wird zum Signieren von Authentifizierungstokens verwendet, die an den Keystore gesendet werden, um Attestierungen zur Passwortbestätigung bereitzustellen. Trusty Gatekeeper fordert den Schlüssel bei jeder Verwendung von KeyMint an und speichert den Wert nicht oder legt ihn nicht im Cache ab. Implementierungen können dieses Secret auf jede Weise freigeben, die die Sicherheit nicht beeinträchtigt.

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

Android bietet eine generische C++-Gatekeeper-Implementierung, die nur durch das Hinzufügen von gerätespezifischen Routinen vervollständigt werden muss. Die Trusty-Implementierung basiert darauf. Informationen zum Implementieren eines TEE-Gatekeepers mit gerätespezifischem Code für Ihre TEE finden Sie in den Funktionen und Kommentaren in system/gatekeeper/include/gatekeeper/gatekeeper.h. Zu den wichtigsten Aufgaben einer konformen Implementierung gehören:

  • Einhaltung der IGatekeeper HAL
  • Zurückgegebene Authentifizierungstokens müssen gemäß der HardwareAuthToken-Spezifikation formatiert sein (siehe HardwareAuthToken.aidl).
  • Der TEE-Gatekeeper muss einen HMAC-Schlüssel mit KeyMint teilen können, und zwar mit einer der folgenden Methoden:
    • Vereinbarung für gemeinsame Geheimnisse:Gatekeeper kann an der gerätespezifischen Verhandlung des HMAC-Schlüssels teilnehmen, indem er die ISharedSecret-HAL implementiert. Dazu müssen Gatekeeper und KeyMint beide Zugriff auf ein gemeinsames freigegebenes Geheimnis haben.
    • Direkter Zugriff:Gatekeeper kann den HMAC-Schlüssel über einen TEE-internen Interprozess-Kommunikationsmechanismus von KeyMint abrufen, entweder bei Bedarf oder bei der ersten Verwendung (wird danach im Cache gespeichert).

Sichere Nutzer-IDs (SIDs)

Eine Nutzer-SID ist die TEE-Darstellung eines Nutzers (ohne starke Verbindung zu einer Android-Nutzer-ID). Die SID 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 tritt normalerweise nur auf, 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 Schlüssel, die damit verknüpft waren, bleiben erhalten.

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

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

Hinweis: Da ein nicht vertrauenswürdiger Aufruf der Funktion enroll() die Nutzer-SID ändert, werden die mit diesem Passwort verknüpften Schlüssel durch den Aufruf unbrauchbar. Angreifer können das Passwort für das Gerät ändern, wenn sie das Android-Betriebssystem steuern. Dabei werden jedoch root-geschützte, sensible Schlüssel zerstört.

Anfragen drosseln

Gatekeeper muss in der Lage sein, Brute-Force-Angriffe auf Nutzeranmeldedaten sicher zu drosseln. Wie in GatekeeperVerifyResponse.aidl dargestellt, gibt die HAL ein Zeitlimit in Millisekunden zurück. Das Zeitlimit informiert den Client, dass er Gatekeeper erst wieder aufrufen soll, wenn das Zeitlimit abgelaufen ist. Der Gatekeeper sollte keine Anfragen bearbeiten, wenn eine Zeitüberschreitung bevorsteht.

Gatekeeper muss einen Fehlerzähler schreiben, bevor ein Nutzerpasswort überprüft wird. Wenn die Passwortbestätigung erfolgreich ist, sollte der Fehlerzähler gelöscht werden. So werden Angriffe verhindert, die das Drosseln 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 die gleiche Weise gedrosselt werden.

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