Chiffrement complet du disque

Le chiffrement complet du disque consiste à encoder toutes les données utilisateur sur un appareil Android à l'aide d'un clé chiffrée. Une fois qu'un appareil est chiffré, toutes les données créées par l'utilisateur sont automatiquement chiffrés avant de les valider sur le disque et toutes les lectures déchiffrent automatiquement les données avant de les renvoyer au processus appelant.

Le chiffrement complet du disque a été introduit sur Android dans la version 4.4, mais Android 5.0 a été introduit ces nouvelles fonctionnalités:

  • Créé 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 beaucoup de temps. Systèmes de fichiers ext4 et f2fs uniquement sont compatibles avec le chiffrement rapide.
  • A ajouté l'élément forceencrypt fstab pour chiffrer au premier démarrage.
  • Ajout de la compatibilité avec les schémas et le chiffrement sans mot de passe.
  • Ajout d'un stockage basé sur le matériel de la clé de chiffrement à l'aide de la fonctionnalité de signature de l'environnement d'exécution sécurisé (TEE) (par exemple, dans une TrustZone). Pour en savoir plus, consultez la section Stocker la clé chiffrée. plus de détails.

Attention : Les appareils mis à niveau vers Android 5.0, puis chiffrés, peuvent être rétablis dans un état non chiffré en rétablissant la configuration d'usine. Nouvel Android 5.0 Les appareils chiffrés au premier démarrage ne peuvent pas revenir à un état non chiffré.

Fonctionnement du chiffrement complet du disque Android

Le chiffrement de disque complet Android est basé sur dm-crypt, une fonctionnalité du noyau qui fonctionne au niveau de la couche de périphérique de bloc. Par conséquent, le chiffrement fonctionne avec les cartes Embedded MultiMediaCard (eMMC) et les périphériques flash similaires qui se présentent au noyau en tant qu'appareils de bloc. Le chiffrement n'est pas possible avec YAFFS, qui communique directement avec une puce flash NAND brute.

L’algorithme de chiffrement est 128 Advanced Encryption Standard (AES) avec chiffrement-bloc (CBC) et ESSIV:SHA256. La clé principale est chiffrée avec AES 128 bits via des appels à la bibliothèque OpenSSL. Vous devez utiliser 128 bits ou plus pour la clé (256 étant facultatif).

Remarque:Les OEM peuvent chiffrer la clé principale avec une version 128 bits ou plus.

Dans la version 5.0 d'Android, il existe quatre types d'états de chiffrement:

  • par défaut
  • Code
  • mot de passe
  • schéma

Lors du 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". Cependant, 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 Open Source Android.

