dm-crypt/Luks – Begriffe, Funktionsweise und die Rolle des Hash-Verfahrens – I

Die DSGVO zwingt Freelancer, sich stärker als zuvor mit der Sicherung von Daten, die im Rahmen von Kundenprojekten auf eigenen Systemen anfallen, zu befassen. Das beinhaltet dann u.a. Sicherungsmaßnahmen für den Verlust/Diebstahl von Laptops. Unter anderen Vorzeichen gilt das Gleiche übrigens auch für Server und PCs eines Home-Office. Man wird dann zum Schluss kommen, dass man eine Teil- oder Vollverschlüsselung seines Storage-Unterbaus vornehmen muss. Unter Linux liegt es nahe, dafür das Duo dm-crypt/LUKS einzusetzen. Recherchiert man im Internet zu diesem Toolset, so stößt man immer wieder auf Fragen zu grundsätzlichen Verfahren, die zum Einsatz gebracht werden. Leider sind die Antworten aus meine Sicht nicht immer so klar, wie man sich das wünschen würde. Gräbt man tiefer, landet man schnell bei relativ komplexen Darstellungen.

Im Rahmen von LUKS kommen u.a. auch Passphrase-Hashes zum Einsatz. Ich selbst bin anfänglich u.a. darüber gestolpert, dass dafür (angeblich) SHA1 herangezogen wird. Bei “SHA1” läuten automatisch ein paar Alarmglocken. Jemand, der mal mit “JtR” oder “hashcat” gearbeitet hat, wird ggf. auch beunruhigt durch Artikel wie
https://articles.forensicfocus.com/2018/02/22/bruteforcing-linux-full-disk-encryption-luks-with-hashcat/
https://dfir.science/2014/08/how-to-brute-forcing-password-cracking.html

Sind diese Sorgen berechtigt? Nein, ein wenig mehr Beschäftigung mit dem LUKS-Verfahren relativiert solche Ängste beträchtlich. Aus Diskussionen weiß, dass das Thema auch andere Linux-Freunde interessiert. Ich möchte in diesem Beitrag deshalb auf einige wichtige Ingredienzen und grundlegende Verfahren von LUKS eingehen – so wie ich sie sehe. Als Beleg werde ich Links zu weiterführender Literatur angeben und auch ein paar kompakte Zitate zu LUKS-internen Verfahrensschritten. Erst auf dieser Grundlage lässt sich dann der Einsatz von Hash-Verfahren vernünftig diskutieren.

Die praktische Anwendung und konkrete dm-crypt/LUKS-Kommandos für die (Voll-) Verschlüsselung eines Laptops behandle ich in einer späteren Serie von Posts.

Ein paar grundlegende Ingredienzen von dm-crypt/Luks

dm-crypt kann unabhängig von LUKS eingesetzt werden. Die Kombination mit LUKS (“Linux unified Key Setup”) bietet aber erhebliche Vorteile. Ich will auf ein alleinstehendes dm-crypt hier nicht eingehen; im Kontext dieses Artikels kann man dm-crypt als ein Wrapper-Verfahren für LUKS verstehen. dm-crypt bietet in diesem Sinne ein User-Interface um LUKS-verschlüsselte Storage Devices zu erstellen und zu benutzen. LUKS liegt übrigens in zwei Varianten vor: LUKS1 und LUKS2. Die Unterschiede werden im nächsten Post bedeutsamer als in dieser Einführung. Mit Hilfe von LUKS kann man Storage-Devices verschlüsseln. Das können z.B. Partitioen oder LVM-Volumes auf einer HDD oder SSD sein. Möglich ist aber auch die Verschlüsselung von datei-basierten Loop-Devices als Krypto-Container.

Unter LUKS kommen mehrere Schlüssel zum Einsatz, die sorgfältig zu unterscheiden sind:

Master-Key
Für die Ver- und Entschlüsselung der “Daten” eines mit LUKS-Storage-Devices [LSD] wird ein sog. “Master-Key” verwendet. Der kommt in einem symmetrischen Verschlüsselungsverfahren [SEA; “Symmetric Encryption Algorithm”] zum Einsatz; das SEA-Verfahren kann der User beim Einrichten eines LUKS-Devices aus einer vorgegebenen Menge an Verfahren wählen. Festlegen kann er dabei auch die Länge des Master-Keys – z.B. 256 Bit. Der Master-Key wird im Rahmen eines Initialisierungsverfahrens für ein LUKS-Device zufällig in der vorgegebener Länge erzeugt. Der Kernel muss diesen Master-Key später in der Interaktion mit dem Storage-System benutzen –
also muss der Master-Key dem Kernel beim oder nach dem Booten des Systems auf Basis vorhandener Information bereitgestellt werden. Darauf kommen wir unten zurück; es ist aber wohl klar, dass der Master-Key nicht im Klartext auf der Platte hinterlegt werden kann.

