Portier

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

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 basé sur le matériel . Autrement dit, une attestation Gatekeeper informe Keystore que les clés liées à l'authentification (par exemple, les clés que les applications ont créées) 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 classeur C++ contenant une logique indépendante de la plate-forme et correspondant à l'interface Java GateKeeperService .
  • Couche d'abstraction matérielle Gatekeeper (HAL) . L'interface HAL dans hardware/libhardware/include/hardware/gatekeeper.h et le module d'implémentation.
  • Gardien (TEE) . L'homologue TEE de gatekeeperd . Une implémentation basée sur TEE de Gatekeeper.

Gatekeeper nécessite l'implémentation de 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 incluant des fonctions virtuelles pures de création/d'accès aux clés et de calcul des signatures).

Le LockSettingsService fait une demande (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 contrôle d'accès
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 à la notification des authentifications d'appareils à Keystore. Le démon gatekeeperd s'exécute dans son propre processus et est séparé du serveur système.

Implémentation HAL

Le démon gatekeeperd utilise HAL pour interagir avec l'homologue TEE du démon gatekeeperd pour l'authentification par mot de passe. L'implémentation HAL doit pouvoir signer (inscrire) et vérifier les blobs. Toutes les implémentations doivent respecter le format standard du jeton d'authentification (AuthToken) généré à chaque vérification de mot de passe réussie. Pour plus de détails sur le contenu et la sémantique de AuthToken, consultez format AuthToken .

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

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

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

Trusty et autres implémentations

Le système d'exploitation Trusty est le système d'exploitation de confiance open source 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 tant que le TEE a accès à une clé matérielle et à une horloge monotone sécurisée qui fonctionne 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 de mot de passe. Trusty Gatekeeper demande la clé à Keymaster pour chaque utilisation et ne conserve pas ou ne cache pas 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 le TEE GateKeeper, les principales responsabilités d'une implémentation conforme incluent :

  • 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 en mesure 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.

Identifiants sécurisés de l'utilisateur (SID)

Un SID utilisateur est la représentation TEE d'un utilisateur (sans connexion forte à 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 inscrit un nouveau mot de passe sans en fournir un précédent. Ceci est connu comme une réinscription non approuvée et n'est pas autorisé par le cadre Android dans des circonstances normales. Une réinscription de confiance se produit lorsqu'un utilisateur fournit un ancien mot de passe valide ; dans ce cas, le SID utilisateur est migré vers le nouveau descripteur de mot de passe, en conservant les clés qui lui é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 le AuthToken renvoyé par la fonction de verify et associés à toutes les clés de magasin de clés liées à l'authentification (pour plus de détails sur le format AuthToken et le magasin de clés, voir Authentification ). Comme un appel non fiable à la fonction d' enroll modifiera le SID de l'utilisateur, l'appel rendra les clés liées à ce mot de passe inutiles. 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 les clés sensibles protégées par la racine au cours du processus.

Limitation des demandes

GateKeeper doit être en mesure de limiter en toute sécurité les tentatives de force brute sur un identifiant utilisateur. Comme indiqué dans hardware/libhardware/include/hardware/gatekeeper.h , HAL permet de renvoyer un délai d'attente en millisecondes. Le délai d'attente informe le client de ne plus appeler GateKeeper tant que le délai d'attente ne s'est pas écoulé ; 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 l'émission d'un appel de verify . La fonction d' enroll vérifie également le mot de passe de l'utilisateur (si 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é d'écrire le compteur d'échecs 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ée par relecture (RPMB).