IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Kategorie: BIOS & Firmware

Beitraege rund um BIOS, UEFI und Firmware: Setup-Optionen erklaert, Gegenproben aus dem laufenden System, Serverboards im Alltag.

BIOS erklärt, Teil 6: 256 GB ECC, ein Scrubber der jeden Tag putzt und ein Reparaturmechanismus im Speicherriegel

In dieser Folge geht es um Advanced > Chipset Configuration > North Bridge > Memory Configuration. Wer die Serie bis hierhin nicht mitgelesen hat: alle Teile liegen unter BIOS & Firmware, und es lohnt sich nicht, sie in der Reihenfolge zu lesen. Jede Folge steht für sich.

Was verbaut ist

Aptio Setup, Memory Topology, alle acht Module mit 2933 Megatransfers und 32 Gigabyte als Registered DIMM
DIMMA1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMB1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMC1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMD1: 2933MT/s ATP DRx4 32GB RDIMM
DIMME1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMF1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMG1: 2933MT/s ATP DRx4 32GB RDIMM
DIMMH1: 2933MT/s ATP DRx4 32GB RDIMM

Acht Steckplätze, acht Module, jedes 32 GB. Das ist die Seite Memory Topology, und sie sagt in acht Zeilen mehr über den Aufbau der Maschine als jedes Datenblatt.

RDIMM heisst Registered DIMM. Zwischen dem Speichercontroller und den eigentlichen Speicherchips sitzt ein Registerbaustein, der Adress- und Steuersignale zwischenspeichert und neu ausgibt. Der Grund ist elektrisch: je mehr Chips an einem Kanal hängen, desto stärker belastet das die Signalleitungen. Der Registerbaustein bricht diese Last auf. Deshalb gibt es in Servern acht Module pro Sockel und in Desktops vier, und deshalb kann man normale Desktop-Riegel hier nicht einsetzen. Der Preis ist ein Takt Latenz zusätzlich.

DRx4 beschreibt den Aufbau: Dual Rank, jeder Chip liefert 4 Bit. Zwei Ranks bedeutet, dass auf dem Modul zwei unabhängige Gruppen von Chips sitzen, zwischen denen der Controller umschalten kann. Während eine Gruppe noch mit einer Anfrage beschäftigt ist, kann er die andere schon ansprechen, was den Durchsatz verbessert.

Und 2933MT/s, obwohl auf den Modulen 3200 steht. Das ist keine Fehlfunktion, sondern die CPU. Der Xeon Gold 5315Y ist die Einstiegsvariante der Ice-Lake-Serie, und Intel hat den Speichertakt an die Prozessorstufe gekoppelt. Die teureren Modelle fahren 3200, meiner eben 2933. Die Riegel könnten mehr, sie dürfen nicht. Genau so meldet es auch das Betriebssystem:

dmidecode -t memory | grep -E "Speed|Configured"
#   Speed: 3200 MT/s
#   Configured Memory Speed: 2933 MT/s

Was das Modul kann, und was es tatsächlich tut. Der Unterschied sind rund acht Prozent Speicherbandbreite, die ich nicht bekomme. Verschmerzbar.

ECC, der Teil den alle kennen

Erstaunlicherweise gibt es auf dieser Seite gar keinen Schalter namens ECC. Bei registrierten Servermodulen ist Fehlerkorrektur keine Option, sondern eine Eigenschaft der Hardware. Sie ist da, sie ist an, fertig.

Falls es jemand nicht parat hat: ECC speichert zu je 64 Bit Nutzdaten 8 zusätzliche Prüfbits. Damit lässt sich ein gekipptes Bit erkennen und reparieren, und zwei gekippte Bits lassen sich zumindest erkennen. Das ist der Unterschied zwischen „im Log steht eine korrigierte Zeile“ und „irgendwo in einer Datei steht jetzt ein falsches Byte, viel Spass beim Suchen“.

Bits kippen häufiger als man denkt. Kosmische Strahlung, Alphateilchen aus dem Gehäusematerial, schlicht Alterung. Bei 256 GB, die dauerhaft laufen, ist das keine theoretische Grösse mehr.

Patrol Scrub, und die Zahl aus dem Handbuch

Patrol Scrub                      [Enable at End of POST]

Das ist mein Lieblingsschalter auf dieser Seite. ECC korrigiert nämlich nur dann, wenn jemand die betroffene Speicherstelle liest. Ein Bit in einem Speicherbereich, den seit drei Wochen niemand angefasst hat, kippt unbemerkt. Kippt in derselben Zeile ein zweites, ist der Fehler nicht mehr korrigierbar.

Patrol Scrub geht deshalb im Hintergrund den gesamten Speicher durch, liest jede Zeile, lässt ECC prüfen und schreibt sie korrigiert zurück. Vorbeugendes Putzen, damit sich Einzelfehler nicht zu Doppelfehlern summieren.

Das Handbuch nennt dazu eine Zahl, die man sonst nirgends findet:

the IO hub reads and writes back one cache line every 16K cycles … roughly 64 GB of memory behind the IO hub is scrubbed every day

Eine Cache-Zeile alle 16.000 Takte, macht etwa 64 GB pro Tag. Bei meinen 256 GB dauert ein kompletter Durchlauf also rund vier Tage. Das klingt langsam, ist aber genau der Punkt: der Scrubber soll im Hintergrund verschwinden und nicht die Speicherbandbreite auffressen, die eigentlich für Arbeit gedacht ist.

Enable at End of POST heisst, dass er nach dem Selbsttest startet, also bevor das Betriebssystem läuft, und dann durchgehend weiterarbeitet.

PPR: der Reparaturmechanismus im Riegel

Aptio Setup, Memory Configuration, mit Enhanced PPR, PPR Type, Speichertakt und den Untermenüs für Topologie und RAS
Enhanced PPR                      [Disable]
PPR Type                          [Hard PPR]
Enforce POR                       [POR]

PPR steht für Post Package Repair, und dahinter steckt etwas, das mich beim Nachlesen ehrlich überrascht hat: moderne DDR4-Module haben Ersatzzeilen eingebaut. Fällt eine Speicherzeile dauerhaft aus, kann die Firmware sie stilllegen und eine Reservezeile an ihre Stelle setzen. Der Riegel repariert sich also selbst, im laufenden Betrieb einer Maschine, ohne dass ihn jemand anfasst.

Hard PPR bedeutet, dass diese Umleitung dauerhaft in den Riegel gebrannt wird und einen Neustart übersteht. Die Alternative Soft PPR gilt nur bis zum nächsten Ausschalten. Hart ist sinnvoller, kostet aber eine der wenigen Reservezeilen unwiderruflich.

Enforce POR steht für Plan of Record und ist die Frage, ob das Board die von Intel freigegebenen Speicherparameter erzwingt oder ob es auch aggressivere Kombinationen zulässt. Auf einem Serverboard mit 256 GB ECC ist die Antwort selbstverständlich ja.

Data Scrambling for DDR4 [Enable] weiter unten macht etwas ganz anderes, als der Name vermuten lässt. Das ist keine Verschlüsselung. Die Daten werden vor dem Schreiben mit einem Pseudozufallsmuster verwürfelt, damit auf den Datenleitungen keine langen Folgen identischer Bits entstehen. Solche Muster erzeugen Störungen auf den Nachbarleitungen und einen unruhigen Stromverbrauch. Verwürfeln macht das Signalbild gleichmässiger. Wer glaubt, sein Speicher sei damit verschlüsselt, irrt sich, dafür wäre TME zuständig, und über den habe ich in Teil 4 geschrieben.

Memory RAS: das Menü das kleiner ist als erwartet

Aptio Setup, Memory RAS Configuration, mit Mirror Mode auf Disabled und der Schwelle für korrigierbare Fehler
Memory RAS Configuration Setup
Enable Pcode WA for SAI PG        [Disabled]
Mirror Mode                       [Disabled]
UEFI ARM Mirror                   [Disabled]
Correctable Error Threshold       512

RAS steht für Reliability, Availability, Serviceability, und ich hatte hier ehrlich gesagt mehr erwartet. In Intel-Dokumentation tauchen an dieser Stelle regelmässig Rank Sparing, ADDDC Sparing und PCLS auf. Auf diesem Board gibt es davon nichts, die Seite hat genau diese vier Zeilen und keinen Rollbalken.

Mirror Mode ist die interessanteste Option, gerade weil sie aus ist. Speicherspiegelung schreibt jeden Wert doppelt, auf zwei verschiedene Kanäle. Fällt eine Stelle dauerhaft aus, übernimmt die Kopie, ohne dass die Maschine stehenbleibt. Der Preis ist die Hälfte des Speichers: aus 256 GB würden 128.

Für einen Datenbankserver, bei dem eine Stunde Ausfall Geld kostet, kann das die richtige Rechnung sein. Für meine Workstation nicht. ECC fängt Einzelfehler ohnehin ab, Patrol Scrub verhindert dass sie sich anhäufen, und wenn wirklich ein Modul stirbt, tausche ich es. 128 GB zu verschenken, um mir einen Neustart zu ersparen, ist mir zu teuer.

Correctable Error Threshold 512 ist die Schwelle, ab der die Firmware eine Speicherstelle als auffällig meldet. Einzelne korrigierte Fehler passieren, das ist Normalbetrieb. 512 an derselben Stelle sind ein Muster.

Die Gegenprobe, und warum ich sie erst nachrüsten musste

An dieser Stelle kommt der Teil, bei dem ich mich selbst ertappt habe. Der ganze Aufwand oben, ECC, Scrubber, PPR, Fehlerschwellen, läuft ins Leere, wenn niemand hinsieht. Linux erfasst Speicherfehler über das EDAC-Subsystem, und das war bei mir aktiv:

ls /sys/devices/system/edac/mc/
#   mc0  mc1  mc2  mc3

Vier Speichercontroller, alle angebunden. Nur landeten die Ereignisse ausschliesslich im Kernel-Ringpuffer, und der ist nach einem Neustart leer. Ich hätte also gemerkt, wenn gerade etwas passiert. Ich hätte nie gemerkt, dass ein bestimmter Riegel seit Wochen langsam schlechter wird. Genau das ist aber der Fall, für den man ECC überhaupt haben will.

Nachgerüstet ist das mit einem einzigen Paket:

apt-get install rasdaemon
ras-mc-ctl --error-count
#   CPU_SrcID#0_MC#0_Chan#0_DIMM#0   CE 0   UE 0
#   ... (acht Zeilen)
ras-mc-ctl --summary
#   No Memory errors.

rasdaemon schreibt die Ereignisse in eine SQLite-Datenbank und führt sie pro Modul. CE sind korrigierte Fehler, UE nicht korrigierbare. Bei mir stehen beide auf null, und jetzt weiss ich das auch für die Vergangenheit und nicht nur für diesen Bootvorgang.

Ein Wermutstropfen: die acht Zähler heissen MC#0_Chan#0_DIMM#0 und nicht DIMMA1. Das Paket bringt für dieses Board keine Zuordnungstabelle mit. Ich könnte eine schreiben, die Reihenfolge liegt nahe, aber ich habe es bewusst gelassen. Ein falsches Etikett ist schlimmer als gar keins, weil es einen im Fehlerfall an den falschen Steckplatz schickt.

Nächste Folge: NUMA auf einer Maschine mit genau einem Sockel, warum das trotzdem ein Thema ist, und was Uncore und UPI eigentlich sind.

Siehe auch

Falls jemand von euch schon einmal ein PPR-Ereignis in freier Wildbahn gesehen hat, also einen Riegel der sich tatsächlich selbst repariert hat: das würde ich gerne hören. Ihr dürft mich jederzeit fragen.

BIOS erklärt, Teil 5: SpeedStep, Turbo, C-States und der Schalter der mir eine Woche Rätselraten erspart hätte

Willkommen bei Teil 5. Die bisherigen Folgen findest du gesammelt unter BIOS & Firmware. Heute geht es um Advanced > CPU Configuration > Advanced Power Management Configuration.

Advanced

Aptio Setup, Advanced Power Management Configuration, mit Power Technology auf Custom und sechs Untermenüs

Die Seite selbst ist kurz:

Power Technology                  [Custom]
Power Performance Tuning          [OS Controls EPB]
ENERGY_PERF_BIAS_CFG Mode         [Balanced Performance]
> CPU P State Control
> Hardware PM State Control
> Frequency Prioritization
> CPU C State Control
> Package C State Control
> CPU T State Control

Die erste Zeile ist wichtiger als sie aussieht. Power Technology kennt neben Custom noch Disable und Energy Efficient, und solange sie nicht auf Custom steht, sind die sechs Untermenüs Dekoration: die Firmware setzt dann ihre eigenen Werte und überschreibt, was man darunter einstellt. Wer sich also wundert, warum eine Änderung im C-State-Menü nichts bewirkt, sollte zuerst hier nachsehen.

Power Performance Tuning auf OS Controls EPB heisst, dass das Betriebssystem den Energy Performance Bias steuern darf und nicht das BIOS. Das ist genau das, was man auf einer Linux-Maschine will. Der dritte Wert ENERGY_PERF_BIAS_CFG Mode ist der Vorgabewert, den die Firmware setzt, solange sich niemand darum kümmert, und Balanced Performance ist dafür eine vernünftige Mitte.

P-States: die Frequenz

Aptio Setup, CPU P State Control, mit SpeedStep, Turbo Mode und der Tabelle der Speed-Select-Profile
SpeedStep (P-States)              [Enable]
AVX P1                            [Nominal]
Dynamic SST-PP                    [Disable]
Intel SST-PP                      [Base]
Activate SST-BF                   [Disable]
Configure SST-BF                  [Enable]
EIST PSD Function                 [HW_ALL]
Turbo Mode                        [Enable]
CPU Flex Ratio Override           [Disable]
CPU Core Flex Ratio               23

SpeedStep ist der Klassiker: die CPU darf ihre Frequenz und Spannung an die Last anpassen. Intel nennt das seit Ewigkeiten EIST, Enhanced Intel SpeedStep Technology. Ohne diesen Schalter läuft der Prozessor stur auf Basistakt, verbraucht im Leerlauf deutlich mehr und wird wärmer, ohne dafür irgendetwas zurückzugeben. Der bleibt an.

Turbo Mode ist die Gegenrichtung: die CPU darf über den Basistakt hinaus, solange Temperatur und Stromaufnahme es hergeben. Bei meinem Xeon Gold 5315Y sind das 3,2 GHz Basis und 3,6 GHz Turbo. Linux bestätigt beide Enden:

lscpu | grep MHz
#   CPU max MHz:  3600,0000
#   CPU min MHz:   800,0000

EIST PSD Function auf HW_ALL regelt, wer die Frequenzwechsel koordiniert. Bei HW_ALL macht das die Hardware für alle Kerne einer Domäne selbst, bei SW_ALL müsste das Betriebssystem mitreden. Hardware ist hier schneller und weiss ohnehin mehr, das lässt man so. ALso ich, öhm. joar. 😀

Der Teil der mich überrascht hat: Speed Select

Mitten auf der Seite steht eine kleine Tabelle, die ich vorher noch nie in einem BIOS gesehen habe:

Intel SST-PP            Base | Config 3 | Config 4
  Core Count             08  |    06    |    04
  Current P1 Ratio [0]   32  |    32    |    34
  Package TDP (W)       140  |   125    |   115
  Tjmax                 103  |   100    |   101

Das ist Intel Speed Select Technology, Variante Performance Profile. Die Idee dahinter: dieselbe CPU kann in mehreren fest definierten Betriebspunkten laufen, und man wählt beim Booten aus, welchen man haben möchte. Meine hat drei. Im Auslieferungszustand Base sind es acht Kerne bei 3,2 GHz und 140 Watt. Wählt man Config 4, bleiben vier Kerne übrig, dafür steigt der Basistakt auf 3,4 GHz und die Verlustleistung fällt auf 115 Watt.

Man tauscht also Kerne gegen Takt, und zwar nicht per Turbo-Zufall, sondern als garantierte Zusicherung. Für Software, die pro Kern lizenziert wird, ist das bares Geld. Für Lasten, die nicht parallelisieren, sind 200 MHz mehr Basistakt spürbar. Und für mich? Ehrlich gesagt nutzlos. Ich habe acht Kerne gekauft, weil ich acht Kerne wollte, und 200 MHz sind kein Argument dafür, die Hälfte davon wegzuwerfen.

Trotzdem finde ich es bemerkenswert, dass so etwas in einem BIOS steht, das ansonsten aussieht wie 2005. SST-BF daneben ist die verwandte Idee auf Kernebene: Base Frequency, einzelne Kerne bekommen dauerhaft mehr Takt, die übrigen entsprechend weniger. Steht bei mir auf Disable, und das passt, denn dafür müsste ich meine Last gezielt auf die schnellen Kerne pinnen. Wer das tut, weiss warum. Wer es nicht tut, gewinnt nichts.

Und hier lag die Antwort

Aptio Setup, Hardware PM State Control, Hardware P-States steht auf Disable
Hardware PM State Control
Hardware P-States                 [Disable]

Ein Untermenü mit genau einer Zeile, und diese Zeile hat mich mehr gefreut als der ganze Rest der Seite. Um zu erklären warum, muss ich kurz ausholen.

Seit dem Umbau ist mir aufgefallen, dass Linux die Frequenzsteuerung auf dieser Maschine anders macht als erwartet. intel_pstate, der Treiber der bei Intel-CPUs normalerweise das Kommando übernimmt, läuft hier im passiven Modus:

cat /sys/devices/system/cpu/intel_pstate/status        # passive
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver # intel_cpufreq
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # schedutil

Passiv bedeutet: der Treiber verhält sich wie ein gewöhnlicher cpufreq-Treiber und lässt den Kernel-Governor entscheiden. Aktiv bedeutet, dass er die Entscheidung selbst trifft und dabei Hardware-Unterstützung nutzt. Aktiv ist normalerweise der bessere Modus, weil die CPU schneller reagiert als jeder Governor es könnte.

Der Kernel schaltet in den aktiven Modus, wenn die CPU HWP beherrscht, Hardware P-States. Ice Lake beherrscht das. Nur taucht das entsprechende Flag bei mir gar nicht auf:

grep -o hwp /proc/cpuinfo | head -1
#   (keine Ausgabe)

Ich hatte das eine Weile für eine Eigenheit des Kernels gehalten, für eine Frage der Xeon-Variante, für irgendetwas Kompliziertes. Es war nichts davon. Es war dieser eine Schalter, zwei Menüebenen tief in einem Untermenü, das ich beim ersten Mal nicht geöffnet hatte. Ich sag doch, ich bin auch nur doof.

Was tut HWP eigentlich? Ohne HWP sagt das Betriebssystem der CPU, welche Frequenz sie fahren soll. Mit HWP sagt es ihr nur noch, worauf es ihm ankommt, irgendwo zwischen Sparsamkeit und Leistung, und die CPU sucht sich den Rest selbst. Der Vorteil ist die Reaktionszeit: die Hardware sieht Lastwechsel im Mikrosekundenbereich, der Governor im Millisekundenbereich. Bei kurzen, stossweisen Lasten, wie sie ein Desktop dauernd produziert, macht das einen Unterschied.

Werde ich es umstellen? Vermutlich ja, aber nicht heute und nicht ohne Messung. Auf der alten Maschine hatte ich Ärger mit schedutil, der mir zu träge hochgetaktet hat, insofern habe ich eine Vermutung wohin es geht. Aber genau solche Vermutungen sind der Grund, warum man am Ende Dinge kaputtoptimiert. Erst messen, dann drehen.

C-States: das Nichtstun

Aptio Setup, CPU C State Control, mit Monitor MWAIT, C6 Report und Enhanced Halt State
Enable Monitor MWAIT              [Enable]
CPU C6 Report                     [Auto]
Enhanced Halt State (C1E)         [Enable]

P-States regeln, wie schnell die CPU arbeitet. C-States regeln, wie tief sie schläft wenn sie gerade nichts tut. Je höher die Nummer, desto mehr wird abgeschaltet und desto länger dauert das Aufwachen. Was auf meiner Maschine ankommt, steht im sysfs:

POLL   0 us
C1     1 us
C1E    4 us
C6   170 us

C6 ist der interessante: dort wird der Kernzustand weggeschrieben und der Kern faktisch abgeschaltet. Das spart richtig Strom, kostet aber 170 Mikrosekunden zum Aufwachen. Für einen Rechner unter dem Schreibtisch ist das vollkommen egal. Für einen Paketfilter, der Latenz im einstelligen Mikrosekundenbereich garantieren soll, ist es das nicht, und genau deshalb steht in Tuning-Anleitungen für Netzwerkkram regelmässig, man solle die tiefen C-States abschalten.

Enable Monitor MWAIT ist die Voraussetzung für den ganzen Mechanismus: MONITOR und MWAIT sind die beiden Befehle, mit denen ein Kern sagt „weck mich, wenn sich diese Speicherstelle ändert“ und sich danach schlafen legt. Ohne sie bleibt nur die alte HLT-Schleife.

Package C State [Auto] eine Menüebene weiter ist die Steigerung davon: nicht mehr einzelne Kerne, sondern das ganze Paket samt Uncore und Speichercontroller. Das geht natürlich nur, wenn wirklich alle Kerne gleichzeitig nichts tun.

T-States, und warum sie aus sind

Software Controlled T-States      [Disable]

Der dritte Buchstabe im Bunde, und der unangenehmste. T-States drosseln nicht die Frequenz, sondern schieben Pausen ein: die CPU bekommt für einen Teil der Zeit schlicht keinen Takt. Das ist deutlich brutaler als ein P-State und eigentlich eine Notbremse für den Fall, dass es zu heiss wird.

Auf Disable heisst, dass das Betriebssystem diese Notbremse nicht selbst ziehen darf. Der thermische Schutz der Hardware bleibt davon unberührt, der arbeitet unabhängig weiter. Bei Tjmax 103 Grad und CPU-Temperaturen um die 40 im Leerlauf ist das eine sehr theoretische Diskussion.

Der Rest

Frequency Prioritization
RAPL Prioritization               [Disable]

RAPL ist Intels Mechanismus zur Leistungsbegrenzung. Mit RAPL Prioritization verteilt die Firmware ein knappes Leistungsbudget gezielt auf einzelne Kerne, statt alle gleichmässig zu drosseln. Das ergibt Sinn, wenn man dauerhaft am Powerlimit fährt und weiss, welche Kerne die wichtige Arbeit machen. Meine Maschine ist von beidem weit entfernt.

Was ich mitnehme

Der ganze Block ist erstaunlich gut eingestellt für ein Board, das im Auslieferungszustand von einem Serverhersteller kam. SpeedStep an, Turbo an, C-States an, T-States aus, das würde ich genau so einstellen. Ob da Supermicro oder Thomas Krenn sich Mühe gegeben hat?

Der einzige echte Fund ist Hardware P-States [Disable]. Und der ist vor allem deshalb schön, weil er zeigt, wozu so ein Durchgang gut ist: ich habe seit Wochen ein Verhalten beobachtet, das mich gewundert hat, und die Ursache lag die ganze Zeit sichtbar in einem Menü. Ich musste nur hineinschauen.

Nächste Folge: der Speicher. ECC, Patrol Scrub, PPR, und die Frage warum 256 GB DDR4-3200 in dieser Maschine mit 2933 laufen, klingt ja falsch oder?

Siehe auch

Falls jemand von euch intel_pstate im aktiven Modus gegen schedutil gemessen hat, auf einem Xeon und nicht auf einem Notebook: erzähl mir davon, bevor ich es selbst ausprobiere. Ihr dürft mich gerne fragen.

BIOS erklärt, Teil 4: AES-NI, SGX, TME und ein Schalter der nichts bewirkt

In der letzten Folge ging es um die obere Hälfte der CPU-Seite, also Kerne, Threads und Prefetcher. Die untere Hälfte ist die spannendere, weil dort keine Leistungsschalter mehr stehen, sondern Sicherheitsfunktionen. Und weil mindestens einer davon eine richtig gute Geschichte hat.

Zur Erinnerung für alle die neu dazustossen: ich gehe hier das BIOS meines Supermicro-Serverboards durch, Themenblock für Themenblock, alle Folgen liegen unter BIOS & Firmware.

AES-NI, oder: der Grund warum es eine Karte gab

Aptio Setup, CPU Configuration, mit Hyper-Threading, den fünf Prefetchern und AES-NI
AES-NI                          [Enable]

Ein Schalter und dahinter steckt eine ganze Ära. AES-NI sind sechs zusätzliche Prozessorbefehle, die AES in Hardware rechnen statt in Software. Der Unterschied ist keine Feinheit, er liegt grob bei einer Grössenordnung, und obendrein sind die Hardwarebefehle immun gegen die Cache-Timing-Seitenkanäle, mit denen man Software-AES angreifen kann. Aber vor allem is et dann ers rischtig flott mit der Crypto.

Ob die CPU es kann und darf, sieht man sofort im OS mit:

grep -o ' aes ' /proc/cpuinfo | head -1
#    aes

Warum es diesen Schalter überhaupt gibt, ist eine berechtigte Frage. Man schaltet AES-NI ja nicht ab, weil man gern langsam verschlüsselt. Die ehrliche Antwort ist vermutlich, dass er aus einer Zeit stammt, in der AES-NI ein Unterscheidungsmerkmal zwischen Produktlinien war, und niemand hat ihn seitdem entfernt. Oder hat jemand eine bessere Erklärung?

Über genau diese Zeit habe ich hier schon geschrieben. In meinem Beitrag zur Intel QuickAssist 8950-SCCP steckt eine Karte, die es nur deshalb gab, weil manche CPUs kein AES-NI hatten. Wer 2013 ein NAS mit einer Atom-CPU verschlüsseln wollte, brauchte Hilfe. Heute ist der Schalter eine Formalie, damals war er die Grenze zwischen „geht“ und „geht nicht“.

Virtualisierung und ein Schalter der Vertrauen heisst

Intel Virtualization Technology [Enable]
Enable SMX                      [Disable]

Der erste ist VT-x, im Handbuch etwas altmodisch VMX und in einer noch älteren Fassung sogar Vanderpool Technology genannt, nach dem Codenamen von 2003. Ohne ihn läuft keine Hardware-Virtualisierung, also weder KVM noch VirtualBox mit brauchbarer Geschwindigkeit. Bleibt selbstverständlich an.

Der zweite ist interessanter. SMX steht für Safer Mode Extensions und ist die Grundlage für Intel TXT, Trusted Execution Technology. Vereinfacht gesagt geht es darum, dass eine Maschine beim Start beweisen kann, dass sie genau die Software geladen hat, die sie laden sollte. Ein gemessener Start, verankert in der Hardware, ähnlich wie Measured Boot mit einem TPM, nur eine Ebene tiefer.

Dabei ist mir etwas aufgefallen, das ich nicht restlos erklären kann. Im Setup steht SMX auf Disable. In /proc/cpuinfo steht das Flag smx trotzdem drin. Die naheliegende Deutung ist, dass das Flag die Fähigkeit der CPU beschreibt und der BIOS-Schalter nur die Freigabe, dass CPUID also weiterhin „kann ich“ meldet, während die Firmware „darfst du nicht“ sagt. Belegen kann ich das nicht, ich habe es nur beobachtet. Wer da genauer Bescheid weiss, immer her damit. Ich bin ja auch nur doof.

Speicherverschlüsselung, und warum SGX daran hängt

Total Memory Encryption (TME)   [Disabled]

TME verschlüsselt den kompletten Arbeitsspeicher. Der Schlüssel wird bei jedem Start neu erzeugt, liegt im Speichercontroller und verlässt die CPU nie. Für das Betriebssystem ist das unsichtbar, es merkt schlicht nichts davon.

Wogegen hilft das? Gegen Angriffe, die physisch am Speicher ansetzen. Der Klassiker ist der Cold-Boot-Angriff, bei dem man die Riegel kühlt, aus der laufenden Maschine reisst und in einem anderen Gerät ausliest, weil DRAM seinen Inhalt für Sekunden bis Minuten behält. Dazu kommt alles, was per DMA am Speicher horcht. Bei einem Server im fremden Rechenzentrum ist das kein theoretisches Szenario. Sucht das mal auf YouTube ist so, das sieht immer krass aus. Vielleicht kann ich so etwas selbst irgendwann mal probieren.

Bei mir steht es auf Disabled, und das ist der Werksdefault. Meine Maschine steht in meiner Wohnung, die Systemplatte ist ohnehin mit LUKS verschlüsselt, und das Angriffsmodell, gegen das TME hilft, setzt jemanden voraus der hier steht während die Kiste läuft. Falls das passiert, habe ich grössere Probleme. Reizvoll finde ich es trotzdem, denn die Kosten sind gering: die Verschlüsselung sitzt im Speichercontroller und macht sich in Messungen kaum bemerkbar.

Ein Detail, über das ich beim Lesen des Handbuchs gestolpert bin, erklärt den Aufbau des Menüs:

*If the feature above is set to Enabled, the next five features are displayed*

Erst wenn TME an ist, erscheinen die fünf Zeilen darunter, und dazu gehört auch SGX. Die Enklaven-Technik hängt hier also an der Speicherverschlüsselung. Das ergibt Sinn, denn der geschützte Speicherbereich einer Enklave muss ja gegen genau die Zugriffe abgesichert sein, die TME abdeckt. Im Setup sieht man davon nur eine flache Liste, im Handbuch die Abhängigkeit.

SGX, und wie Intel die UHD-Blu-ray auf dem PC beerdigt hat

SW Guard Extensions (SGX)       [Disabled]
SGX Factory Reset               [Disabled]
SGX Package Info In-Band Access [Disabled]

SGX ist die Idee, dass ein Programm einen Speicherbereich anlegen kann, in den niemand hineinsehen darf. Nicht andere Programme, nicht der Kernel, nicht der Hypervisor, nicht einmal jemand mit Root. Die CPU verschlüsselt den Bereich und gibt ihn nur dem Code frei, der ihn angelegt hat. Diese Enklaven waren als Fundament für vertrauliche Berechnungen in fremden Rechenzentren gedacht.

Die Geschichte drumherum ist allerdings die bessere. SGX war jahrelang in normalen Desktop-Prozessoren drin, und die prominenteste Anwendung war nicht vertrauliches Rechnen, sondern Kopierschutz. Die Wiedergabe einer Ultra-HD-Blu-ray auf dem PC verlangte SGX, weil der Schlüsselaustausch in einer Enklave passierte. Dann hat Intel SGX ab der elften Generation aus den Consumer-CPUs entfernt, und damit war die UHD-Blu-ray-Wiedergabe auf neuen PCs vorbei. Wer eine Scheibe abspielen wollte, brauchte plötzlich einen älteren Prozessor.

Ich finde das aus mehreren Gründen bemerkenswert. Erstens ist es ein schönes Beispiel dafür, wie eine Sicherheitstechnik zweckentfremdet wird und dann an einer Produktentscheidung stirbt, die mit ihrem eigentlichen Zweck nichts zu tun hat. Zweitens hat es Leute getroffen, die für ihre legal gekauften Scheiben plötzlich keinen legalen Abspielweg mehr hatten, während der inoffizielle Weg weiterhin problemlos funktionierte. Kopierschutz eben.

Im Xeon lebt SGX weiter, dort war es nie der Kopierschutz sondern das Verkaufsargument. Bei mir steht es trotzdem aus, weil ich keine Software habe die Enklaven nutzt, und weil es ohnehin nur zusammen mit TME ginge. Der Vollständigkeit halber, im laufenden System taucht folgerichtig nichts davon auf:

grep -c ' sgx' /proc/cpuinfo    # 0
ls /sys/devices/system/cpu/ | grep -c sgx    # 0

46 Bit, wegen Hyper-V

Limit CPU PA to 46 bits         [Enable]

PA steht für Physical Address. Der Schalter begrenzt die Breite der physischen Adressen auf 46 Bit, was 64 Terabyte adressierbarem Speicher entspricht. Bei 256 GB im Rechner ist das reichlich weit weg von jeder Grenze. 46 Bit und 64 Bit, da muss ich direkt an fe80 bei IPv6 denken und das man die Luft gelassen hat, weil MAC Adressen auch irgendwann zu wenige sind. Ok da sind es 48 Bit aber denken muss ich daran.

Die Begründung im Handbuch ist knapp und ziemlich entlarvend:

Use this feature to limit the CPU physical address to 46 bits to support older hyper-v.

Ältere Hyper-V-Versionen kamen mit breiteren Adressen nicht klar, also gibt es im BIOS eines Serverboards von 2021 einen Schalter, der die CPU künstlich einschränkt, damit eine bestimmte Microsoft-Software läuft. Das ist Abwärtskompatibilität in ihrer reinsten Form. Der Effekt lässt sich direkt nachlesen:

grep -m1 'address sizes' /proc/cpuinfo
#   address sizes : 46 bits physical, 57 bits virtual

46 physisch, wie eingestellt. Die 57 virtuellen Bit sind übrigens eine ganz andere Baustelle, das ist Five-Level Paging, ebenfalls neu mit Ice Lake.

Eine Seriennummer im Prozessor

Aptio Setup, untere Hälfte der CPU Configuration, mit TME, SGX, PPIN Control und Extended APIC
PPIN Control                    [Lock/Disable]

PPIN steht für Protected Processor Inventory Number, eine eindeutige Nummer pro physischer CPU. Gedacht ist sie für die Fehleranalyse in grossen Flotten: wenn ein Prozessor Speicherfehler meldet, will man wissen welcher es war, und zwar auch nachdem er längst ausgebaut wurde.

Eine eindeutige, unveränderliche Hardwarenummer ist allerdings genau die Sorte Datenpunkt, an der sich vor Jahren schon einmal die Gemüter erhitzt haben. Der Pentium III hatte eine Seriennummer, der Aufschrei war so gross, dass Intel sie wieder entfernt hat. PPIN ist die gleiche Idee, nur diesmal mit einem Schalter davor und beschränkt auf Serverprozessoren.

Hier ist mir eine Abweichung aufgefallen. Das Handbuch nennt als mögliche Werte:

The options are Unlock/Disable and Unlock/Enable.

Im Setup steht aber Lock/Disable, ein Wert den das Handbuch gar nicht kennt. Passend dazu fehlt im laufenden System das Flag:

grep -c intel_ppin /proc/cpuinfo    # 0

Meine Lesart: Lock bedeutet, dass das Register gesperrt ist und die Nummer nicht ausgelesen werden kann, und das Handbuch ist an dieser Stelle schlicht nicht auf dem Stand der Firmware. Für mich ist das der Wunschzustand, ich brauche keine Seriennummer und niemand sonst braucht sie von mir. Nur schön dokumentiert ist es eben nicht.

Und zum Schluss der Schalter, der nichts bewirkt

Extended APIC                   [Disable]

Das ist mein Lieblingsfund auf dieser Seite, weil er aussieht wie eine vergessene Optimierung. Der APIC ist der Interrupt-Controller. x2APIC ist seine erweiterte Fassung, die mehr adressierbare Prozessoren und schnelleren Zugriff über Register statt über den Speicher erlaubt. Auf Disable denkt man reflexhaft: aha, hier liegt Leistung brach, das schalte ich mal ein.

Nur ist die Funktion längst aktiv. Aus dem Kernel-Log meiner laufenden Maschine:

DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
DMAR-IR: Enabled IRQ remapping in x2apic mode
x2apic enabled
APIC: Switched APIC routing to: cluster x2apic

Der Grund ist eine Abhängigkeit, die man kennen muss: Interrupt-Remapping über VT-d verlangt x2APIC. Sobald der Kernel die IOMMU mit Interrupt-Remapping hochfährt, schaltet er x2APIC selbst ein, unabhängig davon was die Firmware vorher getan hat. Der BIOS-Schalter steuert nur, ob die Firmware das schon vorab macht. B.T.W.: habe ihr euch MMU beim Commodore C128 mal angeschaut?

Ich lasse ihn deshalb bewusst in Ruhe, und ich schreibe das hier so ausführlich auf, weil er genau die Art Schalter ist, an dem man beim nächsten Setup-Besuch wieder hängenbleibt und denkt, man hätte etwas übersehen. Hat man nicht.

Nächste Folge: Speicher. ECC, Patrol Scrub, und die Frage warum mein DDR4-3200 mit 2933 läuft und das völlig in Ordnung ist.

Siehe auch

Weiss jemand genauer, warum das smx-Flag in /proc/cpuinfo auftaucht obwohl der BIOS-Schalter auf Disable steht? Ich habe dazu keine belastbare Quelle gefunden und würde es gern richtig verstehen. Ihr dürft mich jederzeit fragen.

BIOS erklärt, Teil 3: acht Kerne, sechzehn Threads und fünf Prefetcher

Ein Detail, das mich an dieser Maschine bis heute amüsiert: die Kiste, die hier steht, hat weniger Kerne als die, die sie ersetzt hat. Vorher waren es zwei Xeon E5-2687W v3, zusammen 20 Kerne und 40 Threads. Jetzt ist es ein einzelner Xeon Gold 5315Y mit 8 Kernen und 16 Threads. Auf dem Papier ein deutlicher Rückschritt, in der Praxis für fast alles was ich mache ein Fortschritt, weil jeder einzelne Kern erheblich mehr leistet und weil PCIe 4.0 und 256 GB Speicher am Ende mehr wert sind als zwölf zusätzliche langsame Kerne.

Womit wir bei der Seite wären, um die es heute geht. Das hier ist die dritte Folge meiner Reise durch das BIOS dieses Supermicro-Boards, alle Teile stehen gesammelt unter BIOS & Firmware. Dran ist Advanced > CPU Configuration, und zwar die obere Hälfte. Die untere mit AES-NI, SGX und den Sicherheitsfunktionen bekommt die nächste Folge, sonst wird es zu lang.

Der Teil zum Anschauen

Aptio Setup, Processor Configuration, mit Prozessorsignatur, Takt, Mikrocode-Stand und den Cache-Grössen

Oben auf der Seite steht ein Block, an dem man nichts einstellen kann. Trotzdem lohnt sich der Blick, weil dort Dinge stehen, die man sonst zusammensuchen müsste:

Processor BSP Revision          606A6 - ICX M1
Processor ID                    000606A6
Processor Frequency             3.200GHz
Processor Max Ratio             20H
Processor Min Ratio             08H
Microcode Revision              0D000421
L1 Cache RAM(Per Core)          80KB
L2 Cache RAM(Per Core)          1280KB
L3 Cache RAM(Per Package)       12288KB

606A6 ist die Prozessorsignatur, aufgedröselt: Familie 6, Modell 6A, Stepping 6. ICX M1 ist Intels interne Bezeichnung dafür, ICX steht für Ice Lake. Die beiden Ratios sind Multiplikatoren in hexadezimal, 08H sind 8 und 20H sind 32. Mit dem üblichen Referenztakt von 100 MHz ergibt das 800 MHz im Leerlauf und 3,2 GHz als Basistakt. Genau diese Spanne meldet auch Linux:

lscpu | grep MHz
#   CPU max MHz:  3600,0000
#   CPU min MHz:   800,0000

Die 3600 oben drüber sind der Turbo, der geht über den Basisratio hinaus. Dazu mehr, sobald ich das Power-Management-Menü nachgereicht bekomme, das fehlt mir in meiner Aufzeichnung noch.

Am interessantesten finde ich die Cache-Zeilen. 1280 KB L2 pro Kern klingt viel, und das ist es auch. Bei Ice Lake hat Intel den L2 gegenüber der Vorgängergeneration deutlich aufgebohrt und im Gegenzug den gemeinsamen L3 kleiner gemacht. 12 MB L3 für acht Kerne sind für einen Xeon nicht üppig. Der Gedanke dahinter ist, dass Daten näher am Kern liegen und seltener über den Ring wandern müssen. Ob das für die eigene Last aufgeht, merkt man erst beim Messen, aber die Zahlen im Setup erzählen die Designentscheidung ziemlich direkt.

Das Microcode Revision 0D000421 ist übrigens der Wert, den auch Linux meldet:

grep -m1 microcode /proc/cpuinfo
#   microcode : 0xd000421

Das BIOS bringt also bereits den Mikrocode mit, den auch das Betriebssystem laden würde. Wer sich fragt, ob ein BIOS-Update wegen Mikrocode nötig wäre: hier eindeutig nein.

Kerne abschalten, in hexadezimal

Aptio Setup, CPU1 Core Disable Bitmap, mit dem Hinweis dass mindestens ein Kern aktiv bleiben muss
> CPU1 Core Disable Bitmap

Ein eigenes Untermenü mit genau einem Eintrag, und dieser Eintrag ist herrlich unhöflich. Das Handbuch beschreibt ihn so:

Select 0 to enable all cores or FFFFFFFFFFF to disable all cores. One core must be enabled.

Man gibt also eine Bitmaske in hexadezimal ein, in der jedes gesetzte Bit einen Kern abschaltet. Keine Auswahlliste, keine Zahl „wie viele Kerne hätten Sie gern“, eine Bitmaske. Und dann der wunderbare Nachsatz, dass mindestens ein Kern übrig bleiben muss, was man vermutlich nicht schreiben würde, wenn es nicht mal jemand ausprobiert hätte.

Wozu macht man so etwas? Der häufigste Grund ist Lizenzkosten. Es gibt genug Software, die pro Kern abgerechnet wird, und wenn eine Maschine dafür zu viele hat, schaltet man welche ab. Der zweite Grund ist Testen: Verhalten einer Anwendung auf weniger Kernen prüfen, ohne die Hardware zu tauschen. Bei mir steht das erwartungsgemäss auf 0, alle 16 logischen Prozessoren sind da:

cat /sys/devices/system/cpu/online     # 0-15
cat /sys/devices/system/cpu/offline    # leer

Wichtig zu verstehen ist der Unterschied zum Abschalten unter Linux. Wenn ich dort einen Kern offline nehme, existiert er weiter, er bekommt nur keine Arbeit mehr. Die Bitmaske im BIOS blendet ihn aus, bevor das Betriebssystem überhaupt startet. Für eine Lizenzzählung, die sich ansieht was die Maschine meldet, ist das ein Unterschied.

Hyper-Threading

Hyper-Threading [ALL]           [Enable]

Der bekannteste Schalter der Seite. Aus acht physischen Kernen werden sechzehn logische, weil jeder Kern zwei Befehlsströme gleichzeitig verwaltet und die Recheneinheiten teilt, die gerade nichts zu tun haben. Der Gewinn liegt je nach Last irgendwo zwischen nichts und dreissig Prozent.

Es gibt drei gute Gründe, das abzuschalten, und keiner davon trifft auf mich zu. Der erste sind Seitenkanalangriffe: mehrere der Spectre-Nachfolger nutzen aus, dass sich zwei Threads einen Kern teilen, und wer fremden Code auf seiner Maschine ausführen lässt, fährt ohne Hyper-Threading sicherer. Der zweite ist Latenz: bei harten Echtzeitanforderungen ist ein Kern, der sich mit niemandem abstimmen muss, berechenbarer. Der dritte sind wieder Lizenzen.

Für eine Workstation, auf der ich weiss was läuft, überwiegt der Durchsatz. Bleibt an.

Die fünf Prefetcher

Aptio Setup, CPU Configuration, mit Hyper-Threading, den fünf Prefetchern und AES-NI

Und jetzt der Teil, der wirklich interessant ist:

Hardware Prefetcher             [Enable]
Adjacent Cache Prefetch         [Enable]
DCU Streamer Prefetcher         [Enable]
DCU IP Prefetcher               [Enable]
LLC Prefetch                    [Enable]

Fünf Zeilen, die aussehen wie eine Liste von Marketingbegriffen und in Wirklichkeit fünf verschiedene Stücke Hardware beschreiben. Alle haben dieselbe Aufgabe: raten, welche Daten die CPU als nächstes braucht, und sie schon mal holen. Speicher ist quälend langsam gegenüber dem Prozessor, ein Zugriff der bis zum RAM durchschlägt kostet ein Vielfaches dessen, was aus dem Cache kommt. Jeder erfolgreiche Rateversuch spart diese Wartezeit.

Sie raten nur unterschiedlich:

  • Hardware Prefetcher ist der Streaming-Prefetcher für den L2. Er erkennt, dass ein Programm Speicher der Reihe nach durchläuft, und holt vorausschauend nach. Der klassische Fall ist eine Schleife über ein grosses Array.
  • Adjacent Cache Prefetch ist der simpelste von allen. Er holt zu jeder angeforderten 64-Byte-Cachezeile gleich die benachbarte mit, arbeitet also faktisch in 128-Byte-Blöcken. Die Wette lautet: wer diese Zeile braucht, braucht gleich auch die daneben.
  • DCU Streamer Prefetcher macht dasselbe wie der erste, aber eine Ebene näher am Kern, für den L1-Datencache. DCU steht für Data Cache Unit.
  • DCU IP Prefetcher ist der cleverste. IP steht hier für Instruction Pointer. Er merkt sich pro Befehl, welche Zugriffsmuster dieser Befehl in der Vergangenheit erzeugt hat, und extrapoliert daraus. Damit erwischt er auch Muster mit konstantem Abstand, etwa jedes achte Element einer Struktur, an denen ein reiner Streaming-Prefetcher scheitert.
  • LLC Prefetch zieht Daten in den gemeinsamen L3, den Last Level Cache.

Das Handbuch beschreibt den DCU IP Prefetcher übrigens als etwas, das „IP addresses“ vorlädt und damit „network connectivity“ verbessert. Das ist schlicht falsch, da hat jemand Instruction Pointer mit Internet Protocol verwechselt und den Satz nie wieder gelesen. Solche Sätze stehen in erstaunlich vielen Handbüchern, und sie sind eine gute Erinnerung daran, dass auch offizielle Dokumentation nur von Menschen geschrieben wird.

Die Gegenprobe: was davon kommt wirklich an

Das Schöne an diesen fünf Schaltern ist, dass man sie nicht glauben muss. Sie landen in einem Prozessorregister, und das kann man auslesen. MSR 0x1A4 heisst Prefetch Control, und die unteren vier Bits schalten die Prefetcher ab, wenn sie gesetzt sind:

modprobe msr
rdmsr -0 0x1a4
#   0000000000000000

Null. Kein Bit gesetzt, also kein Prefetcher abgeschaltet. Das deckt sich exakt mit dem, was das Setup anzeigt. Die Zuordnung ist Bit 0 für den Hardware Prefetcher, Bit 1 für Adjacent Cache Line, Bit 2 für den DCU Streamer und Bit 3 für den DCU IP Prefetcher. Man beachte die umgekehrte Logik: gesetztes Bit bedeutet aus.

Ich mag solche Gegenproben. Ein Screenshot zeigt, was das Setup behauptet. Das Register zeigt, was die CPU tatsächlich macht. Bei Firmware ist das nicht immer dasselbe.

Wann man daran drehen würde

Fast nie, ehrlich gesagt. Die Prefetcher sind für allgemeine Lasten deutlich im Plus, sonst hätte Intel sie nicht eingebaut. Es gibt aber Fälle, in denen sie schaden:

Bei Datenbanken und Graphen-Workloads mit stark zufälligem Zugriffsmuster liegt der Prefetcher regelmässig daneben, holt Daten die keiner braucht, und verdrängt dabei Daten die jemand gebraucht hätte. Bei Echtzeitanwendungen sind sie eine Jitter-Quelle, weil sie Speicherbandbreite zu unvorhersehbaren Zeitpunkten verbrauchen. Und bei manchen HPC-Codes, die ihre Zugriffe selbst sehr genau steuern, stört der Prefetcher mehr als er hilft.

Der entscheidende Punkt: das misst man, das rät man nicht. Und der grosse Vorteil des MSR ist, dass man dafür gar nicht ins BIOS muss. Man kann die Bits im laufenden System setzen, messen, und wieder zurücksetzen. Wer das ernsthaft ausprobiert, sollte allerdings wissen, dass wrmsr genau so gefährlich ist wie es klingt, und dass die Einstellung pro logischem Prozessor gilt.

Nächste Folge: die untere Hälfte derselben Seite. AES-NI, TME, SGX und ein Schalter namens Extended APIC, der aussieht wie eine vergessene Optimierung und keine ist.

Siehe auch

Hat jemand von euch schon mal Prefetcher gezielt abgeschaltet und dabei etwas gemessen, das sich gelohnt hat? Das würde mich wirklich interessieren, ihr dürft mich jederzeit fragen.

BIOS erklärt, Teil 2: Boot Feature, oder was ein Interrupt von 1981 hier noch tut

Der erste Start der neuen Maschine war laut. Nicht akustisch, sondern optisch: eine Wand aus weissem Text auf schwarzem Grund, Speichertest, Controller die sich melden, Netzwerkkarten die ihre MAC-Adressen ausspucken, und das alles über mehrere Bildschirmseiten. Bei einem Desktop-Board wäre da ein Herstellerlogo gewesen und darunter vielleicht ein dezenter Fortschrittsbalken. Ich habe die Textwand gelassen wie sie ist, und der Grund dafür steht in den ersten beiden Zeilen des Menüs, um das es heute geht.

Das hier ist Teil 2 der Serie, in der ich das BIOS meines Supermicro-Boards Stück für Stück durchgehe. Die bisherigen Folgen findest du gesammelt in der Kategorie BIOS & Firmware. Heute: Boot Feature, die erste Seite unter Advanced, neun Einstellungen rund um das Einschalten.

Die Anzeige, oder: warum ich kein Logo will

Aptio Setup, Seite Boot Feature, mit Quiet Boot, Wait for F1, INT19 Trap Response, Watchdog und Restore on AC Power Loss
Quiet Boot                        [Disabled]
Option ROM Messages               [Force BIOS]
Bootup NumLock State              [On]

Quiet Boot ist der Schalter für genau die Textwand von oben. Auf Enabled zeigt das Board beim Start ein Logo, auf Disabled die POST-Meldungen. Das Logo ist hübscher, aber es versteckt genau die Informationen, die man braucht wenn etwas nicht stimmt. Auf einer Maschine mit vier Netzwerkports, einem Beschleuniger und einer NVMe an einem Breakout-Kabel möchte ich beim Booten sehen, wer sich meldet und wer nicht. Das kostet mich drei Sekunden Wartezeit und hat mir schon zweimal eine Fehlersuche erspart.

Option ROM Messages ist der kleine Bruder davon. Steckkarten bringen eigene Firmware mit, das Option ROM, und die möchte beim Start etwas ausgeben. Force BIOS heisst: das BIOS bestimmt, wie diese Ausgaben aussehen und dass sie überhaupt erscheinen. Keep Current überlässt das der Karte. Auch hier gilt, ich möchte die Meldungen sehen.

Bootup NumLock State ist der harmloseste Schalter des ganzen Setups und trotzdem einer, über den sich Menschen erstaunlich zuverlässig streiten. Er legt fest, ob der Ziffernblock nach dem Einschalten an ist. Bei mir: an.

Wait For „F1“ If Error

Wait For "F1" If Error            [Disabled]

Das ist der Klassiker unter den Server-Fallstricken. Steht der Schalter auf Enabled und beim Start tritt irgendein Fehler auf, dann bleibt die Maschine stehen und wartet darauf, dass jemand F1 drückt. Bei einem Rechner unter dem Schreibtisch ist das ärgerlich. Bei einem Server im Rechenzentrum ist es der Grund, warum man nachts hinfährt.

Der Fehler muss dabei nicht dramatisch sein. Eine leere CMOS-Batterie reicht, oder eine Konfigurationsänderung, die das BIOS für erwähnenswert hält. Auf Disabled protokolliert das Board den Fehler und bootet trotzdem weiter. Für alles ohne Tastatur davor ist das die einzig sinnvolle Einstellung. Wer den Rechner täglich vor sich hat, kann anderer Meinung sein, dann merkt man wenigstens sofort dass etwas war.

Der Interrupt aus dem Jahr 1981

INT19 Trap Response               [Immediate]

Und hier wird es schön. Das Handbuch erklärt den Schalter so:

Interrupt 19 is the software interrupt that handles the boot disk function.

Interrupt 19h, genauer INT 19h, ist der Bootstrap Loader aus dem BIOS des originalen IBM PC von 1981. Der Ablauf war denkbar einfach: das BIOS beendet seinen Selbsttest und ruft INT 19h auf. Was dahinter liegt, lädt den ersten Sektor eines Laufwerks und übergibt die Kontrolle dorthin. Das war der komplette Bootvorgang.

Interessant wird es durch das, was Steckkarten daraus gemacht haben. Ein SCSI-Controller mit eigenem Option ROM konnte sich in INT 19h einhängen, den Aufruf abfangen und stattdessen von seiner eigenen Platte booten. Genau so wurden Karten bootfähig, ohne dass das Mainboard-BIOS je von ihnen gehört hatte. Immediate heisst, die Karte darf sich den Interrupt sofort greifen. Postponed heisst, sie muss warten bis das System-BIOS fertig ist.

Meine Maschine bootet im reinen UEFI-Modus, ohne CSM, und lädt einen EFI-Bootloader von der NVMe. INT 19h spielt dabei überhaupt keine Rolle mehr. Der Schalter ist trotzdem noch da, weil irgendwo auf der Welt noch eine Karte steckt, die ihn braucht. Ich mag solche Fundstücke. Man scrollt durch ein Setup von 2025 und stolpert über einen Mechanismus, der älter ist als die meisten Leute, die ihn konfigurieren.

Neustart bei Fehlschlag, und der Watchdog

Re-try Boot                       [Disabled]
Watch Dog Function                [Disabled]

Re-try Boot startet die Maschine automatisch neu, wenn der erste Bootversuch fehlschlägt. Klingt hilfreich, ist es in einer Endlosschleife aber nicht. Wenn die Bootplatte weg ist, dann ist sie auch beim vierzigsten Versuch weg, und ich bekomme statt einer klaren Fehlermeldung eine Maschine die im Sekundentakt neu startet. Auf Disabled bleibt sie stehen und sagt mir was los ist. Wer eine Maschine an einem Ort betreibt, an den er schlecht hinkommt, wägt das anders ab.

Der Watchdog ist ein anderes Kaliber. Laut Handbuch löst er nach fünf Minuten aus und macht dann wahlweise einen Reset oder einen NMI, also einen nicht maskierbaren Interrupt. Der Sinn dahinter: eine Software auf dem laufenden System muss den Timer regelmässig zurücksetzen. Passiert das nicht mehr, weil das System hängt, greift der Watchdog ein.

Der Haken ist der zweite Halbsatz. Es braucht diese Software. Ohne einen Dienst, der den Timer füttert, hat man einen Timer der nach fünf Minuten unangekündigt die Reset-Leitung zieht, und das ist keine Verfügbarkeitsmassnahme sondern eine Zeitbombe. Unter Linux gäbe es dafür watchdogd, und wenn ich das eines Tages sauber einrichte, schalte ich den Schalter an. Vorher nicht.

Zwei Schalter, die ich gar nicht sehe

Im Handbuch stehen an dieser Stelle noch Front USB Port(s) und Rear USB Port(s), mit denen sich die USB-Anschlüsse einzeln abschalten lassen. Auf einem Rechner an einem öffentlich zugänglichen Ort ist das eine ernstzunehmende Massnahme. In meinem Setup tauchen die beiden Zeilen nicht auf, und das Handbuch sagt auch warum:

The next two features are available for configuration if the SFT-DCMS-SINGLE license is installed.

Wer Teil 1 gelesen hat, kennt die Lizenz schon. Sie ist der Grund, warum ich meine BIOS-Konfiguration nicht maschinell auslesen kann. Dass sie zusätzlich zwei Sicherheitseinstellungen im Setup versteckt, hatte ich nicht erwartet. Das ist kein Management-Feature für Flottenbetreiber mehr, das ist eine Funktion des Boards, das ich gekauft habe, hinter einer Bezahlschranke im eigenen Setup.

Nach dem Stromausfall bleibt sie aus

Restore on AC Power Loss          [Stay Off]
Power Button Function             [4 Seconds Override]

Drei Möglichkeiten gibt es: Stay Off, Power On und Last State. Der Werksdefault ist Last State, also der Zustand von vor dem Stromausfall. Bei mir steht es auf Stay Off, und das ist eine bewusste Entscheidung gegen den naheliegenden Reflex.

Der Reflex sagt: klar soll die Maschine wieder hochkommen, sonst steht sie nach einem Stromausfall im Urlaub zwei Wochen tot herum. Für einen Server stimmt das auch. Für meine Workstation nicht. Wenn hier der Strom weg war, dann ist etwas passiert, und ich möchte selbst entscheiden wann und ob die Kiste wieder angeht. Dazu kommt der Fall, den man leicht übersieht: ein flatternder Strom, der mehrfach hintereinander kommt und geht. Mit Power On fährt das Board dann jedes Mal wieder an, mitten in den nächsten Ausfall hinein. Ein Rechner der aus ist, kann nicht kaputtgehen.

Beim Power Button Function habe ich 4 Seconds Override gelassen. Kurz drücken meldet dem Betriebssystem einen Shutdown-Wunsch, den es sauber abarbeitet. Vier Sekunden halten schneidet den Strom hart ab. Die Alternative Instant Off macht das sofort, ohne Rückfrage, und dafür sehe ich keinen Grund. Ein versehentlicher Stups ans Gehäuse soll keine ungespeicherte Arbeit kosten.

Fazit

Neun Schalter, davon acht auf Default und einer bewusst geändert. Das ist ungefähr die Quote, die sich durch das ganze Setup zieht, und sie ist auch in Ordnung so. Interessant sind trotzdem alle neun, weil hinter jedem eine Entscheidung steckt, die jemand mal getroffen hat.

Falls du beim Watchdog oder bei INT 19h anderer Meinung bist oder ich etwas verkürzt dargestellt habe: immer her damit. Besonders bei INT 19h würde mich interessieren, ob jemand noch aktiv Hardware betreibt, bei der Postponed einen Unterschied macht. Ich habe keine gefunden.

Nächste Folge: die CPU. Kerne, Threads und die fünf Prefetcher, von denen die Hälfte Namen trägt, die nach Marketing klingen und es nicht sind.

Siehe auch

Wie steht bei dir Restore on AC Power Loss, und aus welchem Grund? Schreib es mir gerne, ihr dürft mich jederzeit fragen.

Neunzehn Sekunden für einen Schlüssel: was der TPM-Chip unter Linux wirklich kann

TPM-2.0-Chip auf einem Mainboard mit Schlüssel und Stoppuhr, unter Linux als sicherer Hardware-Schlüsselspeicher und für Measured Boot genutzt, aber deutlich langsamer als die CPU bei der RSA-Schlüsselerzeugung.

Es gibt Dinge, die unter Linux in der breiten Masse vernachlässigt werden. Secure Boot ist so ein Beispiel, TPM ist ein anderes. Vielleicht ist es an der anfangs bescheidenen Unterstützung gescheitert, vieleicht sind die Themen technisch einfach unangenehm, am ehesten aber liegt es daran, dass der Mehrwert für die meisten überschaubar bleibt. Heute nehme ich mir den TPM vor.

Aufgefallen ist mir der Chip zweimal. Das erste Mal, als er durch die Medien ging, weil die Angst groß wurde, Microsoft mache damit unsere IT kaputt, und weil jemand anfing, sehr viele Patente einzureichen. Das zweite Mal viele Jahre später, als TPM 2.0 zur harten Voraussetzung für Windows 11 wurde. Dazwischen lagen zwanzig Jahre, in denen der Chip in fast jedes Endgerät gewandert ist, ohne dass sich jemand dafür interessiert hat.

In Notebooks und Fertig-PCs ist er heute meist fest verlötet. Bei Server-Mainboards kauft man ihn dagegen als Option dazu, ein kleines Steckmodul auf einem eigenen Header. Der Chip in meinem Testgerät ist ein Infineon OPTIGA SLB 9670, und genau dieselbe Chip-Familie sitzt auf den steckbaren TPM-Modulen für Supermicro-Boards. Damit schließt der Beitrag an die BIOS-Serie an, in der ich mich gerade Menü für Menü durch ein Serverboard arbeite.

Freigestelltes TPM-Steckmodul für einen Supermicro-Header, Beschriftungsseite mit „TPM2.0 SPI", „Trusted Platform Module 2" und „For Super".
Das nachgerüstete TPM-Modul für den JTPM1-Header, hier freigestellt. Auf der Rückseite steckt ein echter Infineon SLB9670. Bei vielen Server-Boards gehört der Chip nicht zum Lieferumfang.

Erst die Geschichte, dann die Hände in den Chip. Alle Ausgaben hier sind echt und stammen vom 10. August 2026, gemessen auf einem Fujitsu Celsius H780 mit Linux Mint 22.3, Kernel 7.0.0-28-generic und tpm2-tools 5.6. Wo ich etwas nur aus Dokumentation kenne oder wo ich vermute, steht das dabei.

Angefangen hat alles mit einer Seriennummer in der CPU

Mitte der neunziger Jahre wollte Intel eine Identifizierungsfunktion direkt in den Prozessor bringen. Der erste Schritt war 1999 die Prozessor-Seriennummer im Pentium III, eine eindeutige Kennung, die jede Software auslesen konnte. Der öffentliche Widerstand war so heftig, dass Intel zurückzog. Das Vorhaben verschwand aber nicht, es suchte Deckung in einem Konsortium. Dieses Detail ist wichtig, weil es das Muster für alles setzt, was danach kam.

1999 gründeten Compaq, HP, IBM, Intel und Microsoft die Trusted Computing Platform Alliance, kurz TCPA. Im April 2003 wurde daraus die Trusted Computing Group, TCG, getragen von AMD, HP, IBM, Intel und Microsoft. Aus einer Firmenidee war ein Industriestandard geworden.

Der Chip, der nach einem Senator benannt wurde

In der Debatte bekam der TPM den Spottnamen „Fritz-Chip“. Der Name ging auf den US-Senator Fritz Hollings aus South Carolina zurück, der den CBDTPA vorantrieb, ein Gesetzesvorhaben, das Kopierschutz in aller Consumer-Elektronik verpflichtend machen sollte. Der Spottname war also ein politischer Vorwurf und keine technische Bezeichnung. Er hat trotzdem länger gehalten als das Gesetz, aus dem er kam.

Vertrauen, aber nicht dein Vertrauen

Ross Anderson von der Universität Cambridge schrieb 2002 und 2003 die Trusted Computing FAQ. Dieses Dokument hat die Debatte stärker geprägt als jede Herstellerankündigung, und es liegt bis heute unverändert online. Sein Kernargument in einem Satz: bei „Trust“ geht es nicht darum, dass der Nutzer dem Rechner vertraut, sondern darum, dass der Rechner dem Nutzer nicht vertraut.

Richard Stallman legte 2002 mit „Can you trust your computer?“ nach und prägte den Gegenbegriff treacherous computing, verräterisches Rechnen. Die FSF benutzt ihn heute noch. IBM antwortete mit einer Gegendarstellung von David Safford, „Clarifying Misinformation on TCPA“.

Die EFF ging einen dritten Weg, und der ist der interessanteste. Seth Schoen veröffentlichte im Oktober 2003 Trusted Computing: Promise and Risk und schlug ein konkretes Feature vor, den Owner Override. Der Eigentümer des Rechners sollte die Attestierung überstimmen können, seinem Bank-Server also erzählen dürfen, sein Opera sei ein Internet Explorer. Die Kritik hatte damit einen Reparaturvorschlag und war nicht bloß dagegen. Die TCG hat den Owner Override nie übernommen.

Microsoft nannte sein eigenes Vorhaben Palladium und benannte es am 24. Januar 2003 in Next-Generation Secure Computing Base um, NGSCB. Der Name wurde harmloser, die Architektur blieb dieselbe.

Zwei Patente von 2001, und ein Cypherpunk der zurückschoss

Im Dezember 2001 wurden Microsoft zwei Patente erteilt. Das eine ist US 6,330,670, „Digital rights management operating system“, angemeldet im Januar 1999, erteilt am 11. Dezember 2001, als Erfinder Paul England, John DeTreville und Butler Lampson. Das andere ist US 6,327,652, „Loading and identifying a digital rights management operating system“. Zusammen decken sie viele Grundelemente eines vertrauenswürdigen Betriebssystems ab.

Die Sorge dahinter war handfest und nicht abwegig. Wenn Palladium unter dieses Patent fällt, dann verletzt jeder unabhängige Nachbau das Patent. Also jeder einzelne Entwickler, jedes Open-Source-Projekt, jeder Wettbewerber. Ohne Lizenz von Microsoft kein freies Trusted Computing. Kritiker beschrieben das damals als Kombination aus Patentschutz und faktischem Zwang zur Nutzung, mit deutlich wettbewerbsrechtlichem Geschmack.

Der Gegenzug kam im August 2002 von einem Cypherpunk, der unter dem Namen Lucky Green auftrat. Er meldete selbst ein Patent an, und zwar auf Verfahren, mit denen Software auf einer Palladium- oder TCPA-Plattform gegen Kopieren geschützt werden kann. Der Zweck war offen defensiv: wer die Ansprüche hält, kann verhindern, dass genau diese Anwendungen ausgerollt werden. Auf einem Panel der USENIX Security wurde er gefragt, ob Microsoft nicht einfach Prior Art geltend machen könne. Sein Argument: Prior Art müsste unter Eid erklärt werden, und nach Jahren Arbeit am Projekt und einem ausführlichen eigenen DRM-Patent sei kaum vorstellbar, dem Palladium-Team wäre relevante Prior Art entgangen. Im September 2002 hielt er zusätzlich einen Vortrag mit dem Titel „TCPA: the mother(board) of all Big Brothers“.

Was daraus geworden ist

Die Auflösung ist unbequemer, als es beide Lager damals gedacht haben. NGSCB ist gescheitert, aber nicht an den Patenten. Im Mai 2004 stellte Microsoft die vollständige Architektur zurück, und die Begründung war wirtschaftlich: die Hardware-Landschaft war nicht reif, und vor allem waren die unabhängigen Softwarehersteller nicht bereit, ihre Anwendungen auf die nötigen neuen APIs umzuschreiben. Curtained Memory und der Nexus-Kernel fielen weg, die TPM-Unterstützung blieb übrig.

Der Chip selbst wurde offen. Nach TPM 1.2 kam TPM 2.0, veröffentlicht 2014 und als ISO/IEC 11889 internationaler Standard. Die TCG stellt die Referenz-Implementierung unter eine royalty-free Copyright-Lizenz, das Patentregime zwischen den Mitgliedern ist RAND. Damit war der Nachbau möglich und dem Patenthebel die Grundlage entzogen.

Linux hat es dann einfach implementiert. Der Treiber tpm_tis sitzt im Kernel, IBM brachte TrouSerS für TPM 1.2, für TPM 2.0 entstand mit Beteiligung von Intel und TCG der tpm2-tss-Stack samt tpm2-tools. Seit Linux 4.12 gibt es den Resource Manager im Kernel unter /dev/tpmrm0, wodurch der frühere Userspace-Daemon tpm2-abrmd für die meisten Fälle überflüssig wurde. Nichts davon brauchte eine Lizenz von Microsoft.

Die befürchtete Abriegelung kam trotzdem, nur von woanders. Kein einziger der Horror-Fälle aus der TCPA-FAQ wurde durch den TPM Realität. Wo Nutzer heute tatsächlich ausgesperrt werden, steckt eine andere Technik dahinter: Widevine beim Streaming, Play Integrity und früher SafetyNet bei Android, verriegelte Bootloader bei Telefonen, die Secure Enclave bei Apple, Attestierung bei Spielkonsolen. Der TPM wurde stattdessen ein langweiliger Schlüsselspeicher.

Ein Teil der Angst hat sich dann doch erfüllt, nur in anderer Form. Windows 11 macht TPM 2.0 zur harten Voraussetzung, und damit gilt funktionierende Hardware plötzlich als nicht unterstützt. Das ist keine DRM-Geschichte, sondern eine Elektroschrott- und Lebensdauer-Geschichte. Der Mechanismus ist aber derselbe: eine Hardware-Eigenschaft entscheidet, was auf dem Gerät laufen darf.

Und dann kam der Kreis zurück. 2023 schlugen Chrome-Entwickler bei Google die Web Environment Integrity API vor. Der Browser sollte sich von einer Vertrauensinstanz einen Nachweis über seine Umgebung ausstellen lassen, den Webseiten dann prüfen können. Das ist praktisch Wort für Wort das Szenario, vor dem Anderson zwanzig Jahre früher gewarnt hatte, nur ohne TPM. Nach massivem Widerstand zog Google den Vorschlag im November 2023 für Chromium auf dem Desktop zurück.

Hat die Patentanmeldung von damals also geholfen?

Das ist die Frage, mit der ich in die Recherche gegangen bin, und die Antwort ist zweiteilig. Die defensive Patentanmeldung hat, soweit öffentlich nachvollziehbar, nichts bewirkt. Es gibt kein erteiltes Patent, das man heute als den Grund benennen könnte, warum TCPA-DRM nicht kam. Der Gegenzug war eine wirksame Geste, aber kein wirksames Rechtsmittel. Gewirkt hat etwas anderes: erstens die Wirtschaftlichkeit, weil die Softwarehersteller nicht umschreiben wollten und es damit kein Produkt gab, zweitens die Öffnung der Spezifikation und die ISO-Standardisierung, die den Nachbau erlaubten.

Der zweite Teil verdient Anerkennung. Die Kampagne selbst hat gewirkt, nur nicht juristisch, sondern politisch. Der Lärm um TCPA hat plausibel dazu beigetragen, dass die TCG die Spezifikation öffnete, die aggressivsten Ideen fallen ließ und dass Fernattestierung zwanzig Jahre lang aus dem Consumer-Web draußen blieb. Als der Versuch 2023 mit Web Environment Integrity wiederkam, war das Muster des Widerstands eingeübt und der Vorschlag nach Monaten weg. Wichtig dabei: das ist meine Deutung. Die Kausalkette von der Kampagne 2002 zur offenen Spezifikation 2014 ist nirgends dokumentiert, das ist ein Plausibilitätsargument und keine Messung.

Bleibt der Eindruck: die Angst war berechtigt und falsch adressiert. Berechtigt, weil die Mechanik der Fernattestierung tatsächlich genau das kann, was befürchtet wurde. Falsch adressiert, weil der TPM davon der harmloseste Teil war und am Ende zu dem wurde, was jetzt kommt. Ein langsamer, sturer kleiner Chip, der Schlüssel nicht herausgibt.

Erst suchen, ganz ohne TPM-Werkzeug

Bevor ihr irgendetwas installiert: der Kernel weiß längst, ob da ein Chip sitzt. Er sagt es beim Start.

# dmesg | grep -i tpm
[    0.000000] efi: ACPI=0x7990e000 ACPI 2.0=0x7990e014 TPMFinalLog=0x713bb000 SMBIOS=0x7035e000 SMBIOS 3.0=0x7035b000 ESRT=0x70358c98 MEMATTR=0x5f5c2018 MOKvar=0x70323000 INITRD=0x592eda98 RNG=0x798ce018 TPMEventLog=0x798c0018
[    0.010528] ACPI: SSDT 0x0000000079905000 000554 (v01 INTEL  Tpm2Tabl 00001000 INTL 20160422)
[    0.010531] ACPI: TPM2 0x0000000079904000 000034 (v04 FUJ    PC       01170000 FUJ  00000001)
[    0.010607] ACPI: Reserving TPM2 table memory at [mem 0x79904000-0x79904033]
[    0.569145] tpm_tis MSFT0101:00: 2.0 TPM (device-id 0x1B, rev-id 16)

Drei Dinge stehen da drin. In der ersten Zeile übergibt UEFI die Adresse des Event-Logs, TPMEventLog=0x798c0018, also der Liste aller Messungen aus dem Startvorgang. Dann die ACPI-Tabelle TPM2, über die die Firmware mitteilt, wo und wie der Chip ansprechbar ist. Und in der letzten Zeile das Ergebnis: der Treiber tpm_tis hat unter der ACPI-Kennung MSFT0101 ein TPM der Version 2.0 gefunden.

Danach existieren zwei Gerätedateien, und der Unterschied zwischen ihnen ist wichtig.

# ls -la /dev/tpm*
crw-rw---- 1 tss root  10,   224 Aug 10 09:31 /dev/tpm0
crw-rw---- 1 tss tss  252, 65536 Aug 10 09:31 /dev/tpmrm0

/dev/tpm0 ist der rohe Zugang zum Chip. Daran kann genau ein Prozess gleichzeitig arbeiten, und wer die Ressourcen im Chip verwaltet, ist selbst dafür verantwortlich. /dev/tpmrm0 geht über den Resource Manager im Kernel, der das Ein- und Auslagern der Schlüssel-Kontexte übernimmt und mehrere Nutzer nebeneinander erlaubt. In der Praxis nimmt man immer /dev/tpmrm0, und die tpm2-tools tun das von sich aus.

Die Version steht ebenfalls im sysfs, und die solltet ihr prüfen, bevor ihr weiterlest.

# ls /sys/class/tpm/tpm0/
dev  device  pcr-sha1  pcr-sha256  power  ppi  subsystem  tpm_version_major  uevent

# cat /sys/class/tpm/tpm0/tpm_version_major
2

Eine 2 heißt TPM 2.0 und alles in diesem Beitrag gilt. Eine 1 heißt TPM 1.2, und dann gilt fast nichts davon, weil es ein anderer Standard mit einem anderen Software-Stack ist. Nebenbei verrät das Verzeichnis noch etwas: es gibt eine pcr-sha1– und eine pcr-sha256-Bank, der Chip führt die Messregister also in zwei Hash-Verfahren parallel.

Und weil der Kernel das ohnehin bereitstellt, kommt hier der erste kleine Aha-Moment, noch ganz ohne installiertes Paket. Die Messwerte des Startvorgangs liegen als Dateien herum.

# cat /sys/class/tpm/tpm0/pcr-sha256/0
7DE4ABE4ED8D8291D9B58D71F3B2988F5DA81EBE58D4AE518012E877FA1E04F1
# cat /sys/class/tpm/tpm0/pcr-sha256/1
41CBF90AFF5CEEFAA9E9C52E7A3D5B4C8518EA65861C753AF8DB005C5330F53F
# cat /sys/class/tpm/tpm0/pcr-sha256/7
F5841722D3DCC8886F14E92CA2D7304932CF17E2247A85D3B7BB41FE2C02CB4E

Das sind drei der Platform Configuration Register, kurz PCR. Merkt euch den Wert von PCR 7, der taucht später mehrfach auf.

Die Falle mit lsmod

Das ist eine häufige Fehldiagnose, deshalb steht sie hier als eigener Punkt. Auf meinem Testsystem liefert lsmod | grep tpm nämlich schlicht nichts. Kein Modul, keine Ausgabe. Der Chip arbeitet trotzdem einwandfrei, weil tpm_tis in diesen Kernel fest eingebaut ist und deshalb in der Modulliste gar nicht erscheinen kann. Wer nach lsmod urteilt, hält ein funktionierendes TPM für abwesend. Fragt stattdessen nach der Treiberbindung.

# ls -l /sys/class/tpm/tpm0/device/driver
lrwxrwxrwx 1 root root 0 Aug 10 09:31 /sys/class/tpm/tpm0/device/driver -> ../../../bus/platform/drivers/tpm_tis

# cat /sys/class/tpm/tpm0/device/modalias
acpi:MSFT0101:MSFT0101:

Der Symlink zeigt, welcher Treiber das Gerät tatsächlich bedient. Das ist die Antwort auf die Frage, die lsmod nicht beantworten kann.

Wenn nichts auftaucht

Bleibt dmesg stumm und existiert kein /dev/tpm0, dann gibt es drei realistische Ursachen, in dieser Reihenfolge.

  • Im Firmware-Setup abgeschaltet. Die Option heißt je nach Hersteller „Security Device Support“, „TPM State“, „Trusted Computing“, „PTT“ oder „fTPM“. Wo diese Menüs bei einem Serverboard liegen und wie man sich dort zurechtfindet, habe ich in der BIOS-Serie ausführlich aufgeschrieben.
  • Physisch nicht vorhanden. Bei Server-Boards ist der TPM oft ein steckbares Modul auf einem eigenen Header, bei Supermicro etwa die AOM-TPM-Module auf dem Anschluss JTPM1. Wer ihn nicht mitbestellt hat, hat einen leeren Steckplatz. Bei Notebooks ist der Chip dagegen fast immer verlötet.
  • Vorhanden, aber als fTPM in der CPU statt als eigener Chip. Woran man das unterscheidet, steht weiter unten, und man liest es an einer einzigen Zeile ab.

Zwei Details aus dem Firmware-Setup, die hier gut passen. Erstens sind SHA-1-Bank und SHA-256-Bank oft getrennt schaltbar. Dass mein Testgerät beide Banks führt, ist also keine Selbstverständlichkeit, sondern eine Einstellung. Zweitens steht in demselben Menü meist ein TPM Clear. Finger weg, solange ihr nicht genau wisst, was daran hängt. Ein Clear wirft die Hierarchien im Chip weg, und damit ist alles, was gegen diesen Chip versiegelt war, unwiederbringlich verloren. Auch der BitLocker-Schlüssel eines parallel installierten Windows.

Die Schichten, bevor das erste Paket installiert wird

Es hilft, den Stack einmal von unten nach oben gesehen zu haben. Sonst installiert man ein Paket und wundert sich später, welche der vielen Bibliotheken wofür zuständig ist.

Schichtmodell vom Infineon SLB 9670 über den Kerneltreiber tpm_tis und die Gerätedateien bis zu tpm2-tools, tpm2-openssl und tpm2-pkcs11
Der Weg eines Kommandos vom Werkzeug bis in den Chip. Über /dev/tpm0 arbeitet genau ein Prozess, über /dev/tpmrm0 mehrere.

Ganz unten der Chip, darüber der Kerneltreiber, darüber die beiden Gerätedateien. Erst dann kommt Userspace: die TCTI-Schicht kümmert sich um den Transport zur Gerätedatei, die ESAPI-Schicht um Kommandos, Sessions und HMAC-Absicherung. Ganz oben die drei Werkzeuge, die man tatsächlich in die Hand nimmt. Für die Pflichtausstattung reichen zwei Pakete.

PaketWofür
tpm2-toolsdie tpm2_*-Kommandozeile, alles in diesem Beitrag läuft darüber
libtss2-*der TSS2-Stack darunter, meist schon über systemd installiert

Dazu zwei optionale, die ich beide benutze, weil sie den Chip an Software anschließen, die von TPM nichts wissen muss.

PaketWofür
tpm2-opensslProvider für OpenSSL 3, Schlüssel im Chip über die gewohnten openssl-Aufrufe
libtpm2-pkcs11-1 und libtpm2-pkcs11-toolsPKCS#11-Schnittstelle, damit SSH und Browser den Chip nutzen können

Und zwei, die ich ausdrücklich nicht installiere.

PaketWarum nicht
tpm2-abrmdResource Manager im Userspace mit D-Bus-Schnittstelle. Seit Linux 4.12 macht der Kernel das über /dev/tpmrm0 selbst. Das Projekt ist nicht tot, es wird weiter gepflegt und ist für Simulatoren, Tests und manche Integrationen nach wie vor sinnvoll. Beides parallel zu betreiben führt aber zu Konflikten, deshalb hier bewusst nur der Kernel-Weg.
clevis, clevis-tpm2binden ausschließlich LUKS2-Header. Ohne LUKS nutzlos, und auf diesem Gerät gibt es kein LUKS.
# apt-get install -y tpm2-tools tpm2-openssl libtpm2-pkcs11-1 libtpm2-pkcs11-tools

Auf meinem Mint 22.3 sind damit tpm2-tools 5.6, tpm2-openssl 1.2.0 und tpm2-pkcs11 1.9.0 gelandet. Der TSS2-Stack war schon da, den bringt systemd mit. Auf Fedora und RHEL heißt das Hauptpaket ebenfalls tpm2-tools, dazu tpm2-tss, unter Arch genauso tpm2-tools mit tpm2-tss als Abhängigkeit.

Eine Kleinigkeit, über die jeder beim ersten Mal stolpert: /dev/tpmrm0 gehört tss:tss. Entweder arbeitet ihr mit sudo, oder ihr nehmt euren Benutzer in die Gruppe tss auf. Die Rechte in der Ausgabe von ls -la /dev/tpm* weiter oben sagen genau das, crw-rw---- und keine Rechte für alle anderen.

Spricht der Chip?

Es gibt drei Stufen, aufsteigend im Aussagewert. Die erste ist der Lebenstest.

# tpm2_getrandom --hex 16

Kommen 16 Bytes zurück, dann funktioniert die ganze Kette von der Bibliothek über die Gerätedatei bis in die Hardware. Der Zufall kommt dabei wirklich aus dem Chip, und er ist gemächlich, dazu unten die Zahlen. Stufe zwei ist tpm2_getcap properties-fixed, da sagt der Chip, wer er ist. Stufe drei ist tpm2_getcap properties-variable, da sagt er, in welchem Zustand er ist. Beide sind gleich interessant, nur aus unterschiedlichen Gründen.

Wer ist dieser Chip

# tpm2_getcap properties-fixed
TPM2_PT_FAMILY_INDICATOR:
  raw: 0x322E3000
  value: "2.0"
TPM2_PT_LEVEL:
  raw: 0
TPM2_PT_REVISION:
  raw: 0x74
  value: 1.16
TPM2_PT_DAY_OF_YEAR:
  raw: 0x109
TPM2_PT_YEAR:
  raw: 0x7E0
TPM2_PT_MANUFACTURER:
  raw: 0x49465800
  value: "IFX"
TPM2_PT_VENDOR_STRING_1:
  raw: 0x534C4239
  value: "SLB9"
TPM2_PT_VENDOR_STRING_2:
  raw: 0x36373000
  value: "670"
TPM2_PT_VENDOR_TPM_TYPE:
  raw: 0x0
TPM2_PT_FIRMWARE_VERSION_1:
  raw: 0x7003F
TPM2_PT_FIRMWARE_VERSION_2:
  raw: 0xD1900
TPM2_PT_INPUT_BUFFER:
  raw: 0x400
TPM2_PT_HR_TRANSIENT_MIN:
  raw: 0x3
TPM2_PT_HR_PERSISTENT_MIN:
  raw: 0x7
TPM2_PT_ACTIVE_SESSIONS_MAX:
  raw: 0x40
TPM2_PT_PCR_COUNT:
  raw: 0x18
TPM2_PT_NV_COUNTERS_MAX:
  raw: 0x8
TPM2_PT_NV_INDEX_MAX:
  raw: 0x680

Rohe Hex-Werte, die plötzlich Sinn ergeben, wenn man sie einmal übersetzt. Das ist einer meiner Lieblingsmomente an dem ganzen Thema.

  • TPM2_PT_MANUFACTURER: 0x49465800 ist ASCII IFX, also Infineon.
  • VENDOR_STRING_1 und _2 ergeben zusammengesetzt SLB9 und 670, also ein Infineon OPTIGA SLB 9670.
  • TPM2_PT_REVISION: 0x74 ist Spezifikations-Revision 1.16, datiert auf Tag 265 des Jahres 2016.
  • FIRMWARE_VERSION_1: 0x7003F ist Firmware 7.63.
  • TPM2_PT_PCR_COUNT: 0x18 sind 24 PCRs.
  • TPM2_PT_HR_PERSISTENT_MIN: 0x7 heißt, dass nur sieben persistente Schlüsselplätze garantiert sind. Diese Zahl wird später richtig wichtig.
  • TPM2_PT_NV_COUNTERS_MAX: 0x8 sind genau acht monotone Zähler.

Und dann TPM2_PT_NV_INDEX_MAX: 0x680, also 1664. Hier lauert eine Fehldeutung, die in vielen Texten steht: das ist nicht der gesamte NV-Speicher des Chips, sondern die maximale Größe eines einzelnen NV-Index-Datenbereichs. Wie viel NV insgesamt frei ist, sagt diese Eigenschaft überhaupt nicht. Das steht im Datenblatt des Herstellers und liegt bei diesem Chip im Bereich einiger Kilobyte. Ich habe es nicht ermittelt, also behaupte ich hier auch keine Gesamtgröße.

Diskreter Chip oder fTPM in der CPU

Diese Unterscheidung ist keine Nebensächlichkeit, und man liest sie direkt am Hersteller-String ab.

Hersteller-StringWas es ist
IFX, NTC, STM, IBMdiskreter Chip auf dem Board oder auf einem Steckmodul
INTCIntel Platform Trust Technology, läuft in der Management Engine
AMDAMD fTPM, läuft im Platform Security Processor

Ein diskreter Chip hängt an einem physischen Bus, den man anzapfen kann. Ein fTPM hat diesen Bus nicht, dafür hat er andere Probleme. Beides kommt im Angriffs-Abschnitt zurück.

Für mein Testsystem ist die Sache klar: IFX, also ein diskreter Infineon SLB 9670. Aus Linux-Sicht hängt er als memory-mapped TIS an der ACPI-Kennung MSFT0101 und wird von tpm_tis bedient. Ob die physische Leitung dahinter LPC oder SPI ist, lässt sich aus dem Betriebssystem allein nicht entscheiden, weil der PCH einen SPI-TPM auch als MMIO-TIS durchreichen kann. Das ist also plausibel, aber nicht gemessen. Die einzige echte Antwort wäre ein Foto vom offenen Gerät, und dafür müsste das Notebook auseinander.

32 Fehlversuche, und deshalb reicht eine kurze PIN

Jetzt der Zustand, und das ist der wichtigste einzelne Abschnitt des ganzen Beitrags, weil er später alles trägt.

# tpm2_getcap properties-variable
TPM2_PT_PERMANENT:
  ownerAuthSet:              0
  endorsementAuthSet:        0
TPM2_PT_STARTUP_CLEAR:
  phEnable:                  1
  shEnable:                  1
TPM2_PT_LOCKOUT_COUNTER: 0x0
TPM2_PT_MAX_AUTH_FAIL: 0x20
TPM2_PT_LOCKOUT_INTERVAL: 0x1C20
TPM2_PT_LOCKOUT_RECOVERY: 0x15180

Diese drei Werte werden fast immer verwechselt, also einmal sauber.

  • MAX_AUTH_FAIL: 0x20 sind 32 fehlgeschlagene Authentifizierungsversuche, danach sperrt der Chip.
  • LOCKOUT_INTERVAL: 0x1C20 sind 7200 Sekunden, also 2 Stunden. Nach dieser Zeit wird der Fehlerzähler um genau eins verringert.
  • LOCKOUT_RECOVERY: 0x15180 sind 86400 Sekunden, also 24 Stunden. Das ist aber nicht die Erholung des normalen Zählers, sondern die Wartezeit, bevor nach einem fehlgeschlagenen Versuch mit lockoutAuth erneut mit lockoutAuth gearbeitet werden darf.

Einmal vorgerechnet, weil die Zahlen so viel deutlicher sind: ein einzelner Fehlversuch altert nach 2 Stunden aus. Von 32 verbrauchten Versuchen zurück auf null dauert also 64 Stunden und nicht 24.

Und das ist der eigentliche Mehrwert des ganzen Bauteils. Der Chip zählt Fehlversuche und sperrt. Deshalb reicht bei einem TPM eine sechsstellige PIN, wo ein Passwort-Hash auf der Platte eine Passphrase mit hoher Entropie bräuchte. Wer die Platte hat, probiert Millionen Passphrasen pro Sekunde durch. Wer vor dem TPM sitzt, bekommt 32 Versuche und darf dann zwei Stunden warten, um einen einzigen zurückzubekommen. Die Stärke kommt nicht aus dem Geheimnis, sie kommt aus der Hardware, die das Raten unterbindet. Fast jeder Text über TPM lässt diesen Punkt weg, und dann klingt die kurze PIN nach Leichtsinn.

Das Geburtszertifikat des Chips

Jetzt kommt der Teil, den ich in keinem der üblichen TPM-Howtos gesehen habe. In dem Chip liegt ab Werk ein Zertifikat, ausgestellt vom Hersteller auf den Endorsement Key. Erst die Liste der belegten NV-Indizes, dann das Zertifikat selbst.

# tpm2_getcap handles-nv-index
- 0x1410001
- 0x1410002
- 0x1410003
- 0x1800100
- 0x1810008
- 0x1820002
- 0x1880001
- 0x1880011
- 0x1C00002
- 0x1C0000A
- 0x1C10102
- 0x1C10103
- 0x1C10104
- 0x1C10105

# tpm2_nvreadpublic 0x1C00002
0x1c00002:
  name: 000bcfecbb34d24d7356b39b8a0fb0c82c7b052a0335fc8ca2fa602cf1395e5ff804
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: ppwrite|writedefine|ppread|ownerread|authread|no_da|written|platformcreate
    value: 0x62072001
  size: 1184

0x1C00002 ist der TCG-Standardindex für das RSA-EK-Zertifikat, 0x1C0000A derselbe für ECC. 1184 Bytes, das passt zu einem X.509-Zertifikat. Also raus damit und mit gewohnten Werkzeugen anschauen.

# tpm2_nvread 0x1C00002 -o ek_rsa.der
WARN: Reading full size of the NV index

# openssl x509 -inform der -in ek_rsa.der -noout -subject -issuer -dates
subject=
issuer=C = DE, O = Infineon Technologies AG, OU = OPTIGA(TM) TPM2.0, CN = Infineon OPTIGA(TM) RSA Manufacturing CA 035
notBefore=Aug 21 14:09:40 2019 GMT
notAfter=Aug 21 14:09:40 2034 GMT

Zwei Dinge fallen sofort auf. Der Aussteller ist eine echte Hersteller-CA, „Infineon OPTIGA(TM) RSA Manufacturing CA 035“, und Infineon hat diesen Chip am 21. August 2019 signiert. Und der Subject ist leer. Ein TPM hat keinen Namen. Die Identität steckt woanders, nämlich in den Erweiterungen.

# openssl x509 -inform der -in ek_rsa.der -noout -text
            X509v3 Key Usage: critical
                Key Encipherment
            X509v3 Subject Alternative Name: critical
                DirName:/2.23.133.2.1=id:49465800/2.23.133.2.2=SLB 9670 TPM2.0/2.23.133.2.3=id:073f
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 CRL Distribution Points:
                Full Name:
                  URI:http://pki.infineon.com/OptigaRsaMfrCA035/OptigaRsaMfrCA035.crl
            X509v3 Certificate Policies:
                Policy: 1.2.276.0.68.1.20.1
            X509v3 Extended Key Usage:
                2.23.133.8.1

Der Subject Alternative Name trägt drei TCG-OIDs, und die decken sich exakt mit dem, was der Chip vorher selbst über sich gesagt hat. 2.23.133.2.1 ist der Hersteller, id:49465800, also wieder IFX. 2.23.133.2.2 ist das Modell, SLB 9670 TPM2.0. 2.23.133.2.3 ist die Firmware, id:073f, was genau die 7.63 von oben bestätigt. Die Extended Key Usage 2.23.133.8.1 ist tcg-kp-EKCertificate, dieses Zertifikat darf also nichts anderes sein als der Nachweis eines Endorsement Keys. Und Infineon veröffentlicht dazu eine Sperrliste.

Was ich hier bewusst weglasse, sind die Zertifikats-Seriennummer und der öffentliche EK-Schlüssel. Beide kennzeichnen dauerhaft und eindeutig genau dieses eine Notebook, und die TCG behandelt den EK aus genau diesem Grund als datenschutzrelevant. Damit erklärt sich beiläufig, warum es überhaupt Attestierungsschlüssel gibt: damit man für eine Attestierung nicht jedes Mal die dauerhafte Chip-Identität vorzeigen muss.

Das hier ist die Wurzel, auf der Fernattestierung aufsetzt. Ein Prüfer kann feststellen, dass in dieser Maschine ein echter, von Infineon signierter TPM sitzt, ohne dem Betriebssystem eine einzige Zeile zu glauben. Genau formuliert beweist das Zertifikat aber nur die Echtheit des Chips. Dass ein bestimmter Attestierungsschlüssel wirklich in diesem Chip liegt, ist ein zusätzlicher Schritt, und den nehme ich mir im Server-Teil vor.

Drei Dinge, alles andere ist Kombination

