Gatekeeper

Le sous-système Gatekeeper effectue l'authentification par schéma/mot de passe de l'appareil dans un environnement d'exécution sécurisé (TEE). Gatekeeper enregistre et valide les mots de passe à l'aide d'une clé secrète intégrée au matériel. De plus, Gatekeeper limite les tentatives de validation consécutives infructueuses et doit refuser de traiter les requêtes en fonction d'un délai avant expiration donné et d'un nombre donné de tentatives infructueuses consécutives.

Lorsque les utilisateurs valident leurs mots de passe, Gatekeeper émet un jeton d'authentification signé avec une clé HMAC par démarrage qui n'est disponible que pour les composants sécurisés. Ce jeton est envoyé au Keystore basé sur du matériel. Autrement dit, un jeton d'authentification Gatekeeper informe Keystore que les clés liées à l'authentification (par exemple, les clés créées par les applications) peuvent être utilisées par les applications.

Architecture

Gatekeeper comprend trois composants principaux:

  • gatekeeperd (daemon Gatekeeper) : service de liaison C++ dans Android qui contient une logique indépendante de la plate-forme implémentant l'interface AIDL IGateKeeperService, basée sur une implémentation sous-jacente spécifique au fournisseur de IGatekeeper.
  • Service de couche d'abstraction matérielle (HAL) Gatekeeper : implémentation spécifique au fournisseur de l'interface AIDL IGatekeeper. Ce service HAL s'exécute dans Android, mais la fonctionnalité de base de Gatekeeper doit s'exécuter dans un environnement sécurisé. Il communique donc généralement avec le TA Gatekeeper.
  • Application sécurisée (TA) Gatekeeper : implémentation spécifique au fournisseur qui s'exécute dans le TEE et effectue la validation du mot de passe ou du schéma.

LockSettingsService envoie une requête (via Binder) qui atteint le daemon gatekeeperd dans l'OS Android. Le daemon gatekeeperd envoie ensuite une requête au service HAL IGatekeeper, qui à son tour atteint son homologue TA Gatekeeper dans le TEE:

Flux Gatekeeper

Figure 1 : Flux de données de haut niveau pour l'authentification par GateKeeper.

Le daemon gatekeeperd permet aux API du framework Android d'accéder au HAL et participe au signalement des authentifications de l'appareil au keystore. Le daemon gatekeeperd s'exécute dans son propre processus et est distinct du serveur système.

Implémentation de HAL

Le démon gatekeeperd utilise le HAL IGatekeeper pour interagir avec le TA Gatekeeper sous-jacent pour l'authentification par mot de passe. L'implémentation de la TA Gatekeeper doit pouvoir signer (enregistrer) et valider les blobs. Toutes les implémentations doivent respecter le format standard pour le jeton d'authentification (HardwareAuthToken) généré à chaque validation de mot de passe réussie. Pour en savoir plus sur le contenu et la sémantique de HardwareAuthToken, consultez la définition de HardwareAuthToken.aidl.

