Zusammenfassung

  • Der Policy-Baum aus RFC 5280 vervielfacht denselben logischen Zustand, wenn mehrere Abbildungen zu derselben Policy führen; auch die Nachfolger werden kopiert, sodass der schlechteste Fall exponentiell wächst.
  • RFC 9618 teilt diese Zustände in einem gerichteten azyklischen Graphen. Pfadgültigkeit und endgültige Policy-Menge bleiben gleich, während die Struktur linear an Policies und Abbildungen der Eingabe gebunden ist.
  • Eine belastbare Freigabe braucht zwei Belege: semantische Äquivalenz für schwierige Policy-Fälle und reproduzierbare Grenzen für Speicher, CPU und Warteschlangen unter bösartigen Eingaben.

Der Auditbericht enthielt Hunderte Testfälle. Der neue Zertifikatsprüfer akzeptierte und verwarf genau dieselben Ketten wie sein Vorgänger. Die Abnahme schien nur noch eine Unterschrift zu benötigen.

Nicht im Bericht standen die erzeugten Policy-Knoten, der maximale Speicher oder die Zeit bis zur Entscheidung. Eine kurze, gezielt aufgebaute Kette konnte weiterhin einen Worker blockieren, obwohl ihr endgültiges Ergebnis korrekt war. Der Test hatte das Urteil geprüft, aber nicht die Rechenvollmacht der Eingabe.

RFC 9618 schließt diese Lücke für einen präzisen Teil der X.509-Validierung. Es genügt nicht, dass zwei Algorithmen dieselbe Antwort liefern. Auch der Weg zur Antwort muss gegenüber nicht vertrauenswürdigen Daten begrenzt sein.

Policy-Verarbeitung ist nicht Pfadsuche

Die Erweiterung certificatePolicies enthält Policy-OIDs und optionale Qualifier. Eine Zertifizierungsstelle kann Policies einschränken und eine OID ihres Ausstellerbereichs auf eine OID des nachgeordneten Bereichs abbilden. Die Anwendung liefert ihre anfänglich akzeptierten Policies.

RFC 5280 verarbeitet diese Informationen innerhalb eines bereits vorliegenden Zertifizierungspfads. Das ist nicht dessen Ermittlung. RFC 4158 beschreibt, wie Kandidaten zwischen Zielzertifikat und Vertrauensanker gefunden werden. RFC 9618 beginnt danach und fragt, welche Policies die Kette überleben.

RFC 5280 speicherte den Zwischenzustand als valid_policy_tree. Jeder Mapping-Weg erhielt einen eigenen Zweig. Wenn zwei Aussteller-Policies dieselbe Subject-Policy erreichen, entstehen zwei Kopien desselben Zustands. An der nächsten Tiefe werden deren Kinder erneut vervielfacht.

Das Beispiel aus RFC 9618 verwendet in jedem Zwischenzertifikat zwei OIDs und die vollständige Abbildung beider OIDs auf beide OIDs der nächsten Stufe. Mit jeder Tiefe verdoppelt sich der Baum. Die codierte Kette wächst mäßig; die interne Darstellung wächst exponentiell.

So entsteht der Denial-of-Service: Ein TLS-Server mit Client-Zertifikaten oder ein Identitätsdienst kann erheblich mehr Ressourcen aufwenden als der Absender. Der Angreifer muss weder eine Signatur fälschen noch eine gültige Identität erlangen. Es reicht, den Prüfer vor seiner Ablehnung zu beschäftigen.

Die Norm verweist auf reale Fälle. Der OpenSSL-Änderungsnachweis beschreibt exponentiellen Ressourcenverbrauch bei Policy-Prüfung und eine Knotenbegrenzung für CVE-2023-0464. Apple nennt bei CVE-2023-23524 die Verarbeitung eines bösartig präparierten Zertifikats als Ursache eines Denial-of-Service. Auch die OpenSSL-Versionshistorie vermerkt die Begrenzung.

Der Graph teilt Zustand, nicht Bedeutung

valid_policy_graph aus RFC 9618 enthält pro Tiefe und Policy-OID höchstens einen Knoten. Erreichen mehrere Vorgänger dieselbe Policy, hat dieser Knoten mehrere Eltern. Seine Nachfolger müssen nicht für jeden Elternpfad erneut gespeichert werden.

Die Information bleibt erhalten. Der alte Baum ist die Aufzählung aller Wurzel-Blatt-Pfade des Graphen. Für die Frage, welche End-Policies erreichbar sind, ist diese vollständige Materialisierung unnötig. Deshalb verändern sich weder die Gültigkeit des Zertifizierungspfads noch die endgültig gültigen Policies.

