Laptop – SSD mit dm-crypt/Luks -Verschlüsselung und Opensuse Leap 15 – I – Vorüberlegungen

Eine Verschlüsselung von Daten auf Laptops ist in Zeiten der DSGVO Pflicht, da Laptops verloren gehen oder gestohlen werden können. Mein in die Jahre gekommener Laptop benötigt eh' einen neue (jungfräuliche) SSD. Zudem muss ich auf Opensuse Leap 15 wechseln. Ein guter Anlass, eine Verschlüsselung von Betriebssystem- und Daten-Partitionen unter Opensuse Leap 15 zu testen.

Vor einem Tausch der SSD wollte ich zunächst ausprobieren, ob eine Betriebssystem-Verschlüsselung unter Opensuse Leap 15.0 mit dem Laptop überhaupt funktioniert. Die meisten Linux-Profis setzen die Kombination "dm-crypt/LUKS" zur Verschlüsselung von Partitionen oder Volumes ein. Dabei spielen verschiedene Parameter eine Rolle, für die unter Opensuse normalerweise der YaST-basierte Partitioner Default-Werte vorgibt.

Ich nahm mir diesmal allerdings die Freiheit, die LUKS-Partitionen selbst mit eigener Parametersetzung vorzubereiten. Danach wurde das ganze Unternehmen unerwartet abenteuerlich und es taten sich etliche Falltüren auf. Es gab u.a. Probleme mit dem SuSE-Installer; nicht mehr bootfähige Systeme, nicht funktionales Kryptographie-Setup, Dracut-Probleme sind nur einige Stichworte. Man glaubt, man hat eine Lösung und schon zieht ein Neuinstallieren des Bootloaders über YaST alles wieder in den Abgrund. Probleme mit dem Grafik-System (Optimus; Nouveau, KMS) kamen zwischenzeitlich dazu - mit komischen Querbeziehungen zu systemd beim Shutdown und Aushängen des verschlüsselten Volumes für das /root-Filesystem.

Der ganze Themenkreis erfordert neben praktischen Installations- und Konfigurations-Schritten aber auch einige "theoretische" Vorüberlegungen. Kryptierung allein bietet schließlich noch keine hinreichende Sicherheit ... und man muss auch an Konsequenzen für den praktischen Betrieb eines solchen Laptops denken. Zudem kann man verschiedene Wege gehen. Beispiele für Varianten sind:

  • Vollverschlüsselung unter Einschluss des root-Filesystems oder Einsatz von Daten-Containern?
  • Vollverschlüsselung des Hosts oder nur darunter virtualisierter Systeme?
  • LVM on LUKS oder LUKS on LVM ?

Das sind nur drei wichtige Variationsmöglichkeiten - über die schon im Vorfeld der praktischen Installation entscheiden werden muss. Ich denke, das ist einige Blog-Posts wert ...

Ich beginne mit einer Reihe von "theoretischen" Vorüberlegungen, die jedoch praktische Auswirkungen auf die Sicherheit der Daten haben. Um eine ständige Unterscheidung zwischen LVM-Volumes und Partitionen zu vermeiden, spreche ich nachfolgend generell
von "Volumes". An den Stellen, wo die Unterscheidung wichtig wird, werde ich sie explizit treffen. "Betriebssystem" kürze ich im Weiteren mit OS ab.

Für "theoretische" Grundlagen zu grundsätzlichen Abläufen unter LUKS können Interessierte einen Blick in meine früheren Blog-Posts werfen; dort sind auch viele Links zu weiterführender Literatur im Internet angegeben:
dm-crypt/Luks – Begriffe, Funktionsweise und die Rolle des Hash-Verfahrens – I
dm-crypt/Luks – Begriffe, Funktionsweise und die Rolle des Hash-Verfahrens – II

Die praktische Umsetzung von LUKS auf Kommando-Ebene zeige ich im Zuge dieser Artikel-Serie.

Unterscheidung Vollverschlüsselung - Teilverschlüsselung

Wir unterscheiden im Folgenden zwischen Voll- und Teilverschlüsselung. Unter einer Voll-Verschlüsselung verstehe ich dabei einen Ansatz, in dem

  • sowohl das Volume für das OS, mit dem auf die zu schützenden Daten zugegriffen wird,
  • als auch separate Volumes zur Lagerung der zu schützenden Daten,
  • als auch Swap-Volumes

verschlüsselt werden. Bei Abweichungen spreche ich von Teilverschlüsselung.

Teilverschlüsselung - Datencontainer und/oder ausschließliche Verschlüsselung von separaten Partitionen/Volumes für Daten?

Viele Leute (auch IT-Profis) wählen zum "Schutz" ihrer Daten den "bequemen" Ansatz, diese in verschlüsselten Containern (Files) oder Partitionen/Volumes zu hinterlegen. Sehr beliebt ist unter Linux und Windows etwa der Einsatz von VeraCrypt. Dabei operiert das OS selbst auf einem unverschlüsselten Volume, weil sich die Anwender (z.T. aus guten Gründen) an eine Vollverschlüsselung nicht herantrauen. So kenne ich etwa mehrere Leute, die unter Windows ihre Daten in verschlüsselten Krypto-Containern auf der Systemplatte ablegen und meinen, nun seien die Daten bei einem Verlust oder Diebstahl des Laptops sicher. Das ist ein Irrtum (nicht nur wegen MS Windows). Die Gründe lassen sich u.a. mit folgenden Stichworten charakterisieren:

  • Pufferung von Daten/Dateien durch das Betriebssystem und Anwendungen in "temporären" Verzeichnissen/Dateien/Datenbanken sowie anwendungsspezifische Backup-Dateien.
  • Dateianalysatoren und Indexer für schlagwortbasierte Suchverfahren, die ggf. automatisch ganze Verzeichnisbäume und deren Inhalte durchforsten und Ergebnisse in Datenbanken hinterlegen.

Durch solche Verfahren landen Daten oder Datenfragmente bei der Bearbeitung von Dateien des Kryptocontainers (dekryptiert) auf dem unverschlüsselten (!) Filesystem des Betriebssystems [OS].

Zur Bearbeitung muss man die Dateien ja öffnen und ihren Inhalt entschlüsseln. Mindestens im RAM liegen die Daten dann im Klartext vor. Würden das OS oder die aktuelle Anwendung vom RAM immer nur auf den Krypto-Container zurückschreiben, wäre die Welt in Ordnung; das ist aber in vielen Anwendungen und Betriebssystemen nicht ohne besondere Einstellungen der Fall. Auch unter Linux landen Daten u.a. im /tmp-Verzeichnis, im home-Verzeichnis des Users oder gar im Swap. Hinzu kommen weitere anwendungsspezifische Orte im Filesystem. Kritisch in dieser Hinsicht sind etwa bestimmte Mail-Systeme.

Das gleiche Thema haben wir, wenn wir nur bestimmte Partitionen/Volumes eines Linux-Laptops für die Aufnahme von Daten verschlüsseln würden - aber das OS auf einem unverschlüsselten Volume desselben Geräts betreiben würden. Hier fungiert dann gleich eine ganze Partition oder ein Volume als "Container". Es gilt aber auch für begrenzte "Container", die man mit LUKS etwa auf Basis von datei-basierten Loop-Devices aufbauen könnte; ja, das geht.

Analoges gilt aber auch bei Einsatz externer Krypto-Container - z.B. auf USB-Sticks oder USB-Platten: Die Daten sind dort nur genau so sicher, wie sie es auf dem Laptop oder der PC selbst wären, von denen aus man regelmäßig mit dem externen Container arbeitet. Gerade bei mobilen Leuten ist das also ein Thema. All diese Ansätze entsprechen in Zeiten der DSGVO sicher nicht dem Stand der Technik.

Erstes Fazit: Für eine sichere Datenhaltung kommen wir um eine Verschlüsselung der Volumes für das OS sowie ggf. separate Datenvolumes sowie Swap-Bereiche nicht herum.

Teilverschlüsselung - das Problem mit SSDs

Man könnte bei HDDs noch wie folgt argumentieren: Wenn ich alle Bereiche und Dateien kenne, die das System oder Anwendungen zur Pufferung, Backups, Indizierung etc. nutzen, könnte ich diese Bereiche regelmäßig löschen und mit Nullen überschreiben. Das funktioniert leider nicht bei SSDs, die heute in die meisten Laptops eingebaut sind. Die oben diskutierte Thematik schlägt dann voll zu:

SSD-Controller verteilen ankommende Daten zur Begrenzung von Ausfällen z.T. in mehrfacher Kopie auf verschiedene Speicherelemente (Wear-Leveling). Das geschieht für den Anwender transparent im Hintergrund. Ohne Spezialwerkzeuge hat man als normaler User keinen Zugriff auf diese Storage-Breiche. Selbst wenn man alle Systembereiche für Pufferung etc. kennt und mit zufälligen Daten überschreibt - es blieben unverschlüsselte Reste auf der SSD erhalten. An die kommen Hacker, de physikalischen Zugriff auf die SSD haben, im Zweifelsfall aber mit Spezialwerkzeugen heran. Einer der Entwickler von Veracrypt lehnt deshalb gar vom Einsatz von SSDs auf Hochsicherheitssystemen ab. Siehe hierzu:
https://sourceforge.net/p/veracrypt/discussion/technical/thread/9cd45bb3/
https://www.veracrypt.fr/en/Security%20Requirements%20and%20Precautions.html
https://www.veracrypt.fr/en/Wear-Leveling.html

Das bedeutet:

Keine schützenswerten Daten dürfen den internen SSD-Controller je unverschlüsselt erreichen.

LUKS und auch Veracrypt sorgen dafür, dass das bei der Interaktion mit einem Storage-System passiert. Setzt man SSDs ein, so müssen also alle genutzten Partitionen, auf denen man schützenswerte Daten hält und auf denen ggf. unverschlüsselte Kopien oder Fragmente landen könnten, verschlüsselt werden. Allein hieraus ergibt sich eine Vollverschlüsselung für den Linux-Betrieb auf SSDs.

Das bedeutet aus meiner Sicht nicht zwingend, dass die komplette jungfräuliche SSD verschlüsselt werden muss. Aber mit OS-Installationen auf unverschlüsselten Partitionen darf man später NICHTS (!) Geheimhaltungswürdiges anfassen. Das ist in der Praxis gar nicht so einfach - und verlangt erhebliche Selbstdisziplin. Wer sicher gehen will, wird daher entweder die gesamte SSD oder zumindest alle OS-, Daten- und Swap-Partitionen, auf und mit denen regulär gearbeitet wird, verschlüsseln.

SSDs werfen übrigens noch ein zweites Problem im Zusammenhang mit Verschlüsselung auf: das des sog. Trimmens. Darauf komme ich in einem späteren Blog-Artikel zurück.

Teilverschlüsselung - das Hibernation-Problem

Besonders im Fall von Laptops gibt es das Thema "Hibernation". Beim Übergang in den maximal stromsparenden Zustand werden aktuelle RAM-Inhalte auf die Platte geschrieben (unter Linux evtl. in den SWAP-Bereich). Nach dem Öffnen eines Krypto-Devices wird im RAM aber der sog. "Master-Key" für das symmetrische Verfahren zur Datenverschlüsselung vorrätig gehalten. Das ist nicht nur bei LUKS so!

Auch das ist ein Grund dafür, auf Laptops alle Volumes/Partitionen die vom OS genutzt werden, zu verschlüsseln. Ein Angreifer könnte etwa einen Laptop in die Hände bekommen, der sich schon in einem Hibernation-Zustand befindet oder ihn nach gewisser Zeit erreichen wird. Der typische Fall für Freelancer ist der Verlust beim Umstieg zwischen zwei Zügen. Oder der gezielte Diebstahl in der Mittagspause.

Man sollte sich für seine Distribution in jedem Fall darum kümmern, was als Platz für Hibernation genutzt wird. Natürlicherweise bietet sich der SWAP an. Im Fall ist das auch der Fall; der Swap-Space muss auf einem Laptop mit Hibernation deshalb auch eine hinreichende Größe haben. Siehe:
https://doc.opensuse.org/documentation/leap/reference/html/book.opensuse.reference/cha.power-mgmt.html
Unter Suse müssten wir auf einem System mit aktiviertem Hibernation den SWAP-Space also verschlüsseln.

Es gibt übrigens ein ganz ähnliches Problem im Zusammenhang mit Virtualisierung. Dort kann man Gastsysteme in einen "Saved"-Zustand überführen, in dem auch der RAM der virtuellen Maschine in deinem vorgegebenen Verzeichnis-Bereich des OS - also ggf. auf einem unverschlüsselten Bereich des Systems gespeichert wird. Aber genug für heute ...

Zwischenfazit

Erste einfache Überlegungen sprechen gegen eine Teilverschlüsselung von (mobilen) Systemen, die Sicherheit geheim zu haltender Daten auf dem Stand der Technik garantieren sollen. Im nächsten Beitrag stellen wir Überlegungen zur Verschlüsselung virtualisierter Systeme an.

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

Im letzten Post
dm-crypt/Luks – Begriffe, Funktionsweise und die Rolle des Hash-Verfahrens – I
bin ich auf ein paar wichtige Elemente und die Funktionsweise von LUKS eingegangen. Auf dieser Grundlage können wir uns nun ein paar Gedanken zum Einsatz von Hash-Verfahren - wie etwa SHA - im Rahmen von LUKS machen.

Folgendes hatten wir bereits herausgearbeitet:
Unter LUKS muss ein PBKDF-Verfahren aus einer beliebig langen Zugangs-Passphrase eine Byte-Sequenz definierter Länge berechnen. PBKDF steht dabei für "Password-based Key Definition Function"; konkret verwendet LUKS1 die Funktion PBKDF2 (RFC2898). Den Ergebnisstring von PBKDF2 hatte ich im letzten Beitrag "PB-Key" genannt. Bitte beachtet: "PB-Key" ist keine offizieller Begriff aus dem LUKS Wortschatz. Ich verwende den Begriff hier im Blog lediglich zur klaren Unterscheidung von anderen LUKS-Keys. Der PB-Key wird zur Ent-/Ver-Schlüsselung des sog. "Master-Keys" [MK] eingesetzt. Der Master-Key wird bei der Initialisierung eines LUKS-Devices zufällig erzeugt und später in einem symmetrischen Krypto-Verfahren zur Verschlüsselung der geheim zu haltenden Daten des Devices herangezogen. Der PB-Key ist im normalen Betrieb also nur ein Hilfsmittel, um den zentralen Master-Key zu ermitteln. Nichtsdestoweniger hängt die Sicherheit des Systems maßgeblich am PBKDF.

Das Erzeugen eines Strings definierter Länge (hier des PB-Keys) aus einem beliebig langen String (hier: der Passphrase) ist eine klassische Aufgabe von Hash-Algorithmen. Wir vermuten also (zu Recht!), dass LUKS im Rahmen des PBKDF Hash-Verfahren benutzen muss. Tatsächlich war das über lange Zeit default-mäßig SHA-1. Siehe etwa die Git-Hub-Dokumentation zu dm-crypt/Luks; unter dem Punkt 5 "Security Aspects" kann man dort lesen, dass LUKS standardmäßig SHA-1 einsetzt
(https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions).

Nun gilt aber SHA-1 schon seit längerer Zeit als unsicher. Deshalb findet man im Internet zahlreiche besorgte Diskussionen zum Einsatz von SHA-1 unter LUKS (s. die vielen Links am Ende des Artikels). Wie ist dieses Thema zu beurteilen? Diese Frage hat auch mich als Anwender beschäftigt - u.a. auch wegen der Anforderung der DSGVO, als Dienstleister im regelmäßigen Umgang mit personenbezogenen Daten Sicherheit auf dem Stand der Technik zu belegen. Ich hatte aber auch ein grundsätzliches Interesse an dem Thema.

Wo kommt das Hash-Verfahren in LUKS zum Tragen?

Unter LUKS wird ein vorab definierter Hash-Algorithmus im Rahmen des PBKDF2-Verfahrens eingesetzt. Das geschieht über ein sog. HMAC-Verfahrens und iterativ (s.u.). PBKDF2 ist aus Anwendersicht selbst ein komplexes Hash-Verfahren, das Keys in Form von Hashes erzeugt. LUKS generiert mit Hilfe von PBKDF2 aus (bis zu 8) Passwörtern (PB-Key-) Hashes für (bis zu 8) sog. Key-Slots. Diese Hashes werden aber nicht im System gespeichert. Ein PBKDF2-erzeugter Hash wird von LUKS nur eingesetzt, um den MK zu entschlüsseln oder bei Neuanlage eines Key-Slots auch zu verschlüsseln (s. den letzten Post).

PBKDF2 hat aber noch eine wichtige Aufgabe in LUKS: Es erzeugt einen (Vergleichs-) Hash für den (entschlüsselten) Master-Key - den sog. MK-Digest. Dieser "Digest" wird tatsächlich dauerhaft im "LUKS Partition Header" [PHDR] abgelegt und ist für die Funktionalität von LUKS unerlässlich, sobald man mehrere Key-Slots verwendet; siehe hierzu meinen letzten Blog-Post. Das ist übrigens ein Grund dafür, warum man den Hash-Algorithmus nur für das gesamte LUKS-Device und nicht für einzelne Slots definiert. Der MK-Digest dient aber nur zu einem Zweck: Als Vergleichs-Hash für die per PB-Key versuchsweise entschlüsselten Master-Key-Kandidaten der aktiven Slots. Er ist nicht direkt zur Ver- oder Entschlüsselung von irgendetwas brauchbar. Vielmehr setzt seine Nutzung logisch bereits eine korrekte Entschlüsselung des echten Master-Keys voraus.

Hash-Verfahren und Schwächen von SHA-1

Hash-Verfahren werden u.a. für die Erzeugung von Passwort-Hashes definierter Länge verwendet. In dieser Funktion sind sie vielen IT-Leuten, aber auch Anwendern bekannt. Linux-Distributionen nutzen zur Passwortbehandlung heute überwiegend SHA-512; die Ergebnisse kann man sich als root in der "/etc/shadow"-Datei ansehen. Ich werde gleich darauf zurück kommen, worin der Unterschied zum Einsatz in LUKS besteht. Hashes werden aber auch in Signatur- und Authentifizierungs-Verfahren eingesetzt - zusammen mit asymmetrischer Verschlüsselung (s.u.).

Hash-Algorithmen müssen die Anforderung erfüllen, dass sie auch mit hohem Aufwand nicht invertiert werden können; es soll auf vernünftigen Zeitskalen nicht möglich sein, aus dem Hash den Ursprungstext zu ermitteln. Jeder algorithmische Ansatz für eine Invertierung soll zumindest mehr Zeit kosten als ein Brute-Force-Angriff. Genau deshalb sind Hash-Verfahren auch keine (normalen) Verschlüsselungsalgorithmen; beim Erzeugen eines Hashes betritt man eine Einbahnstraße. Man kann mit verschiedenen Texten/Passwörtern erzeugte Hashes nur vergleichen. Für den sicheren Einsatz von Hash-Algorithmen spielt zudem der Punkte der Kollisionsfreiheit eine Rolle. Kollisionsfreiheit bezieht sich auf die Vermeidung oder statistische Unwahrscheinlichkeit von Situationen, in denen z.B. zwei oder mehr Passwörter zum selben Hash führen. Es soll auch nicht möglich sein, Kollisionsstrings mit algorithmischen Verfahren auf sinnvollen Zeitskalen zu berechnen.

In der Praxis trägt auch die benötigte CPU-Zeit des Hash-Berechnungsverfahrens wesentlich zur Sicherheit bei. Ist ein Verfahren auf modernen CPUs zu schnell darstellbar, kommt als typischer Angriffsvektor eine Brute-Force-Attacke in Frage: Dabei werden viele (gut) geratene Passwörter (z.B. auf Basis eines Wörterbuchs) mit hoher Geschwindigkeit in Hashes umgewandelt und getestet. Der Test kann in einem direkten Vergleich mit einem bereits bekannten String bestehen; er kann aber auch das Eingeben des Hashes in eine verarbeitende Anwendung erfordern. Um Rechenzeit zu sparen, kann man als Angreifer versuchen, die zu testenden Hashes vor einem Angriff in einer generell einsetzbaren (großen) Tabelle (Rainbow-Tabelle) zusammenzustellen. Man entkoppelt dabei den Rechenaufwand vom eigentlichen Angriffsprozess. Besonders effizient sind solche Angriffe, wenn es gelingt, den Ziel-Hash vom angegriffenen Computer zu entwenden - und man die generierten Hashes zum Testen nicht an weitere verarbeitende Anwendungsprozesse übergeben muss.

Man kann das Verfahren SHA-1 nun aus zwei Gründen als unsicher ansehen; nur der erste betrifft dabei die algorithmische Festigkeit (siehe https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html):

  • SHA-1 ist nicht kollisionsfrei genug. Es gibt effiziente algorithmische Ansätze, um Kollisionsstrings zu ermitteln. Ressourcen-starke Organisationen können bei Anwendung dieser Algorithmen genügend Rechenpower einsetzen, um zu bekannten Hashes Kollisions-Passwörter zu finden. Das wurde bereits demonstriert.
  • SHA-1 ist in der Praxis nicht CPU-intensiv genug; die Berechnung des 160-Bit umfassenden Hash-Outputs erfordert auf modernen CPUs/GPUs nur sehr geringe Zeit. Damit können extrem viele "Passwörter" in endlicher Zeit durchprobiert werden - im Besonderen auf GPUs.

Siehe hierzu auch Links am Ende des Beitrags.

Über die Bedeutung des zweiten Punkts kann man trefflich streiten. Es geht dabei nicht um ein Knacken durch Invertierung des algorithmischen Verfahrens; mir ist nicht bekannt, dass dies für SHA-1 je gelungen wäre. Es geht eher um Brute-Force-Angriffe. In der Praxis von Hackern, die Passwörter knacken wollen, ist dieser Punkt deshalb durchaus relevant; je mehr Passwörter man in kurzer Zeit mit Tools wie JtR oder Hashcat durchprobieren kann, desto besser ist es aus Sicht des Hackers. Die Sicherheit hängt unter solchen Bedingungen auch stark an der Zufälligkeit der Zeichenwahl für das Passwort. Im realen Leben verwenden die meisten Anwender aber keineswegs hinreichend zufällige Passwörter genügender Länge (und Entropie). Die Chance durch geschicktes und sprachspezifisches Raten auf ein einfaches Passwort zu stoßen, sind entsprechend hoch. Das Thema relativiert sich für SHA-1 aber dadurch, dass modernen CPUs SHA-256 und SHA-512 gut unterstützen. Z.T. erfolgen die Berechnungen sogar effizienter als von SHA1. Die Lösung bzgl. des Problems kurzer CPU-Zeiten besteht daher nicht nur für SHA-1 in einer künstlichen Verlängerung des Erzeugungsprozesses für den Hash (Stretching; s.u.).

Es ist bei SHA-1 vor allem aber der zweite Punkt, der als kritisch bewertet wurde - mit erheblichen Auswirkungen für die elektronische Kommunikation im Internet. Der Grund war der, dass SHA-1-Hashes vielfach für die Erstellung von Signaturen, die zum Nachweis elektronischer Identitäten dienen, eingesetzt wurde. Solche Signaturen spielen im Besonderen bei der Prüfung der Identität von Web-Servern und Web-Domänen eine Rolle. Hier geht es dem Angreifer darum, einen bekannten Hash (Signatur) aus einem zu eigenen String/Text zu produzieren, der nicht mit dem Original-String/Text (z.B. einem Zertifikat) identisch ist. In der Praxis kommen zum Nachweis der Identität zwar auch unabhängige Institutionen und asymmetrische Kryptierung ins Spiel; aber da kann der Angreifer ggf. tricksen. Ich verdeutliche das, um klar zu machen, wie wenig diese Schwäche sich auf eine Manipulation von LUKS übertragen lässt:

Ein Client (z.B. ein Browser), der die Identität eines Web-Servers prüfen will, prüft einen vom Server übermittelten sog. Zertifikatsstring, indem er dessen Hash mit einem, von einer Beglaubigungsinstitution (Certification Authority; CA) kryptierten Hash (Signatur) vergleicht. Die CA hat dazu das originale Zertifikat zuvor selbst gehasht und mit Hilfe des privaten Schlüssels eines asymmetrischen Krypto-Verfahrens kryptiert. Das Ergebnis ist die Signatur, die dem Zertifikat als separate Information angefügt wurde. Der Client ermittelt den Hash des Zertifikats über einen vorgegebenen Hash-Algorithmus. Dann entschlüsselt er die "Signatur" mit dem öffentlichen Schlüssel der CA - und vergleicht den so erhaltenen Hash-Wert mit dem selbst ermittelten. Im positiven Fall ist die Identität verifiziert. Kann man nun als Angreifer auf Basis eines Kollisions-Strings ein Fake-Zertifikat produzieren, das denselben Hash produziert (Kollision), muss man es nur noch von einer (schlampigen) CA signiert bekommen und dem Client an passender Stelle unterjubeln. Das war/ist im Kern das Problem mit SHA1-basierten SSL-Zertifikaten. Das Entscheidende an dieser SHA1-Schwäche ist, dass der Hash bekannt sein muss - und man mit großer CPU-Power wie Spezialalgorithmen Kollisionsstrings ermittelt haben muss.
Siehe:
https://konklone.com/post/why-google-is-hurrying-the-web-to-kill-sha-1
http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art012

In einigen Foren im Internet wurde nun die Frage aufgeworfen, ob diese Schwächen nicht auch irgendwie auf LUKS durchschlagen. Siehe hierzu Links unten.

Schlagen die Schwächen von SHA-1 auf LUKS durch?

Ich tendiere dazu, diese Frage mit Nein zu beantworten. Das beruht auf 4 Überlegungen; die ersten beiden gelten dabei unabhängig vom Hash-Algorithmus:

  • Argument 1: Der Hash, der in LUKS als Key zur Entschlüsselung des Master-Keys benutzt wird, wird nirgendwo im System hinterlegt! Er wird lediglich zwischenzeitlich berechnet und in einem weiteren (symmetrischen) Verfahren als Key zur De-Kryptierung eines später zur eigentlichen Datenverschlüsselung genutzten Schlüssels eingesetzt. Insofern ist der Hash einem Angreifer (natürlich) auch nicht bekannt. Das macht bestimmte Angriffsverfahren irrelevant.
  • Argument 2: Der im Rahmen des LUKS-Verfahrens berechnete Hash beruht nicht auf einer einmaligen Anwendung von SHA. Das PBKDF2-Verfahren ist deutlich komplexer: Es verwendet SHA im Rahmen eines HMAC-Verfahrens unter Einschluss von Salting - und es arbeitet vor allem iterativ. Durch Hunderttausende oder Millionen von Iterationen wird die Zeit für eine PB-Key-Berechnung in den Bereich von Sekunden erhöht. 256-Bit Salts wirken dem Erstellen von vorberechneten Tabellen entgegen. Die Kombination aus Komplexitätserhöhung, Verlängerung von Passwörtern und Iterationen wird auch als Passwort-Stretching bezeichnet.
  • Argument 3: Seit Luks-Version 1.7.x wird SHA-256 als Default genutzt. Für neuere Installationen ist die Debatte irrelevant.
  • Argument 4: Eine schwache Passphrase bleibt eine schwache Passphrase - egal wie gut ein Hash-Verfahren ist. Man kann diese Schwäche nur teilweise durch Erhöhung des Rechenaufwands und durch Salts kompensieren.

Ich erläutere diese Punkte nachfolgend.

Der Hash zu den PB-Keys ist dem Angreifer nicht bekannt und nicht hinterlegt

Diesen Punkt hatten wir bereits im letzten Blog-Beitrag herausgearbeitet. Er zementiert nur, dass es bei Angriffen auf LUKS nicht um die Invertierung eines dem Angreifer bekannten Hashes geht. Das ist ganz anders als bei Angriffen auf erbeutete Passwort-Hashes eines Betriebssystems. Ein testweise berechneter Hash muss unter LUKS vielmehr in einem direkten nächsten Schritt zwingend in ein Dekryptierungsverfahren eingebracht und nicht mit einem bekannten String verglichen werden. Siehe hierzu: https://unix.stackexchange.com/questions/101398/why-does-luks-need-to-generate-hash-values).

Würde der Angreifer den unter LUKS erzeugten Hash (PB-KEY) in Erfahrung bringen (z.B. durch einen Dump des RAM), wäre sowieso schon alles verloren (siehe den letzten Beitrag). Der Witz ist ja gerade, dass der Hash nur temporär berechnet und zur Invertierung des Master-Keys eingesetzt wird. Angriffsvektoren, bei denen erzeugte Hashes mit einem bekannten Hash verglichen werden könnten, stehen im Zusammenhang mit LUKS so gar nicht zur Debatte. Ein Vergleich mit Angriffen auf Passwort-Listen hinkt schon aus logischen Gründen!

