Expérimentations avec GELI (Geom Eli)

Références


Avant de vous lancer dans les manipulations proposées, il est impératif de bien avoir en tête la page de man, en particulier la section des exemples.

Fonctionnement de GELI

GELI (GEOM ELI) est un framework d'abstraction cryptographique permettant d'encrypter des partitions ou des systèmes de fichiers montés “sur une loopback” (sur un device “md”).

GELI utilise plusieurs paramètres pour protéger l'accès aux données encryptées :

  • un fichier de “clé” (données aléatoires), appelé keyfile
  • un mot de passe, appelée passphrase
  • un fichier de “clé” ET un mot de passe
  • “rien” : ni fichier de “clé” (valide), ni mot de passe

Nous verrons par la suite comment manipuler les clés pour passer d'un système de protection à l'autre mais auparavent, il faut avoir initialisé la partition (appelée provider) qu'utilisera GELI avec certains paramètres comme l'algorythme, la taille de la clé, et la taille d'un secteur.

Création d'un système de fichier de test (sur device "md")

Pour les différents essais, nous allons utiliser un système de fichier de 128Mo monté sur une “loopback” à la place d'une vraie partition de disque.

% dd if=/dev/zero of=file.md bs=1m count=128 
% mdconfig -a -t vnode -f file.md
md1

La pseudo partition ainsi créée se trouve désormais sur /dev/md1. Dans le cas d'un système de fichier standard, il serait tout à faire possible de formater /dev/md1 puis de le monter dans un répertoire pour avoir accès directement au système de fichiers de cette “image” mais ce système de fichier ne serait alors pas encrypté.

Configuration d'un provider

Il faut bien comprendre qu'il n'y a pas de moyen de modifier l'algorythme utilisé, la taille de la clé (interne) ou la taille d'un secteur après avoir initialisé un provider sans passer par des étapes de création de provider intermédiaire et de dump/restore des systèmes de fichiers cryptés.

Choisissez bien les valeurs d'initialisation dès le départ

Initialisation

Par défaut, la commande geli init sans option utilise l'algorythme AES, une taille de clé de 128 bits, une taille de secteur de 512 octets et uniquement une passphrase (pas de keyfile)

% geli init md1
Enter new passphrase: pass
Reenter new passphrase: pass
% geli attach md1
Enter passphrase: pass
% geli list
Geom name: md1.eli
Cipher: AES
KeyLength: 128
Crypto: software
UsedKey: 0
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134217216 (128M)
   Sectorsize: 512
   Mode: r0w0e0
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1

Nous utiliserons d'autres options d'initialisation :

% geli init -a aes -l 256 -s 4096 md1
Enter new passphrase: pass
Reenter new passphrase: pass
% geli attach md1
Enter passphrase:
% geli list    
Geom name: md1.eli
Cipher: AES
KeyLength: 256
Crypto: software
UsedKey: 0
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134213632 (128M)
   Sectorsize: 4096
   Mode: r0w0e0
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1

Nous disposons désormais d'un device /dev/md1.eli sur lequel nous pouvons procéder aux habituelles manipulations de partitionnement et formatage et sur lequel nous allons mettre un fichier qui servira de témoin que nos prochaines manipulations de clés préservent l'intégrité des données du volume crypté.

% newfs -U -O2 /dev/md1.eli 
/dev/md1.eli: 128.0MB (262136 sectors) block size 16384, fragment size 4096
        using 4 cylinder groups of 32.00MB, 2048 blks, 2048 inodes.
        with soft updates
super-block backups (for fsck -b #) at:
 160, 65696, 131232, 196768
% mount /dev/md1.eli /mnt
% cp /boot/kernel/pf.ko /mnt
% ls -al /mnt
-r-xr-xr-x   1 root  wheel     208550 Mar 12 08:35 pf.ko
% umount /mnt
% geli detach md1  
% mount /dev/md1 /mnt
mount: /dev/md1 on /mnt: incorrect super block
% geli attach md1
Enter passphrase: pass
% mount /dev/md1 /mnt
mount: /dev/md1: Operation not permitted
% mount /dev/md1.eli /mnt
% ls -al /mnt
-r-xr-xr-x   1 root  wheel     208550 Mar 12 08:35 pf.ko
% umount /mnt

Utilisation des clés

chaque provider peut utiliser 2 clés (key), numérotées de 0 à 1. Chaque clé (key) peut utiliser au choix :

  • un fichier keyfile seul
  • une passphrase seule
  • un fichier keyfile ET une passphrase

Le taille maximum d'un fichier keyfile est de 64 octets (voir g_eli.h)

L'utilisation d'un fichier keyfile peut paraitre inutile à première vue, surtout lorsque ce fichier est présent au même endroit que le provider (la partition à encrypter), mais j'en vois au moins deux bénéfices : - augmenter l'entropie d'une passphrase “faible” (trop courte par exemple) - augmenter la sécurité des données contenues dans le provider à partir du moment où le fichier keyfile est stocké ailleurs (sur une clé USB par exemple)

A noter que lorsque le fichier keyfile est utilisé, la destruction de ce dernier supprime l'accès aux données contenues dans le provider (hors backup).

Génération des keyfiles

% dd if=/dev/random of=md1.key0 bs=64 count=1 
% dd if=/dev/random of=md1.key1 bs=64 count=1

Manipulations des clés d'un provider

Ajout d'un keyfile sans passphrase

(provider précédemment attaché)

% geli setkey -n 1 -K md1.key1 -P md1  
% geli detach md1
% geli geli attach -k md1.key1 -p md1
% mount /dev/md1.eli /mnt
% ls -al /mnt
-r-xr-xr-x   1 root  wheel     208550 Mar 12 08:35 pf.ko
% geli list
Geom name: md1.eli
Cipher: AES
KeyLength: 256
Crypto: software
UsedKey: 1
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134213632 (128M)
   Sectorsize: 4096
   Mode: r1w1e1
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1  

Donc pour l'instant, nous avons pour le provider md1 :

  • key 0 : passphrase “pass”
  • key 1 : keyfile md1.key1 (sans passphrase)

Cela signifie que quelqu'un en possession du fichier keyfile md1.key1, du fichier image “file.md”, d'un FreeBSD peut tout à fait accéder aux données présentent sur le provider md1.

Par défaut, la commande geli attach demande une passphrase

% umount /mnt
% geli detach md1
% geli attach -k md1.key1 md1
Enter passphrase: pass ou <entrée>
Wrong key for md1.

Il faut donc que celui qui manipule le provider sache exactement si un fichier keyfile ou une passphrase sont utilisés sinon cela génère une erreur de clé et il faut donc tester plusieures combinaisons de keyfile et passphrase en aveugle pour tenter d'avoir accès au contenu du provider.

Ajout d'une passphrase

On l'a vu, la clé numéro 1 (key 1) comporte uniquement un fichier keyfile sans passphrase, nous alons donc lui ajouter une passphrase.

On vérifie si le provider est attaché (pour la forme, les manipulations de clés sont identiques que le provider soit attaché ou non)

% geli list
(rien)

On positionne une passphrase à la clé numéro 1 (key 1) tout en continuant à utiliser le fichier keyfile md1.key1

% geli setkey -n 1 -k md1.key1 -K md1.key1 -p md1
Enter new passphrase: pass1
Reenter new passphrase: pass1

Si on ne spéficie pas le flag “-K” (“new key”) alors la clé numéro 1 passe d'une protection par keyfile à une protection par passphrase SANS keyfile (passphrase only) alors que nous voulons une protection par keyfile ET passphrase.

On vérifie si l'ancien accès sans passphrase fonctionne encore

% geli attach -k md1.key1 -p md1
Wrong key for md1. 

Avec la passphrase cette fois ci

% geli attach -k md1.key1 md1
Enter passphrase: pass1
% geli list
Geom name: md1.eli
Cipher: AES
KeyLength: 256
Crypto: software
UsedKey: 1
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134213632 (128M)
   Sectorsize: 4096
   Mode: r0w0e0
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1

Vérification du contenu du provider :

% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko

“Nettoyage”

% umount /mnt
% geli detach md1
Changer une passphrase

Actuellement, le provider md1 utilise :

  • key 0 : passphrase “pass”
  • key 1 : keyfile md1.ky1 et passphrase “pass1”

Nous allons procéder au changement de passphrase de la clé numéro 0

% geli setkey -n 0 md1
Enter passphrase: pass
Enter new passphrase: pass0
Reenter new passphrase: pass0
% geli attach md1
Enter passphrase: pass0
% geli list
Geom name: md1.eli
Cipher: AES
KeyLength: 256
Crypto: software
UsedKey: 0
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134213632 (128M)
   Sectorsize: 4096
   Mode: r0w0e0
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko 
Supprimer une clé
% umount /mnt
% geli detach md1
% geli delkey -n 1 md1
(pas de confirmation)

On vérifie si on a encore accès au provider avec la clé numéro 1 (key 1) qui utilisait le keyfile md1.key1 et la passphrase pass1

% geli attach -k md1.key1 md1
Enter passphrase: pass1
Wrong key for md1. 
"feature"

En trichant un peu, il est possible de ne pas utiliser de fichier de clé keyfile ni de passphrase. Biensûr, cette configuration ne doit pas être utilisée dans la réalité.

% geli setkey -n 1 -K /dev/null -P md1
Enter passphrase: pass
% geli attach -k /dev/null -p md1
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko  

Backup/Restore des metadatas

Une chose importante avec GELI, est qu'il est possible de backuper les métadatas d'un provider ou de les restorer.

% geli backup md1 md1.backup

Le fichier contenant les métadatas doit bien évidemment être mis en sécurité, à un autre endroit que là où est utilisé le provider

Suite aux commandes exécutées ci-dessus, le provider md1 utilise les clés suivantes :

  • key 0 : passphrase “pass0”
  • key 1 : aucune clé

Le fichier “md1.backup” contient donc ces métadatas ci et le provider md1 n'utilise aucun fichier de clé keyfile.

Générons un nouveau fichier keyfile et changeons la passphrase de la clé numéro 0 (key 0)

% dd if=/dev/random of=md1.newkey0 bs=64 count=1
% geli setkey -n 0 -K md1.newkey0 md1
Enter passphrase: pass0
Enter new passphrase: newpass0
Reenter new passphrase: newpass0

On vérifie qu'on n'accède plus au contenu du provider md1 avec l'ancienne passphrase

% geli attach md1
Enter passphrase: pass0
Wrong key for md1. 

et qu'on y accède bien avec le nouveau fichier keyfile et la nouvelle passphrase

% geli attach -k md1.newkey0 md1
Enter passphrase: newpass0
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko 
% umount /mnt
% geli detach md1

On backup les nouvelles métadatas du provider md1

% geli backup md1 md1.newbackup

On remet les anciennes métadatas et normalement, on ne devrait plus pouvoir utiliser la nouvelle clé numéro 0 mais l'ancienne.

% geli restore md1.backup md1 
% geli attach -k md1.newkey0 md1
Enter passphrase: newpass0
Wrong key for md1.
% geli attach md1
Enter passphrase: newpass0
Wrong key for md1.
% geli attach md1
Enter passphrase: pass0
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko 
% umount /mnt
% geli detach md1




IMPORTANT : qu'implique très exactement la possibilité de restorer des métadatas pour un provider GELI ?

  • la possibilité de détruire rapidement l'accès au contenu du provider et d'en retrouver ultérieurement les données en restorant les métadatas (à condition d'avoir encore l'ensemble des éléments constituant la clé comme le fichier keyfile et la passphrase)
  • la possibilité de générer une clé initiale (comportant keyfile et/ou passphrase) qui servira à faire du “recovery” dans le cas où l'utilisateur détruit son keyfile ou oublie sa passphrase

Supprimer l'accès à un provider

Il peut arriver qu'on ai besoin de détruire l'accès à un provider, ce qui peut se faire en supprimant le fichier keyfile mais garde un accès au provider dans le cas où une des clés utilise une passphrase.

Il y a une commande beaucoup plus efficace et rapide, à utiliser dans les situations d'urgence

% geli kill md1
(aucune confirmation)

La commande geli kill supprime toutes les clés du provider et détache le provider si celui-ci était attaché.

ATTENTION : l'utilisation de la commande geli kill alors que le provider était encore monté a provoqué un reboot de la machine de tests ; les métadatas ont correctement été détruites.
Il va donc être important de vérifier le comportement de cette commande sur une vraie partition.


Même avec la passphrase ou le fichier keyfile il est désormais impossible d'accéder au contenu du provider

% geli attach md1
Cannot read metadata from md1: Invalid argument.
% geli attach -k md1.newkey0 md1
Cannot read metadata from md1: Invalid argument.

Vérification de la restoration après une commande geli kill ; tout à l'heure nous avons utilisé les métadatas de la première clé (dont la passphrase est pass0), là nous restorons les métadatas de la nouvelle clé comportant le keyfile md1.newkey0 et la passphrase newpass0

% geli restore md1.newbackup md1
% geli attach -k md1.newkey0 md1
Enter passphrase: newpass0
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko

Se créer un accès de "sécurité" à un provider

En tant qu'admin, il est tout à fait possible de se prémunir contre la suppression d'un fichier de clé (keyfile) ou l'oubli de sa passphrase par un utilisateur. Soit en utilisant une des deux clés du provider, mais il serait encore possible à l'utilisateur en question de supprimer votre clé

Soit en ayant vos propres métadatas indépendamment de celles de l'utilisateur pour un même provider. C'est l'idée derrière l'exemple de la page de man.

Restorons les métadatas utilisant le fichier de clé (keyfile) md1.newkey0 et la passphrase associée newpass0

% geli restore md1.newbackup md1
% geli attach -k md1.newkey0 md1
Enter passphrase: newpass0
% geli list
Geom name: md1.eli
Cipher: AES
KeyLength: 256
Crypto: software
UsedKey: 0
Flags: NONE
Providers:
1. Name: md1.eli
   Mediasize: 134213632 (128M)
   Sectorsize: 4096
   Mode: r0w0e0
Consumers:
1. Name: md1
   Mediasize: 134217728 (128M)
   Sectorsize: 512
   Mode: r1w1e1
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko
% umount /mnt

Mettons en place des métadatas destinés à l'entité “IT” pour les utilisateurs étourdis :

On sauvegarde les métadatas de l'utilisateur (il n'a pas encore oublié sa passphrase et on aura besoin des métadatas pour lui remettre ses accès aux données contenues dans son provider)