Verändert wird die Schranke. Die Graphgröße ist linear durch die Gesamtzahl der Policies und Mappings in der Kette begrenzt. Große Eingaben verursachen weiterhin Arbeit; eine kompakte kombinatorische Eingabe erzeugt jedoch kein exponentiell größeres Objekt mehr.

Damit bleibt der gemeinsame Standard schlank. Er bestimmt Semantik und Invarianten für anyPolicy, Zähler, Mapping, Beschneidung und Ergebnis. Lokale Implementierungen dürfen ihre Datenstrukturen wählen, solange sie Bedeutung und Ressourcengrenze einhalten.

Ein altes Ausgabeformat kann den Fehler zurückholen

RFC 5280 bezeichnete den vollständigen valid_policy_tree als Ausgabe. Ein älterer Aufrufer kann ihn verlangen, obwohl der Prüfer intern effizient mit einem Graphen arbeitet. Das Expandieren aller Graphpfade stellt exakt das exponentielle Objekt wieder her.

RFC 9618 stuft diese Ausgabe deshalb als veraltet ein und empfiehlt die durch Autoritäten beziehungsweise Nutzer eingeschränkten Policy-Mengen. Die Anwendung benötigt meist das Ergebnis, nicht jede gleichwertige Herleitung.

Eine verzögerte Rekonstruktion bleibt für Altsysteme möglich. Sie ist aber nicht begrenzt, nur später. Wer sie behält, muss sie aus dem gemeinsamen Zulassungspfad herauslösen, quotieren, messen und einem verantwortlichen Bedarf zuordnen.

Hier wird Kompatibilität zur Governance-Frage. Eine unbesessene Diagnose-API darf nicht die Verfügbarkeit jeder Authentisierung bestimmen. Der tatsächliche Verbraucher und sein zwingender Output müssen benannt werden; historische Gewohnheit ist keine allgemeine Anforderung.

Grenzwerte sind eigenständige Policy-Entscheidungen

Bis zur Graphmigration können Tiefe oder Baumknoten begrenzt werden. Eine zu geringe Tiefe verwirft legitime Pfade, eine hohe Tiefe lässt weiterhin starke Verzweigung zu. RFC 9618 zeigt, dass mehr Policies je Zertifikat trotz Tiefenlimit ein Wachstum um O(N^(Tiefe/2)) erlauben können.

Ein Knotenlimit schützt nur, wenn es vor Ressourcenverlust deterministisch greift. Nachzuweisen sind Abbruchpunkt, Speicher, CPU, Fehlerantwort, Wiederholung und Wirkung auf parallele Anfragen. Ein Konfigurationswert ohne Ablaufdaten ist keine Betriebsbestätigung.

Auch das Abschalten der Policy-Verarbeitung ist kein stiller Ausweg. Sind die betreffenden Erweiterungen als kritisch markiert, muss eine Implementierung ohne Unterstützung das Zertifikat wegen einer unbekannten kritischen Erweiterung zurückweisen. Bedeutung darf nicht zur Kostensenkung ignoriert werden.

Äquivalenz und Aufwand in einem Prüfprotokoll

Die semantische Suite umfasst einfache Policies, mehrere Mappings, anyPolicy, explizite Policy-Anforderung, Mapping-Hemmung, Hemmung von anyPolicy, Beschneidung und leere Ergebnismengen. Sie vergleicht nicht nur Erfolg oder Fehler, sondern die endgültige nutzerbeschränkte Menge.

Die Komplexitätssuite variiert Tiefe, OIDs je Zertifikat und Mapping-Dichte unabhängig. Sie erfasst Eingabebytes, Knoten, Kanten, Spitzenspeicher, Allokationen, CPU- und Laufzeit, Abbruchgrund sowie Warteschlangen unter Parallelität.

Beide Suiten müssen verbunden sein. Jeder Semantikfall benötigt seine Ressourcenspur, jeder Angriffstest sein exaktes Urteil. Sonst erscheint sowohl ein schneller, aber inhaltlich falscher Prüfer als auch ein kompatibler, aber erschöpfbarer Prüfer erfolgreich.

Schließlich muss der laufende Stand belegt werden: geladene Bibliothek, Build-Optionen, aktive Policy-Konfiguration, Aufrufe der alten Baum-API und Prozessidentität. Die Veröffentlichung einer Norm oder die Installation eines Pakets beweist nicht die tatsächliche Ausführung.

RFC 9618 begrenzt nicht alle X.509-Kosten. Pfadaufbau, Signaturen, Widerruf, Parsing und Anwendungsfreigabe bleiben getrennt. Es entfernt eine bestimmte Verstärkung, ohne die zugesagte Entscheidung zu ändern. Gerade deshalb ist der Erfolg messbar.

Quellen