Clés encapsulées matériellement

Comme la plupart des logiciels de cryptage de disques et de fichiers, le cryptage de stockage d'Android repose traditionnellement sur les clés de cryptage brutes présentes dans la mémoire système afin que le cryptage puisse être effectué. Même lorsque le cryptage est effectué par du matériel dédié plutôt que par un logiciel, le logiciel doit généralement toujours gérer les clés de cryptage brutes.

Cela n'est généralement pas considéré comme un problème car les clés ne seront pas présentes lors d'une attaque hors ligne, qui est le principal type d'attaque contre lequel le cryptage de stockage est destiné à se protéger. Cependant, il y a un désir d'offrir une protection accrue contre d' autres types d'attaques, comme les attaques de démarrage à froid , et les attaques en ligne où un attaquant pourrait être en mesure de fuir la mémoire du système sans compromettre complètement l'appareil.

Pour résoudre ce problème, Android 11 a introduit le support pour les clés enveloppées matériel, où le support matériel est présent. Les clés encapsulées matériellement sont des clés de stockage qui ne sont connues que sous forme brute pour le matériel dédié ; le logiciel ne voit et ne fonctionne avec ces clés que sous forme encapsulée (cryptée). Ce matériel doit être capable de générer et d'importer des clés de stockage, d'encapsuler des clés de stockage sous des formes éphémères et à long terme, de dériver des sous-clés, de programmer directement une sous-clé dans un moteur de chiffrement en ligne et de renvoyer une sous-clé distincte au logiciel.

Note: Un moteur Crypto en ligne (ou le matériel de chiffrement en ligne) fait référence au matériel qui encrypte / déchiffre les données alors qu'il est sur son chemin vers / depuis le périphérique de stockage. Il s'agit généralement d'un contrôleur hôte UFS ou eMMC qui implémente les extensions crypto définies par la spécification JEDEC correspondante.

Concevoir

Cette section présente la conception de la fonctionnalité de clés encapsulées matériellement, y compris la prise en charge matérielle requise pour celle-ci. Cette discussion se concentre sur le chiffrement de fichiers (FBE), mais la solution s'applique à un cryptage des métadonnées aussi.

Une façon d'éviter d'avoir besoin des clés de chiffrement brutes dans la mémoire système serait de les conserver uniquement dans les emplacements de clés d'un moteur de chiffrement en ligne. Cependant, cette approche se heurte à certains problèmes :

  • Le nombre de clés de chiffrement peut dépasser le nombre d'emplacements de clés.
  • Les moteurs de chiffrement en ligne ne peuvent être utilisés que pour chiffrer/déchiffrer des blocs complets de données sur disque. Cependant, dans le cas de FBE, le logiciel doit toujours être capable d'effectuer d'autres travaux cryptographiques tels que le cryptage des noms de fichiers et la dérivation des identifiants de clé. Le logiciel aurait toujours besoin d'accéder aux clés FBE brutes pour effectuer cet autre travail.

Pour éviter ces problèmes, les clés de stockage sont plutôt transformés en clés enveloppé le matériel, qui ne peut être déballés et utilisés par le matériel dédié. Cela permet de prendre en charge un nombre illimité de clés. De plus, la hiérarchie des clés est modifiée et partiellement déplacée vers ce matériel, ce qui permet de renvoyer une sous-clé au logiciel pour des tâches qui ne peuvent pas utiliser un moteur de chiffrement en ligne.

Hiérarchie des clés

Les clés peuvent être obtenues à partir d' autres touches en utilisant une KDF (fonction de dérivation de clé) tels que HKDF , résultant en une hiérarchie de clés.

Le schéma suivant représente une hiérarchie clé typique pour FBE lorsque les touches enveloppées matériels ne sont pas utilisés:

Hiérarchie des clés FBE (standard)
Figure 1. hiérarchie de clé de FBE (standard)

