Le chiffrement de partitions avec dm-crypt et device-mapper

Posted by Wxcafe on Wed 10 July 2013

Le chiffrement en tant que concept informatique est traditionnellement associé au chiffrement de fichiers, c’est a dire au fait de passer d’un fichier en clair a un fichier chiffré dit cyphertext. Cependant, il ne se limite pas a ça, et peut aussi servir a garantir l’intégrité d’un système d’exploitation, ou bien la confidentialité d’un support de stockage, par exemple. Nous allons ici voir comment mettre en place un système de ce type sous GNU/Linux. Cet article n’a pas pour but de vous apprendre a mettre en place un système basé sur une procédure de boot sécurisée, mais plutôt d’expliquer les concepts qui entrent en jeu dans l’utilisation du sous-système du noyau Linux dm_crypt et de présenter un rapide tutoriel concernant la création d’un support chiffré sur lequel garder vos informations confidentielles (par exemple, votre clé GPG)

dm-crypt est un sous-système de device-mapper, qui est lui-même un sous-système du noyau Linux, et s’appuie sur LUKS, un standard de chiffrement de disques. Comme son nom l’indique, device-mapper est un système qui a pour but de mapper des block devices. Pour être plus clair, le kernel considère comme “block device” tout fichier spécial (en gros, les fichiers disques dans /dev/, les systèmes de fichiers type LVM, les RAID logiciels, et, dans le cas qui nous intéresse, les systèmes de fichier chiffrés). Son mode de fonctionnement est simple : a partir d’un “fichier de périphérique” (trad. Wikipédia), il en “crée” un nouveau, virtuel, ayant des propriétés différentes. Par exemple, un disque partitionné via LVM apparaîtra comme un seul disque dans /dev, et device-mapper est requis pour pouvoir en voir les partitions (qui apparaîtront donc dans /dev/mapper)

Ainsi, dans le cas qui nous intéresse ici, device-mapper prend un système de fichier chiffré, crée un périphérique virtuel non chiffré dans /dev/mapper, et déchiffre a la volée tous les accès disques a ce périphérique non chiffré en les traduisant sur le système de fichier chiffré, le tout de manière tout a fait transparente pour les applications utilisant le disque en question. Cela induit bien entendu une baisse de performance relativement significative dans le cas d’un chiffrement du système de fichier root, mais quasiment insignifiante dans le cas de chiffrement de partitions de données.

D’ailleurs, certain-e-s se demandent peut-être comment le système peut démarrer si le système de fichier root est chiffré. Dans ce cas précis, la procédure de boot doit s’appuyer sur une image initrd (l’initrd est un système de fichier minimal qui sert uniquement a initialiser le système. Les kernels de base de la plupart des distributions GNU/Linux en utilisent un dans tous les cas, pour des raisons de compatibilité) et sur une partition de boot qui elle n’est pas chiffrée. Ainsi, le bootloader de niveau 2 (grub, syslinux,…) charge en mémoire le kernel depuis la partition de boot, puis ce dernier décompresse et charge l’initrd en RAM, celui-ci a son tour lance un script permettant de charger les modules nécessaires a la suite du boot (que ce soit pour un boot sans disque root local, ou bien comme ici avec un système chiffré), puis le système de fichier “cible” est remonté sur la racine, et l’initrd est démonté est la RAM qu’il occupait est libérée, puis la procédure de boot normale reprend depuis le système de fichier maintenant monté sur la racine.

La méthode la plus évidente pour contourner le chiffrement du disque est alors de remplacer le fichier compressé initrd dans /boot, qui n’est pas chiffrée, par un autre modifié, copiant par exemple la phrase de passe permettant de déchiffrer la partition cible. Plusieurs méthodes permettent de se prémunir contre ce genre d’attaques : l’une des plus simple est de faire un checksum du fichier initrd utilisé et reconnu comme sûr, et de vérifier lors du vrai boot que l’initrd présente toujours le même checksum. Cela dit, cette méthode a l’inconvénient d’intervenir après les faits, et de nécessiter au moins un accès a un fichier initrd reconnu comme sûr.
Une autre approche consisterait a placer le système de fichier /boot sur un périphérique dédié, protégé en écriture de façon matérielle (par exemple, une carte SD) ou, de façon encore plus efficace, sur un périphérique chiffré et protégé en écriture de façon matérielle. Ainsi, il n’est pas possible pour un attaquant de modifier ce système de fichier, et l’initrd est alors toujours de confiance. Cependant, cela a pour conséquence de rendre la mise a jour de l’initrd et du noyau beaucoup plus difficile qu’elle ne le serait sans.

