02 Feb 2019, 00:00

Notes sur dm-crypt et LUKS

Share

Source principale : la FAQ (ou en tout cas un mirroir) de cryptsetup

dm-crypt et LUKS

dm-crypt chiffre/déchiffre à la volée les données grâce à la master key, qui est directement dérivée du mot de passe fourni. Aucune structure spéciale n’est visible sur le disque, c’est un pur chiffrement 1:1. Si des secteurs sont corrompus, cela n’affectera aucunement les autres secteurs. Il n’y a aucun garde-fou intégré ; si on se trompe dans la clé entrée, ou dans les paramètres de chiffrement, les données seront lues/écrites avec la mauvaise clé, donc risque non-négligeable de perte de données si fausse manipulation.

LUKS (Linux Unified Key Setup) est une surcouche à dm-crypt qui stocke la master key salée puis chiffrée dans une en-tête LUKS, qui précède les données chiffrées. Cette clé est déchiffrable grâce à plusieurs mots de passe (jusqu’à 8 différents) stockés dans des “key slots”, situés dans le header également. On peut donc ajouter/supprimer des mots de passe différents pour un même volume. Avec un mauvais mot de passe, LUKS ne nous laissera pas lire/écrire des données incorrectes.
Il est essentiel de backuper ce header à part, car sans lui, il sera impossible d’utiliser les données chiffrées. Il “décrit” la manière dont les données doivent être déchiffrées. Notamment grâce au sel, qui est cryptographiquement non-retrouvable.

Installation et chiffrement

On installe

apt install cryptsetup

Il faut consacrer un périphérique (disque, partition…) à LUKS. Toutes les données dessus seront bien sûr détruites. Ici, c’est sdX.
Il est conseillé d’effacer tous les headers d’anciens FS sur la cible, pour être sûr de ne pas avoir de fsck automatique ou autres joyeusetés qui détruiraient les données chiffrées :

sudo wipefs -a /dev/sdX

On crée le conteneur luks

sudo cryptsetup -y -v luksFormat /dev/sdX

-y : double check du mot de passe
-v : verbose

On déverrouille et mappe le conteneur :

sudo cryptsetup open /dev/sdX c1

Le conteneur sera accessible sur /dev/mapper/c1 (plus tard, lorsque udisks reconnaitra tout seul le conteneur (ou le FS dessus ?), ce sera typiquement /dev/mapper/luks-bla-bla-uuid)

On formate en ext4

sudo mkfs.ext4 /dev/mapper/c1

On peut ensuite monter la partition

sudo mount /dev/mapper/c1 /mnt

Et on a une partition chiffrée, qui s’utilise comme n’importe quel périphérique !

On peut la fermer avec

sudo cryptsetup close c1

Lister les contaneurs mappés

sudo dmsetup ls --target crypt

lsblk --fs
peut aussi être utile.

Sauvegarde et restauration de l’en-tête !

Une fois que l’on compte se servir du périphérique pour stocker durablement des vraies données, il est indispensable de backuper le header du conteneur. Sans lui (corruption, création d’une table de partition sur le disque…), plus de données !

cryptsetup luksHeaderBackup /dev/sdX --header-backup-file /path/to/backup.img

Et pour restaurer en cas de besoin :

cryptsetup luksHeaderRestore /dev/sdX --header-backup-file /path/to/backup.img

Gestion des clés

Source

On peut créer un fichier clé aléatoire via le périphérique /dev/urandom, et le passer en read-only pour root. Pour ceci :

sudo dd if=/dev/urandom of=/root/keyfile bs=1024 count=4
sudo chmod 0400 /root/keyfile

pour un fichier de 4ko.
Puis on ajoute ce fichier clé à notre conteneur LUKS (qui doit déjà exister, et avoir donc au moins 1 mot de passe) :

sudo cryptsetup luksAddKey /dev/sdX /root/keyfile

Attention, l’en-tête du conteneur ayant été modifiée, il faut penser à mettre à jour le backup !

luksKillSlot  ??
luksRemoveKey ??

Déverrouillage et montage automatique au boot

Pour déverrouiller automatiquement une partition chiffrée via LUKS au démarrage du système, il faut créer une entrée dans le fichier /etc/crypttab, de ce format :

mapper_name	UUID=01234567-89ab-cdef-0123-456789abcdef	none	luks

mapper_name correspond au nom du mapper qui sera présent dans le dossier /dev/mapper/, et on peut remplacer none par (par exemple) /root/keyfile si on souhaite utiliser un fichier de clé pour déverrouiller le conteneur. Il est bien sûr conseillé de laisser ce fichier clé à un endroit non accessible (par exemple sur une partition déverouillée manuellement par mot de passe).

