Festplattenverschlüsselung unter Linux

(2008-04-03)

Linux/UNIX-kenntnisse erforderlich! (in den Bereichen Dateisystem, Konsole)

Vorab: Ja, ich weiß, dass es schon genügend Anleitungen zu dem Thema gibt, aber ich möchte es sicherheitshalber noch mal mit allen Hürden, vor die ich gestellt wurde, aufschreiben.

Inhaltsverzeichnis:

1) Das System vorbereiten

1.1) Module

Zum Verschlüsseln brauchen wir die Module (oder die fest einkompilierte Kernelunterstützung) dm_crypt, loop, blowfish (oder das entsprechende Modul des Ciphers deiner Wahl) und sha256 (oder das entsprechende Modul des Hash-Algorithmus deiner Wahl).

Diese Module werden bei den meisten aktuellen Linux-distributionen mitgeliefert, sind aber meist nicht aktiviert. Ob die Module geladen sind, sieht man in der Ausgabe von lsmod. Die fest einkompilierte Unterstützung sieht man in cat /proc/crypto. Ein Modul lädt man mit modprobe dm_crypt (beziehungsweise mit dem entsprechenden Namen des Moduls natürlich.

Der typische Ablauf sieht also so aus:

# modprobe dm_crypt
# modprobe loop
# lsmod | egrep "(^dm_crypt|^loop)"
loop                   17288  4 
dm_crypt               12424  1 

Wenn man jedoch seinen eigenen Kernel kompiliert hat und dabei die erwähnten Module außer Acht gelassen hat, kann man dies nachholen, indem man entweder im Menü von „make menuconfig” die Module auswählt, oder die Einstellungen direkt in der Datei .config bearbeiten.

Dazu wechselt man in das Verzeichnis /usr/src/linux und öffnet die Datei .config mit einem Texteditor. Nun sucht man die folgenden Einstellungen:

  • CONFIG_DM_CRYPT
  • CONFIG_CRYPTO_SHA256
  • CONFIG_CRYPTO_BLOWFISH
  • CONFIG_BLK_DEV_LOOP

Sollte bei einem der Einträge ein „=y” dahinterstehen, ist er im Kernel fix einkompiliert. Ist er auskommentiert (durch ein Raute-Zeichen am Anfang der Zeile), ist er deaktiviert. Um ihn als Modul zu kompilieren, löscht man nun das Raute-Zeichen am Anfang der Zeile und fügt ein „=m” ans Ende der Zeile an.

Durch ein make modules kann man diese Module nun kompilieren lassen.

Anschließend müssen die Module noch an den richtigen Platz gebracht werden. Hierzu benötigen wir die momentan verwendete Kernelversion, die man mit einem uname -r angezeigt bekommt. Der Pfad zu den Kernelmodulen setzt sich aus /lib/modules/ und der Kernelversion zusammen, bie mir wäre das momentan /lib/modules/2.6.15-25-386/.

Das Modul dm_crypt muss in den Modulordner kernel/drivers/md/, loop nach kernel/drivers/block/ und die Hash- und Cipher-Module müssen in kernel/drivers/crypto/:

# cp drivers/md/dm_crypt.ko /lib/modules/2.6.15-25-386/kernel/drivers/md/
# cp drivers/block/loop.ko /lib/modules/2.6.15-25-386/kernel/drivers/block/
# cp crypto/*.ko /lib/modules/2.6.15-25-386/kernel/crypto

Nun müssen wir noch depmod ausführen, damit dem System die neuen Module bekannt werden und die Abhängigkeiten generiert werden.

Jetzt laden wir die neuen Module mit modprobe dm_crypt loop sha256 blowfish. Falls das geklappt hat, lassen wir die Module beim nächsten Start automatisch laden, indem wir sie in der Datei /etc/modules verewigen. Dies kann man mit einem Texteditor oder mit dem Befehl echo -e "dm_crypt\nloop\nsha256\nblowfish" >> /etc/modules erledigen. (Die \n stehen für einen Zeilenumbruch, damit wir nur einen statt vier Befehle verwenden müssen.)

1.2) Hilfsprogramme