Man könnte nun noch auf den Gedanken kommen, dass ein Bruch der Kollisionsfreiheit evtl. dazu genutzt werden könnte, den Master-Key-Digest auszutauschen. Das käme jedoch einem Ersatz des (entschlüsselten) Master-Keys gleich und hätte im Rahmen des symmetrischen Verschlüsselungsverfahrens keinen Sinn. Auch bei einer zugehörigen Manipulation des PB-Keys lässt sich daraus aus meiner Sicht kein sinnvoller Angriff konstruieren. Ein destruktiver Angriff könnte den Master-Key tatsächlich ersetzen. Umso wichtiger sind Backups des PHDR.

Angriffe, die auf Daten-Entschlüsselung abzielen, müssen sich eher dem intelligenten Raten der Passphrase oder dem direkten Abfangen des erzeugten PB-Keys widmen. Dem ersten Angriff wirkt Stretching (s.u.) entgegen. Bzgl. des zeriten Weges gilt: Der Angreifer muss darauf setzen, auf irgendeine illegale Weise den RAM für den cryptsetup-Prozess auszulesen. Das kann einerseits über ein Hacken des Systems auf dem LUKS läuft voraus; ein gehacktes System hat aber sowieso mit einer Vielzahl von Problemen zu kämpfen. Der Schutz des RAMs betrifft aber auch so illustre Punkte wie: Auslesbare RAM-Fragmente nach einem Shutdown; Zugriff während Sleep-Phasen und im Vorfeld von Hibernating; keine hinreichende Abgrenzung prozess-spezifischer RAM_Bereiche auf Virtualisierungshosts; Schwächen von CPUs in der RAM-Behandlung (Spectre, Meltdown).

SHA kommt in HMAC-Form zum Einsatz

SHA wird nicht direkt sondern in ein komplexeres, sog. "HMAC"-Verfahren eingebunden. Ich kann in diesem Beitrag nicht auf Details von HMAC-Funktionen eingehen. Siehe aber: https://en.wikipedia.org/wiki/HMAC. HMAC-Funktionen benutzen zwar Hash-Algorithmen und erzeugen wie diese Hashes; eine HMAC-Funktion verkompliziert das Hashing jedoch durch mehrere eingeschobene Operationen deutlich. HMAC-Funktionen sind zudem weniger anfällig gegen Kollisionen als der zugrunde liegende Hash-Algorithmus selbst. Das liegt an einer zwischenzeitlichen Aufbereitung des Passworts mit anschließender Splittung nach definierten Regeln, erneuter Konkatenierung und Ergänzung mit einem Salt vor einer finalen Anwendung der Hash-Funktion. Dass HMAC-Verfahren durch die Schwächen von SHA1-1 nicht direkt betroffen sind, stellt z.B. auch Bruce Schneier fest: "SHA-1 Broken".

Hinweis für Interessierte:
Die Frage was PBKDF2 in das "HMAC-SHA1"-Verfahren als "Key" und was als "message" einfüttert, wird hier beantworte: .
https://crypto.stackexchange.com/questions/10164/pbkdf2-uses-hmac-sha1-to-generate-keys-but-what-is-the-key-for-the-hmac
Siehe auch: http://www.ietf.org/rfc/rfc2898.txt
Die LUKS-Pasphrase wird also als "Key", das Salt als "message" benutzt.

Stretching - PBKDF2 kostet Zeit und Rechenpower

Der Clou an PBKDF2 ist für mich die Iteration des HMAC-SHA-x Verfahrens; die erneute iterative Anwendung geschieht nicht ein paar Mal. Auf modernen PC-CPUs erfolgt die Iteration vielmehr mehrere hunderttausende Male, ggf. mehrere Millionen Mal. Hierfür gibt es einen Parameter:

Key = PBKDF2(hash_function, passphrase, salt, iterations, KeyLen)

Faktisch wird Anzahl der Iterationen beim Setup eines LUKS-Devices aus der als Options-Parameter (--iter-time) übergebenen Länge eines gewünschten Zeitintervalls (in msec) bestimmt. Es dauert dann die vorgegebene Zeit (z.B. 2 Sekunden), bevor PBDKF2 den finalen Hash - also den von Luks dann weiter verwendeten PB-Key - ausspuckt. Das Kommando "cryptsetup benchmark" erlaubt einen Test - nachfolgend für eine i7-6700K CPU:

mytux:~ # cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1      1002462 iterations per second for 256-bit key
PBKDF2-sha256    1416994 iterations per second for 256-bit key
PBKDF2-sha512    1219274 iterations per second for 256-bit key
PBKDF2-ripemd160  814111 iterations per second for 256-bit key
PBKDF2-whirlpool  782519 iterations per second for 256-bit key
argon2i      12 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id     12 iterations, 1048576 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
....

Die Zahlen verdeutlichen, warum PBKDF2 etwas mit Stretching zu tun hat!

Hinweis:
Man sollte diesen Test speziell auf langsamen CPUs vor der Anlage eines LUKS-Devices durchführen - und erst dann die Zeit (cryptsetup- Option "--iter-time" oder "-i") festlegen. Wichtig ist am Ende weniger die benötigte Zeit als vielmehr eine hohe Anzahl an Iterationen! Das gilt unabhängig vom Hash-Algorithmus! Die Iterationszahl sollte man dabei wohl eher an schnellen Systemen ausrichten. Das ist im besonderen wichtig, wenn man einen Laptop aufsetzt. Ein Angreifer, der den Laptop gestohlen hat, wird die LUKS-Partitionen eher mit anderen Systemen als dem Laptop selbst analysieren. Also seht euch diesen Test auch mal auf anderen Systemen (PCs, Server) an, bevor ihr euch für eine iter-time und damit indirekt für eine Iterationszahl entscheidet. Mir selbst scheint aktuell eine Zahl > 1000000 Iterationen sinnvoll. Siehe auch:
https://security.stackexchange.com/questions/3959/recommended-of-iterations-when-using-pkbdf2-sha256
Die cryptsetup Option "--iter-time" oder "-i" kann übrigens für jeden neuen Key-Slot (Option -S) separat gewählt werden. ($ sudo /sbin/cryptsetup luksAddKey -S 6 -h sha512 -s 512 -i 3000 /dev/sdx)

