LUKS : quelques grammes de paranoïa pour des données bien protégées

LUKS signifie Linux Unified Key Setup. Il s'agit d'un format de cryptage de données standard et indépendant de la plateforme. Cet outil a justement été développé dans une optique de standardisation des processus d'encryptage et de décryptage des données, suite aux expériences malheureuses d'utilisateur. Afin de prétendre à la standardisation de l'outil, il a donc fallu prendre et justifier un ensemble de décisions. Ces décisions ont été regroupées sous une même modèle, TKS1, destiné au processing de clé issue de user password. Ce dispositif d'encryption est basé sur une version améliorée de cryptsetup et utilisant dm-crypt comme support pour la partie encryption de disque. Bien qu'initialement développé pour Linux, il existe aujourd'hui des versions dédiées Windows . LUKS est un processus à lancer sur une partition nouvelle, vierge de toute données dans la mesure où il opère une réorganisation de la structure logique de la partition. Néanmoins, il est possible, en passant par un backup et une restauration explicite à votre charge, de faire en sorte qu'une partition existante passe en cryptée sans perte de données.

Fonctionnement

Un disque encrypté via LUKS a une structure telle que :
LUKS phdr | KM1 | KM2 | ... | KM8 | bulk data
On peut y voir 3 types d'éléments : le Partition header (phdr), les key materials (KM) et les données encryptées (bulk data). Le partition header (phdr) débute au secteur 0 de la partition et contient :
  • les informations propres à l'encodage des données : le cipher utilisé, son mode, la md5sum de la master key ainsi que sa longueur, et un uuid,
  • les informations à propos des key slots, c'est-à-dire les entrées contenant les localisations des key materials.
Lorsqu'un key slot est activé, il y a recopie de la version cryptée de la master key dans la partie KM (Key Material) qui est associée au key slot. Cette version cryptée est verrouillée par le password utilisateur. La master key est construite grâce à PBKDF2 (PKCS #5’s password based key derive function 2). Elle est checksummée et plusieurs fois hashée via PBKDF2. Le résultat et le nombre d'itération sont tous les deux stockés dans le phdr. Normalement, une master key comprend seulement 16 ou 32 octets, ce qui peut poser des soucis de sécurité en cas de remapping en tant que zone réservée. En effet, il devient alors impossible d'accéder au secteur pour purger toute trace de la clé. C'est pour cela que LUKS a prévu une fonction qui splitte les information et gonfle la taille de la master key, ce qui permet de réduire les risques que l'ensemble de la master key soit remappée. Lorsqu'un utilisateur renseigne le mot de passe et après vérification de celui-ci, il y a décryptage du key material contenant la version cryptée de la master key. Il est alors possible de décrypter les données. Grâce à la multitude des key slot, il est possible d'avoir plusieurs mots de passe protégeant les données. Il suffit donc de fournir un de ces mots de passe pour déverrouiller la partition. Le phdr est de taille constante, en revanche, les tailles des KM dépendent de la longueur de la master key. Il existe plusieurs étapes par lesquelles on doit passer pour mettre en place et gérer LUKS. L'initialisation est la première. Elle consiste à construire une master key, et à modifier la structure de la partition à encrypter de telle sorte qu'elle dépende de cette master key. Il y a ensuite définition du password afin de déverrouiller la master key. Pour cela, l'utilisateur doit disposer d'une version non cryptée de la master key. Le password est ensuite crypté par PBKDF2 et crypte à son tour la master key.

Il est possible de changer de mot de passe puisque cela revient à déverrouiller la master key, à ajouter un nouveau password et à supprimer l'ancien.

Prise en main

