Implémenter dm-verity

Android 4.4 ou version ultérieure est compatible avec le démarrage validé via l'option dm-verity (device-mapper-verity), qui fournit des données de l'intégrité des appareils de stockage en mode bloc. dm-verity permet d'éviter les rootkits persistants qui peuvent conserver des privilèges racine et compromettre des appareils. Ce permet aux utilisateurs Android de s'assurer qu'au démarrage d'un appareil, il se trouve que lors de sa dernière utilisation.

Les applications potentiellement dangereuses (PHA) disposant de droits racines peuvent être masquées pour des programmes de détection et de se masquer. Le logiciel d’activation du mode root peut faire car il est souvent plus privilégié que les détecteurs, ce qui permet logiciel de "mentir" aux programmes de détection.

La fonctionnalité dm-verity vous permet d'examiner un appareil de stockage de blocs, du système de fichiers et déterminer si elle correspond aux attentes configuration. Pour ce faire, il utilise un arbre de hachage cryptographique. Pour chaque bloc (généralement 4K), il y a un hachage SHA256.

Les valeurs de hachage étant stockées dans une arborescence de pages, seul le premier niveau "racine" le hachage doit être approuvé pour vérifier le reste de l'arborescence. La possibilité de modifier l’un des blocs équivaudrait à briser le hachage cryptographique. Le schéma suivant illustre 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 de l'appareil. Cette clé permet de valider la signature pour ce hachage et confirmer que la partition du système de l'appareil est protégée et ne sont pas modifiées.

Conditions de fonctionnement

la protection dm-verity se trouve dans le noyau. Ainsi, si un logiciel d'activation du mode root compromet système avant l’utilisation du noyau, il conservera cet accès. Pour y remédier, risque, la plupart des fabricants vérifient le noyau à l’aide d’une clé gravée sur le périphérique. Une fois l'appareil en sortie d'usine, cette clé ne peut plus être modifiée.

Les fabricants utilisent cette clé pour valider la signature au premier niveau qui, à son tour, vérifie la signature aux niveaux suivants, le bootloader de l'application, puis le noyau. Chaque fabricant souhaitant profiter des validations démarrage doit proposer une méthode permettant de vérifier l'intégrité du noyau. En supposant que le noyau a été vérifié, le noyau peut examiner un périphérique de stockage en mode bloc et vérifier qu'il est monté.

Une façon de vérifier un périphérique de stockage en mode bloc consiste à hacher directement son contenu et à le comparer vers une solution de prépaiement. Toutefois, essayer de valider l'intégralité d'un appareil de stockage en mode bloc prendre une période prolongée et consommer une grande partie de la batterie d'un appareil. Les appareils prendraient pendant de longues périodes au démarrage, puis s'épuiser considérablement avant utilisation.

En revanche, dm-verity vérifie les blocs individuellement, y accéder. Lorsqu'il est lu en mémoire, le bloc est haché en parallèle. Le hachage est puis vérifié l'arborescence. Comme la lecture du bloc est très coûteuse, la latence introduite par cette vérification au niveau du bloc est relativement nominales.

Si la validation échoue, l'appareil génère une erreur d'E/S indiquant que le bloc ne peuvent pas être lues. Il semblera que le système de fichiers a été corrompu, comme prévu.

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

Correction des erreurs de transfert

Android 7.0 ou version ultérieure améliore la robustesse de dm-verity avec les erreurs de transfert de machine learning (FEC). La mise en œuvre d'AOSP commence par le code de correction d'erreur Reed-Solomon et applique un appelée "entrelacement" pour réduire la surcharge d'espace et augmenter de blocages corrompus et récupérables. Pour en savoir plus sur FEC, consultez Démarrage validé strict avec correction des erreurs.

Implémentation

Résumé

  1. Générez une image système ext4.
  2. Générez une arborescence de hachage pour cette image.
  3. Créez une table dm-verity pour cette arborescence de hachage.
  4. Signer cette table dm-verity pour générer une table signature.
  5. Regrouper la signature de table et la table dm-verity en métadonnées de vérité.
  6. Concaténez l'image système, les métadonnées de vérification et l'arborescence de hachage.

Consultez la page The Chromium Projects – Démarrage validé. pour obtenir une description détaillée de l'arborescence de hachage et de la table dm-verity.

Générer l'arborescence de hachage

Comme décrit dans l'introduction, l'arborescence de hachage fait partie intégrante de dm-verity. La L'outil cryptsetup une arborescence de hachage. Une autre solution compatible est définie 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 4 000 blocs, chacun lui a 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 à l'identique, avec les hachages SHA256 de la couche 1.

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

