(Short english summary at end)

L'un des avantages à avoir chiffré tout son disque avec LUKS, c'est que ce système permet de modifier après coup la ou les phrases secrètes ou clés qui le verrouillent. On peut donc assez aisément : [1]

  • Installer plusieurs phrases secrètes différentes permettant de déverrouiller la machine, ce qui est utile si la machine a plusieurs utilisateurs légitimes : ainsi, aucun n'a besoin de connaître la phrase secrète de l'autre. Chacun la sienne !
  • Ajouter une clé de déchiffrement qui ne sera pas une phrase secrète, mais un fichier hébergé sur un stockage externe (qui peut lui-même être chiffré, ce qui permet d'obtenir la "dual form authentication", ou authentification à double critère).
  • Supprimer une phrase ou clé existante si l'on ne souhaite plus utiliser l'une des méthodes, si l'un des utilisateurs ne doit plus avoir accès à la machine ou si une phrase ou clé a été compromise, etc.

La méthode hybride permet également de verrouiller le système avec une phrase secrète longue et complexe - donc fastidieuse à taper - et alternativement avec un support externe contenant une clé qui peut être protégée par un mot de passe plus simple, voire pas de mot de passe du tout, en fonction des besoins de sécurité que l'on aura.

En terme de support externe, nous pourrons envisager l'usage d'une clé "flash drive" USB,[2] ou d'une carte mémoire type SD, etc, pour peu que la machine considérée soit équipée d'un lecteur adéquat.

En partant du principe que nous avons déjà un système entièrement chiffré sur la base de mon précédent article, la mise en oeuvre d'une clé sur support externe - avec ou sans double authentification - va être relativement simple : Je fournis ici un "bootkeyscript"[3] qui fait tout le boulot.

En premier lieu, procurons-nous évidemment un support externe utilisable sur notre machine, et que nous utiliserons. Nous pouvons le partitionner et le formater de la manière de notre choix, le script "bootkeyscript" détectera automatiquement le système de fichiers utilisé.

Si nous voulons utiliser une clé "simple" sur support externe, non protégée elle-même par mot de passe, nous pouvons nous contenter de mettre celle-ci dans une partition FAT existante de n'importe quel support externe, que nous pourrons également utiliser "comme d'habitude" pour y stocker tous documents et fichiers de notre choix, en prenant simplement grand soin de ne jamais effacer par mégarde la clé de notre système !

Si nous voulons chiffrer la clé elle-même, nous créerons sur le support externe une petite partition que nous chiffrerons avec LUKS avant d'y créer un filesystem ext2 sur lequel nous stockerons enfin la clé.
Ceux qui ne désirent pas cette "double protection" peuvent sauter l'étape de création d'une partition chiffrée sur le support externe.

Création d'une partition chiffrée sur le support externe

Nous utiliserons donc un outil de partitionnement (fdisk, gparted, etc...) pour créer sur le support amovible une petite partition (typiquement 10 Mo) de type "Linux" (83), non formatée. Pour la suite de cet article, nous considérerons la partition créée, et située sur /dev/sdb2. Adaptez bien évidemment les instructions qui suivent à l'emplacement de votre propre partition, sur votre propre périphérique, au risque de détruire irrémédiablement des données sur votre système.

Commençons par remplir notre partition de clés de données aléatoires, selon la méthode habituelle :

dd if=/dev/urandom of=/dev/sdb2 bs=1M

Compte tenu de sa taille modeste, ça ne devrait prendre que quelques secondes.

Faisons ensuite de cette partition un volume chiffré LUKS :

cryptsetup luksFormat /dev/sdb2

Après un avertissement auquel il nous faut répondre "YES", il nous sera demandé de taper deux fois la phrase secrète ou mot de passe que nous utiliserons pour protéger nos clés. Rappelons-nous que nous devrons le taper à chaque boot, et que cela vient en supplément de la possession matérielle du support. À moins d'être paranoïaque, nous pouvons donc nous contenter d'un mot de passe relativement court et facile à taper - mais de préférence, pas à deviner ;-)
Une fois le volume chiffré créé, nous devons l'activer :

cryptsetup luksOpen /dev/sdb2 ext_keys

Après avoir tapé le mot de passe, si nous tapons "ls -l /dev/mapper", nous devrions voir y apparaître un périphérique nommé "ext_keys", qui correspond au volume chiffré "/dev/sdb2" actuellement ouvert.

Il nous faut maintenant "formater" cette partition pour y créer un filesystem ext2 :

mke2fs -m 0 -L ext_keys /dev/mapper/ext_keys

Génération d'un fichier-clé de 256 octets aléatoires

