Linux Betriebssystem verschlüsseln + USB Keystick

Linux Betriebssystem verschlüsseln + USB Keystick
Photo by Markus Winkler / Unsplash

In dieser Kurzanleitung wird ein weiterer Schlüssel zu einem existierenden Luks-Volume hinzugefügt.
Der neue Schlüssel wird versteckt auf einem USB Stick abgelegt und das Betriebssystem so konfiguriert, dass es an der entsprechenden Stelle sucht und den Schlüssel zum Öffnen verwendet.

Wichtig zu wissen ist, sofern die /boot Partition nicht verschlüsselt ist, die Position des Schlüssels ausgelesen werden kann, da diese in der grub.cfg und ggf. im Init-RamFS liegt, sofern man in der Crypttab weitere Dateisysteme mit dem USB-Stick öffnen möchte.

Möchte man dies auch umgehen, ist die Verschlüsselung der /boot Partition nötig und eine Eingabe des Kennworts im Bootloader (z.B. Grub) nötig.
Dieses Szenario ist aber nicht Bestandteil dieser Anleitung, kann aber genau so konfiguriert werden.
Die Passwort-Eingabe im Bootload öffnet /boot und / und ggf. weitere Volumes werden dann über den USB-Stick-Schlüssel geöffnet.

Die Anleitung ist vornehmloch für Debian / Ubuntu und Archlinux geeignet. Es wird davon ausgegangen, dass der USB-Stick als sdc erkannt wurde und das verschlüsselte Volume sda2 ist.

Alle Operationen wurden mit Root-Rechten ausgeführt.

Partitionierung anlegen

Es wird eine Partitionstabelle und eine Partition angelegt und mit NTFS formatiert. Dies kann hilfreich sein, damit Dritte, wenn Sie den USB-Stick irgendwo anschließen, ggf. ein Dateisystem angezeigt bekommen und keinen Verdacht schöpfen.
Hierbei muss persönlich abgewogen werden, ob man das Dateisystem vorher noch mit Daten vollschreibt, oder den -f Parameter deaktiviert um das gesamte Dateisystem zu initalisieren. Je nach Tiefe einer USB-Stick Analyse könnte der Key so ermittelt werden.

# Partitionstabelle anlegen um eine Partition mit Fake Dateisystem zu erzeugen
parted -s /dev/sdc mklabel msdos

# Partition anlegen
parted -s /dev/sdc mkpart primary 1m 100%free

# NTFS Dateisystem erzeugen (kann aber auch jedes andere FS sein!)
# -f aktiviert den Schnellmodus
mkfs.ntfs -f /dev/sdc1

# UUID der Partition (PARTUUID) auslesen (wird später benötigt!)
# blkid  | grep sdc
/dev/sdc1: BLOCK_SIZE="512" UUID="xxxxxxxxxxxxxxxx" TYPE="ntfs" PARTUUID="xxxxxxxx-01"

Schlüssel erzeugen und auf USB-Stick schreiben

Der Schlüssel wird in diesem Beispiel 4096 Bit groß und in die Datei /root/keyfile geschrieben.
Der dd Befehl liest einen Block von 4906 Bytes aus der Datei /dev/random und schreibt diesen in das Keyfile.

Danach wird mit dd das Keyfile gelesen und an eine beliebige Stelle der Partition geschrieben. Hierbei ist die Blocksize wieder 4096, aber mittels seek wird bestimmt, wie viele Blocksizes übersprungen werden sollen. In diesem Beispiel sind es 1234 * 4096 Bytes, bedeutet es wird ab der Position (4194304. Byte geschrieben. - 4194304 / 1024 (Byte/KiByte)/ 1024 (KiByte / MiByte) / 1024 (MiByte / GiByte) - wodurch der Stick mindestens 4 GiByte groß sein muss ...). Bei einem kleineren USB Stick kann auch ein Wert wie 7 verwendet werden.

Die Verschiebung (Offset) ist aber im späteren Verlauf wichtig.  

# neuen Schlüssel erzeugen erzeugen
dd if=/dev/random  of=/root/keyfile bs=4096 count=1

# Keyfile auf Partition schreiben
dd of=/dev/sdc1 bs=4096 seek=1234 if=/root/keyfile

Key zum Volume hinzufügen + Key-Stick konfigurieren

Es wird angenommen, dass /dev/sda2 die verschlüsselte Systempartition ist. Diese kann je nach lokaler Konfiguration (HDD,SSD, NVME, RAID, LVM, ...) abweichen!

Unbedingt auf die korrekten Werte beim skip achten, der dem seek Wert beim Schreiben auf den USB-Stick entspricht.

# aktuelle Slotbelegung ausgeben
cryptsetup luksDump /dev/sda2

# Keyfile als Schlüssel hinzufügen
cryptsetup luksAddKey /dev/sda2 /root/keyfile

# erneut Slotbelegung ausgeben und ermitteln, welcher dazu gekommen ist
cryptsetup luksDump /dev/sda2


# testen des Keys (ermittelter Slot, z.B. 5)
cryptsetup luksOpen --test-passphrase --key-slot 5 /dev/sda2 -d <(dd if=/dev/sdc1 bs=4096 count=1 skip=1234)


# UUID der Partition prüfen, diese wurde bereits am Anfang der Anleitung ermittelt. Nun wird noch mal geprüft ob diese stimmt:

ls -hla /dev/disk/by-partuuid/xxxxxxxx-01
lrwxrwxrwx 1 root root 10 16. Nov 22:57 /dev/disk/by-partuuid/xxxxxxxx-01 -> ../../sdc1


# Grub konfigurieren, der Syntax ist wie folgt:
# cryptkey=$PFAD_ZUR_PARTITION$:$SEEK_BYTES:$KEYSIZE
# Die SEEK_BYTES = seek * key_size (z.B. 1234 * 4096 = 
/etc/default/grub
cryptkey=/dev/disk/by-partuuid/xxxxxxxx-01:4194304:4096

# Grub-Config neu generieren
# Archlinux
grub-mkconfig -o /boot/grub/grub.cfg
# Debian / Ubuntu
update-grub

# (optional falls Crypttab genutzt wird)
NAME      UUID=DISK_UUID   /dev/disk/by-partuuid/xxxxxxxx-01   luks,tries=3,keyfile-size=4096,keyfile-offset=4194304

# Initramfs neu bauen
# Archlinux (-p linux oder -p linux-lts, je nachdem welches Paket installiert ist)
mkinitcpio -p linux
# Ubuntu
update-initramfs -k all -u

Danach kann man bei Bedarf noch den Schlüssel löschen und andere Slots aufräumen, wenn ein Boot mit USB-Stick funktioniert hat:

# X steht für den Slot der gelöscht werden soll
cryptsetup luksKillSlot /dev/sda2 X

rm /root/keyfile

Referenzen

Archlinux Wiki
https://wiki.archlinux.org/title/dm-crypt/Device_encryption
https://wiki.archlinux.org/title/dm-crypt/Encrypting_an_entire_system