Sur la plupart des distributions, il existe un package répondant au doux nom de cryptsetup, disponible sur les dépôts officiels. Pour jouer un peu, nous allons partir des sources, comme ça aucun paramétrage ne nous échappera et nous n'aurons plus de mauvaises excuses si cela ne fonctionne pas comme on veut. La dernière version en date est la 1.1.3, uploadée sur le serveur le 03 Juillet. Pour dire si la Communauté est active... C'est parti pour le rapatriement des sources !
$ wget http://cryptsetup.googlecode.com/files/cryptsetup-1.1.3.tar.bz2
$ tar jxf cryptsetup-1.1.3.tar.bz2
$ cd cryptsetup-1.1.3
Pour éviter que vous ne fassiez du stop-n'go comme moi, voici les principales requirements que j'ai rencontrées :
  • libdevmapper-devel
  • libgcrypt-devel, qui implique libgpg-error-devel
L'installation se fait à la régulière :
$ ./configure
$ make
$ make install
[...]
Libraries have been installed in:
/usr/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
[...]
Le make check est optionnel, mais conseillé. Beaucoup bavard, il permet de s'assurer que tout fonctionne au poil. L'installation est donc rapide et sans douleur. Voyons ce qu'il en retourne. Ne cherchez pas de luks quelque chose, vu que LUKS est une amélioration de cryptsetup, c'est cette commande qu'il faut invoquer.
$ cryptsetup --help
cryptsetup 1.1.3
Utilisation: cryptsetup [OPTION...] <action> <action-specific>]
-v, --verbose                       Affiche des messages d'erreur plus détaillés
--debug                         Afficher les messages de débogage
-c, --cipher=CHAINE                 L'algorithme (« cipher ») utilisé pour chiffrer le disque (voir /proc/crypto)
-h, --hash=CHAINE                   L'algorithme de hachage utilisé pour créer la clé de chiffrement à partir de la phrase de passe
-y, --verify-passphrase             Vérifie la phrase de passe en la demandant deux fois
-d, --key-file=CHAINE               Lit la clé depuis un fichier (qui peut être /dev/random)
--master-key-file=CHAINE        Lit la clé (maîtresse) du volume depuis un fichier.
-s, --key-size=BITS                 La taille de la clé de chiffrement
-S, --key-slot=ENTIER               Numéro de l'emplacement pour la nouvelle clé (par défaut, le premier disponible)
-b, --size=SECTEURS                 La taille du périphérique
-o, --offset=SECTEURS               Le décalage à partir du début du périphérique sous-jacent
-p, --skip=SECTEURS                 Combien de secteurs de données chiffrées sauter au début
-r, --readonly                      Créer un « mapping » en lecture seule
-i, --iter-time=msecs               Temps d'itération de PBKDF2 pour LUKS (en ms)
-q, --batch-mode                    Ne pas demander confirmation
--version                       Afficher la version du paquet
-t, --timeout=secs                  Délai d'expiration de la demande interactive de phrase de passe (en secondes)
-T, --tries=ENTIER                  How often the input of the passphrase can be retried
--align-payload=SECTEURS        Utiliser une limite de <n> secteurs pour aligner les données - pour luksFormat
--non-exclusive                 (Obsolète, voir la page de man).
--header-backup-file=CHAINE     Fichier contenant une sauvegarde de l'en-tête LUKS et des emplacements de clés.

Options d'aide :
-?, --help                          Afficher ce message d'aide
--usage                         Afficher, en résumé, la syntaxe d'invocation

