Le chiffrement complet du disque consiste à encoder toutes les données utilisateur sur un appareil Android à l'aide d'une clé chiffrée. Une fois un appareil chiffré, toutes les données créées par l'utilisateur sont automatiquement chiffrées avant d'être écrites sur le disque, et toutes les lectures déchiffrent automatiquement les données avant de les renvoyer au processus appelant.
Le chiffrement de disque complet a été introduit dans Android 4.4, mais Android 5.0 a ajouté les nouvelles fonctionnalités suivantes :
- Création d'un chiffrement rapide, qui ne chiffre que les blocs utilisés sur la partition de données pour éviter que le premier démarrage ne prenne trop de temps. Seuls les systèmes de fichiers ext4 et f2fs sont actuellement compatibles avec le chiffrement rapide.
- Ajout de l'indicateur fstab
forceencryptpour chiffrer au premier démarrage. - Ajout de la compatibilité avec les schémas et le chiffrement sans mot de passe.
- Ajout du stockage de la clé de chiffrement reposant sur le matériel à l'aide de la fonctionnalité de signature de l'environnement d'exécution sécurisé (TEE), comme dans une TrustZone. Pour en savoir plus, consultez Stocker la clé chiffrée.
Attention : Les appareils mis à niveau vers Android 5.0, puis chiffrés, peuvent être ramenés à un état non chiffré en rétablissant la configuration d'usine. Les nouveaux appareils Android 5.0 chiffrés au premier démarrage ne peuvent pas être ramenés à un état non chiffré.
Fonctionnement du chiffrement complet du disque Android
Le chiffrement complet du disque Android est basé sur dm-crypt, qui est une fonctionnalité du noyau fonctionnant au niveau de la couche du périphérique de bloc. C'est pourquoi le chiffrement fonctionne avec les cartes multimédias intégrées (eMMC) et les périphériques flash similaires qui se présentent au noyau en tant que périphériques de bloc. Le chiffrement n'est pas possible avec YAFFS, qui communique directement avec une puce NAND brute.
L'algorithme de chiffrement est AES (Advanced Encryption Standard) 128 bits avec CBC (Cipher-Block Chaining) et ESSIV:SHA256. La clé principale est chiffrée avec AES 128 bits via des appels à la bibliothèque OpenSSL. Vous devez utiliser une clé de 128 bits ou plus (256 bits étant facultatif).
Remarque : Les OEM peuvent utiliser un chiffrement de 128 bits ou plus pour la clé principale.
Dans la version 5.0 d'Android, il existe quatre types d'états de chiffrement :
- par défaut
- Code
- mot de passe
- schéma
Au premier démarrage, l'appareil crée une clé principale de 128 bits générée de manière aléatoire, puis la hache avec un mot de passe par défaut et un sel stocké. Le mot de passe par défaut est "default_password". Toutefois, le hachage résultant est également signé via un TEE (tel que TrustZone), qui utilise un hachage de la signature pour chiffrer la clé principale.
Vous trouverez le mot de passe par défaut défini dans le fichier cryptfs.cpp du projet Android Open Source.
Lorsque l'utilisateur définit le code ou le mot de passe sur l'appareil, seule la clé de 128 bits est à nouveau chiffrée et stockée. (Par exemple, les modifications du code, du mot de passe ou du schéma de l'utilisateur n'entraînent PAS le rechiffrement des données utilisateur.) Notez qu'un appareil géré peut être soumis à des restrictions concernant le code, le schéma ou le mot de passe.
Le chiffrement est géré par init et vold.
init appelle vold, et vold définit les propriétés pour déclencher des événements dans init. D'autres parties du système examinent également les propriétés pour effectuer des tâches telles que l'état du rapport, la demande de mot de passe ou l'invite à réinitialiser les paramètres d'usine en cas d'erreur fatale. Pour appeler les fonctionnalités de chiffrement dans vold, le système utilise les commandes cryptfs de l'outil de ligne de commande vdc : checkpw, restart, enablecrypto, changepw, cryptocomplete, verifypw, setfield, getfield, mountdefaultencrypted, getpwtype, getpw et clearpw.
Pour chiffrer, déchiffrer ou effacer /data, /data ne doit pas être monté. Toutefois, pour afficher une interface utilisateur, le framework doit démarrer et nécessite /data pour s'exécuter. Pour résoudre ce problème, un système de fichiers temporaire est installé sur /data.
Cela permet à Android d'inviter l'utilisateur à saisir des mots de passe, d'afficher la progression ou de suggérer un effacement des données si nécessaire. Il impose toutefois une limite : pour passer du système de fichiers temporaire au véritable système de fichiers /data, le système doit arrêter tous les processus avec des fichiers ouverts sur le système de fichiers temporaire et redémarrer ces processus sur le véritable système de fichiers /data. Pour ce faire, tous les services doivent appartenir à l'un des trois groupes suivants : core, main et late_start.
core: ne jamais arrêter après le démarrage.main: Arrêtez, puis redémarrez l'ordinateur après avoir saisi le mot de passe du disque.late_start: ne démarre qu'après le déchiffrement et le montage de/data.
Pour déclencher ces actions, la propriété vold.decrypt est définie sur différentes chaînes.
Pour arrêter et redémarrer des services, les commandes init sont les suivantes :
class_reset: arrête un service, mais permet de le redémarrer avec class_start.class_start: redémarre un service.class_stop: arrête un service et ajoute un indicateurSVC_DISABLED. Les services arrêtés ne répondent pas àclass_start.
Flows
Il existe quatre flux pour un appareil chiffré. Un appareil n'est chiffré qu'une seule fois, puis suit une procédure de démarrage normale.
- Chiffrer un appareil qui ne l'était pas :
- Chiffrez un nouvel appareil avec
forceencrypt: chiffrement obligatoire au premier démarrage (à partir d'Android L). - Chiffrer un appareil existant : chiffrement initié par l'utilisateur (Android K et versions antérieures).
- Chiffrez un nouvel appareil avec
- Démarrer un appareil chiffré :
- Démarrer un appareil chiffré sans mot de passe : démarrer un appareil chiffré sans mot de passe défini (pertinent pour les appareils équipés d'Android 5.0 et versions ultérieures).
- Démarrage d'un appareil chiffré avec un mot de passe : démarrage d'un appareil chiffré pour lequel un mot de passe a été défini.
En plus de ces flux, l'appareil peut également ne pas réussir à chiffrer /data.
Chacun de ces flux est expliqué en détail ci-dessous.
Chiffrer un nouvel appareil avec forceencrypt
Il s'agit du premier démarrage normal pour un appareil Android 5.0.
- Détecter un système de fichiers non chiffré avec l'indicateur
forceencrypt/datan'est pas chiffré, mais il doit l'être, carforceencryptl'exige. Démontez/data. - Commencer le chiffrement
/datavold.decrypt = "trigger_encryption"déclencheinit.rc, ce qui entraîne le chiffrement de/dataparvoldsans mot de passe. (Aucun n'est défini, car il s'agit d'un nouvel appareil.) - Monter tmpfs
voldmonte un/datatmpfs (en utilisant les options tmpfs dero.crypto.tmpfs_options) et définit la propriétévold.encrypt_progresssur 0.voldprépare le tmpfs/datapour le démarrage d'un système chiffré et définit la propriétévold.decryptsur :trigger_restart_min_framework - Afficher le framework pour montrer la progression
Comme l'appareil n'a pratiquement aucune donnée à chiffrer, la barre de progression n'apparaît pas souvent, car le chiffrement est très rapide. Pour en savoir plus sur l'UI de progression, consultez Chiffrer un appareil existant.
- Lorsque
/dataest chiffré, supprimez le framework.volddéfinitvold.decryptsurtrigger_default_encryption, ce qui démarre le servicedefaultcrypto. (Cela lance le flux ci-dessous pour monter des données utilisateur chiffrées par défaut.)trigger_default_encryptionvérifie le type de chiffrement pour déterminer si/dataest chiffré avec ou sans mot de passe. Étant donné que les appareils Android 5.0 sont chiffrés au premier démarrage, aucun mot de passe ne devrait être défini. Par conséquent, nous déchiffrons et montons/data. - Monter
/datainitmonte ensuite/datasur un RAMDisk tmpfs à l'aide des paramètres qu'il récupère à partir dero.crypto.tmpfs_options, qui est défini dansinit.rc. - Framework de démarrage
volddéfinitvold.decryptsurtrigger_restart_framework, ce qui poursuit le processus de démarrage habituel.
Chiffrer un appareil existant
Voici ce qui se passe lorsque vous chiffrez un appareil Android K ou version antérieure non chiffré qui a été migré vers L.
Ce processus est initié par l'utilisateur et est appelé "chiffrement sur place" dans le code. Lorsqu'un utilisateur choisit de chiffrer un appareil, l'UI s'assure que la batterie est complètement chargée et que l'adaptateur secteur est branché afin qu'il y ait suffisamment d'énergie pour terminer le processus de chiffrement.
Avertissement : Si l'appareil n'a plus de batterie et s'éteint avant la fin du chiffrement, les données des fichiers sont partiellement chiffrées. La configuration d'usine de l'appareil doit être rétablie, ce qui entraîne la perte de toutes les données.
Pour activer le chiffrement sur place, vold lance une boucle pour lire chaque secteur du véritable périphérique de bloc, puis l'écrit sur le périphérique de bloc de chiffrement. vold vérifie si un secteur est utilisé avant de le lire et de l'écrire, ce qui rend le chiffrement beaucoup plus rapide sur un nouvel appareil qui contient peu ou pas de données.
État de l'appareil : définissez ro.crypto.state = "unencrypted"
et exécutez le déclencheur on nonencrypted init pour poursuivre le démarrage.
- Vérifier le mot de passe
L'UI appelle
voldavec la commandecryptfs enablecrypto inplace, oùpasswdcorrespond au mot de passe de l'écran de verrouillage de l'utilisateur. - Supprimer le framework
voldrecherche les erreurs, renvoie -1 s'il ne peut pas chiffrer et affiche une raison dans le journal. S'il peut chiffrer, il définit la propriétévold.decryptsurtrigger_shutdown_framework. Cela entraîne l'arrêt des servicesinit.rcdans les classeslate_startetmain. - Créer un pied de page de crypto-monnaie
- Créer un fichier de fil d'Ariane
- Redémarrer
- Détecter le fichier de fil d'Ariane
- Commencer le chiffrement
/datavoldconfigure ensuite le mappage cryptographique, ce qui crée un périphérique de bloc cryptographique virtuel qui mappe sur le périphérique de bloc réel, mais chiffre chaque secteur lors de l'écriture et déchiffre chaque secteur lors de la lecture.voldcrée et écrit ensuite les métadonnées de chiffrement. - Pendant le chiffrement, montez tmpfs.
voldmonte un/datatmpfs (à l'aide des options tmpfs dero.crypto.tmpfs_options) et définit la propriétévold.encrypt_progresssur 0.voldprépare le tmpfs/dataau démarrage d'un système chiffré et définit la propriétévold.decryptsurtrigger_restart_min_framework. - Afficher le framework pour montrer la progression
trigger_restart_min_frameworkentraîne le démarrage de la classe de servicesmainparinit.rc. Lorsque le framework constate quevold.encrypt_progressest défini sur 0, il affiche l'UI de la barre de progression, qui interroge cette propriété toutes les cinq secondes et met à jour une barre de progression. La boucle de chiffrement met à jourvold.encrypt_progresschaque fois qu'elle chiffre un autre pourcentage de la partition. - Mettre à jour le pied de page de chiffrement lorsque
/dataest chiffréLorsque
/dataest chiffré,voldefface l'indicateurENCRYPTION_IN_PROGRESSdans les métadonnées.Une fois l'appareil déverrouillé, le mot de passe est utilisé pour chiffrer la clé principale et le pied de page de chiffrement est mis à jour.
Si le redémarrage échoue pour une raison quelconque,
volddéfinit la propriétévold.encrypt_progresssurerror_reboot_failedet l'UI doit afficher un message demandant à l'utilisateur d'appuyer sur un bouton pour redémarrer. Cette situation ne devrait jamais se produire.
Démarrer un appareil chiffré avec le chiffrement par défaut
Voici ce qui se passe lorsque vous démarrez un appareil chiffré sans mot de passe. Étant donné que les appareils Android 5.0 sont chiffrés au premier démarrage, aucun mot de passe ne devrait être défini. Il s'agit donc de l'état de chiffrement par défaut.
- Détecter les
/datachiffrés sans mot de passeDétecter que l'appareil Android est chiffré, car
/datane peut pas être installé et l'un des indicateursencryptableouforceencryptest défini.volddéfinitvold.decryptsurtrigger_default_encryption, ce qui démarre le servicedefaultcrypto.trigger_default_encryptionvérifie le type de chiffrement pour déterminer si/dataest chiffré avec ou sans mot de passe. - Déchiffrer /data
Crée l'appareil
dm-cryptsur le périphérique de bloc afin que l'appareil soit prêt à l'emploi. - Monter /data
voldmonte ensuite la partition/dataréelle déchiffrée, puis prépare la nouvelle partition. Il définit la propriétévold.post_fs_data_donesur 0, puis définitvold.decryptsurtrigger_post_fs_data. Cela entraîne l'exécution des commandespost-fs-dataparinit.rc. Ils créent les répertoires ou les liens nécessaires, puis définissentvold.post_fs_data_donesur 1.Une fois que
voldvoit le 1 dans cette propriété, il définit la propriétévold.decryptsurtrigger_restart_framework.. Cela entraîne le redémarrage des services dans la classemainparinit.rcet le démarrage des services dans la classelate_startpour la première fois depuis le démarrage. - Framework de démarrage
Le framework démarre maintenant tous ses services à l'aide du fichier
/datadéchiffré, et le système est prêt à être utilisé.
Démarrer un appareil chiffré sans chiffrement par défaut
Voici ce qui se passe lorsque vous démarrez un appareil chiffré avec un mot de passe défini. Le mot de passe de l'appareil peut être un code, un schéma ou un mot de passe.
- Détecter un appareil chiffré avec un mot de passe
Détecter que l'appareil Android est chiffré, car l'indicateur
ro.crypto.state = "encrypted"volddéfinitvold.decryptsurtrigger_restart_min_framework, car/dataest chiffré avec un mot de passe. - Monter tmpfs
initdéfinit cinq propriétés pour enregistrer les options de montage initiales fournies pour/dataavec les paramètres transmis depuisinit.rc.voldutilise les propriétés suivantes pour configurer le mappage cryptographique :ro.crypto.fs_typero.crypto.fs_real_blkdevro.crypto.fs_mnt_pointro.crypto.fs_optionsro.crypto.fs_flags(nombre hexadécimal ASCII à huit chiffres précédé de 0x)
- Démarrer le framework pour demander le mot de passe
Le framework démarre et constate que
vold.decryptest défini surtrigger_restart_min_framework. Cela indique au framework qu'il démarre sur un disque tmpfs/dataet qu'il doit obtenir le mot de passe de l'utilisateur.Toutefois, il doit d'abord s'assurer que le disque a été correctement chiffré. Il envoie la commande
cryptfs cryptocompleteàvold.voldrenvoie 0 si le chiffrement a réussi, -1 en cas d'erreur interne ou -2 si le chiffrement a échoué.voldle détermine en recherchant l'indicateurCRYPTO_ENCRYPTION_IN_PROGRESSdans les métadonnées de chiffrement. Si elle est définie, cela signifie que le processus de chiffrement a été interrompu et qu'il n'y a aucune donnée utilisable sur l'appareil. Sivoldrenvoie une erreur, l'UI doit afficher un message invitant l'utilisateur à redémarrer l'appareil et à rétablir sa configuration d'usine, et lui fournir un bouton à appuyer pour ce faire. - Déchiffrer des données avec un mot de passe
Une fois
cryptfs cryptocompleteexécuté, le framework affiche une UI demandant le mot de passe du disque. L'interface utilisateur vérifie le mot de passe en envoyant la commandecryptfs checkpwàvold. Si le mot de passe est correct (ce qui est déterminé par le montage réussi du/datadéchiffré à un emplacement temporaire, puis par son démontage),voldenregistre le nom du périphérique de bloc déchiffré dans la propriétéro.crypto.fs_crypto_blkdevet renvoie l'état 0 à l'UI. Si le mot de passe est incorrect, la valeur -1 est renvoyée à l'UI. - Framework Stop
L'UI affiche un graphique de démarrage crypto, puis appelle
voldavec la commandecryptfs restart.volddéfinit la propriétévold.decryptsurtrigger_reset_main, ce qui entraîneinit.rcà effectuerclass_reset main. Cela arrête tous les services de la classe principale, ce qui permet de démonter le tmpfs/data. - Monter
/datavoldmonte ensuite la véritable partition/datadéchiffrée et prépare la nouvelle partition (qui n'a peut-être jamais été préparée si elle a été chiffrée avec l'option d'effacement, qui n'est pas prise en charge dans la première version). Il définit la propriétévold.post_fs_data_donesur 0, puis définitvold.decryptsurtrigger_post_fs_data. Cela entraîne l'exécution des commandespost-fs-datadeinit.rc. Ils créent les répertoires ou les liens nécessaires, puis définissentvold.post_fs_data_donesur 1. Lorsquevolddétecte la valeur 1 dans cette propriété, il définit la propriétévold.decryptsurtrigger_restart_framework. Cela entraîne le redémarrage des services dans la classemainparinit.rcet le démarrage des services dans la classelate_startpour la première fois depuis le démarrage. - Démarrer le framework complet
Le framework démarre maintenant tous ses services à l'aide du système de fichiers
/datadéchiffré, et le système est prêt à être utilisé.
Échec
Un appareil qui ne parvient pas à déchiffrer les données peut présenter un problème pour plusieurs raisons. L'appareil commence par la séquence de démarrage normale :
- Détecter un appareil chiffré avec un mot de passe
- Monter tmpfs
- Framework de démarrage pour demander le mot de passe
Toutefois, une fois le framework ouvert, l'appareil peut rencontrer des erreurs :
- Le mot de passe correspond, mais les données ne peuvent pas être déchiffrées
- L'utilisateur saisit un mot de passe incorrect 30 fois
Si ces erreurs ne sont pas résolues, invitez l'utilisateur à rétablir la configuration d'usine :
Si vold détecte une erreur lors du processus de chiffrement, et si aucune donnée n'a encore été détruite et que le framework est opérationnel, vold définit la propriété vold.encrypt_progress sur error_not_encrypted.
L'interface utilisateur invite l'utilisateur à redémarrer l'appareil et l'informe que le processus de chiffrement n'a jamais démarré. Si l'erreur se produit après la fermeture du framework, mais avant l'affichage de l'UI de la barre de progression, vold redémarre le système. Si le redémarrage échoue, vold.encrypt_progress est défini sur error_shutting_down et -1 est renvoyé, mais il n'y aura rien pour détecter l'erreur. Cette situation ne devrait pas se produire.
Si vold détecte une erreur lors du processus de chiffrement, il définit vold.encrypt_progress sur error_partially_encrypted et renvoie -1. L'UI doit ensuite afficher un message indiquant que le chiffrement a échoué et fournir un bouton permettant à l'utilisateur de rétablir la configuration d'usine de l'appareil.
Stocker la clé chiffrée
La clé chiffrée est stockée dans les métadonnées de chiffrement. La sauvegarde matérielle est implémentée à l'aide de la fonctionnalité de signature de l'environnement d'exécution sécurisé (TEE). Auparavant, nous chiffrions la clé principale avec une clé générée en appliquant scrypt au mot de passe de l'utilisateur et au sel stocké. Afin de rendre la clé résistante aux attaques hors du boîtier, nous étendons cet algorithme en signant la clé résultante avec une clé TEE stockée. La signature résultante est ensuite transformée en clé de longueur appropriée par une autre application de scrypt. Cette clé est ensuite utilisée pour chiffrer et déchiffrer la clé principale. Pour stocker cette clé :
- Générez une clé de chiffrement de disque (DEK) et un salt de 16 octets chacun.
- Appliquez scrypt au mot de passe de l'utilisateur et au sel pour générer la clé intermédiaire 1 (KI1) de 32 octets.
- Ajoutez des octets nuls à IK1 pour atteindre la taille de la clé privée liée au matériel (HBK). Plus précisément, nous ajoutons des octets comme suit : 00 || IK1 || 00..00 ; un octet zéro, 32 octets IK1, 223 octets zéro.
- Signez IK1 avec HBK en ajoutant des octets de remplissage pour produire IK2 de 256 octets.
- Appliquez scrypt à IK2 et au sel (le même sel qu'à l'étape 2) pour produire IK3 de 32 octets.
- Utilisez les 16 premiers octets d'IK3 comme KEK et les 16 derniers octets comme IV.
- Chiffrez la DEK avec AES_CBC, avec la clé KEK et le vecteur d'initialisation IV.
Modifier le mot de passe
Lorsqu'un utilisateur choisit de modifier ou de supprimer son mot de passe dans les paramètres, l'UI envoie la commande cryptfs changepw à vold, et vold rechiffre la clé principale du disque avec le nouveau mot de passe.
Propriétés de chiffrement
vold et init communiquent entre eux en définissant des propriétés. Voici la liste des propriétés disponibles pour le chiffrement.
Propriétés Vold
| Propriété | Description |
|---|---|
vold.decrypt trigger_encryption |
Chiffrez le lecteur sans mot de passe. |
vold.decrypt trigger_default_encryption |
Vérifiez si le disque est chiffré sans mot de passe.
Si tel est le cas, déchiffrez-le et installez-le. Sinon, définissez vold.decrypt sur trigger_restart_min_framework. |
vold.decrypt trigger_reset_main |
Défini par vold pour arrêter l'UI demandant le mot de passe du disque. |
vold.decrypt trigger_post_fs_data |
Défini par vold pour préparer /data avec les répertoires nécessaires, etc. |
vold.decrypt trigger_restart_framework |
Défini par vold pour démarrer le framework réel et tous les services. |
vold.decrypt trigger_shutdown_framework |
Défini par vold pour arrêter l'intégralité du framework afin de démarrer le chiffrement. |
vold.decrypt trigger_restart_min_framework |
Défini par vold pour démarrer l'UI de la barre de progression du chiffrement ou inviter à saisir un mot de passe, selon la valeur de ro.crypto.state. |
vold.encrypt_progress |
Lorsque le framework démarre, si cette propriété est définie, saisissez le mode UI de la barre de progression. |
vold.encrypt_progress 0 to 100 |
L'UI de la barre de progression doit afficher la valeur en pourcentage définie. |
vold.encrypt_progress error_partially_encrypted |
L'interface utilisateur de la barre de progression doit afficher un message indiquant que le chiffrement a échoué et proposer à l'utilisateur de réinitialiser l'appareil aux paramètres d'usine. |
vold.encrypt_progress error_reboot_failed |
L'UI de la barre de progression doit afficher un message indiquant que le chiffrement est terminé et proposer à l'utilisateur un bouton pour redémarrer l'appareil. Cette erreur ne devrait pas se produire. |
vold.encrypt_progress error_not_encrypted |
L'interface utilisateur de la barre de progression doit afficher un message indiquant qu'une erreur s'est produite, qu'aucune donnée n'a été chiffrée ni perdue, et proposer à l'utilisateur un bouton pour redémarrer le système. |
vold.encrypt_progress error_shutting_down |
L'UI de la barre de progression n'est pas en cours d'exécution. Il n'est donc pas clair qui répond à cette erreur. Et cela ne devrait jamais se produire. |
vold.post_fs_data_done 0 |
Défini par vold juste avant de définir vold.decrypt sur trigger_post_fs_data. |
vold.post_fs_data_done 1 |
Définissez init.rc ou init.rc juste après avoir terminé la tâche post-fs-data. |
Propriétés init
| Propriété | Description |
|---|---|
ro.crypto.fs_crypto_blkdev |
Défini par la commande vold checkpw pour une utilisation ultérieure par la commande vold restart. |
ro.crypto.state unencrypted |
Défini par init pour indiquer que ce système fonctionne avec un /data ro.crypto.state encrypted non chiffré. Défini par init pour indiquer que ce système s'exécute avec un /data chiffré. |
|
Ces cinq propriétés sont définies par init lorsqu'il tente de monter /data avec les paramètres transmis par init.rc. vold les utilise pour configurer le mappage crypto. |
ro.crypto.tmpfs_options |
Défini par init.rc avec les options que init doit utiliser lors du montage du système de fichiers tmpfs /data. |
Actions d'initialisation
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption