Portier

Le sous-système Gatekeeper effectue une authentification par modèle de périphérique/mot de passe dans un environnement d'exécution sécurisé (TEE). Gatekeeper enregistre et vérifie les mots de passe via un HMAC avec une clé secrète matérielle. De plus, Gatekeeper limite les tentatives de vérification consécutives ayant échoué et doit refuser de répondre aux demandes en fonction d'un délai d'attente donné et d'un nombre donné de tentatives consécutives infructueuses.

Lorsque les utilisateurs vérifient leurs mots de passe, Gatekeeper utilise le secret partagé dérivé de TEE pour signer une attestation d'authentification à envoyer au Keystore matériel . Autrement dit, une attestation Gatekeeper informe Keystore que les clés liées à l'authentification (par exemple, les clés créées par les applications) peuvent être libérées pour être utilisées par les applications.

Architecture

Gatekeeper implique trois composants principaux :

  • gatekeeperd (démon Gatekeeper). Un service de liaison C++ contenant une logique indépendante de la plate-forme et correspondant à l'interface Java GateKeeperService .
  • Couche d'abstraction matérielle du portier (HAL) . L'interface HAL dans hardware/libhardware/include/hardware/gatekeeper.h et le module d'implémentation.
  • Gardien d'accès (TEE) . L'homologue TEE de gatekeeperd . Une implémentation de Gatekeeper basée sur TEE.

Gatekeeper nécessite l'implémentation du Gatekeeper HAL (en particulier les fonctions dans hardware/libhardware/include/hardware/gatekeeper.h ) et du composant Gatekeeper spécifique à TEE (basé en partie sur le fichier d'en-tête system/gatekeeper/include/gatekeeper/gatekeeper.h qui inclut des fonctions virtuelles pures pour créer/accéder à des clés et des signatures informatiques).

Le LockSettingsService effectue une requête (via Binder) qui atteint le démon gatekeeperd dans le système d'exploitation Android. Le démon gatekeeperd fait alors une requête qui parvient à son homologue (Gatekeeper) dans le TEE :

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

Le démon gatekeeperd donne aux API du framework Android l'accès à HAL et participe au reporting des authentifications des appareils à Keystore. Le démon gatekeeperd s'exécute dans son propre processus et est distinct du serveur système.

Implémentation HAL

Le démon gatekeeperd utilise le HAL pour interagir avec son homologue gatekeeperd pour l'authentification par mot de passe. L’implémentation HAL doit être capable de signer (s’inscrire) et de vérifier les blobs. Toutes les implémentations doivent adhérer au format standard du jeton d'authentification (AuthToken) généré lors de chaque vérification de mot de passe réussie. Pour plus de détails sur le contenu et la sémantique de l'AuthToken, voir Format AuthToken .

Les implémentations du fichier d'en-tête hardware/libhardware/include/hardware/gatekeeper.h doivent implémenter les fonctions enroll et verify :

  • La fonction enroll prend un objet blob de mot de passe, le signe et renvoie la signature sous forme de handle. Le blob renvoyé (à partir d’un appel à enroll ) doit avoir la structure affichée dans system/gatekeeper/include/gatekeeper/password_handle.h .
  • La fonction verify doit comparer la signature produite par le mot de passe fourni et s'assurer qu'elle correspond au descripteur de mot de passe enregistré.

La clé utilisée pour l'inscription et la vérification ne doit jamais changer et doit pouvoir être redérivée à chaque démarrage de l'appareil.

Implémentations fiables et autres

Le système d'exploitation Trusty est le système d'exploitation open source de confiance de Google pour les environnements TEE et contient une implémentation approuvée de GateKeeper. Cependant, vous pouvez utiliser n'importe quel système d'exploitation TEE pour implémenter Gatekeeper à condition que le TEE ait accès à une clé matérielle et à une horloge sécurisée et monotone qui tourne en suspend .

Trusty utilise un système IPC interne pour communiquer un secret partagé directement entre Keymaster et l'implémentation Trusty de Gatekeeper (le Trusty Gatekeeper ). Ce secret partagé est utilisé pour signer les AuthTokens envoyés à Keystore afin de fournir des attestations de vérification du mot de passe. Trusty Gatekeeper demande la clé à Keymaster pour chaque utilisation et ne conserve ni ne met en cache la valeur. Les implémentations sont libres de partager ce secret d'une manière qui ne compromet pas la sécurité.

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

Android fournit une implémentation C++ générique de GateKeeper qui ne nécessite que l'ajout de routines spécifiques à l'appareil pour être complète. Pour implémenter un TEE Gatekeeper avec un code spécifique à l'appareil pour votre TEE, reportez-vous aux fonctions et aux commentaires dans system/gatekeeper/include/gatekeeper/gatekeeper.h . Pour TEE GateKeeper, les principales responsabilités d'une implémentation conforme comprennent :

  • Adhésion au Gatekeeper HAL.
  • Les AuthTokens renvoyés doivent être formatés conformément à la spécification AuthToken (décrite dans Authentication ).
  • Le TEE Gatekeeper doit être capable de partager une clé HMAC avec Keymaster, soit en demandant la clé via un TEE IPC à la demande, soit en conservant un cache valide de la valeur à tout moment.

ID sécurisés des utilisateurs (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é avec un générateur de nombres pseudo-aléatoires cryptographiques (PRNG) chaque fois qu'un utilisateur enregistre un nouveau mot de passe sans fournir de précédent. Ceci est connu sous le nom de réinscription non fiable et n’est pas autorisé par le framework Android dans des circonstances normales. Une réinscription fiable se produit lorsqu'un utilisateur fournit un mot de passe précédent et valide ; dans ce cas, le SID utilisateur est migré vers le nouveau handle de mot de passe, en conservant les clés qui y étaient liées.

Le SID utilisateur est HMAC avec le mot de passe dans le descripteur de mot de passe lorsque le mot de passe est inscrit.

Les SID utilisateur sont écrits dans l'AuthToken renvoyé par la fonction verify et associés à toutes les clés Keystore liées à l'authentification (pour plus de détails sur le format AuthToken et le Keystore, voir Authentication ). Comme un appel non fiable à la fonction enroll modifiera le SID de l'utilisateur, l'appel rendra inutiles les clés liées à ce mot de passe. Les attaquants peuvent modifier le mot de passe de l’appareil s’ils contrôlent le système d’exploitation Android, mais ils détruiront ainsi les clés sensibles protégées par la racine.

Limitation des demandes

GateKeeper doit être capable de limiter en toute sécurité les tentatives de force brute sur les informations d'identification d'un utilisateur. Comme indiqué dans hardware/libhardware/include/hardware/gatekeeper.h , le HAL permet de renvoyer un délai d'attente en millisecondes. Le délai d'attente informe le client de ne plus appeler GateKeeper avant l'expiration du délai d'attente ; GateKeeper ne doit pas traiter les demandes s'il y a un délai d'attente en attente.

GateKeeper doit écrire un compteur d'échecs avant de vérifier un mot de passe utilisateur. Si la vérification du mot de passe réussit, le compteur d'échecs doit être effacé. Cela empêche les attaques qui empêchent la limitation 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 (s'il est fourni) et doit être limitée de la même manière.

S'il est pris en charge par l'appareil, il est fortement recommandé que le compteur d'échecs soit écrit dans un stockage sécurisé. Si l'appareil ne prend pas en charge le chiffrement basé sur les fichiers ou si le stockage sécurisé est trop lent, les implémentations peuvent utiliser directement le bloc de mémoire protégé par relecture (RPMB).