<action> est l'une de :
create <nom> <périphérique> - créer un périphérique
remove <nom> - retirer le périphérique
resize <nom> - redimensionner le périphérique actif
status <nom> - afficher le statut du périphérique
luksFormat <périphérique> [<fichier de la nouvelle clé>] - formate un périphérique LUKS
luksOpen <périphérique> <nom>  - ouvrir un périphérique LUKS avec <nom> comme « mapping »
luksAddKey <périphérique> [<fichier de la nouvelle clé>] - ajouter une clé au périphérique LUKS
luksRemoveKey <périphérique> [<fichier de clé>] - retire du périphérique LUKS la clé ou le fichier de clé fourni
luksKillSlot <périphérique> <emplacement de clé> - efface de façon sécurisée la clé avec le numéro <emplacement de clé> du périphérique LUKS
luksUUID <périphérique> - afficher l'UUID du périphérique LUKS
isLuks <périphérique> - teste si <périphérique> a un en-tête de partition LUKS
luksClose <nom> - retirer le « mapping » LUKS
luksDump <périphérique> - afficher les informations LUKS de la partition
luksSuspend <périphérique> - Mettre le périphérique LUKS en hibernation et effacer de façon sécurisée la clé (toutes les entrées/sorties sont suspendues).
luksResume <périphérique> - Réveiller le périphérique LUKS de son hibernation.
luksHeaderBackup <périphérique> - Sauvegarder l'en-tête et les emplacements de clés du périphérique LUKS
luksHeaderRestore <périphérique> - Restaurer l'en-tête et les emplacements de clés du périphérique LUKS
luksDelKey <périphérique> <emplacement de clé> - identique à luksKillSlot - OBSOLÈTE - voir la page de man
reload <nom> <périphérique> - modifier le périphérique actif - OBSOLÈTE - voir la page de man

<nom> est le périphérique à créer dans /dev/mapper
<périphérique> est le périphérique chiffré
<emplacement> est le numéro de l'emplacement de clé LUKS à modifier
<fichier de clé> est un fichier optionnel contenant la nouvelle clé pour l'action luksAddKey

Default compiled-in device cipher parameters:
plain: aes-cbc-essiv:sha256, Key: 256 bits, Password hashing: ripemd160
LUKS1: aes-cbc-essiv:sha256, Key: 256 bits, LUKS header hashing: sha1
Tout d'abord, il faut initialiser une partition vierge (ou si elle ne l'est pas, la backupper, et la cleaner pour qu'elle le soit). Comme moi je n'en ai pas de dispo et que je souhaite quand même jouer un peu, je vais en créer une de toute part de 400M.
$ head -c 400M /dev/zero > luksdev
$ losetup /dev/loop0 luksdev
$ cryptsetup luksFormat /dev/loop0

WARNING!
========
Cette action écrasera définitivement les données sur /dev/loop0.

Are you sure? (Type uppercase yes): YES
Entrez la phrase de passe LUKS :
Verify passphrase:
Et la commande nous rend la main. Si vous êtes sceptique, et je le suis, vous pouvez toujours voir ce qui se passe sur votre partition :
$ cryptsetup luksDump /dev/loop0
LUKS header information for /dev/loop0

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 2056
MK bits:        256
MK digest:      0b 62 b6 db 1b 4d bf 99 1e 36 7a de 4b 07 00 49 56 a7 bc bd
MK salt:        b3 49 2e 88 5b 11 fc 02 d2 74 70 24 a7 54 2c b1
9a 9e dc f3 04 cd 83 52 20 db 88 d7 95 34 25 a3
MK iterations:  17250
UUID:           f19343f6-a783-498f-8304-c6bbf536ede5

Key Slot 0: ENABLED
Iterations:             69360
Salt:                   50 e3 ee 05 3d 19 f7 14 80 ee 24 db 66 69 7e 3e
cf 15 38 0d e9 77 47 43 85 bc ed bc 2a 46 37 02
Key material offset:    8
AF stripes:             4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
Nous avons crée la Master Key comme en témoigne le retour du luksDump avec champs MK (MK bits, MK digest, MK salt et MK iterations). Passons au password pour la verrouiller.
$ cryptsetup luksAddKey /dev/loop0
Entrez une phrase de passe :
Entrez une nouvelle phrase de passe pour l'emplacement de clé :
Verify passphrase:
Attention, ici, c'est la passphrase définie à l'initialisation qui est demandée en premier. Si vous vous trompez, il bronchera et finira la commande :
$ cryptsetup luksAddKey /dev/loop0
Entrez une phrase de passe :
Aucune clé n'est disponible avec cette phrase de passe.
Pour être certain, relançons un luksDump :
$ cryptsetup luksDump /dev/loop0
LUKS header information for /dev/loop0

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 2056
MK bits:        256
MK digest:      0b 62 b6 db 1b 4d bf 99 1e 36 7a de 4b 07 00 49 56 a7 bc bd
MK salt:        b3 49 2e 88 5b 11 fc 02 d2 74 70 24 a7 54 2c b1
9a 9e dc f3 04 cd 83 52 20 db 88 d7 95 34 25 a3
MK iterations:  17250
UUID:           f19343f6-a783-498f-8304-c6bbf536ede5