Bevor irgendein Anwendungsfall kommt: ein TPM bietet im Kern nur drei Dinge an. Alles, was danach als Feature verkauft wird, ist eine Kombination daraus.

  • Schlüssel, die nicht herauskommen. Ein Schlüssel mit dem Attribut fixedTPM wird im Chip erzeugt und verlässt ihn nie. Man kann ihn benutzen, man kann ihn nicht kopieren.
  • PCRs, Register die nur wachsen. 24 Register, hier mit SHA-1- und SHA-256-Bank. Man kann sie nicht setzen, nur erweitern, und die Rechenvorschrift dafür ist neu = hash(alt || messwert). Bei den Registern, auf die es ankommt, nämlich PCR 0 bis 15 auf einer PC-Client-Plattform, geht es nur über einen Neustart zurück. Deshalb kann man die Boot-Historie nicht nachträglich fälschen. Zwei Ausnahmen gehören dazu, sonst wird es ungenau: PCR 16 und PCR 23 sind zur Laufzeit zurücksetzbar. PCR 16 ist ausdrücklich als Debug-Register vorgesehen, und genau deshalb benutze ich es weiter unten für die Demonstration. Gegen ein zurücksetzbares PCR versiegelt niemand etwas Echtes.
  • Sealing, Geheimnisse an einen Zustand binden. Ein Geheimnis wird so verschlüsselt, dass der Chip es nur herausgibt, wenn eine Policy erfüllt ist, typischerweise ein bestimmter PCR-Zustand.

Dazu kommen als Nebenfunktionen die schon erwähnten monotonen Zähler, ein winziger NV-Speicher, ein Zufallszahlengenerator und die Lockout-Logik von oben.

Und weil es das häufigste Missverständnis überhaupt ist, gleich früh und deutlich: ein TPM ist kein Krypto-Beschleuniger, keine Secure Enclave mit eigener Rechenumgebung und kein Schutz gegen einen kompromittierten laufenden Kernel. Er schützt Schlüssel im Ruhezustand und er misst den Startvorgang. Wenn der laufende Kernel übernommen ist, benutzt der Angreifer den TPM einfach mit, ganz höflich über dieselbe Schnittstelle.

Measured Boot in acht Befehlen

Genug Theorie, jetzt der Beweis. Ich baue eine Policy aus dem aktuellen Zustand von PCR 7, erzeuge einen Primary Key im Chip und versiegle damit ein Geheimnis.

# tpm2_startauthsession -S session.ctx
# tpm2_policypcr -S session.ctx -l sha256:7 -L pcr7.policy
76a916a90c7c0906a930cd5cd3e501cb43007331a8b7444222d8aa4c5475f53f
# tpm2_flushcontext session.ctx

Der Hash ist die Policy, und er hängt am Inhalt von PCR 7. Dann der Schlüssel, und ich messe gleich mit, weil die Zahl später noch gebraucht wird.

# time tpm2_createprimary -C o -g sha256 -G ecc256 -c primary.ctx
  value: aes
  raw: 0x6
sym-mode:
  value: cfb
  raw: 0x43
sym-keybits: 128
x: 2be770ed8755bf6f454cb1fea18ba722526d1ee3e9080ab94edda0480b73529d
y: af840b9c69dcac45c9aa3a04085ced5c750bfef5e70c470e4481592ff3026dc7

real	0m0.537s
# echo -n "geheim-nur-bei-diesem-boot" > secret.txt
# tpm2_create -C primary.ctx -g sha256 -u seal.pub -r seal.priv -L pcr7.policy -i secret.txt
keyedhash: ef1dc0bffd0d7529a6d0b44f79bdd14fb8829995c998ffb14d88936f82d3e9f3
authorization policy: 76a916a90c7c0906a930cd5cd3e501cb43007331a8b7444222d8aa4c5475f53f

# tpm2_load -C primary.ctx -u seal.pub -r seal.priv -c seal.ctx
name: 000b50ac9b197a947de6d2ff47d9d80748d4fa1453754bee5f3a8627e307cf8c84fd

# tpm2_startauthsession --policy-session -S s.ctx
# tpm2_policypcr -S s.ctx -l sha256:7
# tpm2_unseal -p session:s.ctx -c seal.ctx
geheim-nur-bei-diesem-boot

Das Geheimnis kommt zurück, weil PCR 7 noch genau den Wert hat, gegen den versiegelt wurde. Schön, beweist aber noch nichts. Interessant wird es erst, wenn sich die Messung ändert.

Dafür wechsle ich auf PCR 16, das Debug-Register. Der Grund ist praktisch: PCR 16 lässt sich ohne Neustart und ohne Firmware-Änderung erweitern, damit ist die Demonstration in einer einzigen Terminal-Sitzung reproduzierbar. Der Mechanismus ist derselbe wie bei PCR 7.

# tpm2_pcrread sha256:16
  sha256:
    16: 0x0000000000000000000000000000000000000000000000000000000000000000

# tpm2_startauthsession -S t.ctx
# tpm2_policypcr -S t.ctx -l sha256:16 -L pcr16.policy
# tpm2_flushcontext t.ctx
# echo -n "unlock-key-material" > s16.txt
# tpm2_create -C primary.ctx -g sha256 -u s16.pub -r s16.priv -L pcr16.policy -i s16.txt
# tpm2_load -C primary.ctx -u s16.pub -r s16.priv -c s16.ctx
# tpm2_startauthsession --policy-session -S p.ctx
# tpm2_policypcr -S p.ctx -l sha256:16
# tpm2_unseal -p session:p.ctx -c s16.ctx
unlock-key-material
# tpm2_flushcontext p.ctx

Und jetzt ändere ich die Messung. Das folgende Kommando ist genau das, was ein ausgetauschter Bootloader auch täte, nur mit einem selbstgewählten Messwert.

# tpm2_pcrextend 16:sha256=$(echo -n "boese-veraenderung" | sha256sum | cut -d" " -f1)
# tpm2_pcrread sha256:16
  sha256:
    16: 0xC6FE6738E4DDC92E1C8E18E290469CCB6B6D305BC1295C4F72B85D0922C25930

Derselbe Unseal-Aufruf wie zwei Blöcke vorher, Zeichen für Zeichen identisch:

# tpm2_startauthsession --policy-session -S p2.ctx
# tpm2_policypcr -S p2.ctx -l sha256:16
# tpm2_unseal -p session:p2.ctx -c s16.ctx
WARNING:esys:src/tss2-esys/api/Esys_Unseal.c:295:Esys_Unseal_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_Unseal.c:98:Esys_Unseal() Esys Finish ErrorCode (0x0000099d)
ERROR: Esys_Unseal(0x99D) - tpm:session(1):a policy check failed
ERROR: Unable to run tpm2_unseal
exit=1

0x99D ist TPM_RC_POLICY_FAIL. Das Geheimnis liegt noch im Blob, es ist nicht gelöscht, es ist nur unerreichbar, solange PCR 16 diesen Wert trägt. Und jetzt der Punkt, auf den es mir ankommt: das ist keine Zugriffskontrolle im Betriebssystem. Da hat kein Dateisystem eine Berechtigung geprüft und kein Dienst eine Regel angewendet. Das ist eine Weigerung der Hardware. Sudo hilft hier nicht, weil root für diese Entscheidung überhaupt nicht zuständig ist.

Firmware, Bootloader und Kernel messen in PCR 7, PCR 4 und PCR 11, daraus entsteht die Policy, die beim Entsiegeln entweder aufgeht oder mit 0x99D scheitert
Wer was misst, und was am Ende über das Entsiegeln entscheidet.

Und wenn ich das Register einfach zurücksetze?

Das ist die Frage, die jeder aufmerksame Leser an dieser Stelle stellt, und sie ist völlig berechtigt. Bei PCR 16 geht das tatsächlich, ohne Neustart.

# tpm2_pcrread sha256:16
  sha256:
    16: 0xC6FE6738E4DDC92E1C8E18E290469CCB6B6D305BC1295C4F72B85D0922C25930
# tpm2_pcrreset 16
# echo $?
0
# tpm2_pcrread sha256:16
  sha256:
    16: 0x0000000000000000000000000000000000000000000000000000000000000000

Dasselbe Kommando gegen PCR 7 lehnt die Hardware ab.

# tpm2_pcrreset 7
ERROR: Esys_PCR_Reset(0x907) - tpm:warn(2.0): bad locality
ERROR: Could not reset PCR index: 7
ERROR: Unable to run tpm2_pcrreset

0x907 ist TPM_RC_LOCALITY. Der Chip unterscheidet, aus welcher Vertrauensstufe ein Kommando kommt, und root auf dem laufenden System hat die Locality, die zum Zurücksetzen eines Boot-Mess-Registers nötig wäre, gar nicht. Das ist der ganze Unterschied zwischen einem Debug-Register und einem Boot-Mess-Register, ausgedrückt in einer Fehlermeldung.

Terminalausgabe: tpm2_pcrreset 16 setzt das Register auf Null zurück, tpm2_pcrreset 7 scheitert mit 0x907 bad locality
PCR 16 lässt sich zurücksetzen, PCR 7 nicht. Root ändert daran nichts.

Die Platte startet ohne Passphrase, aber nur mit PIN

Der Klassiker am Arbeitsplatz ist LUKS2 zusammen mit systemd-cryptenroll. Der Nutzen ist echt: das Notebook startet ohne Eingabe, und ein ausgebautes Laufwerk bleibt trotzdem verschlüsselt.

# systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 --tpm2-with-pin=yes /dev/nvme0n1pX

Ehrlichkeit an dieser Stelle: dieses Kommando habe ich nicht ausgeführt, und ich konnte es auch nicht. Die Maschine hat gar kein LUKS, die Wurzel liegt auf ZFS mit der ZFS-eigenen Verschlüsselung, aes-256-gcm. Der Befehl steht hier also als dokumentiertes Verfahren nach Manpage und nicht als Messung.

Das Wichtigste daran ist das --tpm2-with-pin=yes. Ohne PIN entsperrt sich das Gerät für jeden, der es einschaltet, und die Festplattenverschlüsselung schützt dann nur noch gegen den Ausbau der SSD, nicht gegen den Diebstahl des Rechners. Mit PIN greift die Lockout-Logik von weiter oben, und genau dadurch wird eine kurze PIN sicher.

Bei der Auswahl der PCRs gibt es dann einen echten Zielkonflikt, der meist verschwiegen wird.

  • Nur PCR 7 gebunden übersteht Kernel-Updates, misst aber im Kern nur den Secure-Boot-Zustand. Das ist wenig Aussage für viel Bequemlichkeit.
  • PCR 7 plus 11 gebunden, zusammen mit einem Unified Kernel Image, erfasst tatsächlich Kernel und initrd. Dafür bricht jedes Kernel-Update die Bindung, wenn man nicht mit signierter Policy arbeitet. Eine wichtige Präzisierung dazu, sonst erklärt man die Folgen falsch: PCR 11 ist kein reines Kernel-Register. systemd-stub misst dort das UKI hinein, danach schreibt systemd-pcrphase im Verlauf des Startvorgangs weitere Phasen-Messungen in dasselbe Register. Der Wert von PCR 11 hängt also davon ab, in welcher Boot-Phase man ihn liest, und genau darauf beruht der Trick, dass ein Geheimnis nur im initrd aufgeht und im laufenden System nicht mehr.
  • PCR 0 bis 7 gebunden ist die strengste Variante, und dann sperrt euch jedes BIOS-Update aus. Das ist der Grund, warum es systemd-pcrlock gibt, das die erwarteten Messwerte vorab berechnet und die Policy nachzieht. Dieselbe Manpage bezeichnet sich allerdings selbst noch als experimentell.

Wer welches Register wofür benutzt, hat die UAPI Group in einer PCR-Registry für Linux zusammengetragen. Das ist die Tabelle, die man beim Basteln offen haben will.

Eine Lücke betrifft ziemlich viele Linux-Nutzer, deshalb sage ich sie deutlich: systemd-cryptenroll und clevis luks bind schreiben beide in einen LUKS2-Header. Wer seine Wurzel auf ZFS-Native-Encryption hat, hat keinen. Upstream-ZFS bringt keine TPM-Integration mit. Ein TPM-gestütztes Entsperren bräuchte dort ein eigenes tpm2_unseal, das zfs load-key füttert, gebaut ins initramfs. Das ist eine echte offene Baustelle und kein Rezept, das ich hier nebenbei hinschreibe.

Ein SSH-Schlüssel, der keine Datei hat

Das ist mein Lieblings-Anwendungsfall am Arbeitsplatz, weil der Nutzen in einem Satz erklärt ist. Ein Angreifer mit Lesezugriff auf ~/.ssh bekommt nichts Verwendbares. Der Schlüssel kann die Maschine nicht verlassen. Er ist nicht gestohlen, er ist an das Blech gebunden.

# export TPM2_PKCS11_STORE=/root/tpm-demo/pkcs11store
# mkdir -p $TPM2_PKCS11_STORE
# tpm2_ptool init --path=$TPM2_PKCS11_STORE
action: Created
id: 1

# tpm2_ptool addtoken --pid=1 --label=ssh --sopin=sopin123 --userpin=userpin123 --path=$TPM2_PKCS11_STORE
# tpm2_ptool addkey --algorithm=ecc256 --label=ssh --userpin=userpin123 --path=$TPM2_PKCS11_STORE
public:
  CKA_ID: '63316131396137363763316531666439'

Die CKA_ID wird pro Schlüssel erzeugt, bei euch steht dort etwas anderes. Den öffentlichen Teil holt man sich in einem Format, das sshd versteht, direkt über den PKCS#11-Provider.

# ssh-keygen -D /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO+enW3ZwHsSq8vHLKliloTMR/fpDgWPfti+UQuad0YA8rIXGE8Q9adJqjO6PmZO1DCavBiJgttOE24qrO6BX/0=

Diese Zeile wandert wie gewohnt in authorized_keys. Und damit der Nachweis auch etwas wert ist, zeige ich ihn als Vorher und Nachher. Auf dieser Maschine liegt in /root/.ssh nämlich kein einziger privater Schlüssel, es gibt also keine zweite Erklärung für einen erfolgreichen Public-Key-Login.

# ls /root/.ssh/id_*
ls: cannot access '/root/.ssh/id_*': No such file or directory

# ssh -o BatchMode=yes root@localhost true
root@localhost: Permission denied (publickey,password).

Derselbe Login, nur mit dem Provider dazu:

# ssh -o PKCS11Provider=/usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so root@localhost 'echo LOGIN-OK-VIA-TPM; hostname; id -un'
LOGIN-OK-VIA-TPM
ErrorLap
root

Die PIN habe ich für diesen Test über SSH_ASKPASS nicht interaktiv geliefert, im Alltag fragt ssh einfach danach. Richtig sehenswert wird es aber mit -v, denn da erzählt OpenSSH selbst, mit welchem Bauteil es gerade arbeitet.

debug1: provider /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so: manufacturerID <tpm2-software.github.io> cryptokiVersion 2.40 libraryDescription <TPM2.0 Cryptoki> libraryVersion 1.9
debug1: provider /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so slot 0: label <ssh> manufacturerID <Infineon> model <SLB9670> serial <0000000000000000> flags 0x40d
debug1: Will attempt key:  ECDSA SHA256:otJuTNX5LzFzJKqbTu9UoYROpZSXMMWIWMZUe02v1D4 token
debug1: Will attempt key: /root/.ssh/id_rsa
debug1: Will attempt key: /root/.ssh/id_ecdsa
debug1: Will attempt key: /root/.ssh/id_ed25519
debug1: Will attempt key: /root/.ssh/id_dsa
debug1: Offering public key:  ECDSA SHA256:otJuTNX5LzFzJKqbTu9UoYROpZSXMMWIWMZUe02v1D4 token
debug1: Server accepts key:  ECDSA SHA256:otJuTNX5LzFzJKqbTu9UoYROpZSXMMWIWMZUe02v1D4 token

Drei Sachen daran finde ich stark. Erstens nennt OpenSSH den Chip beim Namen, manufacturerID <Infineon> model <SLB9670>. Der SSH-Client sagt dir, welches Bauteil da gerade unterschreibt. Zweitens steht der TPM-Schlüssel in der Kandidatenliste mit dem Wort token, wo bei allen anderen ein Dateipfad steht, und diese Dateien existieren nicht einmal. Dieser Kontrast in einem Bildschirm ist das ganze Argument: dieser Schlüssel hat keine Datei. Drittens wird der Token-Schlüssel zuerst probiert, noch vor den nicht existierenden Dateien.

Ausgabe von ssh -v: OpenSSH nennt manufacturerID Infineon und model SLB9670, der Schlüssel steht als token in der Kandidatenliste neben Dateipfaden unter /root/.ssh
OpenSSH nennt Hersteller und Modell des Chips. Der Schlüssel steht als token in der Liste, alle anderen Kandidaten sind Dateien, die es nicht gibt.

Lasst mal kurz etwas heraus zoomen 😀 Meine Frau weist mich grade auf mein RBF hin. Wenn ich so konzentriert am Computer sitze und wie in diesem Fall etwas schreibe, dann schaue ich wohl meinen Monitor an, als wenn ich ihn gleich töten möchte. Tjo, und nun? Nun zoomen wir wieder ins Thema!

Die Zahl, die meine eigene Erwartung widerlegt hat

Meine Annahme vor der Messung war schlicht: eine ECDSA-Signatur kostet im Chip rund 97 Millisekunden, also merkt man beim Login nichts. Gemessen kommt etwas anderes heraus.

Weg5 Loginspro LoginAufschlag
Schlüssel auf der Platte, Referenzwert1,552 setwa 310 msReferenz
PKCS11Provider bei jedem Aufruf8,013 setwa 1603 msetwa 1293 ms
Token einmal im ssh-agent2,806 setwa 561 msetwa 251 ms

Die Ursache ist lehrreich. Bei PKCS11Provider baut ssh bei jedem einzelnen Login die komplette Kette neu auf: Store öffnen, Primary Key im TPM erzeugen, Kindschlüssel laden, signieren. Allein die Erzeugung des Primary Keys habe ich weiter oben mit 0,537 Sekunden gemessen. Die eigentliche Signatur ist damit der kleinste Posten in der Rechnung.

# ssh-add -s /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so
Card added: /usr/lib/x86_64-linux-gnu/pkcs11/libtpm2_pkcs11.so
# ssh-add -l
256 SHA256:otJuTNX5LzFzJKqbTu9UoYROpZSXMMWIWMZUe02v1D4 /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1.9.0 (ECDSA)
# time (for i in 1 2 3 4 5; do ssh root@localhost true; done)
real	0m2.806s

Mit ssh-add -s passiert diese Initialisierung einmal pro Sitzung statt einmal pro Verbindung, und die PIN wird auch nur einmal abgefragt. Zwei Gründe, dieselbe Empfehlung, also ganz klar: nehmt ssh-add -s und nicht PKCS11Provider bei jedem Aufruf.

Zur Messhygiene, wie immer: fünf Logins pro Zeile über Loopback, jeweils mit vollem Verbindungsaufbau und Prozessstart, kleine Stichprobe, keine Streuung berechnet. Das sind Größenordnungen und keine Benchmarks.

Der Nebeneffekt, den niemand erwähnt

Diesen Punkt habe ich selbst erst beim Aufräumen gemerkt, und jeder, der dem SSH-Abschnitt folgt, läuft hinein. tpm2_ptool init legt stillschweigend einen Primary Key an und macht ihn persistent im Chip. Vor der Demo waren drei persistente Handles belegt, danach vier.

# tpm2_getcap handles-persistent
- 0x81000000
- 0x81000001
- 0x81000002
- 0x81010001

Und jetzt zurück zu einer Zahl von weiter oben: TPM2_PT_HR_PERSISTENT_MIN ist auf diesem Chip 0x7. Garantiert sind also nur sieben persistente Plätze, und drei davon waren schon vorher weg. Wer bei jedem Basteln ein Handle liegen lässt, macht den Chip irgendwann voll. Den eigenen Müll findet und räumt man so weg:

# tpm2_evictcontrol -C o -c 0x81000000
persistent-handle: 0x81000000
action: evicted

# tpm2_getcap handles-persistent
- 0x81000001
- 0x81000002
- 0x81010001

Dazu eine Warnung, die ich nicht deutlich genug schreiben kann: räumt niemals Handles weg, die ihr nicht selbst angelegt habt. Die drei anderen lagen auf meinem Gerät schon vorher dort, vermutlich aus der Hersteller-Provisionierung oder aus einem früheren Windows-Leben. Wer einen fremden Primary Key entfernt, vernichtet alles, was darunter versiegelt war. Der sichere Weg führt über den Token-Store, denn dort steht das Handle drin, das zum eigenen Werkzeug gehört. Bei mir war es genau das 0x81000000 aus der Ausgabe oben, und ich habe vor dem Entfernen im Store nachgesehen, statt der Reihenfolge zu vertrauen.

Schlüssel im Chip, benutzt über OpenSSL

Für alles, was kein PKCS#11 spricht, gibt es den OpenSSL-3-Provider. Der schönste Moment daran ist ein PEM-Header.

# openssl list -providers -provider tpm2
Providers:
  tpm2
    name: TPM 2.0 Provider
    version: 1.2.0
    status: active

# openssl genpkey -provider tpm2 -algorithm EC -pkeyopt group:P-256 -out tpmkey.pem
# head -2 tpmkey.pem
-----BEGIN TSS2 PRIVATE KEY-----
MIHPBgZngQUKAQOgAwEBAQIEQAAAAQRYAFYAIwALAAYAcgAAABAAEAADABAAINLL

Diese Datei enthält keinen privaten Schlüssel. Sie enthält einen Blob, den ausschließlich dieser eine Chip auspacken kann. Kopiert die Datei auf eine andere Maschine und sie ist wertlos. Signieren geht im Chip, prüfen geht überall.

# printf "attestiere-mich" > d.bin
# openssl pkeyutl -provider tpm2 -provider default -sign -inkey tpmkey.pem -rawin -digest sha256 -in d.bin -out d.sig
# stat -c%s d.sig
70
# openssl pkey -provider tpm2 -provider default -in tpmkey.pem -pubout -out tpmkey.pub.pem
# openssl pkeyutl -verify -pubin -inkey tpmkey.pub.pem -rawin -digest sha256 -in d.bin -sigfile d.sig
Signature Verified Successfully

Zum Prüfen habe ich nur den Standard-Provider gebraucht. Es ist eine ganz normale ECDSA-Signatur, die Gegenseite muss von einem TPM überhaupt nichts wissen. Deshalb lässt sich das in bestehende PKI einbauen, ohne irgendetwas umzustellen, und damit gehen Client-Zertifikate für VPN, 802.1X, mTLS und auch AWS IAM Roles Anywhere.

Der Zufallsgenerator, ehrlich klein geredet

Auf diesem System ist der TPM tatsächlich der Hardware-Zufallsgenerator, den der Kernel benutzt.

# cat /sys/class/misc/hw_random/rng_available
tpm-rng-0 none
# cat /sys/class/misc/hw_random/rng_current
tpm-rng-0

Der Nutzen davon ist vorhanden, aber klein. Moderne CPUs haben RDRAND, der Kernel hat einen guten Entropiepool, und rund 67 Millisekunden pro tpm2_getrandom-Aufruf sind für nichts geeignet, was Durchsatz braucht. Als zusätzliche, unabhängige Quelle im Pool ist es geschenkt und in Ordnung. Mehr würde ich daraus nicht machen.

Fernattestierung, der eigentliche große Fall

Auf Servern liegt der größere Nutzen, nicht am Arbeitsplatz. Das Problem zuerst: bei einer Kiste im Rechenzentrum oder in der Colo weiß man normalerweise nicht, ob sie noch die Software fährt, die man dort installiert hat. Alles, was man fragen kann, ist der Server selbst. Und wenn er kompromittiert ist, lügt er.

