Google is committed to advancing racial equity for Black communities. See how.
Cette page a été traduite par l'API Cloud Translation.
Switch to English

Implémentation de dm-verity

Android 4.4 et supérieur prend en charge le démarrage vérifié via la fonction de noyau optionnelle device-mapper-verity (dm-verity), qui fournit une vérification transparente de l'intégrité des périphériques de bloc. dm-verity aide à empêcher les rootkits persistants qui peuvent conserver les privilèges root et compromettre les périphériques. Cette fonctionnalité permet aux utilisateurs d'Android d'être sûrs lors du démarrage d'un appareil qu'il est dans le même état que lors de sa dernière utilisation.

Les applications potentiellement nuisibles (PHA) avec des privilèges root peuvent se cacher des programmes de détection et se masquer autrement. Le logiciel d'enracinement peut le faire car il est souvent plus privilégié que les détecteurs, ce qui permet au logiciel de «mentir» aux programmes de détection.

La fonction dm-verity vous permet d'examiner un périphérique bloc, la couche de stockage sous-jacente du système de fichiers, et de déterminer s'il correspond à sa configuration attendue. Il le fait en utilisant un arbre de hachage cryptographique. Pour chaque bloc (généralement 4k), il existe un hachage SHA256.

Étant donné que les valeurs de hachage sont stockées dans une arborescence de pages, seul le hachage «racine» de niveau supérieur doit être approuvé pour vérifier le reste de l'arborescence. La possibilité de modifier l'un des blocs équivaudrait à casser le hachage cryptographique. Voir le diagramme suivant pour une représentation de cette structure.

table de hachage dm verity

Figure 1. Table de hachage dm-verity

Une clé publique est incluse dans la partition de démarrage, qui doit être vérifiée en externe par le fabricant du périphérique. Cette clé est utilisée pour vérifier la signature de ce hachage et confirmer que la partition système du périphérique est protégée et inchangée.

Opération

La protection dm-verity vit dans le noyau. Donc, si le logiciel d'enracinement compromet le système avant que le noyau ne démarre, il conservera cet accès. Pour atténuer ce risque, la plupart des fabricants vérifient le noyau à l'aide d'une clé gravée dans l'appareil. Cette clé n'est pas modifiable une fois que l'appareil quitte l'usine.

Les fabricants utilisent cette clé pour vérifier la signature sur le chargeur de démarrage de premier niveau, qui à son tour vérifie la signature aux niveaux suivants, le chargeur de démarrage de l'application et éventuellement le noyau. Chaque fabricant souhaitant profiter d'un démarrage vérifié doit disposer d'une méthode pour vérifier l'intégrité du noyau. En supposant que le noyau a été vérifié, le noyau peut regarder un périphérique bloc et le vérifier au fur et à mesure qu'il est monté.

Une façon de vérifier un périphérique bloc est de hacher directement son contenu et de le comparer à une valeur stockée. Cependant, tenter de vérifier un périphérique bloc entier peut prendre une période prolongée et consommer une grande partie de l'énergie d'un périphérique. Les appareils prendraient de longues périodes à démarrer, puis seraient considérablement vidés avant leur utilisation.

Au lieu de cela, dm-verity vérifie les blocs individuellement et uniquement lors de l'accès à chacun d'eux. Lorsqu'il est lu en mémoire, le bloc est haché en parallèle. Le hachage est ensuite vérifié dans l'arbre. Et comme la lecture du bloc est une opération si coûteuse, la latence introduite par cette vérification au niveau du bloc est comparativement nominale.

Si la vérification échoue, le périphérique génère une erreur d'E / S indiquant que le bloc ne peut pas être lu. Il apparaîtra comme si le système de fichiers a été corrompu, comme prévu.

Les applications peuvent choisir de continuer sans les données résultantes, par exemple lorsque ces résultats ne sont pas nécessaires à la fonction principale de l'application. Cependant, si l'application ne peut pas continuer sans les données, elle échouera.

Correction d'erreur directe

Android 7.0 et supérieur améliore la robustesse de dm-verity avec la correction d'erreur directe (FEC). L'implémentation AOSP commence par le code de correction d'erreur Reed-Solomon commun et applique une technique appelée entrelacement pour réduire la surcharge d'espace et augmenter le nombre de blocs corrompus qui peuvent être récupérés. Pour plus de détails sur FEC, consultez Démarrage vérifié strictement appliqué avec correction d'erreur .

la mise en oeuvre

Sommaire

  1. Générez une image système ext4.
  2. Générez un arbre de hachage pour cette image.
  3. Créez une table dm-verity pour cet arbre de hachage.
  4. Signez cette table dm-verity pour produire une signature de table.
  5. Regroupez la signature de la table et la table dm-verity dans des métadonnées verity.
  6. Concaténez l'image système, les métadonnées Verity et l'arborescence de hachage.

Voir lesprojets Chromium - Démarrage vérifié pour une description détaillée de l'arbre de hachage et du tableau dm-verity.

Générer l'arbre de hachage

Comme décrit dans l'introduction, l'arbre de hachage fait partie intégrante de dm-verity. L'outil cryptsetup générera un arbre de hachage pour vous. Alternativement, un compatible est défini ici:

<your block device name> <your block device name> <block size> <block size> <image size in blocks> <image size in blocks + 8> <root hash> <salt>

Pour former le hachage, l'image système est divisée au niveau de la couche 0 en blocs de 4k, chacun étant attribué un hachage SHA256. La couche 1 est formée en joignant uniquement ces hachages SHA256 en blocs de 4k, ce qui donne une image beaucoup plus petite. La couche 2 est formée de manière identique, avec les hachages SHA256 de la couche 1.