Key Slot 0: ENABLED
Iterations:             69360
Salt:                   50 e3 ee 05 3d 19 f7 14 80 ee 24 db 66 69 7e 3e
cf 15 38 0d e9 77 47 43 85 bc ed bc 2a 46 37 02
Key material offset:    8
AF stripes:             4000
Key Slot 1: ENABLED
Iterations:             65540
Salt:                   1f 23 24 2b 59 3a b6 12 ff 98 e5 b5 f4 bc d9 34
b5 af b4 64 a1 9a 3d 19 9e 07 7d 10 ba fb a2 0d
Key material offset:    264
AF stripes:             4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED
On voit que le Key Slot 1 a été activé et contient des infos. Comme je vous l'ai dit précédemment, on peut ajouter au plus 8 clés, et c'est un élément qu'on retrouve dans le nombre de key slots à disposition. Admettons qu'une des clés -on en a qu'une, ça facilite- a été compromise. Il suffit alors de la supprimer ! Ici, par exemple, je supprime la clé du key slot 1 :
$ cryptsetup luksDelKey /dev/loop0 1
luksDelKey is a deprecated action name.
Please use luksKillSlot.
Entrez une phrase de passe LUKS qui restera valide :

$ cryptsetup luksDump /dev/loop0
LUKS header information for /dev/loop0
[...]
Key Slot 0: ENABLED
Iterations:             69360
Salt:                   50 e3 ee 05 3d 19 f7 14 80 ee 24 db 66 69 7e 3e
cf 15 38 0d e9 77 47 43 85 bc ed bc 2a 46 37 02
Key material offset:    8
AF stripes:             4000
Key Slot 1: DISABLED
Entre temps; j'ai défini une deuxième clé, qui occupe le Key Slot 2. Et par luksKillSlot :
$ cryptsetup luksKillSlot /dev/loop0 1
Entrez une phrase de passe LUKS qui restera valide :

$ cryptsetup luksDump /dev/loop0
LUKS header information for /dev/loop0
[...]
Key Slot 0: ENABLED
Iterations:             69360
Salt:                   50 e3 ee 05 3d 19 f7 14 80 ee 24 db 66 69 7e 3e
cf 15 38 0d e9 77 47 43 85 bc ed bc 2a 46 37 02
Key material offset:    8
AF stripes:             4000
Key Slot 1: DISABLED
Key Slot 2: ENABLED
Iterations:             74283
Salt:                   6e 45 60 fa 5e 93 f8 26 51 9f f6 9b 86 09 7d 32
77 9d 28 f9 a8 10 a1 21 8e 16 39 40 7b 43 93 09
Key material offset:    520
AF stripes:             4000
[...]

Bref, vous avez saisi, il existe plein d'autres options qui permettent de gérer finement la partition.

L'après-LUKS est encore du LUKS

C'est bien beau tout ça me direz-vous, mais comment on fait pour l'utiliser, ta partition ? Et bien comme pour toutes les nouvelles partitions, il faut formatter ! Et pour cela, il faut encore passer par LUKS avant d'utiliser vos outils dédiés au formatage (oui, souvenez-vous, la structure logique a été spécialisée). En réalité, on invoque luksOpen qui a pour rôle d'"ouvrir" le volume crypté. On lui fournit, en plus de votre partition, le nom souhaité du mapping. Le tout sera alors monté sur /dev/mapper/<nom du mapping spécifié>
$ cryptsetup luksOpen /dev/loop0 luksmnt
Entrez la phrase de passe pour /dev/loop0 :