La clé de classe FBE est la clé de chiffrement brute qu'Android transmet au noyau Linux pour déverrouiller un ensemble particulier de répertoires chiffrés, tels que le stockage chiffré des informations d'identification pour un utilisateur Android particulier. (Dans le noyau, cette clé est appelée clé maîtresse fscrypt.) A partir de cette clé, le noyau tire les sous - clés suivants:

  • L'identifiant de la clé. Ceci n'est pas utilisé pour le cryptage, mais est plutôt une valeur utilisée pour identifier la clé avec laquelle un fichier ou un répertoire particulier est protégé.
  • La clé de chiffrement du contenu du fichier
  • La clé de cryptage des noms de fichiers

En revanche, le schéma suivant illustre la hiérarchie des clés pour FBE lorsque des clés encapsulées matériellement sont utilisées :

Hiérarchie des clés FBE (avec clé encapsulée matériellement)
Figure 2. FBE hiérarchie de clé (avec clé enveloppé matériel)

Par rapport au cas précédent, un niveau supplémentaire a été ajouté à la hiérarchie des clés et la clé de chiffrement du contenu du fichier a été déplacée. Le nœud racine représente toujours la clé qu'Android transmet à Linux pour déverrouiller un ensemble de répertoires cryptés. Cependant, cette clé est maintenant sous une forme éphémère et, pour être utilisée, elle doit être transmise à un matériel dédié. Ce matériel doit implémenter deux interfaces qui prennent une clé éphémère :

  • Une interface pour Derive inline_encryption_key et programme directement dans un keyslot du moteur Crypto en ligne. Cela permet au contenu du fichier d'être crypté/décrypté sans que le logiciel ait accès à la clé brute. Dans les noyaux communs Android, cela correspond à l' interface du blk_ksm_ll_ops::keyslot_program opération, qui doit être mis en œuvre par le pilote de stockage.
  • Une interface pour Derive et retour sw_secret ( « secret logiciel » - aussi appelé le « secret brut » dans certains endroits), qui est la clé que Linux utilise pour calculer les sous - clés pour tout autre que le contenu du fichier cryptage. Dans les noyaux communs Android, cela correspond à l' interface du blk_ksm_ll_ops::derive_raw_secret opération, qui doit être mis en œuvre par le pilote de stockage.

Pour calculer inline_encryption_key et sw_secret de la clé de stockage brut, le matériel doit utiliser une KDF cryptographiquement forte. Ce KDF doit suivre les meilleures pratiques de cryptographie ; il doit avoir un niveau de sécurité d'au moins 256 bits, c'est-à-dire suffisant pour tout algorithme utilisé ultérieurement. Il doit également utiliser une étiquette, un contexte et/ou une chaîne d'informations spécifiques à l'application lors de la dérivation de chaque type de sous-clé afin de garantir que les sous-clés résultantes sont isolées cryptographiquement, c'est-à-dire que la connaissance de l'une d'entre elles n'en révèle aucune autre. L'étirement de la clé n'est pas nécessaire, car la clé de stockage brute est déjà une clé uniformément aléatoire.

Techniquement, tout KDF répondant aux exigences de sécurité pourrait être utilisé. Cependant, à des fins de test, il est nécessaire de ré-implémenter le même KDF dans le code de test. Actuellement, un KDF a été examiné et mis en œuvre ; il se trouve dans le code source pour vts_kernel_encryption_test . Il est recommandé d'utiliser du matériel ce KDF, qui utilise NIST SP 800-108 « KDF en mode compteur » avec AES-256-CMAC comme PRF. Notez que pour être compatible, toutes les parties de l'algorithme doivent être identiques, y compris le choix des contextes KDF et des étiquettes pour chaque sous-clé.

Emballage de clé

Pour atteindre les objectifs de sécurité des clés encapsulées matériellement, deux types d'encapsulation de clé sont définis :

  • Emballage Ephémère: le matériel crypte la clé brute en utilisant une clé qui est généré de manière aléatoire à chaque démarrage et n'est pas directement exposée à l' extérieur du matériel.
  • Emballage à long terme: le matériel crypte la clé brute en utilisant une clé unique, persistante intégré dans le matériel qui est pas exposé directement à l' extérieur du matériel.

Toutes les clés transmises au noyau Linux pour déverrouiller le stockage sont encapsulées de manière éphémère. Cela garantit que si un attaquant est capable d'extraire une clé en cours d'utilisation de la mémoire système, cette clé sera inutilisable non seulement hors de l'appareil, mais également sur l'appareil après un redémarrage.