Les implémentations du HAL IGatekeeper par les fournisseurs doivent implémenter les fonctions enroll et verify:

  • La méthode enroll prend un blob de mot de passe, le signe et renvoie la signature en tant que poignée. Le blob renvoyé (à partir d'un appel à enroll) doit avoir la structure illustrée dans system/gatekeeper/include/gatekeeper/password_handle.h.
  • La fonction verify doit comparer la signature générée par le mot de passe fourni et s'assurer qu'elle correspond au gestionnaire de mot de passe enregistré.

La clé utilisée pour l'enregistrement et la validation ne doit jamais changer et doit être dérivable à chaque démarrage de l'appareil.

Trusty et autres implémentations

Le système d'exploitation Trusty est l'OS Open Source sécurisé de Google pour les environnements TEE et contient une implémentation approuvée de Gatekeeper. Toutefois, tout OS TEE peut implémenter Gatekeeper tant que le TEE a accès à une clé persistante basée sur du matériel et à une horloge monotone sécurisée qui fonctionne en mode suspension.

Trusty utilise un système IPC interne pour communiquer un secret partagé directement entre KeyMint et l'implémentation Trusty de Gatekeeper (le Trusty Gatekeeper). Ce secret partagé est utilisé pour signer les jetons d'authentification envoyés au Keystore afin de fournir des attestations de validation du mot de passe. Trusty Gatekeeper demande la clé à KeyMint pour chaque utilisation et ne conserve ni ne met en cache la valeur. Les implémentations sont libres de partager ce secret de quelque manière que ce soit sans compromettre la sécurité.

La clé HMAC utilisée pour enregistrer et valider les mots de passe est dérivée et conservée uniquement dans Gatekeeper.

Android fournit une implémentation générique de Gatekeeper C++ qui ne nécessite que l'ajout de routines spécifiques à l'appareil pour être complète. L'implémentation de Trusty s'appuie sur ce principe. Pour implémenter un TEE Gatekeeper avec du code spécifique à l'appareil pour votre TEE, consultez les fonctions et les commentaires dans system/gatekeeper/include/gatekeeper/gatekeeper.h. Voici les principales responsabilités d'une implémentation conforme:

  • Respect du HAL IGatekeeper.
  • Les jetons d'authentification renvoyés doivent être mis en forme conformément à la spécification HardwareAuthToken (décrite dans HardwareAuthToken.aidl).
  • Le TEE Gatekeeper doit pouvoir partager une clé HMAC avec KeyMint, à l'aide de l'une des méthodes suivantes:
    • Accord sur le secret partagé:Gatekeeper peut participer à la négociation de la clé HMAC à chaque démarrage en implémentant le HAL ISharedSecret. Pour ce faire, Gatekeeper et KeyMint doivent tous deux avoir accès à un secret partagé prédéfini commun.
    • Accès direct:Gatekeeper peut récupérer la clé HMAC de KeyMint à l'aide d'un mécanisme de communication interprocessus interne au TEE, à la demande ou lors de la première utilisation (mise en cache par la suite).

ID utilisateur sécurisés (SID)

Un SID utilisateur est la représentation TEE d'un utilisateur (sans lien fort avec un ID utilisateur Android). Le SID est généré à l'aide d'un générateur de nombres pseudo-aléatoires (PRNG) chaque fois qu'un utilisateur enregistre un nouveau mot de passe sans en fournir un précédent. Il s'agit d'une réinscription non fiable, qui ne se produit normalement que lorsqu'un utilisateur définit un mot de passe ou un schéma pour la première fois.

Une réinscription de confiance se produit lorsqu'un utilisateur fournit un ancien mot de passe valide, par exemple lorsqu'il en modifie un. Dans ce cas, le SID de l'utilisateur est migré vers le nouveau gestionnaire de mots de passe, en conservant les clés qui y étaient associées.

Le SID de l'utilisateur est inclus dans l'authentification HMAC avec le mot de passe dans le gestionnaire de mots de passe lorsque le mot de passe est enregistré.

Les SID utilisateur sont inclus dans le HardwareAuthToken renvoyé par la fonction verify() et associés à toutes les clés Keystore liées à l'authentification (pour en savoir plus sur le format HardwareAuthToken et Keystore, consultez la section Authentification).

Notez qu'un appel non approuvé à la fonction enroll() modifie le SID de l'utilisateur. L'appel rend donc les clés associées à ce mot de passe inutilisables. Les pirates informatiques peuvent modifier le mot de passe de l'appareil s'ils contrôlent l'OS Android, mais ils détruisent les clés sensibles protégées par root au cours du processus.

Limiter les requêtes

Gatekeeper doit pouvoir limiter de manière sécurisée les tentatives par force brute sur des identifiants utilisateur. Comme indiqué dans GatekeeperVerifyResponse.aidl, le HAL permet de renvoyer un délai avant expiration en millisecondes. Le délai avant expiration indique au client de ne pas appeler Gatekeeper à nouveau avant l'expiration du délai. Le Gatekeeper ne doit pas traiter les requêtes si un délai avant expiration est en attente.

Le Gatekeeper doit écrire un compteur d'échecs avant de valider le mot de passe d'un utilisateur. Si la validation du mot de passe aboutit, le compteur d'échecs doit être effacé. Cela empêche les attaques qui empêchent le débit régulé en désactivant la MMC intégrée (eMMC) après avoir émis un appel verify. La fonction enroll vérifie également le mot de passe de l'utilisateur (le cas échéant) et doit être limitée de la même manière.

Si l'appareil le permet, il est vivement recommandé d'écrire le compteur d'erreurs dans un stockage sécurisé. Si l'appareil n'est pas compatible avec le chiffrement basé sur les fichiers ou si le stockage sécurisé est trop lent, les implémentations peuvent utiliser directement le RPMB (Replay Protected Memory Block).