Da das direkte Aufrufen von dm_crypt ein bisschen kompliziert ist, hat der Autor ein Programm namens „cryptsetup” geschrieben, welches den Zugriff vereinfacht.

Außerdem gibt es das Linux Unified Key Setup, kurz LUKS, welches zum einen die Möglichkeit bietet, bis zu 8 Passwörter für ein und die selbe Partiton/Container festzulegen, und zum anderen alle nötigen Informationen im Header der selbigen speichert und damit einen Transport der Daten auf ein anderes System möglich macht.

Bei den aktuellen Debian-Versionen oder Versionen von debianbasierten Distributionen wie zum Beispiel Ubuntu ist entweder das Paket cryptsetup-luks dabei, oder es heißt nur noch cryptsetup und enthält trotzdem (siehe apt-cache show cryptsetup) die LUKS-Erweiterung.

Dieses Paket muss für diese Anleitung installiert sein.

2.) Komplette Partition verschlüsseln

Ich gehe in diesem Beispiel davon aus, dass die zu verschlüsselnde Partition /dev/hda2 heißt.

Damit eine eventulle kryptografische Analyse später so schwer wie möglich wird, beschreiben wir zuerst die komplette Festplatte mit Zufallswerten. Das geht am einfachsten mit dem Programm wipe: wipe -qk /dev/hda2. Dadurch wird es schwieriger, für die Analyse relevante Daten zu finden.

Anschließend erstellen wir mit folgendem Befehl das loopdevice:

cryptsetup -c blowfish-cbc-essiv:sha256 -y -s 256 luksFormat /dev/hda2

Wichtig ist hierbei die Angabe des essiv-Modus, der zwar erst ab Kernel 2.6.10 unterstützt wird, aber nicht – wie seine Alternative plain – gegen Watermark-Attacken anfällig ist.

Cryptsetup fordert uns nun auf, in Großbuchstaben YES einzutippen und fragt uns anschließend nach einer Passphrase:

WARNING!
========
Daten auf /dev/hda2 werden unwiderruflich überschrieben.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:

Nun hat LUKS uns einen entsprechenden (durch die eben angegebene Option -s 256 256-Bit großen Schlüssel erzeugt) Schlüssel geschrieben und den Header auf die Partition geschrieben.

Mit dem Befehl cryptsetup luksOpen /dev/hda2 daten öffnen wir die Partition nun mit dem Namen „daten” (der Name wird nur für den Devicemapper verwendet). Diesen Schritt müssen wir auch in Zukunft ausführen (ob manuell oder über ein Startscript bleibt jedem selbst überlassen), wenn wir an die Daten wollen.

Nach Eingabe der richtigen Passphrase sagt uns cryptsetup, dass alles in Ordnung ist:

# cryptsetup luksOpen /dev/hda2 daten
Enter LUKS passphrase:
key slot 0 unlocked.
Command successful.

Nun steht uns das loopdevice /dev/mapper/daten zur Verfügung, das wir wie eine ganz normale Festplatte verwenden können. Wir erzeugen uns also mit mkfs.ext3 /dev/mapper/daten ein Dateisystem, erstellen einen Mountpoint mit mkdir /mnt/daten und hängen die Festplatte dann mit mount /dev/mapper/daten /mnt/daten dort ein:

# mkfs.ext3 /dev/mapper/daten
mke2fs 1.39 (29-May-2006)
Dateisystem-Label=
OS-Typ: Linux
Blockgröße=4096 (log=2)
Fragmentgröße=4096 (log=2)
23199744 Inodes, 46397471 Blöcke
2319873 Blöcke (5.00%) reserviert für den Superuser
erster Datenblock=0
Maximum filesystem blocks=50331648
1416 Blockgruppen
32768 Blöcke pro Gruppe, 32768 Fragmente pro Gruppe
16384 Inodes pro Gruppe
Superblock-Sicherungskopien gespeichert in den Blöcken:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872

Schreibe Inode-Tabellen: erledigt
Erstelle Journal (32768 Blöcke): erledigt
Schreibe Superblöcke und Dateisystem-Accountinginformationen: erledigt

Das Dateisystem wird automatisch alle 27 Mounts bzw. alle 180 Tage überprüft,
je nachdem, was zuerst eintritt. Veränderbar mit tune2fs -c oder -t .