Password-Based Key
Eine grundlegende Idee (nicht nur in LUKS) ist es, den Master-Key selbst verschlüsselt an definierten Orten im Storage-System zu hinterlegen. Dazu benötigt man wiederum ein sicheres Verschlüsselungsverfahren; LUKS zieht dazu das gleiche SEA-Verfahren heran, das es zur Daten-Verschlüsselung selbst verwendet. Um den Master-Key zu verschlüsseln, braucht man aber auch einen von ihm unabhängigen Schlüssel – ich nenne einen solchen Key in diesem Beitrag zur Unterscheidung vom Master-Key mal “PB-Key“.
Bitte beachtet: PB-Key ist kein offizieller Begriff aus dem LUKS Wortschatz. Ich verwende den Begriff hier im Blog zur deutlichen Unterscheidung von anderen Keys.

Ein PB-Key wird unter LUKS mit Hilfe eines komplexen Verfahrens [PBKDF] auf Basis einer Passphrase, die der User zum Öffnen des Krypto-Devices angeben muss, berechnet. “PB” steht in unseren Abkürzungen für “passphrase-basiert”; PB-KDF für “password-based key derivation function”. Ein PBKDF-Verfahren erzeugt aus einem Passwort oder einer beliebig langen Passphrase einen PB-Key definierter Länge. Aus dieser Anforderung wird klar, dass ein PBKDF Hash-Verfahren einsetzen muss. (Dabei wird neben der Passphrase typischerweise auch ein definierter Salt-String eingesetzt, der den Passphrase-String ergänzt.)

Ein PB-Key selbst braucht nicht im System hinterlegt zu werden; er lässt sich ja jederzeit mit Hilfe des PBKDF aus der Passphrase berechnen. Der PB-Key findet sich bei LUKS deshalb nirgends auf der Platte und auch im RAM nur zwischenzeitlich. LUKS in der Version 1 (LUKS1) nutzt zur Berechnung des PB-Keys aus der Passphrase konkret das wohldefinierte KDF-Verfahren “PBKDF2”; hierzu mehr im nächsten Post. Luks2 verwendet hingegen “Argon2i”. Siehe dazu die unten angegebenen Links. Wie bringt man nun eine Passphrase über den berechneten PB-Key mit dem Master-Key zusammen?

Hinterlegung des Master-Keys in verschlüsselter Form
Mit Hilfe des SEA und eines PB-Keys kann man den Master-Key verschlüsseln und später auch wieder entschlüsseln. Man behandelt den Master-Key quasi als eine mit dem SEA zu verschlüsselnde Information. Als Schlüssel wird dabei der berechnete PB-Key verwendet.
In verschlüsselter Form kann der Master-Key (mit ein paar weiteren Vorsichtsmaßnahmen) schließlich sogar auf dem Storage-Device hinterlegt werden. Als weitere Sicherungsmaßnahme wird der Master-Key dazu in sog. “Stripes” unterteilt – die danach in ihrer Größe auch noch künstlich künstlich aufgeblasen werden. Die verschlüsselten Master-Key-Stripes liegen verteilt in einem Informationsbereich des Storage Devices, den man auch “Key Material Section” nennt. Seine Position bestimmt sich aus einem Offset-Wert. Die Funktion, die LUKS zur Erzeugung der “Stripes” einsetzt, heißt übrigens “AFsplitter”; die dazu inverse Funktion “AFmerge”.

Master-Key Digestm
LUKS nutzt das PBKDF übrigens auch dazu, einen Prüfstring – “MK-Digest” – für den Master-Key zu berechnen – und im Storage-System zu hinterlegen. Diese Information wird neben anderen in einem sog. “Partition Header” (s.u.) hinterlegt.

Key-Slots
Kann es mehrere PB-Keys geben? Ja, das kann es. In LUKS gibt es sogar die Möglichkeit, bis zu 8 Passphrases zu definieren, mit denen der Master-Key ver- und entschlüsselt werden kann. Dementsprechend gibt es auch bis zu 8 verschiedenen Varianten des in Stripes unterteilten und mit verschiedenen PB-Keys verschlüsselten Master-Keys. Sprich: Es gibt bis zu 8 “Key Material Sections” [KMS], die in einem definierten Bereich vor den verschlüsselten Nutzdaten im Storage-Bereich hinterlegt
werden.

Man spricht in diesem Zusammenhang aber auch von bis zu 8 möglichen “Key-Slots” [KSL]: Ein Key-Slot fasst alle Informationen zusammen, die man neben der (vom User) zugelieferten Passphrase benötigt, um den Master-Key zu entschlüsseln. Zu diesen Informationen gehört neben der Anzahl der Stripes u.a. auch die Offset-Information bzgl. der zugehörigen “Key Material Section” sowie ein 256-Bit langer SALT-String, der bei der Erzeugung des PB-Keys mittels des PBKDF verwendet wird. Ein Key-Slot kann aktiv oder inaktiv sein. dm-crypt stellt Kommandos und Verfahren zu Verfügung, die die Anlage und Pflege von LUKS Key-Slots erlauben. Technisch ist ein Key-Slot ein bestimmter Speicherbereich mit Feldern definierter Länge. Auch die 8 Key Slots sind ein Teil des sog. Partition Headers; s.u..

2 Ebenen der Verschlüsselung
LUKS arbeitet also mit 2 Ebenen der Verschlüsselung:

  • Ebene 1: Ver- und Entschlüsselung des Master-Keys auf Basis einer Passphrase (Verfahren: PBKDF + SEA).
  • Ebene 2: Ver- und Entschlüsselung von Daten durch den Kernel mit Hilfe des (entschlüsselten) Master-Keys (Verfahren: SEA).

Partition Header
Ich hatte oben bereits mehrfach von “hinterlegten” Informationen gesprochen. Damit meine ich tatsächlich “Hinterlegung” an einem speziellen Ort auf dem HDD- oder SSD-Device. Die Information bezieht sich dabei auf eine Partition oder ein LVM-Volume, das mit LUKS verschlüsselt wird. LUKS hinterlegt alle wichtigen Infos, die es benötigt, in einem sogenannten “Partition Header” [PHDR] am Anfang eines mit LUKS verschlüsselten Storage-Devices (Partition, LVM-Volume) hinterlegt. Der PHDR umfasst neben grundlegenden Angaben zu den Verschlüsselungsverfahren auch den wichtigen MK-Digest (s.o.). Hinzu kommen alle Key-Slot Informationen – u.a. mit Salts und Offsets-Informationen zu den “Key Material Sections”. An den PHDR schließen sich übrigens die Bereiche an, die die 8 Key Material Sections in definierter Weise darstellen. Ein aktiver Slot zieht die Ablage verschlüsselter Master-Key Daten im zugehörigen KMS nach sich.

Der PHDR benötigt zur Aufnahme seiner Daten natürlich zusätzlichen Platz neben dem Filesystem eines LUKS-Devices – wir sprechen hier über ca. 2 MByte. Das ist wichtig, wenn man aus dem Backup eines Klartext-Volumes mal ein LUKS-Volume erzeugen will – der benötigte Platz der LUKS-Volumes ist etwas größer zu wählen als der vom Klartext-Backup eingenommene Platz!

Grundlegende Abläufe beim Öffnen von LUKS-Devices

Nehmen wir an, wir haben in einem Initialisierungsverfahren für ein Luks-Storage-Device [LSD] den Master-Key erzeugt, ihn mit Hilfe eines PB-Keys und zugehöriger Passphrase verschlüsselt und die verschlüsselte Key Information in der ersten KMS [KMS1] hinterlegt, die dem (ersten) Key-Slot [KSL1] für die Passphrase zugeordnet ist. Später haben wir dann mit dm-crypt den Master-Key sogar nochmals mit Hilfe einer anderen Passphrase verschlüsselt und über einen zweiten Slot [KSL2] bzw. zugehörige KMS2 hinterlegt. Was passiert nun, wenn man als User auf das LUKS-Device zugreifen will? Man spricht auch vom “Öffnen” des LSD. Folgende grundlegende Schritte laufen dabei ab:

  • Schritt 1 – Abfrage der Passphrase: Ein bestimmter manueller Aufruf von dm-crypt/LUKS oder ein darauf zurückgreifendes Verfahren (z.B. ein Boot-Manager) fragt unsere Passphrase ab.
  • Schritt 2 – Berechnen der PB-Keys: Auf Basis der Passphrase berechnet das PBKDF-Verfahren den zugehörigen PB-Key.
  • Schritt 3 – Anwendung des PB-Keys auf alles Slots: Mit Hilfe des SEA-Verfahrens wird die verschlüsselte Information zum Master-Key jedes Slots versuchsweise in einen potentiellen “Master-Key-Kandidaten” [MKK] umgewandelt. (Die Unterteilung der hinterlegten Master-Key-Information in Stripes wird dabei natürlich
    berücksichtigt und rückgängig gemacht.)
  • Schritt 4 – Ermittlung des MK-Digests für alle Slots: Über das PBKDF wird aus den MKKs der aktiven Slots ein zugehöriger MK-Digest berechnet und mit dem im PHDR hinterlegten MK-Digest verglichen.
  • Schritt 5 – Festlegen des Master-Keys: Der MKK desjenigen Slots, der den richtigen MK-Digest aufweist, wird als Master-Key festgelegt und an den Kernel übergeben.
  • Schritt 6 – Nutzen des Master-Keys durch den Kernel: Der Kernel nutzt den ermittelten Master-Key dann zur weiteren Ent-/Ver-Schlüsselung von Daten in der Interaktion mit dem LUKS-Device. Bis das Luks-Device wieder geschlossen wird.