Dans le même temps, Android doit toujours pouvoir stocker une version cryptée des clés sur le disque afin qu'elles puissent être déverrouillées en premier lieu. Les clés brutes fonctionneraient à cet effet. Cependant, il est souhaitable que les clés brutes ne soient jamais présentes dans la mémoire système afin qu'elles ne puissent jamais être extraites pour être utilisées hors de l'appareil, même si elles sont extraites au moment du démarrage. Pour cette raison, le concept d'emballage à long terme est défini.

Pour prendre en charge la gestion des clés enveloppées de ces deux manières différentes, le matériel doit implémenter les interfaces suivantes :

  • Interfaces pour générer et importer des clés de stockage, les renvoyant sous une forme encapsulée à long terme. Ces interfaces sont accessibles indirectement par KeyMint, et ils correspondent à la TAG_STORAGE_KEY tag KeyMint. La capacité « générer » est utilisé par vold pour générer de nouvelles clés de stockage pour une utilisation par Android, alors que la capacité « d'importation » est utilisé par vts_kernel_encryption_test aux touches de test d'importation.
  • Une interface pour convertir une clé de stockage encapsulée à long terme en une clé de stockage encapsulée de manière éphémère. Ceci correspond à la convertStorageKeyToEphemeral méthode KeyMint. Cette méthode est utilisée à la fois par vold et vts_kernel_encryption_test afin de déverrouiller le stockage.

L'algorithme d'enveloppement de clé est un détail d'implémentation, mais il doit utiliser un AEAD puissant tel que AES-256-GCM avec des IV aléatoires.

Modifications logicielles requises

AOSP dispose déjà d'un cadre de base pour la prise en charge des clés encapsulées matériellement. Cela inclut le support des composants tels que userspace vold , ainsi que le support du noyau Linux dans blk-Crypto, fscrypt et touche dm par défaut.

Cependant, certaines modifications spécifiques à la mise en œuvre sont nécessaires.

Modifications de KeyMint

Doit être modifié la mise en œuvre KeyMint de l'appareil pour le soutien TAG_STORAGE_KEY et mettre en œuvre la convertStorageKeyToEphemeral méthode.

En Keymaster, exportKey a été utilisé au lieu de convertStorageKeyToEphemeral .

Modifications du noyau Linux

Le pilote Linux pour le moteur de Crypto en ligne de l'appareil doit être modifié pour fixer BLK_CRYPTO_FEATURE_WRAPPED_KEYS , faire la keyslot_program() et keyslot_evict() opérations de soutien de la programmation / expulsant les clés enveloppées matériel, et mettre en œuvre le derive_raw_secret() opération.

Essai

Bien que le cryptage avec des clés encapsulées matériellement soit plus difficile à tester que le cryptage avec des clés standard, il est toujours possible de tester en important une clé de test et en réimplémentant la dérivation de clé effectuée par le matériel. Ceci est mis en œuvre vts_kernel_encryption_test . Pour exécuter ce test, exécutez :

atest -v vts_kernel_encryption_test

Lire le journal de test et vérifiez que les principaux cas de test enveloppé de matériel (par exemple FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy et DmDefaultKeyTest.TestHwWrappedKey ) ne sont pas ignorés en raison de l' appui pour les clés enveloppées matérielles ne sont pas détectés, les résultats des tests seront encore « passés » dans ce cas.

Activation

Une fois que le matériel enveloppé support clé de l'appareil fonctionne correctement, vous pouvez apporter les modifications suivantes à l'appareil fstab fichier à utiliser Android pour le cryptage FBE et métadonnées:

  • FBE: ajouter le wrappedkey_v0 drapeau au fileencryption paramètre. Par exemple, utiliser fileencryption=::inlinecrypt_optimized+wrappedkey_v0 . Pour plus de détails, consultez la documentation FBE .
  • Chiffrement des métadonnées: ajoutez le wrappedkey_v0 drapeau au metadata_encryption paramètre. Par exemple, l' utilisation metadata_encryption=:wrappedkey_v0 . Pour plus de détails, consultez la documentation de chiffrement des métadonnées .