La taille de l'arborescence de hachage (et l'espace disque utilisé) varie selon le de la partition vérifiée. En pratique, la taille des arbres de hachage a tendance à être petit, souvent moins de 30 Mo.

Si l'un de vos blocs d'un calque n'est pas complètement rempli naturellement par les hachages de la couche précédente, vous devez la remplir avec des zéros pour obtenir le la résolution attendue est 4K. Cela vous permet de savoir que l'arborescence de hachage n'a pas été supprimée et est complétée par des données vides.

Pour générer l'arborescence de hachage, concaténez les hachages de couche 2 avec ceux de la couche 1, la couche 3 aux hachages sur ceux de la couche 2, et ainsi de suite. Écrire 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'arborescence de hachage est le suivant:

  1. Choisissez un salage aléatoire (encodage hexadécimal).
  2. Diviser votre image système en blocs de 4K
  3. Pour chaque bloc, obtenez son hachage SHA256 (salé).
  4. Concaténer ces hachages pour former un niveau
  5. Compléter le niveau avec des 0 jusqu'à une limite de bloc de 4 000
  6. Concaténez le niveau dans votre arborescence de hachage.
  7. Répétez les étapes 2 à 6 en utilisant le niveau précédent comme source pour le niveau suivant jusqu'à vous n'avez 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.

Créer la table de mappage dm-verity

Créez la table de mappage dm-verity, qui identifie l'appareil (ou la cible) de stockage en mode bloc. pour le noyau et l'emplacement de l'arborescence de hachage (qui est la même valeur). Ce Le mappage est utilisé pour la génération et le démarrage de fstab. Le tableau identifie également la taille des blocs et hash_start, l'emplacement de départ de l'arbre de hachage (plus précisément, son numéro de bloc à partir du début de l'image).

Consultez cryptsetup pour voir description détaillée des champs de la table de mappage des cibles de vérification.

Signer la table dm-verity

Signez la table dm-verity pour générer une signature de table. Lors de la validation d'un la signature de la table est validée en premier. Cela se fait par rapport à une clé sur l'image de démarrage à un emplacement fixe. Les clés sont généralement incluses des fabricants pour permettre l'inclusion automatique sur les appareils l'emplacement.

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

  1. Ajoutez une clé RSA-2048 dans un format compatible avec libmincrypt au Partition /boot à /verity_key. Identifier l'emplacement de la clé utilisée pour la validation l'arborescence de hachage.
  2. Dans le fstab de l'entrée concernée, ajoutez verify aux indicateurs fs_mgr.

Regrouper la signature de la table dans des métadonnées

Regroupez la signature de la table et la table dm-verity dans des métadonnées de vérification. L'intégralité bloc de métadonnées est versionnée afin qu'il puisse être étendu, par exemple pour ajouter une seconde le genre de signature ou de modifier un ordre.

Afin de contrôler l'intégrité, un nombre magique est associé à chaque ensemble de métadonnées de la table. qui permet d'identifier le tableau. La longueur étant incluse dans le système ext4, l'en-tête de l'image, ce qui permet de rechercher les métadonnées sans connaître le contenu des données elles-mêmes.

Cela permet de s'assurer que vous n'avez pas choisi de valider une partition non validée. Si oui, l'absence de ce chiffre interrompt le processus de validation. Ce numéro ressemble à:
0xb001b001

Les valeurs en octets en hexadécimales sont les suivantes:

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

Le schéma suivant illustre la répartition des métadonnées de vérification:

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

Ce tableau décrit ces champs de métadonnées.

Tableau 1. Champs de métadonnées de vérification

Champ Objectif Taille Valeur
nombre magique utilisé par fs_mgr pour contrôler l'intégrité 4 octets 0xb001b001
version utilisé pour gérer les versions du bloc de métadonnées 4 octets actuellement 0
signature la signature de la table au format PKCS1.5 avec remplissage ; 256 octets
longueur du tableau la longueur de la table dm-verity en octets 4 octets
table le tableau dm-verity décrit précédemment longueur de la table en octets
padding cette structure a un remplissage de 0 et une longueur de 32 ko 0

Optimiser dm-verity

Pour tirer le meilleur parti de dm-verity, vous devez:

  • Dans le noyau, activez NEON SHA-2 pour ARMv7 et SHA-2 pour ARMv8.
  • Tester différentes options read-ahead et prefetch_cluster afin de trouver la meilleure configuration pour votre appareil.