$ ll /dev/mapper/luksmnt
brw-rw---- 1 root disk 252, 0 2010-07-28 14:52 /dev/mapper/luksmnt
Une fois cette ouverture faite, vous pouvez tout à fait invoquer mkfs.ext4 sur /dev/mapper/luksmnt.
$ /sbin/mkfs.ext4 /dev/mapper/luksmnt
mke2fs 1.41.9 (22-Aug-2009)
Étiquette de système de fichiers=
Type de système d'exploitation : Linux
Taille de bloc=1024 (log=0)
Taille de fragment=1024 (log=0)
102400 i-noeuds, 408572 blocs
20428 blocs (5.00%) réservés pour le super utilisateur
Premier bloc de données=1
Nombre maximum de blocs du système de fichiers=67633152
50 groupes de blocs
8192 blocs par groupe, 8192 fragments par groupe
2048 i-noeuds par groupe
Superblocs de secours stockés sur les blocs :
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

Écriture des tables d'i-noeuds : complété
Création du journal (8192 blocs) : complété
Écriture des superblocs et de l'information de comptabilité du système de
fichiers : complété

Le système de fichiers sera automatiquement vérifié tous les 25 montages ou
après 180 jours, selon la première éventualité. Utiliser tune2fs -c ou -i
pour écraser la valeur.
Si vous souhaitez l'utiliser tel quel, n'oubliez pas de le fermer après usage avec luksClose, mais le mieux tout de même, ce serait de l'intégrer au système et de la monter automatiquement. Pour la monter automatiquement, il vous faut créer le fichier /etc/crypttab tel que :
$ cat /etc/crypttab
# <target name> <source device>         <key file>      <options>
luksmnt /dev/loop0  none    luks
Et retoucher la fstab en accord avec le crypttab, en sachant que c'est le crypttab qui sera évidemment examiné en premier :
$ cat /etc/fstab | grep luks
/dev/mapper/luksmnt /mnt/luks ext4 defaults 0 1
Le mount -a ne bronche pas et vous avez un joli :
$ mount | grep luks
/dev/mapper/luksmnt on /mnt/luks type ext4 (rw)

$ df -h /mnt/luks/
Sys. de fich.         Tail. Occ. Disp. %Occ. Monté sur
/dev/mapper/luksmnt   387M   11M  357M   3% /mnt/luks

$ ll /mnt/luks/
total 12
drwx------ 2 root root 12288 2010-07-28 15:01 lost+found/
Petit précis sur mon montage en loopback d'un fichier, pour le démonter, il suffit de lancer après le luksClose un :
$ losetup -d /dev/loop0
Mais bon, ça n'a rien à voir avec LUKS...

Conclusion

Quand on veut donner dans la parano (mais enfin, qui ne l'est pas ?), LUKS a tout ce qu'il faut là où il faut. Deux ou trois points méritent d'être soulignés au terme de ce tip :
  • LUKS se fait en amont de toute chose, il n'est pas orienté conversion de partition et encryptage à la volée. Si vous souhaitez le mettre en place, je vous conseille donc de le faire avant toute chose, et en évitant de préférence les partitions liées au boot.
  • Le niveau de sécurité de l'ensemble équivaut celui du maillon le plus faible, c'est-à-dire la passphrase. Si vous voulez jouer, mais que votre passphrase (ou celles de vos utilisateurs) est faible, le niveau de sécurité s'en ressentira.
  • LUKS utilise des ressources, donc négociez bien le tir avec les postes utilisateurs (mais bon, il est possible de le renicer).
  • LUKS n'est pas transparent, au boot, si vous avez paramétré l'automount via la fstab, un password sera demandé. Il est possible de faire en sorte que l'authentification de l'utilisateur suffise à LUKS, mais comme je vous l'ai dit, ça ne fait que rabaisser la sécurité. Si vous êtes tout de même intéréssé, visez libpam-mount.
Maintenant que tout est dit -ou presque-, je vous laisse tranquillement revoir vos plans de conquête du Monde à la hausse. ENJOY !
Vus : 2033
Publié par K-Tux : 59