Der TPM löst das, weil er eine Aussage über den Startvorgang signiert, die das Betriebssystem nicht fälschen kann. Zwei Schlüssel braucht es dafür: den Endorsement Key als Chip-Identität und einen Attestierungsschlüssel, mit dem tatsächlich signiert wird.

# tpm2_createek -c ek.ctx -G rsa -u ek.pub
# tpm2_createak -C ek.ctx -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub -n ak.name
loaded-key:
  name: 000b76c23ef9e6c736e89085381db5c9303c6aca84dd4b18785cbcd5820666146650
  qualified name: 000bfce15794118492a81739a638c4745d23eeffda268ef1d016f22bc07c7a0b5e65

Der qualified name ist didaktisch schön, weil er die Abstammung des Schlüssels von seinem Elternschlüssel mit einbezieht. Jetzt das Quote, mit einer Nonce, die sich der Prüfer ausdenkt. Ich nehme deadbeef in Hex.

# tpm2_quote -c ak.ctx -l sha256:0,1,4,7 -q 6465616462656566 -m quote.msg -s quote.sig -o pcr.bin -g sha256
quoted: ff54434780180022000bfce15794118492a81739a638c4745d23eeffda268ef1d016f22bc07c7a0b5e650008646561646265656600000002acc0c6460000020500000000010007003f000d190000000001000b0393000000201a782856983a34bde88eb32ea706d6863119ee0309e3e8296f0021d34ec896d5
pcrs:
  sha256:
    0 : 0x7DE4ABE4ED8D8291D9B58D71F3B2988F5DA81EBE58D4AE518012E877FA1E04F1
    1 : 0x41CBF90AFF5CEEFAA9E9C52E7A3D5B4C8518EA65861C753AF8DB005C5330F53F
    4 : 0xCDB9366A1664E6B6AE408E3DF98F2E5FF47BCD6F0EA19ACBABE643DE586853DD
    7 : 0xF5841722D3DCC8886F14E92CA2D7304932CF17E2247A85D3B7BB41FE2C02CB4E
calcDigest: 1a782856983a34bde88eb32ea706d6863119ee0309e3e8296f0021d34ec896d5

Der quoted-Blob sieht wie Rauschen aus, ist aber lesbar, wenn man weiß wo man hinschaut.

  • ff544347 ist die Konstante TPM_GENERATED_VALUE und markiert die Struktur als im TPM entstanden. Wichtig für das Verständnis: sie allein verhindert keine Fälschung. Der Schutz entsteht daraus, dass ein Attestierungsschlüssel ein restricted Signaturschlüssel ist, der nur Daten unterschreibt, die der Chip selbst erzeugt hat. Diese Konstante ist das Erkennungsmerkmal dafür und nicht der Mechanismus.
  • 8018 ist TPM2_ST_ATTEST_QUOTE, der Strukturtyp.
  • 6465616462656566 ist meine Nonce, unverändert zurück. Genau das schlägt einen Replay.
  • 07003f000d1900 ist die Firmware-Version, die in jedem Quote mitläuft. Das ist wieder die 7.63 von oben.

Geprüft wird offline, und zwar mit nichts als dem öffentlichen Attestierungsschlüssel.

# tpm2_readpublic -c ak.ctx -o ak.pem -f pem
# tpm2_checkquote -u ak.pem -m quote.msg -s quote.sig -f pcr.bin -g sha256 -q 6465616462656566
pcrs:
  sha256:
    0 : 0x7DE4ABE4ED8D8291D9B58D71F3B2988F5DA81EBE58D4AE518012E877FA1E04F1
    1 : 0x41CBF90AFF5CEEFAA9E9C52E7A3D5B4C8518EA65861C753AF8DB005C5330F53F
    4 : 0xCDB9366A1664E6B6AE408E3DF98F2E5FF47BCD6F0EA19ACBABE643DE586853DD
    7 : 0xF5841722D3DCC8886F14E92CA2D7304932CF17E2247A85D3B7BB41FE2C02CB4E
exit=0
Ablaufdiagramm zwischen Verifier, Agent, TPM und der Infineon-CA, von der Nonce über das signierte Quote bis zur Entscheidung vertrauenswürdig oder Quarantäne
Der Ablauf einer Attestierung. Der Prüfer glaubt dem Knoten nichts, er rechnet nach.

Die Lücke, die fast jedes Howto verschweigt

Und hier muss ich mich selbst bremsen, denn die Versuchung ist groß, die beiden vorherigen Abschnitte einfach nebeneinanderzulegen und „echte Hardware bestätigt echten Bootzustand“ daraus zu machen. Das wäre eine Beweiskette mit einem Loch in der Mitte.

tpm2_checkquote mit dem öffentlichen Attestierungsschlüssel beweist genau eine Sache: irgendjemand, der diesen Schlüssel besitzt, hat dieses Quote signiert. Es beweist nicht, dass dieser Schlüssel in demselben Chip steckt, dessen Infineon-Zertifikat ich weiter oben gezeigt habe.

Die fehlende Verbindung heißt Credential Activation. Der Prüfer verschlüsselt dabei ein Geheimnis so, dass es nur ausgepackt werden kann, wenn Endorsement Key und Attestierungsschlüssel im selben TPM liegen, klassisch über TPM2_MakeCredential auf der Prüferseite und TPM2_ActivateCredential auf der Knotenseite. Erst wenn der Knoten das Geheimnis zurückmelden kann, ist bewiesen, dass der Schlüssel zu diesem zertifizierten Chip gehört. Alternativ stellt eine Attestierungs-CA ein echtes AK-Zertifikat aus, nachdem sie diese Prüfung einmal gemacht hat. Wie das im Detail aussieht, steht in RFC 9683. Diesen Schritt habe ich hier nicht durchgeführt. Gemessen sind Quote und Signaturprüfung, die Bindung ist dokumentiertes Verfahren.

Keylime, vier Rollen und ein Prüfer der nicht aufhört

Genau diesen Schritt macht Keylime, und genau deshalb ist Keylime mehr als ein Skript um tpm2_quote herum. Die Architektur hat vier Rollen: einen Agent auf dem Knoten, einen Registrar, einen Verifier und einen Tenant. Der Agent schickt Event-Log, IMA-Hashes und Measured-Boot-Daten, der lokale TPM bürgt für die Echtheit, und über das EK-Zertifikat lässt sich beweisen, dass es überhaupt ein echter TPM ist. Der Verifier prüft dann fortlaufend und nicht nur einmal beim Start.

Damit das nicht nach Bastelei klingt: Keylime läuft in der IBM Cloud als Teil der Compliance-Anforderungen für FedRAMP und HITRUST, und SUSE dokumentiert es offiziell für SUSE Linux Micro. Das ist kein Laborspielzeug.

IMA und EVM, zwei Dinge die ständig verwechselt werden

Beide gehören zur Laufzeit-Integrität, machen aber Verschiedenes.

  • IMA, die Integrity Measurement Architecture, hasht Dateien beim Zugriff. Im Messmodus schreibt sie die Hashes in ein Kernel-Log und erweitert damit PCR 10. Im Appraisal-Modus verweigert sie zusätzlich die Ausführung, wenn Hash oder Signatur nicht passen.
  • EVM schützt die zugehörigen erweiterten Attribute, also die Sicherheits-Metadaten der Datei, mit einem HMAC oder einer Signatur. Ohne EVM könnte ein Angreifer mit Schreibrechten die IMA-Attribute einfach mitfälschen.

Der TPM-Bezug liegt bei IMA und bei PCR 10. Eine veränderte Binärdatei erzeugt eine Messung, die im TPM landet und rückwirkend nicht mehr zu entfernen ist, weil PCRs nur wachsen. Zusammen mit Secure Boot und Measured Boot entsteht so eine Kette von der Firmware bis zur einzelnen ausgeführten Datei. Ohne TPM wäre dieses Logbuch fälschbar, mit TPM nicht.

Verschlüsselte Server, die allein neu starten können

Operativ ist das der handfesteste Nutzen im Rechenzentrum. Ein verschlüsselter Server, der nach einem Reboot auf eine Passphrase wartet, ist ein Betriebsproblem, spätestens um drei Uhr nachts. Mit TPM-Bindung startet er durch. Der Zielkonflikt dahinter ist eine echte Architekturentscheidung.

  • TPM allein. Der Server startet ohne Menschen. Wer den ganzen Server stiehlt, bekommt einen Server, der sich selbst entsperrt.
  • Tang und Clevis, netzgebunden. Entsperrt nur, wenn der Server einen Tang-Server im eigenen Netz erreicht. Aus dem Rack getragen bleibt er zu. Braucht dafür einen erreichbaren Tang-Server, was beim Kaltstart eines ganzen Rechenzentrums ein Henne-Ei-Problem ist.
  • Beides kombiniert über Shamir Secret Sharing in Clevis, also zum Beispiel TPM und Tang zusammen.

Meine Empfehlung, und die ist unspektakulär: im eigenen Rack mit eigenem Netz nehmt Tang plus TPM über Clevis, weil dann beide Bedingungen gleichzeitig gelten müssen. Bei einer einzelnen Kiste in fremder Colo nehmt TPM mit PIN und tippt die eben ein, wenn es tatsächlich einen Kaltstart gibt. Ein Server, der sich ohne jede Bedingung selbst entsperrt, ist Verschlüsselung fürs Protokoll und nicht gegen einen Angreifer.

Maschinenidentität, die man nicht in eine VM klonen kann

Ein Schlüssel der die Maschine nicht verlassen kann ist eine Identität, die man nicht mitkopieren kann. Für Zero-Trust-Architekturen ist das der interessante Teil: SPIRE hat dafür einen TPM-Node-Attestor, und für Kubernetes-Knoten, die sich beim Beitritt beweisen sollen, ist das der saubere Weg. Verglichen mit einem Token in einer Cloud-Init-Datei, das jeder mitlesen und in eine beliebige VM kopieren kann, ist das ein anderes Sicherheitsniveau.

Ein TPM für jede VM, und was er nicht leistet

Ein physischer TPM hat genau eine Instanz und lässt sich nicht sinnvoll auf viele Gäste aufteilen. Die Lösung ist ein virtueller TPM pro VM. swtpm stellt dafür eine TPM-2.0-Implementierung im Userspace bereit, QEMU und libvirt binden sie als Gerät in die VM ein. Der Gast sieht ein ganz normales /dev/tpm0 und braucht keine Anpassung. Der Kernel bringt dazu den vTPM-Proxy-Treiber mit, /dev/vtpmx, über den Container und VMs eigene TPM-Instanzen bekommen. Genau so machen es die Cloud-Anbieter, und genau so kommt Windows 11 in einer VM überhaupt an seine TPM-2.0-Voraussetzung.

Die ehrliche Einordnung gehört dazu, weil das in Cloud-Architekturen regelmäßig falsch verstanden wird. Ein vTPM ist Software. Sein Zustand liegt als Datei auf dem Hypervisor. Wer den Hypervisor kontrolliert, kontrolliert den vTPM, und ein Angreifer mit root auf dem Host kann den Schlüsselzustand kopieren. Ein vTPM löst also das Problem „der Gast braucht ein TPM-Interface“, er liefert aber keine Hardware-Vertrauenswurzel für den Gast. Wer echte Attestierung einer VM will, braucht eine Kette, die beim TPM des Hosts beginnt, oder Confidential-Computing-Technik wie AMD SEV-SNP oder Intel TDX.

Zum Schluss noch ein kleiner Anwendungsfall, der technisch nichts Neues ist und praktisch viel bringt: die Datenbank-Zugangsdaten eines Dienstes so versiegeln, dass sie nur auf dieser Maschine und nur in diesem Bootzustand aufgehen. Derselbe Seal-Mechanismus wie oben, nur mit einem anderen Geheimnis. Ein kopiertes Image oder eine in eine VM gehobene Platte bringt die Zugangsdaten dann nicht mit.

Was geht, aber nichts bringt

Dieser Abschnitt ist mir genauso wichtig wie der Nutzen-Teil, also kürze ich ihn nicht ab. Zuerst das Missverständnis, das sich am leichtesten messen lässt.

1. Der TPM als Krypto-Beschleuniger. Gemessen und erledigt.

OperationWoZeit
RSA-2048-Schlüssel erzeugenTPM19,703 s
RSA-2048-Schlüssel erzeugenCPU, openssl0,220 s
ECC-P-256-Primary erzeugenTPM0,537 s
ECDSA P-256 signieren, 50 malTPM4,862 s
ECDSA P-256 signieren, 50 malCPU, openssl0,286 s
# time tpm2_createprimary -C o -g sha256 -G rsa2048 -c rsa_primary.ctx
real	0m19.703s
user	0m0.039s
sys	0m0.016s

# time openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out /dev/null
real	0m0.220s
user	0m0.210s
sys	0m0.010s

Rund 90 mal langsamer bei der RSA-Schlüsselerzeugung. Ein Detail zur Messhygiene ist mir dabei wichtig: während der 19,7 Sekunden liegen user und sys bei 0,039 und 0,016 Sekunden. Die CPU langweilt sich also, die Zeit vergeht wirklich im Chip. Das ist eine Messung des TPM und nicht des Prozess-Overheads.

Die richtige Schlussfolgerung ist nicht, dass der TPM schlecht wäre, sondern dass er kein Beschleuniger ist und nie einer war. Das ist die interessante Kehrseite zu der Krypto-Beschleunigerkarte, die ich neulich gegen dieselbe Klasse moderner CPU gemessen habe. Dort verlor Spezial-Hardware, die schnell sein wollte. Hier verliert sie noch deutlicher, nur ist das kein Befund, sondern die Bauart. Der TPM wollte nie schnell sein, er wollte stur sein.

2. Massendaten im TPM verschlüsseln. Es gibt keinen Datenpfad dafür, und bei den Zahlen von oben erübrigt sich die Diskussion.

3. LUKS nur am TPM, ohne PIN. Technisch drei Minuten Arbeit. Ergebnis ist ein Notebook, das sich für jeden entsperrt, der den Deckel aufmacht. In Kombination mit dem Bus-Sniffing weiter unten ist das nahe an Sicherheitstheater. Wer die Passphrase-Eingabe loswerden will, nimmt die PIN.

4. Der TPM als Passwortspeicher oder Secret Store. Ein einzelner NV-Index kann auf diesem Chip höchstens 1664 Bytes halten, und es gibt genau 8 NV-Zähler. NV im TPM ist Flash mit begrenzten Schreibzyklen und als Ablage für Inhalte nicht gedacht. Der richtige Weg ist immer derselbe: die Geheimnisse liegen verschlüsselt auf der Platte, und nur der Schlüssel dafür wird im TPM versiegelt. Genau das tun systemd-cryptenroll und Clevis auch.

5. Sealing gegen PCR 0 bis 7 auf einem Gerät, das Firmware-Updates bekommt. Jedes BIOS-Update ändert die Messungen und sperrt euch aus. Ein Fall, in dem die Technik funktioniert und die Betriebspraxis daran zerbricht. Der Ausweg heißt signierte Policies und systemd-pcrlock, und im selben Atemzug gehört dazu, dass sich systemd-pcrlock selbst noch als experimentell bezeichnet.

6. Attestierung ohne unabhängigen Prüfer. Ein Quote, das auf derselben Maschine geprüft wird, beweist nichts. Wenn die Maschine übernommen ist, ist die Prüfung übernommen. Attestierung ergibt nur mit einem separaten Verifier und mit bekannten Referenzwerten Sinn. Sehr viele Aussagen der Art „wir nutzen TPM“ sind bei genauem Hinsehen genau das, eine Selbstprüfung.

7. TPM 1.2 im Jahr 2026. SHA-1 und RSA-2048, kein ECC, keine Algorithmen-Agilität, ein völlig anderer Software-Stack, nämlich TrouSerS statt tpm2-tss. Wer noch einen findet, sollte darauf nichts Neues bauen.

8. Die Erwartung, ein TPM schütze ein laufendes System. Das ist das größte Missverständnis, deshalb steht es hier noch einmal als eigener Punkt. Ein TPM schützt Schlüssel im Ruhezustand und misst den Start. Er tut nichts gegen einen Angreifer, der schon im Kernel sitzt, denn der fragt den Chip einfach ganz normal.

Tabelle mit fünf Vorhaben und der jeweiligen Antwort, von viel Krypto rechnen bis Geheimnisse ablegen
Fünf häufige Vorhaben und die kurze Antwort dazu.

Die Grenzen, und die Angriffe die es wirklich gibt

Ohne diesen Abschnitt wäre der Beitrag Werbung. Der Kern des Problems bei diskreten Chips ist unangenehm einfach: nach dem Entsiegeln gibt der TPM das Geheimnis über den Bus heraus, und klassisch liegt es dort im Klartext. Wer LPC oder SPI anzapft, liest den Schlüssel mit. Für BitLocker ist das seit Jahren praktisch demonstriert, und es ist ausdrücklich nicht auf Windows beschränkt. Securitum hat im September 2024 in einem echten Penetrationstest genau das gegen ein Linux-System mit LUKS und Clevis gezeigt.

Das betrifft mein Testsystem direkt, und ich schreibe das lieber offen hin, als es zu verstecken: der SLB 9670 ist ein diskreter Chip auf dem Board. Der Angriff braucht physischen Zugriff und Löterfahrung, aber er ist kein Papier-Szenario.

Die Gegenmaßnahme kann TPM 2.0 von sich aus: Sessions mit HMAC-Absicherung und Parameter-Verschlüsselung, und systemd benutzt das inzwischen. Die Grenze davon wird oft zu großzügig beschrieben, deshalb genau: das ist keine Vollverschlüsselung des Bus-Protokolls. Parameter Encryption schützt gezielt einzelne sensible Parameter in Kommandos und Antworten, also genau die Stelle, an der ein entsiegelter Schlüssel herauskäme. Kommandocodes, Handles und die übrigen Parameter bleiben sichtbar. Gegen das passive Mitlesen des Schlüssels ist es wirksam, gegen Verkehrsanalyse nicht, und gegen einen aktiven Interposer hilft es nur insofern, als die HMAC-Absicherung Manipulationen auffallen lässt. Der Kernel hat zu dieser Interposer-Frage eine eigene Dokumentationsseite. Und noch eine Einschränkung, die systemd selbst dokumentiert: die Art der Einbindung entwickelt sich weiter, alte Enrollments profitieren nicht rückwirkend. Wer vor Jahren enrolliert hat, sollte das neu machen.

Und dann eine Ironie, die zeigt wie dünn das Eis ist: CVE-2023-1017 saß genau in CryptParameterDecryption, also in dem Code, der diese verschlüsselten Parameter auspackt. Die Schutzfunktion war selbst der Angriffsweg.

Wer jetzt denkt, ein fTPM in der CPU sei automatisch besser, hat nur andere Probleme. faulTPM hat gezeigt, dass sich AMDs fTPM über Spannungs-Glitching am Platform Security Processor angreifen lässt. Und TPM-Fail demonstrierte 2019 Timing-Seitenkanäle, mit denen sich private ECDSA-Schlüssel rekonstruieren ließen, und zwar aus Intel PTT (CVE-2019-11090) und aus dem ST33 von STMicroelectronics (CVE-2019-16863). Zwei Details daran tragen den Punkt: der lokale Angriff auf Intels fTPM brauchte je nach Zugriffsrechten 4 bis 20 Minuten, und der ST33 trug eine Common-Criteria-Zertifizierung nach EAL 4+, die Schutz gegen Seitenkanäle ausdrücklich einschließt. Ein Zertifikat ist also kein Beweis.

Auch die Referenz-Implementierung selbst hatte Löcher. CVE-2023-1017 war ein Out-of-bounds-Write, CVE-2023-1018 ein Out-of-bounds-Read, beide in der TPM-2.0-Module-Library, also im Referenzcode der TCG. Betroffen waren dadurch gleichzeitig Software-TPMs wie libtpms und eine Reihe von Hardware-TPMs, deren Firmware auf diesem Code aufbaut. Gefunden hat sie Quarkslab und meldete sie im November 2022. Zwei Bytes über den Puffer hinaus, im ungünstigen Fall Codeausführung im TPM-Kontext, also genau in dem Bauteil, dessen einzige Aufgabe es ist, eine Vertrauensgrenze zu ziehen.

Was bleibt also unterm Strich: ein TPM hebt die Messlatte von „Platte ausbauen und kopieren“ auf „an das Board löten oder den SoC glitchen“. Das ist ein echter Fortschritt und kein magischer Schild. Mit PIN wird es deutlich stärker, weil dann die Lockout-Logik greift und Bus-Sniffing allein nicht mehr reicht.

Der Zustand dieses Testsystems, unbequem und aufschlussreich

Und jetzt der Teil, der mir selbst am meisten zu denken gibt. Der Chip in diesem Notebook arbeitet einwandfrei, wie alles hier oben zeigt. Benutzt wird er von diesem System für praktisch nichts.

BausteinZustand
Secure Bootaus, und als 00 in PCR 7 gemessen
Wurzel-DateisystemZFS-Native-Encryption, aes-256-gcm, nirgends LUKS
systemd-cryptenrollvorhanden, systemd 255.4, ohne LUKS2 aber nutzlos
clevisnicht installiert, würde hier auch nicht helfen
Unified Kernel Imagenicht im Einsatz
systemd-pcrextend.socketübersprungen, ConditionSecurity=measured-uki nicht erfüllt
systemd-pcrmachine.serviceübersprungen, dieselbe Bedingung
systemd-tpm2-setup-early.serviceübersprungen, dieselbe Bedingung
die elf systemd-pcrlock-*-Unitsalle disabled
TPM als /dev/hwrngaktiv, tpm-rng-0

Die drei übersprungenen Units sind der interessanteste Eintrag in dieser Tabelle. Die Bedingung ConditionSecurity=measured-uki prüft nicht das Dateiformat, sondern den Bootweg. Weil dieses System nicht als gemessenes Unified Kernel Image über systemd-stub gestartet ist, überspringt systemd die halbe TPM-Infrastruktur einfach lautlos, ohne Fehler und ohne Warnung. Das ist genau die These aus der Einleitung, jetzt belegt: der Chip ist da, er funktioniert, und die Distribution benutzt ihn nicht.

Der Event-Log, und die Falle mit ls

Zum Abschluss noch eine Kleinigkeit, über die ich zuerst gestolpert bin. Der Event-Log, dessen Adresse die Firmware ganz oben in der ersten dmesg-Zeile übergeben hat, liegt im securityfs. Und ls behauptet, die Datei sei leer.

# ls -la /sys/kernel/security/tpm0/
total 0
-r--r----- 1 root tss 0 Aug 10 09:30 binary_bios_measurements

# tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements | grep -c EventNum
120

Null Bytes laut ls, und trotzdem 120 Events darin. securityfs gibt für diese Datei einfach keine Größe an. Was in den 120 Einträgen steckt, sortiert sich so:

# tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements | grep EventType | sort | uniq -c | sort -rn
     81   EventType: EV_IPL
     12   EventType: EV_EFI_VARIABLE_BOOT
      8   EventType: EV_SEPARATOR
      5   EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
      3   EventType: EV_EFI_ACTION
      2   EventType: EV_POST_CODE
      2   EventType: EV_EVENT_TAG
      2   EventType: EV_EFI_BOOT_SERVICES_APPLICATION
      1   EventType: EV_S_CRTM_VERSION
      1   EventType: EV_NO_ACTION
      1   EventType: EV_EFI_VARIABLE_AUTHORITY
      1   EventType: EV_EFI_HANDOFF_TABLES
      1   EventType: EV_EFI_GPT_EVENT