& geli backup md1 md1.backup_user

Pour le moment, le provider contient une clé (key 0) qui utilise le keyfile md1.newkey0 et la passphrase newpass0.

On créé le keyfile md1.keyIT et on l'utilise sans passphrase pour la clé numéro 0 (key 0), et on détruit la clé numéro 1 (key 1) si elle existe.

% dd if=/dev/random of=md1.keyIT bs=64 count=1
% geli setkey -n 0 -K md1.keyIT -P md1
% geli delkey -n 1 md1
Master Key 1 is not set.

On backup les métadatas “IT”

% geli backup md1 md1.backupIT

Et on vérifie qu'on a bien accès aux données du provider avec les métadatas “IT” via le fichier de clé (keyfile) sans passphrase.

% geli detach md1
% geli attach -k md1.keyIT -p  md1 
% mount /dev/md1.eli /mnt
% ls -al /mnt/pf.ko 
-r-xr-xr-x  1 root  wheel  208550 Mar 12 08:35 /mnt/pf.ko
% /umount

Il ne reste plus qu'à remettre les métadatas “utilisateur”

% geli detach md1
% geli restore md1.backup_user md1

Dans le cadre d'une utilisation toute légitime par l'équipe “IT”, il est bien évident que le fichier de clé (keyfile) md1.keyIT ne doit pas être laissé au même endroit que le provider mais être conservé en lieu sûr, voir être encrypté avec une clé GnuPG.