Warum kann man als LUKS-Awender die benötigte PBKDF2-Zeit in den Bereich von Sekunden zwingen? Weil man diese Zeit nur einmal beim Öffnen des LUKS-Devices investieren muss. Ein Angreifer muss diese Zeit aber viele, viele Male investieren. Unter folgendem Link findet man eine Tabelle zum Zusammenhang zwischen Password-Stärke, Interationen und Aufwand mit Hashcat als Cracking Tool auf GPUs:
https://support.1password.com/pbkdf2/

Hinweis:
Auch für die Erzeugung des MK-Digest muss man natürlich eine PBKDF2-Iterationszahl festlegen. Diese ist unabhängig von entsprechenden Parametern für die Key-Slots und wird deshalb auch im Hauptteil des LUKS-Partitions-Headers hinterlegt. Man legt die Iterationszahl auch hier indirekt über den Parameter "iter-time" fest, den man beim Aufruf von "cryptseup luksFormat" übergibt.

Vorberechnete Tabellen?

Ein Angreifer, der in Besitz eines LUKS-Devices kommt, kann den PHDR und auch die "Key material Sections" mit den verschlüsselten Master-Key-Daten auslesen (s. den letzten Post). Damit sind ihm auch das symmetrische Verschlüsselungsverfahren, das Hash-Verfahren, Salt sowie Anzahl der Iterationen bekannt. Nun könnte er Rainbow-Tabellen vorbereiten, um sich im Angriffsszenario der Last der PBKDF2-Berechnung zu entziehen und Hashes direkt an das symmetrische Verschlüsselungsverfahren übergeben. Er muss den Rechenaufwand für PBKDF2 natürlich aber vorab aufbringen. Sein Problem ist dabei aber das Salting - um eine generell einsetzbare Tabelle zu erstellen, müsste er vorab auch alle möglichen Salt-Strings (für 256 Bit) in Kombination mit allen zu testenden Passwörtern (z.B. aus einem Wörterbuch) in PBKDF2 einfüttern. Damit sind für einen generellen Einsatz aber wahrlich gigantische Tabellen erforderlich. Ein Angreifer wird solche Tabellen also erst vorbereiten, wenn er den Salt-String kennt - also nach dem Diebstahl. Dann allerdings ist er immer noch mit der Zeitdauer des PBKDF2-Verfahrens konfrontiert.

Ist der Standard wirklich noch SHA-1?

Das hängt davon ab, mit welcher Version von LUKS ihr operiert. Ich bin auch nicht sicher, ob das distributionsabhängig ist. Man sollte es lieber prüfen. Dazu hilft "cryptsetup --help":

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 sieht so aus, als ob SHA-256 inzwischen der Standard ist. Siehe auch:
https://security.stackexchange.com/questions/131035/are-default-options-of-cryptsetup-luks-secure
https://security.stackexchange.com/questions/39306/how-secure-is-ubuntus-default-full-disk-encryption
Ich würde mir dennoch grundsätzlich angewöhnen, den Algorithmus beim Anlegen eines LUKS-Devices selbst festzulegen. Bitte beachtet, dass der Hash-Algorithmus für das Device insgesamt festgelegt werden muss - und nicht pro Slot.

Zugegeben, dieser Punkt nützt Leuten, die ihre Daten bereits auf einem LUKS-Device haben, das mit SHA-1 konfiguriert wurde, wenig, wenn kein kompletter Umzug und Neuaufbau betrieben werden soll.

Passphrase-Qualität

Zuletzt hängt alles an der Qualität der Passphrase. Verwende ich eine Passphrase wie "Esel", muss ich mich nicht wundern, wenn meine Verschlüsselung trotz Stretching in endlicher Zeit gebrochen wird. Egal, wie gut mein Hash-Verfahren ist. Das führt zur Frage, wie lang und gut eine Passphrase für LUKS eigentlich sein sollte. Dazu findet man interessante Überlegungen in folgendem Artikel für die Kombination dm-crypt/Luks:
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
Der Autor kommt zum Schluss:

LUKS: Use > 65 bit. That is e.g. 14 random chars from a-z or a random English sentence of > 108 characters length. If paranoid, add at least 20 bit. That is roughly four additional characters for random passphrases and roughly 32 characters for a random English sentence.

Die Bit-Anzahl misst dabei die statistische Zufälligkeit. 108 Buchstaben in einem zufälligen englischen Satz sind eine ganze Menge Wörter. Man kann die Entropie aber durch Mixen von sinnlosen Wörtern mit angereicherten Elementen erhöhen, sowie Wörter aus verschiedenen Sprachen mischen. Ein anderer Autor kommt zu Ergebnissen, die freundlicher für den Benutzer aussehen:
http://canonical.org/~kragen/cryptsetup

It is reasonable to memorize a phrase of six 5-letter-or-less words chosen from among the 4096 most common words in English. They provide 72 bits of entropy, and LUKS can provide 16 bits of key stretching, for a total of 288 PBKDF2 iterations to exhaust the entire keyspace. A brute-force attack then would require a computational expense currently equal to half a century of world economic output.

Ich empfehle, Wörter aus verschiedenen Sprachen in sinnlosen Sätzen zu mischen - und mit willkürlichen Zahlen/Trennzeichen anzureichern. Dabei sollte man Umlaute vermeiden und auch bzgl. der Trennzeichen auf mögliche wechselnde Tastatur-Layouts aufpassen!

Was sagt die cryptsetup-Doku zur SHA-1-Thematik?

In der Github Doku zu "cryptsetup" liest man unter Punkt "5.20 LUKS is broken! It uses SHA-1!":