Lorsque l'utilisateur définit le code PIN/la carte ou le mot de passe sur l'appareil, seule la clé de 128 bits est re-chiffrée et stockée. (c'est-à-dire que les modifications apportées au code, à la carte ou au schéma de l'utilisateur n'entraînent PAS rechiffrement des données utilisateur.) Notez que appareil géré peut être soumis à des restrictions de code, de schéma ou de mot de passe.

Le chiffrement est géré par init et vold. init appelle vold, et vold définit des 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 des rapports, la demande d'un mot de passe ou l'invite de réinitialisation 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 installé. Toutefois, pour afficher une interface utilisateur (UI), le framework doit démarrer et nécessite /data pour s'exécuter. À résoudre ce problème, un système de fichiers temporaire est installé sur /data. Cela permet à Android de vous demander des mots de passe, d'afficher votre progression ou de suggérer des données effacez les données si nécessaire. En revanche, pour passer du modèle système de fichiers temporaire vers le véritable système de fichiers /data, le système doit arrêter tous les processus avec des fichiers ouverts dans le système de fichiers temporaire et les redémarrer les 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 s'arrête jamais 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 diverses 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 indicateur SVC_DISABLED. Les services arrêtés ne répondent pas à class_start.

Flux

Il existe quatre flux pour un appareil chiffré. Un appareil n'est chiffré qu'une seule fois, puis suit un flux de démarrage normal.

  • Chiffrer un appareil qui n'était pas chiffré :
    • Chiffrer un nouvel appareil avec forceencrypt : chiffrement obligatoire au premier démarrage (à partir d'Android L).
    • Chiffrer un appareil existant: chiffrement déclenché par l'utilisateur (Android K et versions antérieures)
  • 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 (applicable aux appareils équipés d'Android 5.0 ou version ultérieure).
    • Démarrer un appareil chiffré avec un mot de passe : démarrer un appareil chiffré pour lequel un mot de passe est 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 d'un appareil Android 5.0.

  1. Détecter un système de fichiers non chiffré avec l'indicateur forceencrypt

    /data n'est pas chiffré, mais il doit l'être, car forceencrypt l'exige. Désinstaller /data.

  2. Commencer à chiffrer /data

    vold.decrypt = "trigger_encryption" déclenche init.rc, ce qui entraîne le chiffrement de /data par vold sans mot de passe. (Aucun n'est défini, car il s'agit d'un nouvel appareil.)

  3. Monter des tmpfs

    vold installe un /data tmpfs (à l'aide des options tmpfs de ro.crypto.tmpfs_options) et définit la propriété vold.encrypt_progress sur 0. vold prépare le /data tmpfs pour démarrer un système chiffré et définit le propriété vold.decrypt à: trigger_restart_min_framework

  4. Afficher le framework pour afficher la progression

    Étant donné que l'appareil n'a pratiquement aucune donnée à chiffrer, la barre de progression n'apparaîtra pas souvent, car le chiffrement est très rapide. Pour en savoir plus sur l'UI de progression, consultez la section Chiffrer un appareil existant.

  5. Lorsque /data est chiffré, supprimez le framework.

    vold définit vold.decrypt sur trigger_default_encryption, ce qui démarre le service defaultcrypto. (Cela lance le flux ci-dessous pour monter un userdata chiffré par défaut.) trigger_default_encryption vérifie type de chiffrement pour vérifier si /data est 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 doit être défini. Nous déchiffrerons donc et monterons /data.

  6. Monter /data

    init installe ensuite /data sur un disque RAM tmpfs à l'aide des paramètres qu'il récupère à partir de ro.crypto.tmpfs_options, qui est défini dans init.rc.

  7. Démarrer le framework

    vold définit vold.decrypt sur trigger_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 non chiffré ou une version antérieure qui a migré vers la version L.

Ce processus est lancé par l'utilisateur et est appelé "chiffrement en place" dans le code. Lorsqu'un utilisateur choisit de chiffrer un appareil, l'interface utilisateur s'assure que la batterie est complètement chargée et l'adaptateur secteur est branché. pour terminer le processus de chiffrement.

Avertissement : Si l'appareil est à court de batterie et s'arrête avant la fin du chiffrement, les données de fichier restent partiellement chiffrées. L'appareil doit être rétabli à ses paramètres d'usine, et toutes les données sont perdues.

Pour activer le chiffrement sur place, vold lance une boucle pour lire chaque du véritable appareil de stockage en mode bloc, à l'appareil de crypto-bloc. vold vérifie si un secteur se trouve dans avant de les lire et de les écrire. le chiffrement beaucoup plus rapidement sur un nouvel appareil qui a 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.

  1. Vérifier le mot de passe

    L'UI appelle vold avec la commande cryptfs enablecrypto inplace. où passwd est le mot de passe de l'écran de verrouillage de l'utilisateur.

  2. Démanteler le framework

    vold recherche les erreurs, renvoie -1 s'il ne peut pas chiffrer et imprime une raison dans le journal. S'il peut effectuer un chiffrement, la propriété vold.decrypt est définie. à trigger_shutdown_framework. init.rc arrête alors les services des classes late_start et main.

  3. Créer un pied de page de cryptographie
  4. Créer un fichier de fil d'Ariane
  5. Redémarrer
  6. Détecter le fichier de fil d'Ariane
  7. Commencer à chiffrer /data

    vold configure ensuite le mappage cryptographique, qui crée un appareil de crypto-bloc virtuel. qui est mappée au véritable appareil de blocs, mais chiffre chaque secteur au fur et à mesure qu’il est écrit, et déchiffre chaque secteur au fur et à mesure qu’il est lu. vold crée ensuite et écrit les métadonnées de chiffrement.

  8. Pendant le chiffrement, installer tmpfs

    vold installe un /data tmpfs (à l'aide des options tmpfs). de ro.crypto.tmpfs_options) et définit la propriété vold.encrypt_progress sur 0. vold prépare les tmpfs /data pour le démarrage d'un système chiffré et définit la propriété vold.decrypt sur : trigger_restart_min_framework

  9. Afficher le framework pour montrer la progression

    trigger_restart_min_framework entraîne init.rc démarrer la classe de services main. Lorsque le framework voit que vold.encrypt_progress est 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 à jour vold.encrypt_progress chaque fois qu'elle chiffre un autre pourcentage de la partition.

  10. Lorsque /data est chiffré, mettez à jour le pied de page de chiffrement

    Lorsque /data est chiffré, vold est effacé l'option ENCRYPTION_IN_PROGRESS dans 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, vold définit la propriété. vold.encrypt_progress à error_reboot_failed et l'interface utilisateur doit afficher un message demandant à l'utilisateur d'appuyer sur un bouton pour redémarrer. Cela ne devrait jamais se produire.

Démarrer un appareil chiffré avec le chiffrement par défaut

C'est 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 doit être défini. Il s'agit donc de l'état de chiffrement par défaut.

  1. Détecter des /data chiffrés sans mot de passe

    Détecter que l'appareil Android est chiffré, car /data ne peut pas être installé et que l'un des indicateurs encryptable ou forceencrypt est défini.

    vold définit vold.decrypt sur trigger_default_encryption, qui lance le defaultcrypto. trigger_default_encryption vérifie le type de chiffrement pour vérifier si /data est chiffré avec ou sans mot de passe.

  2. Déchiffrer /data

    Crée l'appareil dm-crypt sur l'appareil de blocage afin qu'il soit prêt à l'emploi.

  3. Installer /data

    vold installe ensuite la véritable partition /data déchiffrée. puis prépare la nouvelle partition. Il définit la propriété vold.post_fs_data_done sur 0, puis vold.decrypt sur trigger_post_fs_data. Cela entraîne l'exécution de init.rc. ses commandes post-fs-data. Il crée les répertoires nécessaires ou des liens, puis définissez vold.post_fs_data_done sur 1.

    Lorsque vold voit le 1 dans cette propriété, il définit la propriété. De vold.decrypt à: trigger_restart_framework. Ceci force init.rc à démarrer des services dans la classe main et démarreront également des services dans la classe late_start pour le premier de temps depuis le démarrage.

  4. Démarrer le framework

    Le framework démarre maintenant tous ses services à l'aide du /data déchiffré, et le système est prêt à l'emploi.

Démarrer un appareil chiffré sans chiffrement par défaut

C'est ce qui se passe lorsque vous démarrez un appareil chiffré sur lequel un mot de passe est défini. Le mot de passe de l'appareil peut être un code, un schéma ou un mot de passe.

  1. 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"

    vold définit vold.decrypt sur trigger_restart_min_framework, car /data est chiffré avec un mot de passe.

  2. Monter des tmpfs

    init définit cinq propriétés pour enregistrer les options d'installation initiales indiqué pour /data avec les paramètres transmis depuis init.rc. vold utilise les propriétés suivantes pour configurer le mappage de cryptographie :

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (nombre hexadécimal ASCII à 8 chiffres précédé de 0x)
  3. Démarrer le framework pour demander le mot de passe

    Le framework démarre et constate que vold.decrypt est défini sur trigger_restart_min_framework. Cela indique au cadre qu'il s'agit sur un disque tmpfs /data et 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. vold renvoie 0 si le chiffrement a bien été effectué, -1 en cas d'erreur interne, ou -2 si le chiffrement n'a pas abouti. vold détermine cela en recherchant l'indicateur CRYPTO_ENCRYPTION_IN_PROGRESS dans les métadonnées de cryptographie. S'il était défini, le processus de chiffrement a été interrompu et il n'y a plus utilisables sur l’appareil. Si vold renvoie une erreur, l'UI doit afficher un message demandant à l'utilisateur de redémarrer l'appareil et de rétablir sa configuration d'usine, et de donner à l'utilisateur un bouton sur lequel appuyer pour ce faire.

  4. Déchiffrer des données avec un mot de passe

    Une fois cryptfs cryptocomplete réussi, le framework affiche une UI demandant le mot de passe du disque. L'UI vérifie le mot de passe en envoyant la commande cryptfs checkpw à vold. Si le mot de passe est correct (ce qui est déterminé en montant le /data déchiffré à un emplacement temporaire, puis en le démontant), vold enregistre le nom de l'appareil de bloc déchiffré dans la propriété ro.crypto.fs_crypto_blkdev et renvoie l'état 0 à l'UI. Si le le mot de passe est incorrect, il renvoie -1 à l'interface utilisateur.

  5. Arrêter le framework

    L'UI affiche un graphique de démarrage cryptographique, puis appelle vold avec la commande cryptfs restart. vold définit la propriété vold.decrypt sur trigger_reset_main, ce qui entraîne l'exécution de class_reset main par init.rc. Cela arrête tous les services de la classe principale, ce qui permet de démonter les /data tmpfs.

  6. Monter /data

    vold installe ensuite la véritable partition /data déchiffrée. et prépare la nouvelle partition (qui n'aurait peut-être jamais été préparée si il a été chiffré à l'aide de l'option "Effacer", qui n'est pas prise en charge au premier de sortie). Elle définit la propriété vold.post_fs_data_done sur 0, puis définit vold.decrypt sur trigger_post_fs_data. Cela provoque init.rc pour exécuter ses commandes post-fs-data. Ils créent les répertoires ou liens nécessaires, puis définissent vold.post_fs_data_done sur 1. Lorsque vold voit le "1" cette propriété, elle définit la propriété vold.decrypt sur trigger_restart_framework init.rc redémarre alors les services de la classe main et démarre également les services de la classe late_start pour la première fois depuis le démarrage.

  7. Commencer le framework complet

    Le framework démarre maintenant tous ses services à l'aide du /data déchiffré. système de fichiers et le système est prêt à l'emploi.

Échec

Un appareil qui ne parvient pas à déchiffrer peut être défectueux pour plusieurs raisons. L'appareil commence par la série d'étapes normale pour démarrer:

  1. Détecter un appareil chiffré avec un mot de passe
  2. Installer tmpfs
  3. Démarrer le framework pour demander un mot de passe

Cependant, une fois le framework ouvert, l'appareil peut rencontrer certaines 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 reprises

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 à error_not_encrypted. L'UI invite l'utilisateur à redémarrer et l'informe du processus de chiffrement n'a jamais démarré. Si l'erreur se produit après la destruction du framework, mais avant que l'UI de la barre de progression ne soit opérationnelle, vold redémarre le système. Si le redémarrage échoue, il définit vold.encrypt_progress sur error_shutting_down et renvoie -1. Toutefois, rien ne permet de détecter l'erreur. Cela ne devrait pas se produire.

Si vold détecte une erreur pendant le processus de chiffrement, il définit vold.encrypt_progress à 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 cryptographie. 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é. Pour rendre la clé résiliente contre les attaques hors champ, nous étendons cet algorithme en signant la clé obtenue avec une clé TEE stockée. La signature obtenue est ensuite convertie 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é :

  1. Générez une clé de chiffrement de disque (DEK) aléatoire de 16 octets et une valeur de sel de 16 octets.
  2. Appliquer scrypt au mot de passe de l'utilisateur et la valeur salt pour obtenir une couche intermédiaire de 32 octets clé 1 (IK1).
  3. Remplacez IK1 par des zéros jusqu'à la taille de la clé privée liée au matériel (HBK). Plus précisément, nous remplissons comme suit: 00 || IK1 || 00..00; un zéro octet, 32 octets IK1, 223 zéro octet.
  4. Signer l'IK1 rempli avec HBK pour produire un IK2 de 256 octets
  5. Appliquez scrypt à IK2 et au sel (même sel que l'étape 2) pour générer IK3 de 32 octets.
  6. Utilisez les 16 premiers octets de l'IK3 comme KEK et les 16 derniers octets comme IV.
  7. 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 réenchiffre la clé principale de 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 disque sans mot de passe.
vold.decrypt trigger_default_encryption Vérifiez que le disque est chiffré sans mot de passe. Si c'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 le framework complet et lancer 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 demander un mot de passe, en fonction de la valeur de ro.crypto.state.
vold.encrypt_progress Au démarrage du framework, si cette propriété est définie, saisissez le mode UI de la barre de progression.
vold.encrypt_progress 0 to 100 L'interface utilisateur de la barre de progression doit afficher la valeur de 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 donner à l'utilisateur la possibilité de réinitialiser l'appareil aux paramètres d'usine.
vold.encrypt_progress error_reboot_failed L'UI de la barre de progression devrait afficher un message indiquant "Chiffrement" terminée et donner à l’utilisateur un bouton pour redémarrer l’appareil. Cette erreur ne devrait pas se produire.
vold.encrypt_progress error_not_encrypted L'UI 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 fournir à 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 est donc difficile de savoir qui répond à cette erreur. Et de toute façon, 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éfini par init.rc ou init.rc juste après la fin de 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 chiffrement non chiffré /data ro.crypto.state encrypted Défini par init pour indiquer que ce système s'exécute avec un /data chiffré.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

Ces cinq propriétés sont définies par init lorsqu'il tente d'installer /data avec des paramètres transmis depuis init.rc vold les utilise pour configurer le mappage cryptographique.
ro.crypto.tmpfs_options Défini par init.rc avec les options que init doit utiliser lors de l'installation du système de fichiers /data tmpfs.

actions init

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