Literatur und Zitate

Wo kann der/die interessierte Leser/in die obigen Punkte im Detail nachlesen und nachvollziehen? Für ein Grundverständnis von dm-crypt und LUKS lohnt sich ein Blick in einen Artikel (u.a. vom Erfinder C. Fruhwirt), der im Linux-Magazin aus dem Jahre 2005 publiziert wurde: http://www.linux-magazin.de/ausgaben/2005/08/geheime-niederschrift/. In der Browserversion dieses Artikels werden die 2-er Potenzen für die statistische Belegung von Bit-Sequenzen leider nicht richtig dargestellt; das verwirrt beim Lesen ziemlich. 2128 bedeutet eigentlich 2128, 220 => 220, 240 => 240 :-).

Besonders hilfreich ist ferner ein Blick in das Paper “https://gitlab.com/cryptsetup/cryptsetup/blob/master/docs/on-disk-format.pdf“. Auch dieser Text ist von C. Fruwirth verfasst worden. Der Text ist aus meiner Sicht in Umfang und Prägnanz eine der besten Darstellungen zu LUKS. Auf Seite 9 finden wird dort etwa eine bündige Zusammenfassung zur Verschlüsselung des Master-Keys auf Basis einer neuen Passphrase:

“The user password is entered and processed by PBKDF2. The master key is then split by the AFsplitter into a number of stripes. The number of stripes is determined by the stripes field already stored in the key slot. The split result is written into the key material section, but encrypted. The encryption uses the same cipher setup as the bulk data (cipher type, cipher mode, …), but while for the bulk data the master key is used, the key material section is keyed by the result of the PBKDF2.”

Das Öffnen eines LUKS-Devices wird wie folgt beschrieben:

“First, the user supplies a password. Then the password is processed by PBKDF2 for every active key slot individually and an attempt is made to recover the master key. The recovery is successful, when a master key candidate
correctly checksums against the master key checksum stored in the phdr. Before this can happen, the master key candidate is read from storage, decrypted and after decryption processed by the anti-forensic information splitter in reverse gear, that is AFmerge. When the checksumming of the master key succeeds for one key slot, the correct user key was given and the partition is successfully opened.”

Eine gute Quelle für ein paar theoretische, vor allem aber für praktische Verfahrensfragen ist ferner “http://canonical.org/~kragen/cryptsetup“: Ich zitiere auch daraus mal einen Textabschnitt, der die Dinge für LUKS1 auf den Punkt bringt:

“LUKS works by using a “master key” consisting of truly-random bits, which is then encrypted using one or more passphrases. The passphrase is used to derive a key using PBKDF2, that key is used to encrypt the master key, and the encrypted master key and other parameters are written to the disk. To try a passphrase, as I understand it, the passphrase and parameters are used to derive a key, the key is used to decrypt the encrypted master
key, and the encrypted master key is checked against a stored master-key hash.”

Backup des PHDR

Aus dem bisher gesagten, wird bereits deutlich, dass die im PHDR hinterlegten Informationen essentiell für die Funktion von LUKS sind. Ist der PHDR kaputt, ist alles verloren. Im professionellen Umfeld ist eine Sicherung des PHDR also Pflicht. dm-crypt und Luks stellen die dafür notwendigen Kommandos bereit.

Welche symmetrischen Schlüsselverfahren?