On constate aussi qu'il ne faut que quelques manipulations à un intru pour se créer une clé de secours (keyfile + backup des métadatas) dès qu'il a accès en root à la machine de l'utilisateur et que le provider est attaché.
Si on a un doute quant à la sécurité de ses données, changer de keyfile ou de passphrase ne change rien puisque l'intru à ses propres métadatas et n'a donc pas besoin des votres pour accéder à vos données.
Le seul moyen dans ce cas là est de créer un autre provider temporaire (geli init) et d'y transférer vos données.

Dump / Restore d'un provider

Une fois le provider attaché, il est tout à fait possible d'utiliser les commandes dump/restore classique (pour ses backups, déplacer les données, …)

Bien évidemment, les données ne sont pas encryptées dans le dump.

% dump -0 -f md1.dump /dev/md1.eli 
  DUMP: WARNING: should use -L when dumping live read-write filesystems!
  DUMP: Date of this level 0 dump: Sun Mar 12 14:43:49 2006
  DUMP: Date of last level 0 dump: the epoch
  DUMP: Dumping /dev/md1.eli to md1.dump
  DUMP: mapping (Pass I) [regular files]
  DUMP: mapping (Pass II) [directories]
  DUMP: estimated 227 tape blocks on 0.01 tape(s).
  DUMP: dumping (Pass III) [directories]
  DUMP: dumping (Pass IV) [regular files]
  DUMP: DUMP: 231 tape blocks on 1 volume
  DUMP: finished in less than a second
  DUMP: Closing md1.dump
  DUMP: DUMP IS DONE