Nous allons maintenant monter le volume externe de manière à pouvoir y créer un fichier-clé. Commençons par créer le répertoire qui servira de point de montage :

mkdir /mnt/ext_keys

Puis :

  • Si nous n'avons pas chiffré le volume, nous utilisons directement la partition de l'unité externe :
    • mount -t vfat -o defaults /dev/sdb2 /mnt/ext_keys
  • Si nous avons chiffré le volume, nous montons sa version ouverte depuis /dev/mapper :
    • mount -t ext2 -o noatime /dev/mapper/ext_keys /mnt/ext_keys

Nous n'avons plus qu'à générer un fichier de 256 octets aléatoires que nous nommerons .bootkey (par exemple).

N.B.: Veillez bien à utiliser ici /dev/random et non pas /dev/urandom :

dd if=/dev/random of=/mnt/ext_keys/.bootkey

...à la suite de quoi un "ls -la /mnt/ext_keys/" devrait bien nous montrer la présence de notre fichier-clé aléatoire de 256 octets.

=> Un support externe peut être endommagé ou perdu ! Une mémoire flash n'est pas infaillible ! A ce stade, je vous conseille vivement de faire une copie de votre fichier-clé sur un ou plusieurs autres supports !

Maintenant que notre fichier est généré (et sauvegardé), nous pouvons démonter l'unité externe :

umount /mnt/ext_keys
sync

et, si nous avions utilisé un volume chiffré, nous pouvons le désactiver :

cryptsetup luksClose ext_keys

Première regénération de l'initramfs

Pour pouvoir accéder à notre unité externe lors du boot, nous devrons nous assurer que les modules nécessaires (USB ou SD/MMC) sont bien présents sur l'initramfs que nous utilisons.

Les modules à charger dépendent fortement du matériel que vous possédez. Utilisez la commande "lsmod" pour lister les modules actuellement chargés sur votre système, et déterminer ceux qu'il vous faudra inclure dans l'initramfs.

On aura typiquement pour de l'USB :

  • usbcore
  • ohci_hcd (ou uhci_hcd selon le matériel)
  • ehci_hcd
  • usb_storage
  • sd_mod

Pour un lecteur SD/MMC :

  • mmc_core
  • sdhci
  • mmc_block

