Android 4.4 et versions ultérieures sont compatibles avec le démarrage validé via la fonctionnalité de noyau device-mapper-verity (dm-verity) facultative, qui fournit une vérification transparente de l'intégrité des appareils de bloc. dm-verity permet d'éviter les rootkits persistants qui peuvent conserver les droits d'administration et compromettre les appareils. Cette fonctionnalité permet aux utilisateurs Android de s'assurer, 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 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 bloc, la couche de stockage sous-jacente du système de fichiers, et de déterminer s'il correspond à sa configuration attendue. Pour ce faire, il utilise un arbre de hachage cryptographique. Pour chaque bloc (généralement 4 ko), il existe 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. Consultez le schéma suivant pour voir une représentation de cette structure.
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 vérifier la signature de ce hachage et de confirmer que la partition système de l'appareil est protégée et inchangée.
Conditions de fonctionnement
La protection dm-verity réside dans le noyau. Ainsi, si un logiciel d'activation du mode root compromet système avant que le noyau n’apparaisse, il conserve cet accès. Pour atténuer ce risque, la plupart des fabricants vérifient le noyau à l'aide d'une clé gravée sur l'appareil. Cette clé ne peut pas être modifiée une fois que l'appareil quitte l'usine.
Les fabricants utilisent cette clé pour valider la signature sur le bootloader de premier niveau, qui à son tour valide la signature sur les niveaux suivants, le bootloader de l'application et finalement 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é validé, il peut examiner un périphérique de bloc et le valider lorsqu'il est installé.
Pour vérifier un appareil de bloc, vous pouvez hacher directement son contenu et le comparer à une valeur stockée. 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.
À la place, dm-verity vérifie les blocs individuellement et uniquement lorsqu'ils sont consultés. Lors de la lecture en mémoire, le bloc est haché en parallèle. Le hachage est ensuite validé dans l'arborescence. Étant donné que la lecture du bloc est une opération très coûteuse, la latence introduite par cette validation au niveau du bloc est relativement faible.
En cas d'échec de la validation, l'appareil génère une erreur d'E/S indiquant que le bloc ne peut pas être lu. Il semble 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 les données, elle échoue.
Correction d'erreurs par anticipation
Android 7.0 et les versions ultérieures améliorent la robustesse de dm-verity avec la correction d'erreurs par anticipation (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 la FEC, consultez la section Verified Boot strictement appliqué avec correction d'erreurs.Implémentation
Résumé
- Générez une image système ext4.
- Générez une arborescence de hachage pour cette image.
- Créez une table dm-verity pour cette arborescence de hachage.
- Signez cette table dm-verity pour générer une signature de table.
- Regrouper la signature de table et la table dm-verity en métadonnées de vérité.
- Concatenate l'image système, les métadonnées de validation et l'arborescence de hachage.
Pour obtenir une description détaillée de l'arborescence de hachage et du tableau dm-verity, consultez The Chromium Projects - Verified Boot (Projets Chromium : démarrage validé).
Générer l'arborescence de hachage
Comme décrit dans l'introduction, l'arborescence de hachage fait partie intégrante de dm-verity. L'outil cryptsetup génère un arbre de hachage pour vous. 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 à la couche 0 en blocs de 4 ko, chacun étant associé à un hachage SHA256. La couche 1 est constituée uniquement de ces hachages SHA256 en blocs de 4 ko, 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.
Cela se fait jusqu'à ce que les hachages SHA256 de la couche précédente puissent tenir dans un seul . Lorsque vous obtenez le SHA-256 de ce bloc, vous disposez du hachage racine de l'arborescence.
La taille de l'arborescence de hachage (et l'espace disque utilisé en conséquence) varie en fonction de la taille de la partition validé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 qu'elle est plutôt 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:
- Choisissez un salage aléatoire (encodage hexadécimal).
- Diviser votre image système en blocs de 4K
- Pour chaque bloc, obtenez son hachage SHA256 (salé).
- Concaténer ces hachages pour former un niveau
- Compléter le niveau avec des 0 jusqu'à une limite de bloc de 4 000
- Concatenate le niveau à votre arbre de hachage.
- Répétez les étapes 2 à 6 en utilisant le niveau précédent comme source du suivant jusqu'à ce qu'il ne reste 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 le périphérique de bloc (ou cible) 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 découvrir 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é:
- Ajoutez une clé RSA-2048 dans un format compatible avec libmincrypt au
Partition
/boot
à/verity_key
. Identifiez l'emplacement de la clé utilisée pour valider l'arborescence de hachage. - Dans le fichier fstab de l'entrée concernée, ajoutez
verify
aux indicateursfs_mgr
.
Regrouper la signature de la table dans des métadonnées
Regroupez la signature de la table et la table dm-verity dans les métadonnées Verity. L'ensemble du bloc de métadonnées est versionné afin qu'il puisse être étendu, par exemple pour ajouter un deuxième type de signature ou modifier l'ordre.
Pour vérification, un nombre magique est associé à chaque ensemble de métadonnées de table qui permet de l'identifier. Parce que la longueur est 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 vérification. Ce nombre est au format suivant :
0xb001b001
Les valeurs d'octets au format hexadécimal 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.
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 rempli | 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 est remplie de zéros pour atteindre une longueur de 32 ko. | 0 |
Optimiser la dm-verity
Pour obtenir les meilleures performances possibles avec dm-verity, procédez comme suit :
- Dans le kernel, activez NEON SHA-2 pour ARMv7 et les extensions SHA-2 pour ARMv8.
- Tester différentes options read-ahead et prefetch_cluster afin de trouver la meilleure configuration pour votre appareil.