No, it is not. SHA-1 is (academically) broken for finding collisions, but not for using it in a key-derivation function. And that collision vulnerability is for non-iterated use only. And you need the hash-value in verbatim.
This basically means that if you already have a slot-key, and you have set the PBKDF2 iteration count to 1 (it is > 10'000 normally), you could (maybe) derive a different passphrase that gives you the the same slot-key. But if you have the slot-key, you can already unlock the key-slot and get the master key, breaking everything. So basically, this SHA-1 vulnerability allows you to open a LUKS container with high effort when you already have it open.

Mein Fazit

Insgesamt sollte man wegen SHA1 aus meiner Sicht nicht in Panik verfallen. Dazu gibt es (noch) keinen Grund. Auf einem aktuellen System wird das sowieso nicht mehr als Default verwendet. Wer bzgl. vorhandener LUKS-Devices, die noch SHA-1 nutzen, paranoid ist, hat zwei Möglichkeiten:

  • Den gesamten Daten-Inhalt in ein Backup überführen. Das LUKS-Device mit anderen Parametern neu aufbauen und aus dem Backup füllen.
  • Mühe in gute Passphrases investieren und diese dann systematisch für bestehende Key-Slots austauschen. Dabei auch die Iterationszeit ( und -anzahl) für PBKDF2 anpassen. Das geht nämlich pro Slot.

Dennoch gibt es aus meiner Sicht auch keinen guten Grund, bei neu anzulegenden LUKS-Devices nicht SHA-256 oder gleich SHA-512 zu verwenden. Im Schadensfall wird ein Kunde uns Freelancer womöglich mit Berufung auf die DSGVO auf den ominösen "Stand der Technik" fixieren wollen; deshalb fährt man mit SHA-512 sicher auch aus rechtlicher Perspektive besser. Also:

cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 3000 -v luksFormat /dev/YOURDEVICENAME

Ich werde die praktische Anwendung der gewonnenen Erkenntnisse in weiteren Posts darstellen. Da geht es dann um das Aufsetzen eines Laptops unter Opensuse Leap 15. Bis dann ....

Links


Irreversibilität von Hash-Algorithmen?

https://security.stackexchange.com/questions/11717/why-are-hash-functions-one-way-if-i-know-the-algorithm-why-cant-i-calculate-t

Schwäche von SHA1
https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html
https://konklone.com/post/why-google-is-hurrying-the-web-to-kill-sha-1
https://www.computerworld.com/article/3173616/security/the-sha1-hash-function-is-now-completely-unsafe.html
https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
https://www.schneier.com/blog/archives/2005/02/sha1_broken.html
https://stackoverflow.com/questions/38038841/why-is-sha-1-considered-insecure
http://2012.sharcs.org/slides/stevens.pdf

https://stackoverflow.com/questions/3740443/how-insecure-is-a-salted-sha1-compared-to-a-salted-sha512

SHA1 und HMAC
https://crypto.stackexchange.com/questions/26510/why-is-hmac-sha1-still-considered-secure
https://np.reddit.com/r/Ubuntu/comments/3m4saj/ubuntuserver_installer_is_using_weak_hash/
https://cseweb.ucsd.edu/~mihir/papers/kmd5.pdf

Kollisionen als "Kuriosität" im HMAC-Umfeld
https://mathiasbynens.be/notes/pbkdf2-hmac
https://crypto.stackexchange.com/questions/15218/is-pbkdf2-hmac-sha1-really-broken

SHA1 in LUKS oder Veracrypt unsicher?
https://sourceforge.net/p/veracrypt/discussion/general/thread/82add23d/
https://security.stackexchange.com/questions/79240/about-sha1-in-default-disk-encryption-in-linux
https://ubuntuforums.org/showthread.php?t=1170405
https://ubuntuforums.org/showthread.php?t=2260677
https://security.stackexchange.com/questions/131035/are-default-options-of-cryptsetup-luks-secure
https://security.stackexchange.com/questions/79008/security-of-linux-full-disk-encryption-ubuntu-mint-insecure
https://security.stackexchange.com/questions/131035/are-default-options-of-cryptsetup-luks-securehttps://security.stackexchange.com/questions/79240/about-sha1-in-default-disk-encryption-in-linux
http://hideandhack.blogspot.com/2013/05/do-not-use-sha-1-luks-disk-encryption.html
https://security.stackexchange.com/questions/39306/how-secure-is-ubuntus-default-full-disk-encryption
https://www.wilderssecurity.com/threads/hardening-generic-luks-from-common-distro-installs.389776/

https://www.reddit.com/r/crypto/comments/3m4maq/why_ubuntuserver_installer_is_using_sha1_instead/
https://np.reddit.com/r/Ubuntu/comments/3m4saj/ubuntuserver_installer_is_using_weak_hash/

Beispiel mit teilweise falscher Antwort
https://unix.stackexchange.com/questions/254017/how-to-interpret-cryptsetup-benchmark-results
(In the answer it is claimed that the hash of the user's password is stored)

PBKDF2
https://en.wikipedia.org/wiki/PBKDF2
https://support.1password.com/pbkdf2/
http://www.ietf.org/rfc/rfc2898.txt
https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
https://security.stackexchange.com/questions/133239/what-is-the-specific-reason-to-prefer-bcrypt-or-pbkdf2-over-sha256-crypt-in-pass
https://stackoverflow.com/questions/23946349/for-pbkdf2-using-hmac-sha256-is-more-secure-than-using-hmac-sha-1

SHA512 Empfehlung
https://security.stackexchange.com/questions/40208/recommended-options-for-luks-cryptsetup

Key Stretching
https://unix.stackexchange.com/questions/101398/why-does-luks-need-to-generate-hash-values

Missverständnisse bzgl. des Hashes und Luks
https://unix.stackexchange.com/questions/101347/how-can-i-extract-the-hash-value-of-a-luks-device
https://forums.gentoo.org/viewtopic-t-980544-start-0.html
https://crypto.stackexchange.com/questions/24022/luks-multiple-key-slots-whats-the-intuition
https://security.stackexchange.com/questions/79240/about-sha1-in-default-disk-encryption-in-linux

Cryptsetup-Parameter
https://advanced-analytica.com/2018/04/06/data-security-on-linux/

Rainbow Tables
https://en.wikipedia.org/wiki/Rainbow_table

Argon2
https://password-hashing.net/

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. Rcherchiert 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 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 2 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.

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