Il suffit ensuite d’ajouter les lignes nécessaires dans le fstab, soit sous la forme /dev/mapper/mapper_name, soit avec l’UUID de la partition.

Enfin, il me semble qu’il faut regénérer l’initramfs :

sudo update-initramfs -k all -u

Chiffrer la partition /

debian-installer propose de chiffrer la partition slash. Pour ceci, il faut avoir :

  • préparé une partition /boot à part (pour se simplifier la vie ; ça semble être possible autrement, mais galère)
  • sauvegardé le contenu de l’actuelle partition slash si nécessaire ; je n’ai pas trouver comment réutiliser une partition chiffrée déjà existante (sauf à debootstraper à la main depuis un live-cd, mais c’est pratique debian-installer…)

Lors de la phase de partitionnement, on peut séléctionner “Configurer les volumes chiffrés”. On sélectionne la partition qui deviendra le slash chiffré, on laisse les options par défaut ; on choisit une phrase de passe. On peut annuler l’opération d’effacement si on ne la juge pas nécessaire. Lorsque l’on clique sur “Terminer”, le contenu du volume chiffré devient disponible, généralement en haut de la liste. On peut donc le définir en tant que partition slash.

J’ai eu des soucis lorsque j’ai voulu chiffrer le swap et le home depuis l’install. Tout a bien fonctionné en ne chiffrant que le slash lors de l’install, puis le swap et le home directement depuis l’installation.

Si il y’a besoin de faire une réparation depuis un live-cd, penser à vérifier/modifier le nom du mapper dans /dev/mapper via sudo dmsetup rename oldname newname, et le nom sous lequel il est monté dans /proc/mounts (il faut démonter/remonter si le nom du mapper a changé après le mount).
S’il y’a besoin de regénérer l’initramfs, vérifier que le nom du mapper correspond bien au nom dans /etc/crypttab.

Divers

Pour voir des infos sur le conteneur LUKS :

cryptsetup luksDump /dev/sdX

Pour voir des infos sur un conteneur LUKS une fois mappé (dans cet exemple sur /dev/mapper/c1) :

cryptsetup -v status c1

Voir la master key lorsque le périphérique est déverrouillé (attention aux yeux trop curieux)

sudo dmsetup table --target crypt --showkey /dev/mapper/c1

Redimensionnement

Pour agrandir un conteneur :

  • étendre le conteneur via GParted ou équivalent
  • ouvrir le conteneur
  • sudo cryptsetup resize c1 # mapper name
  • vérifier le fs, qui devrait resize à la bonne taille
  • resize2fs ?

Pour réduire un conteneur, GParted plante si c’est un conteneur LUKS2, ce qui est le cas par défaut.
Pour le faire à la main :

PAS ENCORE OK !!

 - BACKUP DES DONNÉES !

 - # démonter le conteneur, le réparer
 - sudo umount /dev/mapper/mon-conteneur
 - sudo fsck -f /dev/mapper/mon-conteneur
 - sudo resize2fs /dev/mapper/mon-conteneur

 - # déterminer la taille de secteur du conteneur LUKS2, ainsi que sa taille tout court :
 - sudo cryptsetup status mon-conteneur | grep "size" | grep "sector"

 - # déterminer la nouvelle taille, en soustrayant l'espace souhaité (en secteurs) ;
   # par exemple, pour libérer 20G, on fait :
 - new_size = ${luks_size} - (20 * 1024 * 1024 * 1024 / ${sector_size} )
 - # dimensionner le conteneur :
 - sudo cryptsetup resize mon-conteneur -b ${new_size}

 - # si c'est une partition et qu'on veut la réduire (par exemple /dev/sdX5) :
 - # déterminer le début et la fin actuels de la partition sous-jacente (en secteurs) :
 - sudo parted /dev/sdX -> unit -> s -> p # noter les valeurs "Start" et "End" pour la partition qui nous intéresse.

 - # trouver l'offset du conteneur LUKS :
 - sudo cryptsetup status mon-conteneur | grep offset

 - # calculer la nouvelle fin de partition :
 - new_end = (${start_sector} + ${new_size} + ${offset} -1)
 - # redimensionner la partition elle-même : 
 - sudo parted /dev/sdX -> unit -> s -> resizepart 5 ${new_end} # adapter le numero de partition -> yes -> q

Une source et une autre.