Pour en revenir aux systèmes de fichiers chiffrés, leur gestion est faite par un programme dédié, cryptsetup. Ce dernier était en charge de cryptoloop, l’ancien sous-système de chiffrement du kernel Linux (déprécié depuis), et est maintenant responsable de l’utilisation userspace de dm-crypt, qui pour sa part est entièrement kernel-space. Cryptsetup permet ainsi le chiffrement, la manipulation (montage/démontage/…) et la gestion de clé des systèmes de fichier LUKS. Cryptsetup est cependant conçu pour être utilisé en tant que root, et les utilisateurs qui veulent monter de systèmes de fichiers chiffrés devront ainsi obligatoirement être capables de le faire en tant que root.

Voyons comment il faudrait procéder pour créer une image disque chiffrée de 1Go :
Tout d’abord, il nous faut créer le fichier qui contiendra l’image. Pour cela, dans une situation réelle ou l’on cherche a chiffrer un disque, il convient d’utiliser /dev/urandom comme source, pour éviter la détection du système de fichier chiffré sur le disque. Ici, par exemple, nous allons faire :

dd bs=1000 count=1000000 if=/dev/urandom of=image.img

Maintenant que notre image est créée, nous pouvons la chiffrer :

sudo cryptsetup luksFormat image.img

cryptsetup va alors nous demander si nous sommes absolument surs de vouloir formater ce disque (nous allons donc valider en tapant YES), puis une passphrase. Il convient ici de choisir une passphrase particulièrement sûre, puisque toute personne ayant accès a la passphrase aura aussi accès au disque et donc a vos secrets.
Une fois cela fait, nous allons mapper cette image :

sudo cryptsetup luksOpen image.img crypto

cryptsetup nous redemande la passphrase, charge pendant quelques secondes, puis nous redonne le prompt. Que s’est-il passé? En cherchant un peu, nous voyons qu’il n’y a pas de nouveau disque dans /dev. C’est tout a fait normal. En effet, cryptsetup (et par lui, device-mapper et dm-crypt) ne monte pas les systèmes de fichiers chiffrés, il les mappe, et ça n’a rien a voir. On remarque qu’est apparu dans /dev/mapper le fichier crypto. Ce fichier est le disque virtuel qui correspond a notre image. Il se comporte comme toute partition, et peut donc être monté, formaté, etc (il ne peut cependant pas être partitionné. Il se comporte en effet comme une partition, et non comme un véritable disque.) Bon, ceci fait, notre disque virtuel n’est pas formaté. Il nous reviens donc de le faire, pour pouvoir l’utiliser.

sudo mkfs.ext4 /dev/mapper/crypto

Maintenant que notre disque est formaté, il peut être monté :

sudo mount /dev/mapper/crypto /mnt

Et voila, nous avons un système de fichier fonctionnel et chiffré! Si vous voulez vérifier, un mount | grep crypto devrait vous donner le résultat suivant :

/dev/mapper/crypto on /mnt type ext4 (rw,relatime,data=ordered)

Vous pouvez maintenant commencer a stocker tous vos secrets sur ce fichier, ils sont (en fonction de votre passphrase) en sécurité.

Pour résumer :

  • Pour monter vos partitions :

    sudo cryptsetup luksOpen <fichier chiffré> <nom de disque virtuel>
    sudo mount /dev/mapper/<nom de disque virtuel> <emplacement>
    
  • Pour démonter vos partitions :

    sudo umount <emplacement>
    sudo cryptsetup luksClose <nom de disque virtuel>
    

Pour simplifier la vie de tous, j’ai créé deux petits scripts vous permettant de créer et de monter/démonter vos images/disques chiffré-e-s en une seule commande. Ils se trouvent sur github.

Par ailleurs, si vous comptez transferer votre image disque sur un véritable disque (ou clé usb, ou autre), il est préférable de créer une partition de taille appropriée et de faire un dd if=votre_image of=/dev/votre_partition pour ce faire.