Ceci est fait jusqu'à ce que les hachages SHA256 de la couche précédente puissent tenir dans un seul bloc. Lorsque vous obtenez le SHA256 de ce bloc, vous avez le hachage racine de l'arbre.

La taille de l'arborescence de hachage (et l'utilisation de l'espace disque correspondant) varie en fonction de la taille de la partition vérifiée. En pratique, la taille des arbres de hachage a tendance à être petite, souvent inférieure à 30 Mo.

Si vous avez un bloc dans un calque qui n'est pas complètement rempli naturellement par les hachages du calque précédent, vous devez le compléter avec des zéros pour atteindre le 4k attendu. Cela vous permet de savoir que l'arbre de hachage n'a pas été supprimé et est à la place complété avec des données vides.

Pour générer l'arbre de hachage, concaténez les hachages de la couche 2 sur ceux de la couche 1, la couche 3 les hachages sur ceux de la couche 2, et ainsi de suite. Écrivez tout cela sur le disque. Notez que cela ne fait pas référence à la couche 0 du hachage racine.

Pour récapituler, l'algorithme général pour construire l'arbre de hachage est le suivant:

  1. Choisissez un sel aléatoire (codage hexadécimal).
  2. Annuler l'analyse de votre image système en blocs de 4k.
  3. Pour chaque bloc, récupérez son hachage SHA256 (salé).
  4. Concaténer ces hachages pour former un niveau
  5. Remplissez le niveau avec des 0 à une limite de bloc de 4k.
  6. Concaténez le niveau à votre arbre de hachage.
  7. Répétez les étapes 2 à 6 en utilisant le niveau précédent comme source du suivant jusqu'à ce que vous n'ayez qu'un seul hachage.

Le résultat est un hachage unique, qui est votre hachage racine. Ceci et votre sel sont utilisés lors de la construction de votre table de mappage dm-verity.

Construction de la table de mappage dm-verity

Construire la table de mappage dm-verity, qui identifie le dispositif de blocage (ou cible) pour le noyau et l'emplacement de l'arbre de hachage (qui est la même valeur.) Ce mappage est utilisé pour fstab génération et le démarrage. Le tableau identifie également la taille des blocs et le hash_start, l'emplacement de départ de l'arbre de hachage (en particulier, son numéro de bloc depuis le début de l'image).

Voir cryptsetup pour une description détaillée des champs de la table de mappage de cible verity.

Signature de la table dm-verity

Signez la table dm-verity pour produire une signature de table. Lors de la vérification d'une partition, la signature de la table est validée en premier. Cela se fait par rapport à une clé sur votre image de démarrage dans un emplacement fixe. Les clés sont généralement incluses dans les systèmes de construction des fabricants pour une inclusion automatique sur des appareils situés à un emplacement fixe.

Pour vérifier la partition avec cette signature et cette combinaison de touches:

  1. Ajoutez une clé RSA-2048 au format compatible libmincrypt à la partition /boot sur /verity_key . Identifiez l'emplacement de la clé utilisée pour vérifier l'arborescence de hachage.
  2. Dans le fstab de l'entrée appropriée, ajoutez verify aux indicateurs fs_mgr .

Regroupement de la signature de la table en métadonnées

Regroupez la signature de la table et la table dm-verity dans des métadonnées verity. Le bloc entier de métadonnées est versionné afin qu'il puisse être étendu, par exemple pour ajouter un deuxième type de signature ou modifier un certain ordre.

En guise de vérification de cohérence, un nombre magique est associé à chaque ensemble de métadonnées de table qui permet d'identifier la table. Étant donné que la longueur est incluse dans l'en-tête de l'image système ext4, cela permet de rechercher les métadonnées sans connaître le contenu des données elles-mêmes.

Cela garantit que vous n'avez pas choisi de vérifier une partition non vérifiée. Si tel est le cas, l'absence de ce nombre magique arrêtera le processus de vérification. Ce nombre ressemble à:
0xb001b001

Les valeurs d'octet en hexadécimal sont:

  • premier octet = b0
  • deuxième octet = 01
  • troisième octet = b0
  • quatrième octet = 01

Le diagramme suivant illustre la répartition des métadonnées Verity:

<magic number>|<version>|<signature>|<table length>|<table>|<padding>
\-------------------------------------------------------------------/
\----------------------------------------------------------/   |
                            |                                  |
                            |                                 32K
                       block content

Et ce tableau décrit ces champs de métadonnées.

Tableau 1. Champs de métadonnées Verity

Champ Objectif Taille Valeur
nombre magique utilisé par fs_mgr comme contrôle de cohérence 4 octets 0xb001b001
version utilisé pour versionner le bloc de métadonnées 4 octets actuellement 0
Signature la signature du tableau sous forme capitonnée PKCS1.5 256 octets
longueur de la table la longueur de la table dm-verity en octets 4 octets
table la table dm-verity décrite précédemment octets de longueur de table
rembourrage cette structure est 0-rembourrée à 32k de longueur 0

Optimiser dm-verity

Pour obtenir les meilleures performances de dm-verity, vous devez:

  • Dans le noyau, activez NEON SHA-2 pour ARMv7 et les extensions SHA-2 pour ARMv8.
  • Testez différents paramètres de lecture anticipée et de prefetch_cluster pour trouver la meilleure configuration pour votre appareil.