Der lehrreichste Eintrag im ganzen Log ist aber die Nummer 2, weil er ein abstraktes Konzept in vier Zeilen greifbar macht.

- EventNum: 2
  PCRIndex: 7
  EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
  DigestCount: 2
  Digests:
  - AlgorithmId: sha1
    Digest: "57cd4dc19442475aa82743484f3b1caa88e142b8"
  - AlgorithmId: sha256
    Digest: "115aa827dbccfb44d216ad9ecfda56bdea620b860a94bed5b7a27bba1c4d02d8"
    UnicodeName: SecureBoot
    VariableData: "00"

Da steht der Secure-Boot-Zustand meiner Maschine als 00 im Log, und gehasht wandert genau dieser Wert in PCR 7. Das ist die Brücke zwischen dem Firmware-Setup und dem Chip: was ihr im BIOS umschaltet, wird gemessen und landet im TPM. Schaltet Secure Boot ein, und PCR 7 ändert sich. Alles, was gegen PCR 7 versiegelt war, geht danach nicht mehr auf. Wer den Zusammenhang einmal so gesehen hat, versteht auch, warum die Wahl der PCRs weiter oben ein Zielkonflikt ist und keine Geschmacksfrage.

Eine Nebenbemerkung, weil sie so schön zeigt, wie Secure-Boot-PKI in der Praxis funktioniert: im Log steckt auch der Platform Key des Boards, ein „Fujitsu ODM Quanta BIOS PK Certificate“, gültig von August 2012 bis August 2022. Es ist also seit Jahren abgelaufen. Die Firmware interessiert sich nicht dafür.

Was offen bleibt

  • Ob der SLB 9670 auf diesem Board über LPC oder über SPI angebunden ist. Aus dem Betriebssystem heraus nicht entscheidbar.
  • Warum der Login über PKCS11Provider rund 1,3 Sekunden Aufschlag kostet, ist plausibel erklärt, aber nicht einzeln nachgemessen. Ein strace oder ein Trace über tpm2_ptool würde es belegen.
  • systemd-cryptenroll mit LUKS2 konnte ich nicht testen, weil hier kein LUKS existiert.
  • Keylime habe ich nicht aufgesetzt. Die Beschreibung stützt sich auf Dokumentation von SUSE, Red Hat und dem Keylime-Projekt.
  • Die Bindung des Attestierungsschlüssels an den zertifizierten EK, also TPM2_MakeCredential und TPM2_ActivateCredential, habe ich nicht durchgeführt. Gemessen sind nur Quote und Signaturprüfung.
  • Wie viel NV-Speicher der SLB 9670 insgesamt hat, habe ich nicht ermittelt. NV_INDEX_MAX beantwortet diese Frage nicht.
  • Kein vTPM aufgesetzt. Der Abschnitt dazu ist dokumentiert und nicht gemessen.
  • Ob verschlüsselte TPM-Sessions Bus-Sniffing auf diesem konkreten Chip vollständig verhindern, habe ich nicht überprüft. Dafür bräuchte es einen Logic Analyzer.
  • Ein TPM-gestütztes Entsperren einer ZFS-Native-Encryption-Wurzel habe ich nicht gebaut.
  • Wie sich PCR 7 auf diesem Gerät nach dem Aktivieren von Secure Boot verändert. Das wäre ein naheliegender zweiter Teil.

Siehe auch

Wenn ich hier etwas falsch dargestellt habe, oder wenn ihr einen der offenen Punkte schon gelöst habt, dann korrigiert mich gerne. Dann lerne ich selbst etwas. Ihr dürft mich dazu jederzeit fragen.

Und weil mich das wirklich interessiert: setzt ihr den TPM-Chip selbst ein, ignoriert ihr ihn bisher, oder nutzt ihr ihn eher zufällig?

Sieben Einstellungen, kein Setup-Besuch: die BIOS-Konfiguration meines Supermicro-Boards ändern

Im letzten Beitrag ging es darum, die BIOS-Einstellungen meines Supermicro X12SPi-TF überhaupt erst als Datei in die Hand zu bekommen. Das Ergebnis war eine XML mit 372 Einstellungen, und der Weg dorthin führte über eine Lizenz für 28,17 Euro.

Zwei Terminalausgaben untereinander: mit Hardware P-States auf Disable liefert die Suche nach dem hwp-Flag in /proc/cpuinfo keine Ausgabe und intel_pstate läuft passiv, mit Native Mode erscheinen hwp, hwp_epp und hwp_act_window und intel_pstate läuft aktiv.

Damit war die halbe Arbeit getan. Eine Konfiguration auslesen zu können ist schön, aber der eigentliche Gewinn liegt darin, sie auch zurückschreiben zu können. Genau das habe ich jetzt gemacht, und zwar zum ersten Mal überhaupt an dieser Maschine: sieben Einstellungen geändert, ohne den Rechner ins Setup zu booten, ohne Tastatur, ohne die Fernkonsole des Management-Controllers.

Vorweg die gute Nachricht für alle, die schon rechnen: die kleine Lizenz deckt das Schreiben mit ab. Ich hatte damit gerechnet, dass Supermicro genau an dieser Stelle noch einmal die Hand aufhält, und das tut es auch, aber nur an einer sehr kleinen Ecke. Von den 372 Einstellungen tragen 21 den Vermerk, dass sie die große Lizenz verlangen. Es sind ausschliesslich Zertifikatseinträge für KMIP-Server und HTTPS-Boot. Nichts davon betrifft normale Setup-Optionen.

Was ich ändern wollte, und warum

Der langweiligste Teil eines solchen Artikels ist die Liste der geänderten Werte. Der interessante Teil ist die Begründung, deshalb fange ich damit an.

Mein Rechner bootet von einer NVMe-SSD. Er hat das noch nie anders gemacht und wird es auch nicht. Trotzdem lädt das BIOS bei jedem Start die Pre-Boot-Netzwerktreiber für vier Netzwerkanschlüsse, jeweils für IPv4 und IPv6, und baut daraus Boot-Einträge, die niemand benutzt. Dazu kommen die Option-ROMs von drei leeren Steckplätzen.

Ein Option-ROM ist ein kleines Stück Firmware auf einer Steckkarte, das beim Start ins BIOS geladen wird, damit die Karte schon vor dem Betriebssystem funktioniert. Für eine Netzwerkkarte heisst das Netzwerk-Boot, für einen Speichercontroller das Booten von daran angeschlossenen Platten. Wer von keinem dieser Geräte bootet, braucht den Code nicht.

Also:

Network Stack von *Enabled* auf *Disabled*. Damit fällt die komplette UEFI-Netzwerkinitialisierung weg. – Onboard LAN1 Option ROM aus. Der Pre-Boot-Treiber der onboard X550 wird nicht gebraucht. – CPU SLOT6 OPROM aus. Dort steckt meine X710. Dazu gleich mehr, das ist der eigentliche Grund für die Aktion. – CPU SLOT1, SLOT2 und SLOT7 OPROM aus. Alle drei Steckplätze sind leer.

Bei den drei leeren Steckplätzen bin ich ehrlich: der Zeitgewinn ist exakt null. Wo keine Karte steckt, gibt es auch kein Option-ROM zu laden. Ich habe sie trotzdem mitgenommen, weil ich einen dokumentierten Sollzustand haben will und nicht eine Mischung aus bewusst gesetzt und zufällig übrig.

Die siebte Änderung ist die, um die es mir wirklich ging.

Die eine Zeile, die eine Woche Rätselraten beendet hat

Beim Schreiben meiner BIOS-Serie ist mir etwas aufgefallen, das ich mir lange nicht erklären konnte. Mein Prozessor ist ein Xeon Gold 5315Y, Ice Lake-SP. Diese Generation beherrscht Hardware P-States, kurz HWP. Die CPU regelt ihren Takt dabei selbst, in feineren Stufen und deutlich schneller, als das Betriebssystem es könnte.

Nur meldete mein Kernel davon nichts. In /proc/cpuinfo fehlte das hwp-Flag, der Treiber intel_pstate lief im passiven Modus, und die Taktregelung machte der Governor schedutil. Also genau der Zustand, den man auf einer CPU erwartet, die HWP gar nicht kann.

Ich habe eine Weile in Richtung Kernel gesucht. Das war die falsche Richtung. Der Schalter sass im BIOS, ziemlich tief vergraben:

Advanced > CPU Configuration > Advanced Power Management Configuration
        > Hardware PM State Control > Hardware P-States   [Disable]

Der Auslieferungszustand dieser Option ist tatsächlich *Disable*. Es gibt vier Werte, und der Hilfetext im BIOS beschreibt sie so:

Disable                              hardware will choose a P-state setting for
                                     the system based on an OS request
Native Mode                          hardware will choose a P-state setting
                                     based on OS guidance
Native Mode with No Legacy Support   hardware will choose a P-state setting
                                     independently without OS guidance
Out of Band Mode                     hardware autonomously choose a P-state
                                     without OS guidance

Ich habe Native Mode genommen, also die zahmste der drei aktiven Varianten. Der Unterschied zu den beiden anderen ist wichtig: bei *Native Mode* behält das Betriebssystem seinen Einfluss, es wandert nur die Feinsteuerung in die CPU. Bei den beiden anderen wird der Kernel bei der Taktwahl übergangen, und dann kann er dir auch nicht mehr sinnvoll sagen, was die CPU gerade tut.

Was ich bewusst nicht angefasst habe

Diese Liste finde ich wichtiger als die Liste der Änderungen, denn hier hätte ich mir den Rechner unbedienbar machen können.

Das Option-ROM von SLOT4 bleibt an. Dort sitzt die Grafikkarte. Ihr GOP-Modul ist das, was beim Start überhaupt ein Bild auf den Monitor bringt. Wer es abschaltet, sitzt bis zum Laden des Grafiktreibers im Dunkeln, und wenn dabei etwas schiefgeht, sitzt er dauerhaft im Dunkeln.

Onboard Video Option ROM bleibt an. Das ist die Grafik des Management-Controllers, und daran hängt die Fernkonsole. Schaltet man sie ab, bleibt beim Start das Fenster schwarz, über das man aus der Ferne ins Setup kommt. Das ist genau der Rettungsweg, den man sich nicht abschneiden will, wenn man gerade anfängt, das BIOS aus dem laufenden Betrieb heraus umzukonfigurieren.

Beide NVMe-Option-ROMs bleiben an. Das erste trägt das Betriebssystem. Auf das zweite soll irgendwann Windows, und auch wenn der Bootloader auf der ersten Platte das Kommando behält, muss die zweite dem Firmware-Bootmanager sichtbar bleiben.

Legacy USB Support bleibt an. Hier hätte ich vermutlich etwas Startzeit gewinnen können. Ich habe es gelassen, weil ich den Gewinn nicht gemessen habe und das Risiko eine tote Tastatur im Setup wäre. Eine Einstellung, deren Nutzen man nicht beziffern kann, deren Schaden aber konkret ist, ändert man nicht.

Der Weg: eine Teildatei, nicht die ganze

Naheliegend wäre, die ausgelesene XML zu bearbeiten und komplett zurückzuschreiben. Bei 372 Einstellungen und 260 Kilobyte ist das unnötig riskant, und es ist auch nicht der vorgesehene Weg.

Das Werkzeug kennt einen Filter, der genau die Einstellungen ausgibt, die vom Auslieferungszustand abweichen:

./saa -c GetCurrentBiosCfg --file nondefault.xml --overwrite --filter nondefault

Heraus kommt eine kleine Datei mit derselben Struktur wie die grosse, nur eben mit den Menüzweigen, die auch wirklich etwas enthalten. Und genau diese Struktur nimmt das Schreibkommando entgegen. Teildateien sind also kein Trick, sondern der normale Betriebsfall.

Hier der erste Fallstrick, und der hat mich ehrlich geärgert: die eingebaute Hilfe des Werkzeugs beschreibt den Filter als Ziffer.

--filter    Sets filter type to: 1 = nondefault

Die Ziffer 1 wird abgewiesen. Das Kommando bricht ab und wirft den Hilfetext aus, der einem gerade die Ziffer empfohlen hat. Akzeptiert wird ausschliesslich das ausgeschriebene Wort nondefault. Wenn du also an dieser Stelle hängst, liegt es nicht an dir.

Meine Änderungsdatei habe ich nicht getippt, sondern mit einem kleinen Python-Skript aus dem Auslesestand erzeugt. Das klingt nach Übertreibung für sieben Werte, hat aber einen handfesten Grund: die Einstellungen müssen im richtigen Menüzweig stehen, und die Menünamen sind lang und fehleranfällig. CPU SLOT2 PCI-E 4.0 X8(IN X16) OPROM vertippt sich schneller, als man denkt, und ein Tippfehler im Namen führt nicht zu einer Fehlermeldung, sondern dazu, dass die Einstellung stillschweigend nicht gesetzt wird.

Das Schreiben selbst ist unspektakulär:

./saa -c ChangeBiosCfg --file change-boot-oprom-hwp.xml

Status: The BIOS configuration is updated for the managed system
Note: You have to reboot or power up the system for the changes to take effect.

Es gibt eine Option --reboot, die den Neustart gleich mit erledigt. Die habe ich weggelassen. Wann ein Rechner neu startet, entscheide ich lieber selbst.

Der zweite Fallstrick, und der ist gemein

Nach dem Schreiben will man natürlich nachsehen, ob es geklappt hat. Also dasselbe Auslesekommando noch einmal, und dann steht da:

Hardware P-States              = Disable     (geschrieben: Native Mode)
Network Stack                  = Enabled     (geschrieben: Disabled)
CPU SLOT6 PCI-E 4.0 X16 OPROM  = EFI         (geschrieben: Disabled)

Nichts. Alle alten Werte, unverändert.

Der erste Reflex ist, das Schreibkommando noch einmal laufen zu lassen. Tu das nicht. Das Auslesen liefert die aktive Konfiguration, und die ändert sich erst beim nächsten Start. Deine Änderung liegt so lange in einem Bereich, den das Werkzeug nicht anzeigt. Zwischen dem Schreiben und dem Neustart gibt es damit keine Möglichkeit, die Änderung zu überprüfen, ausser dem Rückgabewert des Kommandos.

Das ist unschön, aber es ist logisch. Die Einstellungen werden erst beim Start aus dem Speicher gelesen, und vorher gibt es schlicht nichts Aktives, das anders wäre.

Nach dem Neustart

Und dann stimmt alles. Die Zahl der Abweichungen vom Auslieferungszustand ist von sechs auf dreizehn gestiegen, also genau um meine sieben:

Quiet Boot                            Unchecked
Restore on AC Power Loss              Stay Off
Power Button Function                 4 Seconds Override
Hardware P-States                     Native Mode
Network Stack                         Disabled
Re-Size BAR Support                   Enabled
VGA Priority                          Offboard
CPU SLOT1 PCI-E 4.0 X8 OPROM          Disabled
CPU SLOT2 PCI-E 4.0 X8(IN X16) OPROM  Disabled
CPU SLOT6 PCI-E 4.0 X16 OPROM         Disabled
CPU SLOT7 PCI-E 4.0 X8 OPROM          Disabled
Onboard LAN1 Option ROM               Disabled
WHEA Support                          Disabled

Die Netzwerk-Booteinträge sind verschwunden, übrig bleibt der Bootloader und die eingebaute Shell:

BootCurrent: 000F
BootOrder: 000F,0001
Boot0001* UEFI: Built-in EFI Shell
Boot000F* ubuntu

Und der Punkt, um den es mir ging, ist eingetreten. Der Prozessor meldet jetzt Fähigkeiten, die er die ganze Zeit hatte:

$ grep -o ' hwp[_a-z]*' /proc/cpuinfo | sort -u
 hwp
 hwp_act_window
 hwp_epp
 hwp_pkg_req

$ cat /sys/devices/system/cpu/intel_pstate/status
active

Der Treiber ist damit vom passiven in den aktiven Modus gewechselt. Was dabei kurz irritiert: der Governor heisst jetzt powersave statt schedutil, und das sieht nach einem Rückschritt aus. Ist es nicht. Bei intel_pstate im aktiven Modus ist powersave der Name für den Betrieb, bei dem die Hardware regelt. Wie sie das tut, steuert ein separater Wert:

$ cat /sys/devices/system/cpu/cpu0/cpufreq/energy_performance_preference
balance_performance

Die CPU geht im Leerlauf auf 800 MHz und hat den vollen Turbo bis 3600 MHz zur Verfügung. Genau so soll es sein.

Wichtig war mir noch die Gegenprobe, dass ich mir das Netzwerk nicht zerschossen habe. Die Karte, deren Option-ROM ich abgeschaltet habe, ist schliesslich die, über die diese Maschine am Netz hängt:

$ ethtool ens6f1np1 | grep -E 'Speed|Link detected'
	Speed: 10000Mb/s
	Link detected: yes

Unverändert. Das ist auch zu erwarten, denn der Treiber im laufenden Betrieb kommt aus dem Kernel und hat mit dem Option-ROM nichts zu tun. Das Option-ROM ist reiner Startcode. Trotzdem ist das der Punkt, an dem die meisten zögern, deshalb steht die Messung hier.

Ein Punkt ist noch offen, und den will ich nicht verschweigen: der ursprüngliche Anlass für das Abschalten von SLOT6 war eine Meldung auf der Treiberstatus-Seite im Setup, wo meine Netzwerkkarte seit einem Firmware-Update als *Failed* geführt wird. Ob die Meldung jetzt weg ist, kann ich von aussen nicht sehen. Das prüfe ich beim nächsten Setup-Besuch nach.

Gibt es dafür keine Oberfläche?

Diese Frage lag für mich die ganze Zeit im Raum, und die Antwort ist unbefriedigend.

Es gäbe einen herstellerneutralen Weg unter Linux. Der Kernel kennt eine Geräteklasse namens firmware-attributes, über die sich BIOS-Einstellungen als ganz normale Dateien lesen und schreiben lassen. Der Firmware-Updater fwupd kann das seit Version 1.8.4 direkt bedienen. Das wäre die Lösung: ein Kommando, egal welcher Hersteller.

Auf meiner Maschine sieht das so aus:

$ ls /sys/class/firmware-attributes/
ls: cannot access '/sys/class/firmware-attributes/': No such file or directory

$ fwupdmgr get-bios-setting
This system doesn't support firmware settings

Das Hilfsmodul dafür liegt im Kernel, es ist also nicht so, dass die Infrastruktur fehlen würde:

/lib/modules/7.0.0-28-generic/kernel/drivers/platform/x86/firmware_attributes_class.ko.zst

Was fehlt, ist der Treiber des Herstellers. Der Kernel bringt genau drei mit:

drivers/platform/x86/dell/dell-wmi-sysman     Dell
drivers/platform/x86/lenovo/think-lmi         Lenovo
drivers/platform/x86/hp/hp-bioscfg            HP

Supermicro ist nicht dabei. Statt eines Treibers, der diese Kernel-Schnittstelle bedient, gibt es ein eigenes Werkzeug und eine Lizenz. Auf einem Dell oder Lenovo wäre der Inhalt dieses Beitrags ein Einzeiler ohne Zusatzkosten.

Ganz ohne Oberfläche ist man aber nicht. Das Werkzeug bringt einen textbasierten Editor mit, der das Setup im Terminal nachbaut:

./saa -c GetCurrentBiosCfg --tui

Dazu gibt es --compact, das anschliessend nur die geänderten Zeilen herausschreibt. Über eine SSH-Pipe blieb das Fenster bei mir schwarz, es braucht ein echtes Terminal. Ausprobiert habe ich es deshalb noch nicht richtig. Und es gibt das Werkzeug ausserdem als Windows-Version und als Variante für die UEFI-Shell, also für den Fall, dass überhaupt kein Betriebssystem installiert ist.

Eine echte grafische Oberfläche gibt es auch, sie heisst SSM. Die will dann allerdings wieder die grosse Lizenz.

Zurück auf Anfang

Das Wichtigste zum Schluss, und man legt es sich besser vorher zurecht als hinterher. Vor dem Schreiben habe ich den vollständigen Stand weggesichert. Der Rückweg ist dann dasselbe Kommando mit dieser Datei:

./saa -c ChangeBiosCfg --file bios-current-2026-08-09.xml

Als Notnagel gibt es darunter noch LoadDefaultBiosCfg, das alles auf den Auslieferungszustand zurücksetzt. Das ist aber ein grober Hebel: es wirft auch die sechs Abweichungen weg, die ich absichtlich eingestellt habe, und die stehen dann eben nicht mehr so, wie ich sie haben will. Die Teildatei ist der bessere Weg, der Vollreset die letzte Reserve.

Und weil es hier um Firmware geht, der offensichtliche Hinweis: bei einem Rechner, an den du nicht rankommst, änderst du keine Boot-Einstellungen, ohne dass jemand vor Ort ist oder die Fernkonsole zuverlässig läuft. Ich habe das Option-ROM der Grafik und das des Management-Controllers genau deshalb nicht angefasst.

Was bleibt

Sieben Einstellungen, ein Neustart, kein Setup-Besuch. Das klingt nach wenig, ändert aber die Arbeitsweise. BIOS-Einstellungen waren für mich bisher etwas, das man beim Aufbau einmal einstellt und danach ungern anfasst, weil jede Änderung einen Neustart mit Tastatur und Monitor bedeutet. Jetzt sind sie eine Datei, die ich versionieren, vergleichen und zurückspielen kann.

Der schönste Nebeneffekt war die Sache mit den Hardware P-States. Ich hatte das Verhalten meiner CPU wochenlang für eine Eigenheit des Kernels gehalten und in die falsche Richtung gesucht. Es war eine einzige Zeile in einem Menü, das vier Ebenen tief liegt und das ich beim Durchklicken nie geöffnet hatte. Eine durchsuchbare Datei aller 372 Einstellungen hätte mir das in dreissig Sekunden gezeigt.

Falls du auf demselben Board sitzt: das Auslesen ist der Beitrag davor, das Schreiben braucht keine weitere Lizenz, und die drei Stolperstellen sind der Filter, der nur als Wort funktioniert, die Gegenprobe, die vor dem Neustart nichts zeigt, und die Versuchung, mehr auf einmal zu ändern, als man beim nächsten Start noch reparieren kann.

Siehe auch: Achtundzwanzig Euro für eine Textdatei: die BIOS-Konfiguration meines Supermicro-Boards auslesen und die Serie BIOS erklärt.

Wenn dazu etwas unklar ist oder du es auf deinem Board anders erlebt hast, dürft ihr mich sehr gerne fragen.

Achtundzwanzig Euro für eine Textdatei: die BIOS-Konfiguration meines Supermicro-Boards auslesen

In meiner Serie BIOS erklärt arbeite ich mich durch das Setup eines Supermicro X12SPi-TF. Die Grundlage dafür war bisher eine Bildschirmaufnahme: ich bin durch alle Menüs gelaufen, habe das Video in Einzelbilder zerlegt und die Werte abgetippt. Das funktioniert, ist aber Handarbeit, und Handarbeit übersieht Dinge.

Zwei Terminalausgaben untereinander: ohne Lizenz bricht das Kommando saa mit ExitCode 80 ab, mit der OOB-Lizenz erzeugt dasselbe Kommando eine XML-Datei mit 372 Einstellungen.