# mkdir /mnt/daten
# mount /dev/mapper/daten /mnt/daten

2.1) Die Partition wieder aushängen

Mit folgenden Befehlen hängt man die verschlüsselte Partition wieder aus dem Dateisystem aus und entfernt das Loopdevice:

# umount /mnt/daten
# cryptsetup luksClose daten

3.) Einen verschlüsselten Container erstellen

Ein verschlüsselter Container hat verschiedene Vorteile gegenüber einer komplett verschlüsselten Partition. Zum einen kann man dadurch die Verschlüsselung nur für bestimmte Systembenutzer aktivieren, ohne dass man gleich für jeden Benutzer eine eigene Festplatte einbauen muss. Außerdem kann man den Container auf andere Systeme transportieren, oder natürlich auch – wenn er klein genug ist – auf CD-ROM sichern.

Ein Container ist lediglich eine Datei, die dann über ein Loopdevice eingehängt wird, also genau wie vorhin…

Mit folgendem Befehl schreiben wir uns eine 5GB große Datei, in der wir private Daten wie Bilder und Dokumente ablegen könnten:

# dd if=/dev/urandom of=/home/michael/privat.crypt bs=1024 count=5242880
5242880+0 records in
5242880+0 records out

In die Datei werden also Zufallswerte aus /dev/urandom gelesen, davon 5242880 * 1024 Stück, also 5GB. In der Beispielausgabe fehlt eine Zeile, in der dd angibt, wieviel Bytes das nun waren und wielange das gedauert hat (Ich habe bei mir das System mit anderen Werten aufgesetzt…).

Vor diese Datei klemmen wir nun das Loopdevice /dev/loop0 (0-9 stehen zur Verfügung):

# losetup /dev/loop0 /home/michael/privat.crypt

Und schließlich verschlüsseln wir sie wie in Abschnitt 2:

# cryptsetup -c blowfish-cbc-essiv:sha256 -y -s 256 luksFormat /dev/loop0

WARNING!
========
Daten auf /dev/loop0 werden unwiderruflich überschrieben.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.
# cryptsetup luksOpen /dev/loop0 privat
Enter LUKS passphrase:
key slot 0 unlocked.
Command successful.
# mkfs.ext3 /dev/mapper/privat
# mkdir /home/michael/privat/
# mount /dev/mapper/privat /home/michael/privat

4.) Swapspace verschlüsseln

Hierfür müssen die Module wie unter Abschnitt erwähnt automatisch geladen werden.

Die Verschlüsselung des Swapspace ist wichtig, da dort Daten aus dem Speicher ausgelagert werden, die möglicherweise sensible Passwörter oder sonstige Daten enthalten. Wenn der Swapspace verschlüsselt ist, ist er zumindest so sicher wie ein verschlüsselter Container oder eine verschlüsselte Partition.

Da der Swapspace ohnehin einen Neustart des Systems nicht überleben muss, brauchen wir uns gar kein Passwort ausdenken, sondern benutzen dafür einfach den Zufallsgenerator /dev/urandom. Ähnlich wie in der Datei /etc/fstab kann man verschlüsselte Partitionen in der /etc/crypttab eintragen.

Nach dem Hinzufügen der Zeile für die Swappartition sieht die Datei dann so aus:

# <target name> <source device>         <key file>      <options>
swap /dev/hda3 /dev/urandom swap,cipher=twofish-cbc-essiv:sha256

Vorsicht: /dev/hda3 muss natürlich gegebenenfalls ersetzt werden. Wie die Swappartition heißt, findet man mit dem Befehl cat /etc/fstab | grep swap heraus.

In der /etc/fstab muss „/dev/hda3” durch „/dev/mapper/swap” ersetzt werden.

5.) Mögliche Fehlermeldungen

Failed to setup dm-crypt key mapping.
Check kernel for support for the blowfish-cbc-essiv:sha256 cipher spec and verify
that /dev/hda2 contains at least 258 sectors.
Failed to write to key storage.

Lösung: Eines oder mehrere der benötigten Kernelmodule wurde nicht geladen, siehe Abschnitt 1.1.