Die SEAs müssen so beschaffen sein, dass es nicht möglich ist, aus der kryptierten Information den Master-Key zu ermitteln. AES-Verfahren ab 128 Bit-Schlüssellänge gelten heute noch als sicher. Besser ist es natürlich, 256-Bit als Schlüssellänge zu verwenden. Das ist allerdings auch eine Frage der Performance. Die Kryptierungsarbeit muss der Kernel ja ständig on-the-fly neben seinen sonstigen Aufgaben leisten. Aber Sicherheit hat eben einen Preis. In die Libraries zu dm-crypt/LUKS werden Default-Verfahren übrigens direkt einkompiliert. Die für seine Linux-Distribution einkompilierten Standardparameter, die der Befehl “cryptsetup luksFormat …” einsetzen wird, kann man übrigens abfragen mit “cryptsetup –help”; hier der Output für die Libraries unter Opensuse Leap 15:

mytux:~ # cryptsetup --help
Default compiled-in key and passphrase parameters:
        Maximum keyfile size: 8192kB, Maximum interactive passphrase length 512 (characters)
Default PBKDF2 iteration time for LUKS: 2000 (ms)
Default PBKDF for LUKS2: argon2i
        Iteration time: 2000, Memory required: 1048576kB, Parallel threads: 4

Default compiled-in device cipher parameters:
        loop-AES: aes, Key 256 bits
        plain: aes-cbc-essiv:sha256, Key: 256 bits, Password hashing: ripemd160
        LUKS1: aes-xts-plain64, Key: 256 bits, LUKS header hashing: sha256, RNG: /dev/urandom

Das für LUKs1 maßgebliche Verfahren findet man in der letzten Zeile. Zu den anderen Parametern mehr in kommenden Blog-Posts. Welche anderen Cipher-Verfahren per Parameter an dm-crypt für Luks übergeben werden können, entnimmt man Appendix B des oben angegebenen Papers von C. Fruwirth. Siehe auch:
https://superuser.com/questions/775200/how-do-i-determine-what-ciphers-cipher-modes-i-can-use-in-dm-crypt-luks
https://unix.stackexchange.com/questions/354787/list-available-methods-of-encryption-for-luks

Daten zur relativen Performance der verschiedenen Verfahren findet man hier:
https://lxadm.com/Cipher_benchmark_for_dm-crypt_/_LUKS
Cryptsetup erlaubt inzwischen auch die Durchführung eines Benchmarks für die notwendigen Operationen im RAM über den Befehl “cryptsetup benchmark” (für Daten siehe den nächsten Post. :

Hinweis:
Bei Wahl des Verfahrens “aes-xts-plain64” muss man eine Key-Size von 512 angeben, um letztlich bei “aes256” zu landen. Gründe findet man unter
https://en.wikipedia.org/wiki/Disk_encryption_theory
https://security.stackexchange.com/questions/5158/for-luks-the-most-preferable-and-safest-cipher
https://security.stackexchange.com/questions/101995/explanation-of-the-xts-encryption-mode

AES-basierte Verschlüsselungsverfahren durch Analyse der verschlüsselten Daten zu knacken, ist nach allgemeiner Auffassung ein ziemlich aussichtsloses Unterfangen. Angriffe werden sich daher auf die Kette konzentrieren, die von der
Passphrase über das PBKDF-Verfahren zum Master-Key führen. Damit rückt das PBKDF-Verfahren ins Zentrum des Interesses. Das wird das Thema des nächsten Posts:

dm-crypt/Luks – Begriffe, Funktionsweise und die Rolle des Hash-Verfahrens – II

Links

Theorie Disk Encryption
https://en.wikipedia.org/wiki/Disk_encryption_theory

Grundlagen LUKS
http://www.linux-magazin.de/ausgaben/2005/08/geheime-niederschrift/
https://gitlab.com/cryptsetup/cryptsetup/blob/master/docs/on-disk-format.pdf
http://canonical.org/~kragen/cryptsetup

Szenarios und Einsatz von “crypsetup”
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
https://gitlab.com/cryptsetup/cryptsetup/raw/master/FAQ

Symmetrische Verschlüsselungsverfahren in LUKS
https://unix.stackexchange.com/questions/354787/list-available-methods-of-encryption-for-luks
https://security.stackexchange.com/questions/5158/for-luks-the-most-preferable-and-safest-cipher
https://security.stackexchange.com/questions/101995/explanation-of-the-xts-encryption-mode

PKDF2
https://en.wikipedia.org/wiki/Pbkdf2

Argon / Argon2i
https://en.wikipedia.org/wiki/Argon2
https://www.cryptolux.org/index.php/Argon2
https://www.cryptolux.org/images/0/0d/Argon2.pdf