Was ich eigentlich wollte, ist eine Datei. Eine Liste aller Optionen mit ihrem aktuellen Wert, maschinenlesbar, damit ich sie durchsuchen und mit einem späteren Stand vergleichen kann. Das Board kann das. Es rückt es nur nicht heraus.

Drei Wege, drei Absagen

Der erste Weg führt über Redfish, die HTTP-Schnittstelle des Management-Controllers. Der passende Endpunkt existiert, antwortet aber nicht mit Daten:

GET /redfish/v1/Systems/1/Bios
HTTP 403

"MessageId": "SMC.1.0.OemLicenseNotPassed",
"Message": "Not licensed to perform this request. The following licenses DCMS were needed"

Der zweite Weg ist Supermicros eigenes Kommandozeilenwerkzeug. Es heißt inzwischen SAA, SuperServer Automation Assistant, und liegt dem BIOS-Paket bei. Es kann genau das, was ich suche, und arbeitet dabei nicht über das Netz, sondern direkt über die Firmware:

./saa -c GetCurrentBiosCfg --file bios-current.xml
ExitCode 80
Node product key is not activated.
One of the node product key (SFT-OOB-LIC or SFT-DCMS-SINGLE) should be activated

Der dritte Weg wäre, die UEFI-Variablen selbst zu lesen. Die liegen unter /sys/firmware/efi/efivars/, und tatsächlich gibt es dort Einträge, die nach BIOS-Einstellungen aussehen. Nur sind das undurchsichtige Datenblöcke ohne die Zuordnungstabelle des Boards. Man sieht Bytes, aber man weiß nicht, welches Byte welcher Menüpunkt ist.

Drei unabhängige Wege, dieselbe Sperre. An dieser Stelle habe ich in meinen Notizen etwas geschrieben, das sich später als falsch herausstellte. Dazu komme ich am Ende.

Zwei Lizenzen, und sie sind nicht dasselbe

Lies die beiden Fehlermeldungen oben noch einmal nebeneinander. Sie verlangen nicht das Gleiche. Redfish nennt namentlich DCMS. SAA nennt SFT-OOB-LIC oder SFT-DCMS-SINGLE, also eine von zweien.

Das ist der Punkt, an dem man leicht zu viel Geld ausgibt. Supermicro verkauft für diese Board-Generation zwei Lizenzen. Die kleine heißt Out of Band, kurz OOB. Die große heißt DCMS und kostet etwa das Fünffache. Wer nur die Fehlermeldung von Redfish liest, kauft DCMS. Wer die Fehlermeldung von SAA liest, merkt, dass es für seinen Zweck auch die kleine tut.

Nebenbei taucht dieselbe Lizenz an einer Stelle auf, die ich nicht erwartet hätte. Im Handbuch zum Board stehen bei zwei Sicherheitseinstellungen, nämlich beim Abschalten der vorderen und der hinteren USB-Anschlüsse, die Worte *available for configuration if the SFT-DCMS-SINGLE license is installed*. Es fehlen also nicht nur Management-Schnittstellen. Es fehlen zwei Menüpunkte im Setup selbst.

Warum man den Schlüssel nicht selbst baut

Bei dieser Recherche stößt man unweigerlich auf ein Werkzeug auf GitHub, das Supermicro- Produktschlüssel behandelt. Für die Generationen 9 bis 11 kann es welche erzeugen, denn dort war der Schlüssel ein berechneter Wert über die MAC-Adresse des Management-Controllers.

Für die zwölfte Generation, also mein Board, kann es das nicht, und das Projekt schreibt es selbst deutlich hin: dieses Format lässt sich mit dem Werkzeug prüfen, aber nicht erzeugen. Der Grund ist, dass Supermicro umgestellt hat. Der Schlüssel ist heute eine von Supermicro signierte Datei, und der Management-Controller prüft die Signatur gegen einen öffentlichen Schlüssel in seiner eigenen Firmware. Ohne den privaten Schlüssel des Herstellers entsteht da nichts Gültiges.

Mein Board bestätigt das Format auf Nachfrage:

Node Product Key Format..........JSON

Damit ist die naheliegende Abkürzung nicht moralisch, sondern rechnerisch verschlossen. Man muss die Frage also wirklich beantworten.

Der Kauf, und eine Überraschung beim Erzeugen

Gekauft habe ich im Supermicro eStore. 23,67 Euro netto, 28,17 Euro brutto. Bei der Bestellung wählt man das Mainboard-Modell aus einer Liste, und mein X12SPi-TF steht darin. Das ist erwähnenswert, weil mehrere Händlerbeschreibungen dieser Lizenz nur X10 und X11 nennen. Diese Texte sind veraltet.

Jetzt kommt der Teil, den ich falsch erwartet hatte. Ich dachte, ich kaufe und bekomme einen Schlüssel. So läuft es nicht. Man bekommt zunächst nur eine Zertifikatsnummer und die Aufforderung, den Schlüssel selbst zu erzeugen. Dafür meldet man sich im Store an, wählt die Bestellung aus und gibt an, für welches Gerät der Schlüssel gelten soll: entweder die MAC-Adresse des Management-Controllers oder die Seriennummer des Boards.

Die Bindung an die Hardware entsteht also nicht beim Verkauf, sondern beim Käufer, im Moment des Erzeugens. Das ist konsequent, denn Supermicro weiß beim Verkauf ja gar nicht, in welchem Gerät die Lizenz landen soll. Es heißt aber auch, dass man sich vertippen kann, und dann hat man einen Schlüssel für ein Gerät, das es nicht gibt.

Der Ablauf war zügig. Bestellbestätigung um 14:17, die Freigabe zum Erzeugen um 14:42, der fertige Schlüssel um 14:44, aktiv im Board um 14:46. Unter einer halben Stunde vom Klick bis zur Funktion, und die zugesagte Stunde war damit nicht zu optimistisch.

Der Schlüssel selbst ist eine kleine Textdatei, benannt nach der MAC-Adresse, mit einem JSON-Objekt darin: Lizenzname, Ausstellungsdatum und eine lange Signatur. Mehr ist es nicht.

Eine Kuriosität am Rande: die Mail mit dieser Textdatei trägt einen Ausfuhrhinweis der US-Regierung. Die Ware sei nur für das Bestimmungsland freigegeben und dürfe nicht weiterveräußert oder an Dritte weitergegeben werden. Das gilt hier für eine Datei von wenigen hundert Byte, deren einzige Wirkung darin besteht, in einem Verwaltungscontroller einen Menüpunkt sichtbar zu machen.

Aktivieren

Supermicro nennt vier Wege, den Schlüssel einzuspielen: die Weboberfläche des Management-Controllers, das Werkzeug SUM, die Verwaltungssoftware SSM und Redfish. Die Weboberfläche ist der ruhigste Weg, weil sie eine Bestätigungsseite hat, und bei einem Schlüssel, der genau einmal auf genau ein Gerät passt, will man die haben.

Wer es lieber skriptet, findet die passenden Endpunkte im Management-Controller, und die sind auch ohne Lizenz erreichbar:

POST /redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ActivateLicense
POST /redfish/v1/Managers/1/LicenseManager/Actions/LicenseManager.ClearLicense
GET  /redfish/v1/Managers/1/LicenseManager/QueryLicense

Die Abfrage danach gibt genau den Inhalt der Datei zurück, die man hochgeladen hat. Der Controller speichert den Schlüssel also unverändert und prüft ihn bei Bedarf.

Das Kommando, auf das es ankommt

Nach der Aktivierung meldet SAA einen anderen Zustand:

Node Product Key Activated.......SFT-OOB-LIC
Feature Toggled On...............Yes
BMC Supports OOB BIOS Config.....Yes
BIOS Supports OOB BIOS Config....Yes

Und dasselbe Kommando, das vorher mit ExitCode 80 abgebrochen ist, läuft durch:

./saa -c GetCurrentBiosCfg --file bios-current.xml
File "bios-current.xml" is created.

Heraus kommt eine Datei von 260 Kilobyte mit 60 Menüs und 372 Einstellungen. Zum Vergleich: das offizielle Handbuch beschreibt 180 Optionen. Und die Datei enthält pro Eintrag mehr, als man im Setup sieht, nämlich zusätzlich den Auslieferungszustand und den Hilfetext:

<Setting name="Quiet Boot" checkedStatus="Unchecked" type="CheckBox">
  <Information>
    <DefaultStatus>Checked</DefaultStatus>
    <Help>Enables or disables Quiet Boot option</Help>
  </Information>
</Setting>

Der Auslieferungszustand ist der eigentliche Gewinn. Damit sehe ich auf einen Blick, welche Einstellungen an dieser Maschine vom Werkszustand abweichen, und das ist genau die Liste, die man nach einem BIOS-Update wiederherstellen will.

Zwei komplette Hauptmenüs standen darin, die ich beim Durchklicken schlicht nie geöffnet hatte. Und ein Untermenü, das ich in meinen Notizen als offene Lücke geführt habe, war vollständig enthalten. So viel zum Thema Handarbeit übersieht Dinge.

Was die Lizenz nicht freischaltet

Jetzt der ehrliche Teil, und der ist mir wichtiger als der Erfolg. Ich hatte vor dem Kauf drei Messungen aufgeschrieben, damit ich hinterher vergleichen kann. Drei von vier Erwartungen sind eingetroffen, und die vierte war die interessante.

Der Redfish-Endpunkt, mit dem alles anfing, antwortet weiterhin mit 403 und verlangt weiterhin DCMS. Die kleine Lizenz öffnet den Weg über SAA und eben nicht den über Redfish. Wer also ausdrücklich die Netzwerkschnittstelle braucht, etwa weil er hunderte Server ohne Betriebssystem konfigurieren will, kommt um die große Lizenz nicht herum.

Das hat eine Nebenwirkung, die ich nicht auf dem Zettel hatte. Der Firmware-Updater fwupd kann inzwischen mit Supermicros Redfish-Schnittstelle sprechen. Er sieht bei mir aber nur zwei von zwölf Firmware-Komponenten, und die beiden BIOS-Einträge fehlen. Der Grund ist, dass er zur Identifikation eines Geräts das Objekt lesen muss, das hinter genau diesem gesperrten Endpunkt liegt. Die Lizenz sperrt hier also nicht das Aktualisieren, sondern das Erkennen, und das Aktualisieren scheitert dann als Folge. Nach der Aktivierung sind es unverändert zwei von zwölf.

Und der dritte Weg, den ich vorher gar nicht gesehen hatte: fwupd sieht den BIOS-Speicher auch ganz direkt am Chipsatz, liest die Version korrekt aus und verweigert trotzdem den Dienst:

Internal SPI Controller (BIOS):
    Aktuelle Version: 2.5
    Probleme:         Device firmware has been locked

Das ist keine Lizenzsache, und daran hat sich erwartungsgemäß nichts geändert. Der Speicher ist auf Chipsatzebene schreibgeschützt, weil das Board mit aktivem Root of Trust läuft. Ein BIOS, das sich aus einem laufenden Betriebssystem heraus überschreiben lässt, wäre genau die Lücke, die dieser Schutz verhindern soll. Der Reflex sagt hier Hersteller blockiert Linux. Tatsächlich blockiert eine Sicherheitsfunktion, die ich selbst haben will.

Mein Denkfehler

Bleibt der Satz, den ich weiter oben angekündigt habe. In meinen Notizen stand nach der dritten Absage sinngemäß: drei unabhängige Wege, dieselbe Sperre, nicht erneut versuchen.

Gemessen hatte ich: ohne Lizenz gibt es keinen Weg. Aufgeschrieben hatte ich: es gibt keinen Weg. Und die dritte Möglichkeit, nämlich die Lizenz einfach zu kaufen, kam in meiner Aufzählung der drei gesperrten Wege überhaupt nicht vor, obwohl das Werkzeug sie mir wörtlich genannt hatte.

Dass drei Wege an derselben Sperre scheitern, beweist, dass es eine Sperre gibt. Es beweist nicht, dass sie unüberwindbar ist. Wenn eine Fehlermeldung den Namen der fehlenden Berechtigung nennt, ist das ein Hinweis und kein Schlusspunkt.

Lohnt sich das?

Für einen einzelnen Rechner zu Hause: nur, wenn man Freude daran hat. Ich hätte die Werte auch weiter abschreiben können, und der Screencast hat mir immerhin eine fünfzehnteilige Serie eingebracht, die aus einer XML-Datei nie entstanden wäre. Man liest eine Datei nicht so aufmerksam wie ein Menü, durch das man sich selbst klicken muss.

Für alles, was mehr als eine Handvoll Maschinen betrifft, sieht es anders aus. Konfiguration auslesen, versionieren, nach einem Update wieder einspielen und im Zweifel gegen einen bekannten Stand vergleichen, das ist bei 28 Euro pro Board keine Diskussion. Ärgerlich finde ich nur, dass man diese Rechnung überhaupt aufmachen muss. Es geht um das Auslesen der eigenen Einstellungen auf der eigenen Hardware.

Wenn du auf demselben Board sitzt und dieselbe Fehlermeldung vor dir hast, ist die Kurzfassung: für die Konfiguration reicht die kleine Lizenz, für Redfish brauchst du die große, und für Firmware-Updates brauchst du bei einem X12 mit Root of Trust vermutlich gar keine.

Siehe auch: BIOS erklärt, Teil 1: ein Serverboard als Workstation und der Weg ins Setup und die übrigen Folgen unter BIOS & Firmware.

Wenn dazu etwas unklar ist oder du es auf deinem Board anders erlebt hast, dürft ihr mich sehr gerne fragen.

BIOS erklärt, Teil 1: ein Serverboard als Workstation und der Weg ins Setup

Seit Ende Juli steht bei mir ein anderer Rechner unter dem Schreibtisch. Kein gekaufter, sondern einer aus Teilen die ohnehin schon da waren: ein Supermicro X12SPi-TF, also ein richtiges Serverboard, dazu ein Xeon Gold 5315Y und 256 GB registrierter ECC-Speicher. Die Grafikkarte ist aus der alten Workstation umgezogen, Gehäuse und Netzteil waren neu. Seitdem macht die Kiste genau das, was vorher eine deutlich ältere Dual-Socket-Maschine gemacht hat, nur leiser und mit mehr Luft nach oben.

Aptio Setup, Reiter Main, mit Systemdatum und Systemzeit

Beim Einrichten ist mir dann etwas passiert, das ich so nicht auf dem Zettel hatte. Ich saß im BIOS-Setup, bin die Seiten durchgegangen, und bei einigen Einstellungen dachte ich: kenne ich, habe ich schon hundertmal gesehen. Hätte mich in dem Moment jemand gefragt, was der Schalter denn nun genau tut, wäre ich ins Schwimmen gekommen. Also habe ich nachgeschlagen. Und dann noch mal. Irgendwann stand fest, dass daraus eine kleine Serie werden sollte.

Warum ein Server-BIOS eine andere Hausnummer ist

Aptio Setup, Reiter Advanced, mit der Liste der Untermenüs von Boot Feature bis Supermicro KMS Server Configuration

Ein normales Desktop-Board hat im Setup vielleicht drei Dutzend Schalter, die wirklich etwas bewirken. Der Rest ist Bootreihenfolge, Lüfterkurve und Beleuchtung. Bei diesem Board sieht das anders aus. Das Handbuch beschreibt rund 180 Einstellungen, bei denen man tatsächlich etwas auswählen kann, verteilt auf sieben Hauptmenüs und je nach Zweig bis zu fünf Ebenen tief. Dort stehen Dinge wie Patrol Scrub, Stale AtoS, UMA-Based Clustering oder IIO eDPC Support. Das sind keine Marketingbegriffe, das sind Schalter für Verhalten, das man verstanden haben muss, bevor man daran dreht.

Und genau da liegt für mich der interessante Punkt. Fast alles davon steht auf Auto oder auf dem Herstellerdefault, und das ist in den allermeisten Fällen auch völlig richtig so. Nur ist „steht auf Default“ eben keine Antwort auf die Frage, was eigentlich passiert, wenn man es umstellt. Diese Antwort hätte ich gern. Für jeden Schalter, der auf diesem Board etwas tut.

Wie man auf so einem Board überhaupt ins Setup kommt

Hier fängt der Unterschied zum Desktop schon an. Auf dem Board sitzt ein zweiter, kleiner Computer: der BMC, ein ASPEED AST2600. Der hat seine eigene Netzwerkbuchse, seine eigene IP-Adresse, sein eigenes Betriebssystem, und er läuft auch dann, wenn der eigentliche Rechner aus ist. Solange Strom am Netzteil anliegt, ist der BMC wach. Der BMC bekommt später eine eigene Folge, für heute reicht eine seiner Fähigkeiten: KVM over IP.

Das heisst konkret, ich brauche für das BIOS weder Monitor noch Tastatur am Rechner. Ich rufe im Browser die Weboberfläche des BMC auf, starte dort die Konsole, und sehe das Bild, das die Grafikausgabe gerade produziert. Inklusive POST, inklusive Setup, inklusive Bootloader. Tasten gehen den umgekehrten Weg. Der BMC hängt sich dafür als virtuelle USB-Tastatur und -Maus an den Rechner, und die tauchen unter Linux später auch brav in lsusb auf:

Bus 001 Device 003: ID 0557:9241 ATEN International Co., Ltd SMCI HID KM
Bus 001 Device 004: ID 0b1f:03ee Insyde Software Corp. RNDIS/Ethernet Gadget

Wer schon mal einen Server im Keller stehen hatte und sich gefragt hat, wie man da ohne Bildschirm ins BIOS kommt: so. Und weil das Bild ohnehin durchs Netz geht, kann man es auch gleich aufzeichnen. Genau das habe ich gemacht, und diese Aufnahme ist die Grundlage für alles, was in dieser Serie noch kommt.

Und dann wollte ich die Einstellungen einfach auslesen

Aptio Setup, Reiter Save and Exit, mit den Speicheroptionen, Save as User Defaults und der geschwärzten Boot-Override-Liste

Das war der Moment, in dem die Serie ihre eigentliche Rechtfertigung bekommen hat. Meine Idee war naheliegend: statt 200 Screenshots zu sortieren, hole ich mir die komplette Konfiguration als Datei. Moderne Boards können das, dafür gibt es Redfish, eine HTTP-Schnittstelle auf dem BMC. Ein Aufruf, und man hat jede Einstellung mit Ist-Wert und allen möglichen Werten sauber als JSON.

Der Aufruf ging auch durch. Nur nicht so, wie ich wollte:

GET /redfish/v1/Systems/1/Bios
403 Forbidden
MessageId: SMC.1.0.OemLicenseNotPassed
"Not licensed to perform this request. The following licenses DCMS were needed"

Also der Weg über das Kommandozeilenwerkzeug. Supermicro liefert dafür den SuperServer Automation Assistant mit, und der kennt genau den passenden Befehl. In-Band, also lokal auf der Maschine selbst, ohne Umweg über das Netzwerk:

./saa -c GetCurrentBiosCfg --file bios-current.xml

Ergebnis:

ExitCode                = 80
Description             = Node product key is not activated.
Error message:
        One of the node product key (SFT-OOB-LIC or SFT-DCMS-SINGLE) should be
    activated to execute this task.

Damit ist es amtlich. Das Board weigert sich, mir seine eigene Konfiguration herauszugeben, weil ich keine Lizenz gekauft habe. Nicht ändern, wohlgemerkt. Nur lesen. Der dritte Weg über die UEFI-Variablen im Kernel führt auch nicht weiter, da liegen zwar Blobs, aber ohne die Zuordnungstabellen des Boards sind das einfach nur Bytes.

Ich verstehe das Geschäftsmodell durchaus. Wer dreihundert Server ausrollt, will die Konfiguration automatisiert verteilen, und dafür Geld zu verlangen ist legitim. Nur bin ich eben nicht dreihundert Server, ich bin ein Schreibtisch, und das Auslesen dessen was ich selbst eingestellt habe fühlt sich nicht nach einem Premium-Feature an. Der Screencast über die Konsole ist der Weg drumherum, und ehrlich gesagt ist er für diese Serie sogar der bessere: ein Screenshot zeigt den Schalter so, wie er dir im Setup auch begegnet.

Was in der Serie kommt

Ich gehe das BIOS in Themenblöcken durch, nicht Menüseite für Menüseite. Jede Folge nimmt sich einen Bereich vor und beantwortet für die Schalter darin drei Fragen: was tut das, warum steht es bei mir so, und wann würde man es anders setzen. Grob in dieser Reihenfolge:

  • Boot Feature und Power, also alles rund um Einschalten, Watchdog und das Verhalten nach einem Stromausfall
  • Die CPU, einmal die Seite mit Kernen, Threads und Prefetchern, einmal die mit AES-NI, TME, SGX und den Sicherheitsfunktionen
  • Speicher, ECC, Patrol Scrub und die Frage warum mein DDR4-3200 mit 2933 läuft
  • NUMA und der Uncore-Bereich, der auf einer Single-Socket-Maschine erstaunlich viel Unsinn anzeigt
  • PCIe in drei Folgen: Slots und Lanes, dann Adressraum und Resizable BAR, dann die Fehlerbehandlung, wo es richtig spannend wird
  • Virtualisierung mit VT-d, IOMMU und VMD
  • Storage, Preboot-Netzwerk, Bootreihenfolge und Secure Boot
  • Zum Schluss der BMC selbst, das TPM und die Ereignisprotokolle

Die Folgen sind bewusst kurz gehalten. Ein Thema, einmal sauber durch, und nicht ein Wälzer den keiner zu Ende liest.

Ein Wort dazu, warum ich das überhaupt aufschreibe

Zwei Gründe. Der erste ist eigennützig: indem ich es aufschreibe, muss ich es verstanden haben. Ein Halbwissen überlebt keinen Absatz, in dem man erklären soll warum etwas so ist. Das ist der beste Lerneffekt den ich kenne.

Der zweite Grund ist etwas nachdenklicher. Dieses Wissen ist am Aussterben, und das meine ich ohne Larmoyanz. Wer heute Rechenleistung braucht, klickt sie in einer Cloud zusammen, und dort gibt es kein BIOS mehr, an das man herankäme. Wer eine Frage hat, fragt eine AI und bekommt eine Antwort, die meistens stimmt. Beides ist bequem und für die allermeisten Zwecke völlig ausreichend. Trotzdem muss es am Ende weiterhin Menschen geben, die wissen was unter der Abstraktion passiert. Wenn eine Maschine nicht bootet, hilft kein Terraform.

Und damit zum wichtigsten Teil: wenn ich mich irre, sag es mir bitte. Ich schreibe diese Serie auch, um dazuzulernen, und eine Korrektur ist dafür der schnellste Weg. Ich trage sie dann im jeweiligen Beitrag nach, mit Datum, und lasse sie nicht stillschweigend verschwinden. Gerade bei den Prozessor-Interna und beim PCIe-Teil wird es hier Leute geben, die tiefer drin stecken als ich.

Nächste Folge: Boot Feature und Power. Also die Frage, warum mein Rechner nach einem Stromausfall absichtlich aus bleibt, und was ein Interrupt aus dem Jahr 1981 heute noch in einem UEFI-Setup zu suchen hat.

Siehe auch

Habt ihr auf eurem Board schon mal versucht, die BIOS-Konfiguration maschinell auszulesen, und seid dabei auch gegen eine Lizenz gelaufen? Erzählt es mir gerne, ihr dürft mich jederzeit fragen.

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