Depuis Android 12, le module Android Runtime (ART) est un module Mainline. La mise à jour du module peut nécessiter de recompiler les artefacts de compilation AOT (Ahead-of-Time) des fichiers JAR de bootclasspath et du serveur système. Étant donné que ces artefacts sont sensibles à la sécurité, Android 12 utilise une fonctionnalité appelée signature sur l'appareil pour empêcher toute falsification de ces artefacts. Cette page présente l'architecture de signature sur l'appareil et ses interactions avec d'autres fonctionnalités de sécurité Android.
Conception de haut niveau
La signature sur l'appareil comporte deux composants principaux:
odrefresh
fait partie du module ART Mainline. Il est chargé de générer les artefacts d'exécution. Il vérifie les artefacts existants par rapport à la version installée du module ART, des fichiers JAR de bootclasspath et des fichiers JAR du serveur système pour déterminer s'ils sont à jour ou s'ils doivent être régénérés. Si elles doivent être régénérées,odrefresh
les génère et les stocke.odsign
est un binaire qui fait partie de la plate-forme Android. Il s'exécute au début du démarrage, juste après le montage de la partition/data
. Sa principale responsabilité est d'appelerodrefresh
pour vérifier si des artefacts doivent être générés ou mis à jour. Pour tous les artefacts nouveaux ou mis à jour générés parodrefresh
,odsign
calcule une fonction de hachage. Le résultat d'un tel calcul de hachage est appelé récapitulatif de fichier. Pour tous les artefacts existants,odsign
vérifie que les récapitulatifs des artefacts existants correspondent aux récapitulatifs queodsign
avait précédemment calculés. Cela garantit que les artefacts n'ont pas été altérés.
En cas d'erreur, par exemple lorsque le récapitulatif d'un fichier ne correspond pas, odrefresh
et odsign
jettent tous les artefacts existants sur /data
et tentent de les régénérer. Si cette méthode ne fonctionne pas, le système revient au mode JIT.
odrefresh
et odsign
sont protégés par dm-verity
et font partie de la chaîne de démarrage validé d'Android.
Calcul des récapitulatifs de fichiers avec fs-verity
fs-verity est une fonctionnalité du noyau Linux qui effectue une vérification des données de fichier basée sur un arbre Merkle. L'activation de fs-verity sur un fichier entraîne la création d'un arbre Merkle sur les données du fichier à l'aide de hachages SHA-256, son stockage dans un emplacement masqué à côté du fichier et le marquage du fichier en lecture seule. fs-verity vérifie automatiquement les données du fichier par rapport à l'arbre Merkle à la demande lorsqu'elles sont lues. fs-verity met le hachage racine de l'arbre Merkle à disposition sous la forme d'une valeur appelée récapitulatif de fichier fs-verity, et fs-verity s'assure que toutes les données lues à partir du fichier sont cohérentes avec ce récapitulatif de fichier.
odsign
utilise fs-verity pour améliorer les performances de démarrage en optimisant l'authentification cryptographique des artefacts compilés sur l'appareil au démarrage. Lorsqu'un artefact est généré, odsign
active fs-verity. Lorsque odsign
vérifie un artefact, il vérifie le récapitulatif de fichier fs-verity au lieu du hachage de fichier complet. Vous n'avez donc pas besoin de lire et de hacher l'intégralité des données de l'artefact au démarrage. Les données d'artefact sont hachées à la demande par fs-verity à mesure qu'elles sont utilisées, par bloc.
Sur les appareils dont le noyau n'est pas compatible avec fs-verity, odsign
calcule les récapitulatifs de fichiers dans l'espace utilisateur. odsign
utilise le même algorithme de hachage basé sur un arbre Merkle que fs-verity. Les récapitulatifs sont donc les mêmes dans les deux cas. fs-verity est obligatoire sur tous les appareils lancés avec Android 11 ou version ultérieure.
Stockage des récapitulatifs de fichiers
odsign
stocke les récapitulatifs de fichiers des artefacts dans un fichier distinct appelé odsign.info
. Pour s'assurer que odsign.info
n'est pas falsifié, odsign.info
est signé avec une clé de signature qui présente des propriétés de sécurité importantes. En particulier, la clé ne peut être générée et utilisée que lors du démarrage précoce, auquel cas seul le code approuvé s'exécute. Pour en savoir plus, consultez la section Clés de signature approuvées.
Vérification des récapitulatifs de fichiers
À chaque démarrage, si odrefresh
détermine que les artefacts existants sont à jour, odsign
s'assure que les fichiers n'ont pas été falsifiés depuis leur génération. odsign
le fait en vérifiant les récapitulatifs de fichiers. Tout d'abord, il vérifie la signature de odsign.info
. Si la signature est valide, odsign
vérifie que le récapitulatif de chaque fichier correspond au récapitulatif correspondant dans odsign.info
.
Clés de signature approuvées
Android 12 introduit une nouvelle fonctionnalité Keystore appelée clés d'étape de démarrage, qui répond aux problèmes de sécurité suivants:
- Qu'est-ce qui empêche un pirate informatique d'utiliser notre clé de signature pour signer sa propre version de
odsign.info
? - Qu'est-ce qui empêche un pirate informatique de générer sa propre clé de signature et de l'utiliser pour signer sa propre version de
odsign.info
?
Les clés de l'étape de démarrage divisent le cycle de démarrage d'Android en niveaux et associent de manière cryptographique la création et l'utilisation d'une clé à un niveau spécifié. odsign
crée sa clé de signature à un niveau précoce, lorsque seul le code approuvé est en cours d'exécution, protégé par dm-verity
.
Les niveaux de l'étape de démarrage sont numérotés de 0 à 1000000000. Lors du processus de démarrage d'Android, vous pouvez augmenter le niveau de démarrage en définissant une propriété système à partir de init.rc
. Par exemple, le code suivant définit le niveau de démarrage sur 10:
setprop keystore.boot_level 10
Les clients de Keystore peuvent créer des clés associées à un certain niveau de démarrage. Par exemple, si vous créez une clé pour le niveau de démarrage 10, cette clé ne peut être utilisée que lorsque l'appareil est au niveau de démarrage 10.
odsign
utilise le niveau de démarrage 30, et la clé de signature qu'il crée est associée à ce niveau de démarrage. Avant d'utiliser une clé pour signer des artefacts, odsign
vérifie qu'elle est associée au niveau de démarrage 30.
Cela empêche les deux attaques décrites précédemment dans cette section:
- Les pirates informatiques ne peuvent pas utiliser la clé générée, car au moment où un pirate informatique a la possibilité d'exécuter du code malveillant, le niveau de démarrage a augmenté au-delà de 30, et Keystore refuse les opérations qui utilisent la clé.
- Les pirates informatiques ne peuvent pas créer de clé, car au moment où ils ont la possibilité d'exécuter du code malveillant, le niveau de démarrage a augmenté au-delà de 30, et Keystore refuse de créer une clé avec ce niveau de démarrage. Si un pirate informatique crée une clé qui n'est pas associée au niveau de démarrage 30,
odsign
la rejette.
Keystore garantit que le niveau de démarrage est correctement appliqué. Les sections suivantes expliquent plus en détail comment procéder pour différentes versions de Keymaster.
Implémentation de Keymaster 4.0
Les différentes versions de Keymaster gèrent différemment l'implémentation des clés d'étape de démarrage. Sur les appareils équipés d'un TEE/Strongbox Keymaster 4.0, Keymaster gère l'implémentation comme suit:
- Au premier démarrage, Keystore crée une clé symétrique K0 avec la balise
MAX_USES_PER_BOOT
définie sur1
. Cela signifie que la clé ne peut être utilisée qu'une seule fois par démarrage. - Lors du démarrage, si le niveau de démarrage est augmenté, une nouvelle clé pour ce niveau de démarrage peut être générée à partir de K0 à l'aide d'une fonction HKDF:
Ki+i=HKDF(Ki, "some_fixed_string")
. Par exemple, si vous passez du niveau de démarrage 0 au niveau de démarrage 10, HKDF est appelé 10 fois pour dériver K10 à partir de K0. Lorsque le niveau de démarrage change, la clé du niveau de démarrage précédent est effacée de la mémoire, et les clés associées aux niveaux de démarrage précédents ne sont plus disponibles.
La clé K0 est une clé
MAX_USES_PER_BOOT=1
. Cela signifie qu'il est également impossible d'utiliser cette clé plus tard au démarrage, car au moins une transition de niveau de démarrage (vers le niveau de démarrage final) se produit toujours.
Lorsqu'un client Keystore tel que odsign
demande la création d'une clé au niveau de démarrage i
, son blob est chiffré avec la clé Ki
. Étant donné que Ki
n'est pas disponible après le niveau de démarrage i
, cette clé ne peut pas être créée ni déchiffrée aux étapes de démarrage ultérieures.
Implémentation de Keymaster 4.1 et KeyMint 1.0
Les implémentations Keymaster 4.1 et KeyMint 1.0 sont en grande partie identiques à l'implémentation Keymaster 4.0. La principale différence est que K0 n'est pas une clé MAX_USES_PER_BOOT
, mais une clé EARLY_BOOT_ONLY
, qui a été introduite dans Keymaster 4.1. Une clé EARLY_BOOT_ONLY
ne peut être utilisée que pendant les premières phases de démarrage, lorsqu'aucun code non approuvé n'est en cours d'exécution. Cela offre un niveau de protection supplémentaire: dans l'implémentation de Keymaster 4.0, un pirate informatique qui compromet le système de fichiers et SELinux peut modifier la base de données Keystore pour créer sa propre clé MAX_USES_PER_BOOT=1
avec laquelle signer des artefacts. Une telle attaque est impossible avec les implémentations Keymaster 4.1 et KeyMint 1.0, car les clés EARLY_BOOT_ONLY
ne peuvent être créées que lors du démarrage précoce.
Composant public des clés de signature approuvées
odsign
récupère le composant de clé publique de la clé de signature à partir de Keystore.
Toutefois, Keystore ne récupère pas cette clé publique à partir du TEE/SE qui contient la clé privée correspondante. À la place, il récupère la clé publique à partir de sa propre base de données sur disque. Cela signifie qu'un pirate informatique qui compromet le système de fichiers peut modifier la base de données Keystore pour qu'elle contienne une clé publique faisant partie d'une paire de clés publique/privée sous son contrôle.
Pour éviter cette attaque, odsign
crée une clé HMAC supplémentaire avec le même niveau de démarrage que la clé de signature. Ensuite, lors de la création de la clé de signature, odsign
utilise cette clé HMAC pour créer une signature de la clé publique et la stocke sur le disque. Lors des démarrages suivants, lors de la récupération de la clé publique de la clé de signature, elle utilise la clé HMAC pour vérifier que la signature sur le disque correspond à la signature de la clé publique récupérée. Si elles correspondent, la clé publique est fiable, car la clé HMAC ne peut être utilisée que dans les premiers niveaux de démarrage et ne peut donc pas avoir été créée par un pirate informatique.