En revanche, ces commandes n'ont aucun effet sur la partition non attachée puisqu'elles cherchent un système de fichier qui ne s'y trouve pas.

% dump -0 -f md1.dump /dev/md1     
  DUMP: Date of this level 0 dump: Sun Mar 12 14:44:00 2006
  DUMP: Date of last level 0 dump: the epoch
  DUMP: Dumping /dev/md1 to md1.dump
  DUMP: Cannot find file system superblock
  DUMP: The ENTIRE dump is aborted. 

Configuration d'un système

Nous avons vu comment manipuler des volumes “geli”, des keyfiles, des passphrases et des métadatas manuellement en ligne de commande.
Passons maintenant à la mise en pratique de GELI en condition réelle, c'est à dire en utilisant les fichiers de configuration et des scripts du système.

Configuration d'une partition de swap encryptée

Comme nous allons travailler sur un système déjà installé, celui-ci a certainement une partition de swap activée :

% swapinfo
Device          1K-blocks     Used    Avail Capacity
/dev/da0b          525384        0   525384     0%

(note: pas d'inquiétude à avoir, il s'agit une Sun, et il n'y a pas de slices sur cette architecture)

FreeBSD mixer.xxx.xxx 6.1-PRERELEASE FreeBSD 6.1-PRERELEASE #9: Sun Feb 19 23:06:19 UTC 2006 root@mixer.xxx.xxx:/usr/obj/usr/src/sys/MIXER  sparc64

On désactive le swap

% swapoff /dev/da0b
% swapinfo 
Device          1K-blocks     Used    Avail Capacity 

Par défaut, les options de configuration d'une partition de swap encrpytée sont les suivantes (dans le fichier /etc/defaults/rc.conf) :

geli_swap_flags="-a aes -l 256 -s 4096 -d"      # Options for GELI-encrypted
                                                # swap partitions.  

On modifie le fichier /etc/fstab pour que la partition fasse référence à la partition encryptée

# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/da0b.eli           none            swap    sw              0       0    

On lance les différents scripts

% /etc/rc.d/ecnswap start
$ ls -al /dev/da0b*
crw-r-----  1 root  operator    0, 103 Feb 20 09:02 /dev/da0b
crw-r-----  1 root  operator    0, 114 Feb 20 09:02 /dev/da0b.eli     
% /etc/rc.d/swap1 start
swapon: adding /dev/da0b.eli as swap device 
% swapinfo 
Device          1K-blocks     Used    Avail Capacity
/dev/da0b.eli      525384        0   525384     0%   
% geli status
    Name  Status  Components
da0b.eli     N/A  da0b 

Voilà notre partition de swap qui est encryptée via GELI.

Configuration d'une partition encryptée

On va utiliser une partition existante “twed0s1d”

Initialisation du volume crypté

% geli init -a aes -l 256 twed0s1d
Enter new passphrase: pass
Reenter new passphrase: pass

Edition du fichier /etc/fstab

# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/twed0s1            /mnt            ufs     rw              2       2  

devient

# Device                Mountpoint      FStype  Options         Dump    Pass#
/dev/twed0s1d.eli       /mnt            ufs     rw              2       2  

Et ajout des informations correspondantes dans le fichier /etc/rc.conf

geli_devices="twed0s1d"
geli_twed0s1d_flags=""      

Si on défini la variable geli_twed0s1d_flags avec le paramètre '-p', la passphrase n'est pas demandée, il faut alors spécifier l'usage d'un fichier de clé (keyfile) avec le paramètre '-k' et son chemin complet.

On vérifie avec le script de démarrage

% /etc/rc.d/geli start
Configuring Disk Encryption for twed0s1d.
Enter passphrase: pass
% mount
/dev/twed0s1d.eli on /mnt (ufs, local, soft-updates)

(la partition encryptée a bien évidemment été formatée entre temps)

A noter une chose importante : au moment du boot, le clavier est encore en qwerty US, donc si vous voulez utiliser un autre layout de clavier pour taper votre passphrase, vous êtes encouragé à le configurer dans le kernel en suivant ce tip.

Changelog

  • 2006/03/21 Postée sur le wiki GCU
  • 2006/03/12 Version Initiale – /SClo <sclo(at)teaser.fr>
freebsd/geli.txt · Last modified: 2010/01/12 13:29 (external edit)