Si vous voulez mettre votre clé sur une partition FAT (sur une clé USB par exemple, il faudra également ajouter :

  • fat
  • vfat
  • nls_cp437
  • nls_iso8859_1

Mettez alors cette liste de modules, un par ligne, dans le fichier /etc/initramfs-tools/modules. Le mien, pour une utilisation de cartes SD, contient les lignes suivantes :

mmc_core
sdhci
mmc_block
aes_i586
sha256
dm_mod
dm_crypt

Une fois ceci fait, récréons notre initramfs :

update-initramfs -v -u

Insertion de la nouvelle clé dans le container LUKS principal du système

Nous allons maintenant rebooter notre système (antérieurement chiffré), et, quand celui-ci nous demandera notre phrase secrète, nous allons volontairement taper 3 fois de suite un mot de passe invalide, puis attendre. Au bout d'une trentaine de secondes, nous devrions obtenir un message d'erreur indiquant que le root filesystem est indisponible, puis nous retrouver dans un shell minimal (busybox) à l'intérieur de notre initramfs.

(initramfs)

À partir de là, nous ne pouvons pas faire grand-chose, mais nous pouvons en faire assez pour ajouter notre clé au container :

  • Créons un point de montage "/ext_keys" : mkdir /ext_keys
  • Montons notre unité externe sous ce point : mount -t vfat -o ro /dev/sdb2 /ext_keys (si nous avions chiffré la partition, nous devons d'abord l'ouvrir avec "cryptsetup luksOpen'' avant de la monter à partir de /dev/mapper exactement comme expliqué plus haut)

Ajoutons maintenant la clé au container chiffré du disque dur (en supposant qu'il s'appelle /dev/sda2) :

cryptsetup luksAddKey /dev/sda2  /ext_keys/.bootkey

Le système nous demandera alors la phrase secrète actuelle du container, avant d'ajouter la clé qui se trouve sur le périphérique externe.

Une fois ceci fait, nous pouvons démonter le volume externe (umount /ext_keys), et si nécessaire refermer le volume chiffré correspondant (cryptsetup luksClose ext_keys).
Puis, nous pouvons rebooter "normalement" :

sync
reboot

=> Lors de ce reboot, nous devons toujours taper la phrase secrète habituelle de notre système, car son initramfs ne sait pas encore utiliser la clé résidant sur le support externe.

Génération d'un initramfs compatible avec la clé sur support externe.

Pour que notre système puisse utiliser la clé que nous avons fabriquée puis installée, il nous faut ajouter dans l'initramfs le script "bootkeyscript" que j'ai écrit et que vous trouverez en attachement.
Ce script est très souple, car il détecte automatiquement si la partition contenant la clé est chiffrée ou non, et en demande le mot de passe le cas échéant. De plus, si l'unité externe n'est pas présente, il vous sera possible de taper une phrase secrète à la main - si toutefois votre système en reconnaît encore une comme valide.

Installation du script "bootkeyscript"

Installez ce script dans un répertoire approprié de votre système (je vous suggère /usr/local/sbin), et rendez-le exécutable avec "chmod 755 /usr/local/sbin/bootkeyscript".

Inclusion de l'utilitaire "stty" dans l'initramfs

Créez un script que vous appellerez "include_stty" dans le répertoire /etc/initramfs-tools/hooks, avec le contenu suivant :

#! /bin/sh
. /usr/share/initramfs-tools/hook-functions
copy_exec /bin/stty /bin

Rendez ce script exécutable : chmod 744 /etc/initramfs-tools/hooks/include_stty

Inclusion de l'utilitaire "udevsettle" dans l'initramfs

Créez un script que vous appellerez "include_udevsettle" dans le répertoire /etc/initramfs-tools/hooks, avec le contenu suivant :

#! /bin/sh
. /usr/share/initramfs-tools/hook-functions
copy_exec /sbin/udevsettle /sbin

Rendez ce script exécutable : chmod 744 /etc/initramfs-tools/hooks/include_udevsettle

Edition de /etc/crypttab

Editez votre fichier /etc/crypttab : C'est lui qui indiquera au système qu'il faut utiliser le script, et où se trouve la clé. En fonction du périphérique externe que vous utilisez et du nom que vous avez choisi pour votre fichier-clé, la ligne concernant votre LVM chiffrée devra désormais prendre l'aspect suivant :

# <target name> <source device> <key file> <options>
crypt_VG1 /dev/sda2 sdb2/.bootkey   luks,tries=3,lvm=crypt_VG1-LV_ROOTFS,keyscript=/usr/local/sbin/bootkeyscript

À noter : l'emplacement du "key file" se note ici sous la forme partition/fichier (avec des sous-répertoires si vous le souhaitez), mais sans indiquer "/dev/..." ni le point de montage, qui sont automatiques.

Ne vous trompez pas en modifiant ce fichier ! Par rapport à votre installation antérieure, il vous faut seulement :

  • Modifier "key file" de "none" à l'emplacement de votre fichier-clé ;
  • Ajouter à la fin des options "keyscript=/usr/local/sbin/bootkeyscript"

Le reste ne change pas par rapport à précédemment.

Nous avons presque terminé.

Génération de l'initramfs final :

update-initramfs -v -u

...Et il ne nous reste plus qu'à rebooter proprement.

- Si le périphérique contenant la clé est présent, la machine bootera automatiquement (elle demandera le mot de passe du périphérique-clé automatiquement, uniquement ci celui-ci a été créé ainsi).

- Si le périphérique contenant la clé est absent, vous obtiendrez (et c'est intentionnel) uniquement le message d'erreur :

Missing boot device /dev/sdb2!

...mais en réponse à ce messages d'erreur, vous pouvez taper une phrase secrète, s'il en existe une valide pour le container chiffré du disque dur, et le démarage se poursuivra alors normalement.

Vous avez désormais un système chiffré capable d'être "trimodal" : Il peut démarrer soit avec une phrase secrète, soit avec une clé externe non protégée, soit avec une clé externe protégée, vous offrant ainsi une sécurité extrême.

  • Si les choses ne fonctionnent pas comme désiré, vous pouvez passer le script en mode "debug" en ajoutant "cryptdebug" à la ligne de paramètres de démarrage de votre noyau. Le script affichera alors des messages indiquant sa progression et d'éventuels problèmes.

Une fois que vous serez certain que votre clé externe permet effectivement le démarrage du système, et que vous en avez fait une copie de secours (ailleurs que sur le portable qu'elle protège ;-) vous pourrez, si vous le souhaitez, supprimer complètement la phrase secrète antérieure de votre disque dur chiffré, en utilisant "cryptsetup luksDelKey (voir man cryptsetup), après avoir booté dans l'initrd'' comme expliqué plus haut.

Il ne vous reste plus qu'à penser à ne pas laisser votre clé de contact en permanence sur votre machine : Aussitôt que la machine a démarré, vous pouvez la retirer - et donc utiliser votre lecteur de carte ou prise USB pour y connecter, comme d'habitude, tout autre périphérique de votre choix.


Vous pouvez également vous référer avec fruit au Two Form Factor Authentication and LUKS Whole Disk Encryption with Feisty Fawn HowTo, notez cependant que le script "maison" que je vous fournis ici n'en provient pas : J'ai la faiblesse de penser que mon script est beaucoup plus puissant, et il a l'avantage de ne nécessiter aucune modification des scripts standard du système.


Short english summary :

In this article, I propose a "bootkeyscript" that allows easy use of dual form factor authentication on a fully encrypted LVM Ubuntu (7.10 Gutsy Gibbon) Linux installation. (See one of these excellent HowTos for installing Ubuntu on a fully-encrypted LVM base : "EncryptedFilesystemLVMHowto", "FeistyLUKSTwoFormFactor")

The script that I propose here has some advantages over existing scripts :

  • Doesn't need any change or patch to Ubuntu Gutsy existing scripts, with which it integrates well, making future packages upgrads easy ;
  • Automatically allows in a smart way any combination of the following authentication methods :
    • Single form-factor authentication, using an unencrypted keyfile on an external removable device ;
    • Dual-form factor authentication, using a keyfile residing on a LUKS-encrypted partition on an external device ;
    • Possible automatic fallback to typing a passphrase if keyfile external device is missing (with a purposely obscure Missing boot device! error message).

Short installation instructions :

  • Create a fully (passphrase-controlled) LVM encrypted system as usual, possibly following one of the existing HowTos. Do not change anything in the existing Ubuntu encryption scripts.
  • Create a random keyfile. Install it on an external device partition, either itself LUKS-encrypted with a passphrase (for 2 form-factor auth) or unencrypted (1 form-factor, with key device, without passphrase).
  • Install the key to the main system LUKS container (following usual instructions).
  • List all the modules you will need to access your key device and its filesystem, in the /etc/initramfs-tools/modules file
  • Put such an executable script (mode 744) into /etc/initramfs-tools/hooks, let's call it "include_stty" :
#! /bin/sh
. /usr/share/initramfs-tools/hook-functions
copy_exec /bin/stty /bin

(This will include "stty" into the initramfs, to avoid echoing typed passphrase if not using bootsplash. Using bootsplash wouldn't actually need this)

  • Create an include_udevsettle script the same way :
#! /bin/sh
. /usr/share/initramfs-tools/hook-functions
copy_exec /sbin/udevsettle /sbin
  • Install my "bootkeyscript" script wherever you like on your system (I suggest /usr/local/sbin), mode 755.
  • Update /etc/crypttab with the columns :
    • Key : device/keyfilename i.e. sdb1/.mysystemkey or mmcblk0p2/somedir/somekeyfile (Syntax is devicepartition/filepath)
    • Options : Add "keyscript=/usr/local/sbin/bootkeyscript"
  • Regenerate initramfs (update-initrafms -u)
  • Reboot, enjoy.

Changelog

2008/05/10: bootkeyscript V. 1.5:

  • Much debugged and rewritten version of the script.
  • Works much better than previously for keys on USB flash disks.
  • Includes a "debug" mode that you can set by adding "cryptdebug" to the kernel command line.
  • This article completed with some missing infomation.
  • Compatible with Ubuntu 8.04 Hardy or 7.10 Gutsy

Help Google : Ubuntu Linux 7.10 Gutsy Gibbon LUKS whole disk encryption external device keys, two form factor authentication, how to howto

Notes

[1] Les possibilités de ce système sont immenses. On peut par exemple imaginer, pour un serveur - qui doit être capable de booter sans intervention humaine - de stocker une clé sur une machine distante, et de l'obtenir via Internet, la machine distante étant configurée pour ne fournir cette clé qu'à une adresse IP précise. Le serveur sera ainsi capable de booter tout seul dans son "environnement habituel", mais si jamais il est volé, il deviendra inutilisable en dehors de son adresse IP habituelle, et il sera possible de supprimer la clé de la machine distante sur laquelle elle est stockée. Un tel setup est toutefois extrêmement complexe et va bien au-delà des objectifs de cet article.

[2] L'avantage d'une clé USB est qu'elle peut être bootable, alors qu'une SD-card ne le sera pas - parce que le BIOS du système ne le prévoit généralement pas. Si on utilise une clé USB, on peut même envisager de mettre dessus le "/boot" non chiffré du système (moins de 100 Mo), ainsi que le bootloader grub, ne laissant sur le disque dur qu'un container totalement chiffré et non bootable contenant tout le reste du système. Ce n'est pas particulièrement compliqué à faire, mais c'est là encore en dehors du sujet de cet article.

[3] Évidemment sous licence GNU GPL.