<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.4 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-lamps-x509-policy-graph-04" category="std" consensus="true" submissionType="IETF" updates="5280" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.19.0 -->
  <front>
    <title abbrev="Updates to X.509 Policy Validation">Updates to X.509 Policy Validation</title>
    <seriesInfo name="Internet-Draft" value="draft-ietf-lamps-x509-policy-graph-04"/>
    <author initials="D." surname="Benjamin" fullname="David Benjamin">
      <organization>Google LLC</organization>
      <address>
        <email>davidben@google.com</email>
      </address>
    </author>
    <date year="2024" month="January" day="17"/>
    <area>Security</area>
    <workgroup>Limited Additional Mechanisms for PKIX and SMIME</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 57?>

<t>This document updates RFC 5280 to replace the algorithm for X.509 policy
validation with an equivalent, more efficient algorithm. The original algorithm
built a structure which scaled exponentially in the worst case, leaving
implementations vulnerable to denial-of-service attacks.</t>
    </abstract>
    <note removeInRFC="true">
      <name>Discussion Venues</name>
      <t>Discussion of this document takes place on the
    Limited Additional Mechanisms for PKIX and SMIME Working Group mailing list (spasm@ietf.org),
    which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/spasm/"/>.</t>
      <t>Source for this draft and an issue tracker can be found at
    <eref target="https://github.com/davidben/x509-policy-graph"/>.</t>
    </note>
  </front>
  <middle>
    <?line 64?>

<section anchor="introduction">
      <name>Introduction</name>
      <t><xref target="RFC5280"/> defines a suite of extensions for determining the "policies" which
apply to a certification path. A policy is described by an object identifier
(OID), and a set of optional qualifiers.</t>
      <t>Policy validation in <xref target="RFC5280"/> is complex. As an overview, the certificate
policies extension (<xref section="4.2.1.4" sectionFormat="of" target="RFC5280"/>) describes the policies,
with optional qualifiers, under which an individual certificate was issued.
The policy mappings extension (<xref section="4.2.1.5" sectionFormat="of" target="RFC5280"/>) allows a
CA certificate to map its policy OIDs to other policy OIDs in certificates
that it issues. Subject to these mappings and other extensions, the certification
path's overall policy set is the intersection of policies asserted by each
certificate in the path, collecting the corresponding qualifiers.</t>
      <t>The procedure in <xref section="6.1" sectionFormat="of" target="RFC5280"/> determines this set in the course
of certification path validation. It does so by building a policy tree,
containing policies asserted by each certificate and mappings between
them. This tree can grow exponentially in the depth of the certification path,
which means an attacker, with a small input, can cause a path validator to
consume excessive memory and computational resources. This cost asymmetry
can lead to a denial-of-service vulnerability in X.509-based applications, such
as <xref target="CVE-2023-0464"/> and <xref target="CVE-2023-23524"/>.</t>
      <t><xref target="dos"/> describes this vulnerability. <xref target="policy-graph"/> describes the primary
mitigation for this vulnerability, a replacement for the policy tree structure.
<xref target="updates"/> provides updates to <xref target="RFC5280"/> which implement this change.
Finally, <xref target="other-mitigations"/> discusses alternative mitigation strategies for
X.509 applications.</t>
      <section anchor="summary-of-changes-from-rfc-5280">
        <name>Summary of Changes from RFC 5280</name>
        <t>The algorithm for processing certificate policies and policy mappings is
replaced with one which builds an equivalent, but much more efficient structure.
This new algorithm does not change the validity status of any certification
path, nor which certificate policies are valid for it.</t>
      </section>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
when, and only when, they appear in all capitals, as shown here.</t>
    </section>
    <section anchor="dos">
      <name>Denial of Service Vulnerability</name>
      <t>This section discusses how the path validation algorithm defined in
<xref section="6.1.2" sectionFormat="of" target="RFC5280"/> can lead to a denial-of-service vulnerability in
X.509-based applications.</t>
      <section anchor="policy-trees">
        <name>Policy Trees</name>
        <t><xref section="6.1.2" sectionFormat="of" target="RFC5280"/> constructs the <tt>valid_policy_tree</tt>, a tree of
certificate policies, during certification path validation.
The nodes at any given depth in the tree correspond to
policies asserted by a certificate in the certification path. A node's
parent policy is the policy in the issuer certificate which was mapped to this
policy, and a node's children are the policies it was mapped to in the subject
certificate.</t>
        <t>For example, suppose a certification path contains:</t>
        <ul spacing="normal">
          <li>
            <t>An intermediate certificate which asserts policy OIDs OID1, OID2, and OID5.
It contains mappings OID1 to OID3, and OID1 to OID4.</t>
          </li>
          <li>
            <t>An end-entity certificate which asserts policy OIDs OID2, OID3, and OID6.</t>
          </li>
        </ul>
        <t>This would result in the tree shown in <xref target="basic-tree"/>. Note that OID5 and OID6
are not included or mapped across the whole path, so they do not appear in the
final structure.</t>
        <figure anchor="basic-tree">
          <name>An Example X.509 Policy Tree</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="424" viewBox="0 0 424 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 152,160 L 152,224" fill="none" stroke="black"/>
                <path d="M 152,288 L 152,320" fill="none" stroke="black"/>
                <path d="M 200,232 L 200,280" fill="none" stroke="black"/>
                <path d="M 232,32 L 232,96" fill="none" stroke="black"/>
                <path d="M 256,160 L 256,224" fill="none" stroke="black"/>
                <path d="M 256,288 L 256,320" fill="none" stroke="black"/>
                <path d="M 312,160 L 312,224" fill="none" stroke="black"/>
                <path d="M 312,288 L 312,320" fill="none" stroke="black"/>
                <path d="M 328,32 L 328,96" fill="none" stroke="black"/>
                <path d="M 360,232 L 360,280" fill="none" stroke="black"/>
                <path d="M 416,160 L 416,224" fill="none" stroke="black"/>
                <path d="M 416,288 L 416,320" fill="none" stroke="black"/>
                <path d="M 232,32 L 328,32" fill="none" stroke="black"/>
                <path d="M 232,64 L 328,64" fill="none" stroke="black"/>
                <path d="M 232,96 L 328,96" fill="none" stroke="black"/>
                <path d="M 152,160 L 256,160" fill="none" stroke="black"/>
                <path d="M 312,160 L 416,160" fill="none" stroke="black"/>
                <path d="M 152,192 L 256,192" fill="none" stroke="black"/>
                <path d="M 312,192 L 416,192" fill="none" stroke="black"/>
                <path d="M 152,224 L 256,224" fill="none" stroke="black"/>
                <path d="M 312,224 L 416,224" fill="none" stroke="black"/>
                <path d="M 152,288 L 256,288" fill="none" stroke="black"/>
                <path d="M 312,288 L 416,288" fill="none" stroke="black"/>
                <path d="M 152,320 L 256,320" fill="none" stroke="black"/>
                <path d="M 312,320 L 416,320" fill="none" stroke="black"/>
                <path d="M 324,104 L 348,152" fill="none" stroke="black"/>
                <path d="M 220,152 L 244,104" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="368,280 356,274.4 356,285.6" fill="black" transform="rotate(90,360,280)"/>
                <polygon class="arrowhead" points="356,152 344,146.4 344,157.6" fill="black" transform="rotate(63.43494882292201,348,152)"/>
                <polygon class="arrowhead" points="228,152 216,146.4 216,157.6" fill="black" transform="rotate(116.56505117707799,220,152)"/>
                <polygon class="arrowhead" points="208,280 196,274.4 196,285.6" fill="black" transform="rotate(90,200,280)"/>
                <g class="text">
                  <text x="112" y="52">Root:</text>
                  <text x="280" y="52">anyPolicy</text>
                  <text x="280" y="84">{anyPolicy}</text>
                  <text x="80" y="180">Intermediate:</text>
                  <text x="204" y="180">OID1</text>
                  <text x="364" y="180">OID2</text>
                  <text x="24" y="196">(OID5</text>
                  <text x="92" y="196">discarded)</text>
                  <text x="180" y="212">{OID3,</text>
                  <text x="232" y="212">OID4}</text>
                  <text x="364" y="212">{OID2}</text>
                  <text x="88" y="308">End-entity:</text>
                  <text x="204" y="308">OID3</text>
                  <text x="364" y="308">OID2</text>
                  <text x="24" y="324">(OID6</text>
                  <text x="92" y="324">discarded)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                            +-----------+
           Root:            | anyPolicy |
                            +-----------+
                            |{anyPolicy}|
                            +-----------+
                             /          \
                            /            \
                           v              v
                  +------------+      +------------+
   Intermediate:  |    OID1    |      |    OID2    |
(OID5 discarded)  +------------+      +------------+
                  |{OID3, OID4}|      |   {OID2}   |
                  +------------+      +------------+
                        |                   |
                        |                   |
                        v                   v
                  +------------+      +------------+
     End-entity:  |    OID3    |      |    OID2    |
(OID6 discarded)  +------------+      +------------+
]]></artwork>
          </artset>
        </figure>
        <t>The complete algorithm for building this structure is described in steps (d),
(e), and (f) of <xref section="6.1.3" sectionFormat="of" target="RFC5280"/>, steps (h), (i), (j) of <xref section="6.1.4" sectionFormat="of" target="RFC5280"/>, and steps (a), (b), and (g) of <xref section="6.1.5" sectionFormat="of" target="RFC5280"/>.</t>
      </section>
      <section anchor="exponential-growth">
        <name>Exponential Growth</name>
        <t>The <tt>valid_policy_tree</tt> grows exponentially in the worst case. In
step (d.1) of <xref section="6.1.3" sectionFormat="of" target="RFC5280"/>, a single policy P can produce
multiple child nodes if multiple issuer policies map to P. This can cause the
tree size to increase in size multiplicatively at each level.</t>
        <t>In particular, consider a certificate chain where every intermediate certificate
asserts policies OID1 and OID2, and then contains the full Cartesian product of
mappings:</t>
        <ul spacing="normal">
          <li>
            <t>OID1 maps to OID1</t>
          </li>
          <li>
            <t>OID1 maps to OID2</t>
          </li>
          <li>
            <t>OID2 maps to OID1</t>
          </li>
          <li>
            <t>OID2 maps to OID2</t>
          </li>
        </ul>
        <t>At each depth, the tree would double in size.
For example, if there are two intermediate certificates and one end-entity certificate, the resulting tree would be as depicted in <xref target="exponential-tree"/>.</t>
        <figure anchor="exponential-tree">
          <name>An Example X.509 Policy Tree with Exponential Growth</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="448" width="576" viewBox="0 0 576 448" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,400 L 8,432" fill="none" stroke="black"/>
                <path d="M 24,288 L 24,352" fill="none" stroke="black"/>
                <path d="M 40,360 L 40,392" fill="none" stroke="black"/>
                <path d="M 64,400 L 64,432" fill="none" stroke="black"/>
                <path d="M 80,400 L 80,432" fill="none" stroke="black"/>
                <path d="M 104,160 L 104,224" fill="none" stroke="black"/>
                <path d="M 104,360 L 104,392" fill="none" stroke="black"/>
                <path d="M 128,288 L 128,352" fill="none" stroke="black"/>
                <path d="M 136,400 L 136,432" fill="none" stroke="black"/>
                <path d="M 152,400 L 152,432" fill="none" stroke="black"/>
                <path d="M 168,288 L 168,352" fill="none" stroke="black"/>
                <path d="M 184,360 L 184,392" fill="none" stroke="black"/>
                <path d="M 200,32 L 200,96" fill="none" stroke="black"/>
                <path d="M 208,160 L 208,224" fill="none" stroke="black"/>
                <path d="M 208,400 L 208,432" fill="none" stroke="black"/>
                <path d="M 224,400 L 224,432" fill="none" stroke="black"/>
                <path d="M 248,360 L 248,392" fill="none" stroke="black"/>
                <path d="M 272,288 L 272,352" fill="none" stroke="black"/>
                <path d="M 280,400 L 280,432" fill="none" stroke="black"/>
                <path d="M 296,400 L 296,432" fill="none" stroke="black"/>
                <path d="M 312,288 L 312,352" fill="none" stroke="black"/>
                <path d="M 328,360 L 328,392" fill="none" stroke="black"/>
                <path d="M 352,400 L 352,432" fill="none" stroke="black"/>
                <path d="M 368,400 L 368,432" fill="none" stroke="black"/>
                <path d="M 392,32 L 392,96" fill="none" stroke="black"/>
                <path d="M 392,160 L 392,224" fill="none" stroke="black"/>
                <path d="M 392,360 L 392,392" fill="none" stroke="black"/>
                <path d="M 416,288 L 416,352" fill="none" stroke="black"/>
                <path d="M 424,400 L 424,432" fill="none" stroke="black"/>
                <path d="M 440,400 L 440,432" fill="none" stroke="black"/>
                <path d="M 456,288 L 456,352" fill="none" stroke="black"/>
                <path d="M 472,360 L 472,392" fill="none" stroke="black"/>
                <path d="M 496,160 L 496,224" fill="none" stroke="black"/>
                <path d="M 496,400 L 496,432" fill="none" stroke="black"/>
                <path d="M 512,400 L 512,432" fill="none" stroke="black"/>
                <path d="M 536,360 L 536,392" fill="none" stroke="black"/>
                <path d="M 560,288 L 560,352" fill="none" stroke="black"/>
                <path d="M 568,400 L 568,432" fill="none" stroke="black"/>
                <path d="M 200,32 L 392,32" fill="none" stroke="black"/>
                <path d="M 200,64 L 392,64" fill="none" stroke="black"/>
                <path d="M 200,96 L 392,96" fill="none" stroke="black"/>
                <path d="M 104,160 L 208,160" fill="none" stroke="black"/>
                <path d="M 392,160 L 496,160" fill="none" stroke="black"/>
                <path d="M 104,192 L 208,192" fill="none" stroke="black"/>
                <path d="M 392,192 L 496,192" fill="none" stroke="black"/>
                <path d="M 104,224 L 208,224" fill="none" stroke="black"/>
                <path d="M 392,224 L 496,224" fill="none" stroke="black"/>
                <path d="M 24,288 L 128,288" fill="none" stroke="black"/>
                <path d="M 168,288 L 272,288" fill="none" stroke="black"/>
                <path d="M 312,288 L 416,288" fill="none" stroke="black"/>
                <path d="M 456,288 L 560,288" fill="none" stroke="black"/>
                <path d="M 24,320 L 128,320" fill="none" stroke="black"/>
                <path d="M 168,320 L 272,320" fill="none" stroke="black"/>
                <path d="M 312,320 L 416,320" fill="none" stroke="black"/>
                <path d="M 456,320 L 560,320" fill="none" stroke="black"/>
                <path d="M 24,352 L 128,352" fill="none" stroke="black"/>
                <path d="M 168,352 L 272,352" fill="none" stroke="black"/>
                <path d="M 312,352 L 416,352" fill="none" stroke="black"/>
                <path d="M 456,352 L 560,352" fill="none" stroke="black"/>
                <path d="M 8,400 L 64,400" fill="none" stroke="black"/>
                <path d="M 80,400 L 136,400" fill="none" stroke="black"/>
                <path d="M 152,400 L 208,400" fill="none" stroke="black"/>
                <path d="M 224,400 L 280,400" fill="none" stroke="black"/>
                <path d="M 296,400 L 352,400" fill="none" stroke="black"/>
                <path d="M 368,400 L 424,400" fill="none" stroke="black"/>
                <path d="M 440,400 L 496,400" fill="none" stroke="black"/>
                <path d="M 512,400 L 568,400" fill="none" stroke="black"/>
                <path d="M 8,432 L 64,432" fill="none" stroke="black"/>
                <path d="M 80,432 L 136,432" fill="none" stroke="black"/>
                <path d="M 152,432 L 208,432" fill="none" stroke="black"/>
                <path d="M 224,432 L 280,432" fill="none" stroke="black"/>
                <path d="M 296,432 L 352,432" fill="none" stroke="black"/>
                <path d="M 368,432 L 424,432" fill="none" stroke="black"/>
                <path d="M 440,432 L 496,432" fill="none" stroke="black"/>
                <path d="M 512,432 L 568,432" fill="none" stroke="black"/>
                <path d="M 188,232 L 212,280" fill="none" stroke="black"/>
                <path d="M 380,104 L 404,152" fill="none" stroke="black"/>
                <path d="M 484,232 L 508,280" fill="none" stroke="black"/>
                <path d="M 92,280 L 116,232" fill="none" stroke="black"/>
                <path d="M 188,152 L 212,104" fill="none" stroke="black"/>
                <path d="M 388,280 L 412,232" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="544,392 532,386.4 532,397.6" fill="black" transform="rotate(90,536,392)"/>
                <polygon class="arrowhead" points="516,280 504,274.4 504,285.6" fill="black" transform="rotate(63.43494882292201,508,280)"/>
                <polygon class="arrowhead" points="480,392 468,386.4 468,397.6" fill="black" transform="rotate(90,472,392)"/>
                <polygon class="arrowhead" points="412,152 400,146.4 400,157.6" fill="black" transform="rotate(63.43494882292201,404,152)"/>
                <polygon class="arrowhead" points="400,392 388,386.4 388,397.6" fill="black" transform="rotate(90,392,392)"/>
                <polygon class="arrowhead" points="396,280 384,274.4 384,285.6" fill="black" transform="rotate(116.56505117707799,388,280)"/>
                <polygon class="arrowhead" points="336,392 324,386.4 324,397.6" fill="black" transform="rotate(90,328,392)"/>
                <polygon class="arrowhead" points="256,392 244,386.4 244,397.6" fill="black" transform="rotate(90,248,392)"/>
                <polygon class="arrowhead" points="220,280 208,274.4 208,285.6" fill="black" transform="rotate(63.43494882292201,212,280)"/>
                <polygon class="arrowhead" points="196,152 184,146.4 184,157.6" fill="black" transform="rotate(116.56505117707799,188,152)"/>
                <polygon class="arrowhead" points="192,392 180,386.4 180,397.6" fill="black" transform="rotate(90,184,392)"/>
                <polygon class="arrowhead" points="112,392 100,386.4 100,397.6" fill="black" transform="rotate(90,104,392)"/>
                <polygon class="arrowhead" points="100,280 88,274.4 88,285.6" fill="black" transform="rotate(116.56505117707799,92,280)"/>
                <polygon class="arrowhead" points="48,392 36,386.4 36,397.6" fill="black" transform="rotate(90,40,392)"/>
                <g class="text">
                  <text x="304" y="52">anyPolicy</text>
                  <text x="304" y="84">{anyPolicy}</text>
                  <text x="156" y="180">OID1</text>
                  <text x="444" y="180">OID2</text>
                  <text x="132" y="212">{OID1,</text>
                  <text x="184" y="212">OID2}</text>
                  <text x="420" y="212">{OID1,</text>
                  <text x="472" y="212">OID2}</text>
                  <text x="76" y="308">OID1</text>
                  <text x="220" y="308">OID2</text>
                  <text x="364" y="308">OID1</text>
                  <text x="508" y="308">OID2</text>
                  <text x="52" y="340">{OID1,</text>
                  <text x="104" y="340">OID2}</text>
                  <text x="196" y="340">{OID1,</text>
                  <text x="248" y="340">OID2}</text>
                  <text x="340" y="340">{OID1,</text>
                  <text x="392" y="340">OID2}</text>
                  <text x="484" y="340">{OID1,</text>
                  <text x="536" y="340">OID2}</text>
                  <text x="36" y="420">OID1</text>
                  <text x="108" y="420">OID2</text>
                  <text x="180" y="420">OID1</text>
                  <text x="252" y="420">OID2</text>
                  <text x="324" y="420">OID1</text>
                  <text x="396" y="420">OID2</text>
                  <text x="468" y="420">OID1</text>
                  <text x="540" y="420">OID2</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                        +-----------------------+
                        |        anyPolicy      |
                        +-----------------------+
                        |       {anyPolicy}     |
                        +-----------------------+
                         /                     \
                        /                       \
                       v                         v
            +------------+                      +------------+
            |    OID1    |                      |    OID2    |
            +------------+                      +------------+
            |{OID1, OID2}|                      |{OID1, OID2}|
            +------------+                      +------------+
             /         \                          /         \
            /           \                        /           \
           v             v                      v             v
  +------------+    +------------+    +------------+    +------------+
  |    OID1    |    |    OID2    |    |    OID1    |    |    OID2    |
  +------------+    +------------+    +------------+    +------------+
  |{OID1, OID2}|    |{OID1, OID2}|    |{OID1, OID2}|    |{OID1, OID2}|
  +------------+    +------------+    +------------+    +------------+
    |       |         |       |         |       |         |       |
    v       v         v       v         v       v         v       v
+------+ +------+ +------+ +------+ +------+ +------+ +------+ +------+
| OID1 | | OID2 | | OID1 | | OID2 | | OID1 | | OID2 | | OID1 | | OID2 |
+------+ +------+ +------+ +------+ +------+ +------+ +------+ +------+
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="attack-vector">
        <name>Attack Vector</name>
        <t>An attacker can use the exponential growth to mount a denial-of-service attack against
an X.509-based application. The attacker sends certificate chain as in <xref target="exponential-growth"/> and
triggers the target application's certificate validation process. For example,
the target application may be a TLS <xref target="RFC8446"/> server that performs client
certificate validation. The target
application will consume far more resources processing the input than the
attacker consumed to send it, preventing it from servicing other clients.</t>
      </section>
    </section>
    <section anchor="avoiding-exponential-growth">
      <name>Avoiding Exponential Growth</name>
      <t>This document mitigates the denial-of-service vulnerability described in <xref target="dos"/>
by replacing the policy tree with a policy graph structure, described in this
section. The policy graph grows linearly instead of exponentially. This removes
the asymmetric cost in policy validation.</t>
      <t>X.509 implementations SHOULD perform policy validation by building a policy
graph, following the procedure described in <xref target="updates"/>. This replacement
procedure computes the same policies as in <xref target="RFC5280"/>, however one of the
outputs is in a different form. See <xref target="outputs"/> for details.
<xref target="other-mitigations"/> describes alternative mitigations for implementations that
depend on the original, exponential-sized output.</t>
      <section anchor="policy-graph">
        <name>Policy Graphs</name>
        <t>The tree structure from <xref target="RFC5280"/> is an unnecessarily inefficient
representation of a certification path's policy mappings. A single certificate
policy may correspond to multiple nodes, but each node is identical, with identical
children. This redundancy is the source of the exponential growth described in
<xref target="exponential-growth"/>.</t>
        <t>A policy graph is a directed acyclic graph of policy nodes.
Where <xref target="RFC5280"/> adds multiple duplicate nodes, a policy graph adds a single node with multiple parents.
See <xref target="updates"/> for the procedure for building this structure.
<xref target="exponential-tree-as-graph"/> shows the updated representation of the example in <xref target="exponential-tree"/>.</t>
        <figure anchor="exponential-tree-as-graph">
          <name>A More Efficient Representation of an X.509 Policy Tree</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="576" width="248" viewBox="0 0 248 576" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,160 L 8,224" fill="none" stroke="black"/>
                <path d="M 8,336 L 8,400" fill="none" stroke="black"/>
                <path d="M 8,512 L 8,544" fill="none" stroke="black"/>
                <path d="M 48,232 L 48,328" fill="none" stroke="black"/>
                <path d="M 48,408 L 48,504" fill="none" stroke="black"/>
                <path d="M 80,32 L 80,96" fill="none" stroke="black"/>
                <path d="M 112,160 L 112,224" fill="none" stroke="black"/>
                <path d="M 112,336 L 112,400" fill="none" stroke="black"/>
                <path d="M 112,512 L 112,544" fill="none" stroke="black"/>
                <path d="M 136,160 L 136,224" fill="none" stroke="black"/>
                <path d="M 136,336 L 136,400" fill="none" stroke="black"/>
                <path d="M 136,512 L 136,544" fill="none" stroke="black"/>
                <path d="M 176,32 L 176,96" fill="none" stroke="black"/>
                <path d="M 192,232 L 192,328" fill="none" stroke="black"/>
                <path d="M 192,408 L 192,504" fill="none" stroke="black"/>
                <path d="M 240,160 L 240,224" fill="none" stroke="black"/>
                <path d="M 240,336 L 240,400" fill="none" stroke="black"/>
                <path d="M 240,512 L 240,544" fill="none" stroke="black"/>
                <path d="M 80,32 L 176,32" fill="none" stroke="black"/>
                <path d="M 80,64 L 176,64" fill="none" stroke="black"/>
                <path d="M 80,96 L 176,96" fill="none" stroke="black"/>
                <path d="M 8,160 L 112,160" fill="none" stroke="black"/>
                <path d="M 136,160 L 240,160" fill="none" stroke="black"/>
                <path d="M 8,192 L 112,192" fill="none" stroke="black"/>
                <path d="M 136,192 L 240,192" fill="none" stroke="black"/>
                <path d="M 8,224 L 112,224" fill="none" stroke="black"/>
                <path d="M 136,224 L 240,224" fill="none" stroke="black"/>
                <path d="M 8,336 L 112,336" fill="none" stroke="black"/>
                <path d="M 136,336 L 240,336" fill="none" stroke="black"/>
                <path d="M 8,368 L 112,368" fill="none" stroke="black"/>
                <path d="M 136,368 L 240,368" fill="none" stroke="black"/>
                <path d="M 8,400 L 112,400" fill="none" stroke="black"/>
                <path d="M 136,400 L 240,400" fill="none" stroke="black"/>
                <path d="M 8,512 L 112,512" fill="none" stroke="black"/>
                <path d="M 136,512 L 240,512" fill="none" stroke="black"/>
                <path d="M 8,544 L 112,544" fill="none" stroke="black"/>
                <path d="M 136,544 L 240,544" fill="none" stroke="black"/>
                <path d="M 100,408 L 148,504" fill="none" stroke="black"/>
                <path d="M 100,232 L 148,328" fill="none" stroke="black"/>
                <path d="M 172,104 L 196,152" fill="none" stroke="black"/>
                <path d="M 60,152 L 84,104" fill="none" stroke="black"/>
                <path d="M 100,328 L 148,232" fill="none" stroke="black"/>
                <path d="M 100,504 L 148,408" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="200,504 188,498.4 188,509.6" fill="black" transform="rotate(90,192,504)"/>
                <polygon class="arrowhead" points="200,328 188,322.4 188,333.6" fill="black" transform="rotate(90,192,328)"/>
                <polygon class="arrowhead" points="204,152 192,146.4 192,157.6" fill="black" transform="rotate(63.43494882292201,196,152)"/>
                <polygon class="arrowhead" points="156,504 144,498.4 144,509.6" fill="black" transform="rotate(63.43494882292201,148,504)"/>
                <polygon class="arrowhead" points="156,328 144,322.4 144,333.6" fill="black" transform="rotate(63.43494882292201,148,328)"/>
                <polygon class="arrowhead" points="108,504 96,498.4 96,509.6" fill="black" transform="rotate(116.56505117707799,100,504)"/>
                <polygon class="arrowhead" points="108,328 96,322.4 96,333.6" fill="black" transform="rotate(116.56505117707799,100,328)"/>
                <polygon class="arrowhead" points="68,152 56,146.4 56,157.6" fill="black" transform="rotate(116.56505117707799,60,152)"/>
                <polygon class="arrowhead" points="56,504 44,498.4 44,509.6" fill="black" transform="rotate(90,48,504)"/>
                <polygon class="arrowhead" points="56,328 44,322.4 44,333.6" fill="black" transform="rotate(90,48,328)"/>
                <g class="text">
                  <text x="128" y="52">anyPolicy</text>
                  <text x="128" y="84">{anyPolicy}</text>
                  <text x="60" y="180">OID1</text>
                  <text x="188" y="180">OID2</text>
                  <text x="36" y="212">{OID1,</text>
                  <text x="88" y="212">OID2}</text>
                  <text x="164" y="212">{OID1,</text>
                  <text x="216" y="212">OID2}</text>
                  <text x="60" y="356">OID1</text>
                  <text x="188" y="356">OID2</text>
                  <text x="36" y="388">{OID1,</text>
                  <text x="88" y="388">OID2}</text>
                  <text x="164" y="388">{OID1,</text>
                  <text x="216" y="388">OID2}</text>
                  <text x="60" y="532">OID1</text>
                  <text x="188" y="532">OID2</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
              +-----------+
              | anyPolicy |
              +-----------+
              |{anyPolicy}|
              +-----------+
              /           \
             /             \
            v               v
     +------------+  +------------+
     |    OID1    |  |    OID2    |
     +------------+  +------------+
     |{OID1, OID2}|  |{OID1, OID2}|
     +------------+  +------------+
          |      \    /     |
          |       \  /      |
          |        \/       |
          |        /\       |
          |       /  \      |
          v      v    v     v
     +------------+  +------------+
     |    OID1    |  |    OID2    |
     +------------+  +------------+
     |{OID1, OID2}|  |{OID1, OID2}|
     +------------+  +------------+
          |      \    /     |
          |       \  /      |
          |        \/       |
          |        /\       |
          |       /  \      |
          v      v    v     v
     +------------+  +------------+
     |    OID1    |  |    OID2    |
     +------------+  +------------+
]]></artwork>
          </artset>
        </figure>
        <t>This graph's size is bounded linearly by the total number of certificate
policies (<xref section="4.2.1.4" sectionFormat="of" target="RFC5280"/>) and policy mappings (<xref section="4.2.1.5" sectionFormat="of" target="RFC5280"/>). The policy tree from <xref target="RFC5280"/> is the tree of all paths from the root to a leaf in the policy graph,
so no information is lost in the graph representation.</t>
      </section>
      <section anchor="outputs">
        <name>Verification Outputs</name>
        <t><xref section="6.1.6" sectionFormat="of" target="RFC5280"/> describes the entire <tt>valid_policy_tree</tt> structure as
an output of the verification process. Section 12.2 of <xref target="X.509"/> instead only
outputs the authorities-constrained policies, the user-constrained policies,
and their associated qualifiers.</t>
        <t>As the <tt>valid_policy_tree</tt> is the exponential structure, computing it
reintroduces the denial-of-service vulnerability. X.509 implementations
SHOULD NOT output the entire <tt>valid_policy_tree</tt> structure and instead SHOULD
limit output to just the set of authorities-constrained and/or user-constrained
policies, as described in <xref target="X.509"/>. <xref target="update-outputs"/> and
<xref target="other-mitigations"/> discuss other mitigations for applications where this
option is not available.</t>
        <t>X.509 implementations MAY omit policy qualifiers from the output to simplify
processing. Note <xref section="4.2.1.4" sectionFormat="of" target="RFC5280"/> already recommends that
certification authorities omit policy qualifiers from policy information terms.</t>
      </section>
    </section>
    <section anchor="updates">
      <name>Updates to RFC 5280</name>
      <t>This section provides updates to <xref target="RFC5280"/>. This implements the changes
described in <xref target="avoiding-exponential-growth"/>.</t>
      <section anchor="updates-to-section-61">
        <name>Updates to Section 6.1</name>
        <t>This update replaces a paragraph of <xref section="6.1" sectionFormat="of" target="RFC5280"/> as follows:</t>
        <t>OLD:</t>
        <ul empty="true">
          <li>
            <t>A particular certification path may not, however, be appropriate for
  all applications.  Therefore, an application MAY augment this
  algorithm to further limit the set of valid paths.  The path
  validation process also determines the set of certificate policies
  that are valid for this path, based on the certificate policies
  extension, policy mappings extension, policy constraints extension,
  and inhibit anyPolicy extension.  To achieve this, the path
  validation algorithm constructs a valid policy tree.  If the set of
  certificate policies that are valid for this path is not empty, then
  the result will be a valid policy tree of depth n, otherwise the
  result will be a null valid policy tree.</t>
          </li>
        </ul>
        <t>NEW:</t>
        <ul empty="true">
          <li>
            <t>A particular certification path may not, however, be appropriate for
  all applications.  Therefore, an application MAY augment this
  algorithm to further limit the set of valid paths.  The path
  validation process also determines the set of certificate policies
  that are valid for this path, based on the certificate policies
  extension, policy mappings extension, policy constraints extension,
  and inhibit anyPolicy extension.  To achieve this, the path
  validation algorithm constructs a valid policy set, which may be empty if
  no certificate policies are valid for this path.</t>
          </li>
        </ul>
      </section>
      <section anchor="updates-to-section-612">
        <name>Updates to Section 6.1.2</name>
        <t>This update replaces entry (a) of <xref section="6.1.2" sectionFormat="of" target="RFC5280"/> with the following text:</t>
        <ol spacing="normal" type="(%c)"><li>
            <t><tt>valid_policy_graph</tt>:  A directed acyclic graph of certificate
policies with their optional qualifiers; each of the leaves
of the graph represents a valid policy at this stage in the
certification path validation.  If valid policies exist at
this stage in the certification path validation, the depth of
the graph is equal to the number of certificates in the chain
that have been processed.  If valid policies do not exist at
this stage in the certification path validation, the graph is
set to NULL.  Once the graph is set to NULL, policy processing
ceases.  Implementations MAY omit qualifiers if not returned
in the output.  </t>
            <t>
Each node in the <tt>valid_policy_graph</tt> includes three data objects:
the valid policy, a set of associated policy qualifiers, and a set of
one or more expected policy values.  </t>
            <t>
Nodes in the graph can be divided into depths, numbered starting from zero.
A node at depth x can have zero or more children at depth x+1 and, with the
exception of depth zero, one or more parents at depth x-1. No other edges
between nodes may exist.  </t>
            <t>
If the node is at depth x, the components of the node have
the following semantics:  </t>
            <ol spacing="normal" type="(%d)"><li>
                <t>The <tt>valid_policy</tt> is a single policy OID representing a valid policy for the path of length x.</t>
              </li>
              <li>
                <t>The <tt>qualifier_set</tt> is a set of policy qualifiers associated with the valid policy in certificate x.
It is only necessary to maintain this field if policy qualifiers are returned to the application.
See Section 6.1.5, step (g).</t>
              </li>
              <li>
                <t>The <tt>expected_policy_set</tt> contains one or more policy OIDs that would satisfy this policy in the certificate x+1.</t>
              </li>
            </ol>
            <t>
The initial value of the <tt>valid_policy_graph</tt> is a single node with
<tt>valid_policy</tt> anyPolicy, an empty <tt>qualifier_set</tt>, and an
<tt>expected_policy_set</tt> with the single value anyPolicy.  This node is
considered to be at depth zero.  </t>
            <t>
The graph additionally satisfies the following invariants:  </t>
            <ul spacing="normal">
              <li>
                <t>For any depth x and policy OID P-OID, there is at most one node at depth x whose <tt>valid_policy</tt> is P-OID.</t>
              </li>
              <li>
                <t>The <tt>expected_policy_set</tt> of a node whose <tt>valid_policy</tt> is anyPolicy is always {anyPolicy}.</t>
              </li>
              <li>
                <t>A node at depth x whose <tt>valid_policy</tt> is anyPolicy, except for the one at
depth zero, always has exactly one parent: a node at depth x-1 whose
<tt>valid_policy</tt> is also anyPolicy.</t>
              </li>
              <li>
                <t>Each node at depth greater than 0 has either one or more parent nodes whose <tt>valid_policy</tt> is not anyPolicy,
or a single parent node whose <tt>valid_policy</tt> is anyPolicy.
That is, a node cannot simultaneously be a child of both anyPolicy and some non-anyPolicy OID.</t>
              </li>
            </ul>
            <t>
<xref target="graph-initial"/> is a graphic representation of the initial state of the
<tt>valid_policy_graph</tt>.  Additional figures will use this format to
describe changes in the <tt>valid_policy_graph</tt> during path processing.  </t>
            <figure anchor="graph-initial">
              <name>Initial value of the valid_policy_graph State Variable</name>
              <artset>
                <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="160" width="376" viewBox="0 0 376 160" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                    <path d="M 8,32 L 8,128" fill="none" stroke="black"/>
                    <path d="M 144,32 L 144,128" fill="none" stroke="black"/>
                    <path d="M 8,32 L 144,32" fill="none" stroke="black"/>
                    <path d="M 176,48 L 208,48" fill="none" stroke="black"/>
                    <path d="M 8,64 L 144,64" fill="none" stroke="black"/>
                    <path d="M 176,80 L 208,80" fill="none" stroke="black"/>
                    <path d="M 8,96 L 144,96" fill="none" stroke="black"/>
                    <path d="M 176,112 L 208,112" fill="none" stroke="black"/>
                    <path d="M 8,128 L 144,128" fill="none" stroke="black"/>
                    <polygon class="arrowhead" points="184,112 172,106.4 172,117.6" fill="black" transform="rotate(180,176,112)"/>
                    <polygon class="arrowhead" points="184,80 172,74.4 172,85.6" fill="black" transform="rotate(180,176,80)"/>
                    <polygon class="arrowhead" points="184,48 172,42.4 172,53.6" fill="black" transform="rotate(180,176,48)"/>
                    <g class="text">
                      <text x="72" y="52">anyPolicy</text>
                      <text x="268" y="52">valid_policy</text>
                      <text x="76" y="84">{}</text>
                      <text x="272" y="84">qualifier_set</text>
                      <text x="72" y="116">{anyPolicy}</text>
                      <text x="296" y="116">expected_policy_set</text>
                    </g>
                  </svg>
                </artwork>
                <artwork type="ascii-art"><![CDATA[
    +----------------+
    |   anyPolicy    |   <---- valid_policy
    +----------------+
    |       {}       |   <---- qualifier_set
    +----------------+
    |  {anyPolicy}   |   <---- expected_policy_set
    +----------------+
]]></artwork>
              </artset>
            </figure>
          </li>
        </ol>
      </section>
      <section anchor="updates-to-section-613">
        <name>Updates to Section 6.1.3</name>
        <t>This update replaces steps (d), (e), and (f) of <xref section="6.1.3" sectionFormat="of" target="RFC5280"/> with the following text:</t>
        <ol spacing="normal" type="(%c)" start="4"><li>
            <t>If the certificate policies extension is present in the
certificate and the <tt>valid_policy_graph</tt> is not NULL, process
the policy information by performing the following steps in
order:  </t>
            <ol spacing="normal" type="(%d)"><li>
                <t>For each policy P not equal to anyPolicy in the certificate policies extension,
let P-OID denote the OID for policy P and P-Q denote the qualifier set for policy P.
Perform the following steps in order:      </t>
                <ol spacing="normal" type="(%i)"><li>
                    <t>Let <tt>parent_nodes</tt> be the nodes at depth i-1 in the <tt>valid_policy_graph</tt> where P-OID is in the <tt>expected_policy_set</tt>.
If <tt>parent_nodes</tt> is not empty, create a child node as follows:
set the <tt>valid_policy</tt> to P-OID, set the <tt>qualifier_set</tt> to P-Q, set the <tt>expected_policy_set</tt> to {P-OID}, and set the parent nodes to <tt>parent_nodes</tt>.          </t>
                    <t>
For example, consider a <tt>valid_policy_graph</tt> with a node of depth i-1 where the <tt>expected_policy_set</tt> is {Gold, White},
and a second node where the <tt>expected_policy_set</tt> is {Gold, Yellow}.
Assume the certificate policies Gold and Silver appear in the certificate policies extension of certificate i.
The Gold policy is matched, but the Silver policy is not.
This rule will generate a child node of depth i for the Gold policy.
The result is shown as <xref target="exact-match"/>.          </t>
                    <figure anchor="exact-match">
                      <name>Processing an Exact Match</name>
                      <artset>
                        <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="456" viewBox="0 0 456 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                            <path d="M 8,32 L 8,128" fill="none" stroke="black"/>
                            <path d="M 112,208 L 112,304" fill="none" stroke="black"/>
                            <path d="M 152,32 L 152,128" fill="none" stroke="black"/>
                            <path d="M 208,32 L 208,128" fill="none" stroke="black"/>
                            <path d="M 256,208 L 256,304" fill="none" stroke="black"/>
                            <path d="M 352,32 L 352,128" fill="none" stroke="black"/>
                            <path d="M 8,32 L 152,32" fill="none" stroke="black"/>
                            <path d="M 208,32 L 352,32" fill="none" stroke="black"/>
                            <path d="M 8,64 L 152,64" fill="none" stroke="black"/>
                            <path d="M 208,64 L 352,64" fill="none" stroke="black"/>
                            <path d="M 8,96 L 152,96" fill="none" stroke="black"/>
                            <path d="M 208,96 L 352,96" fill="none" stroke="black"/>
                            <path d="M 8,128 L 152,128" fill="none" stroke="black"/>
                            <path d="M 208,128 L 352,128" fill="none" stroke="black"/>
                            <path d="M 112,208 L 256,208" fill="none" stroke="black"/>
                            <path d="M 112,240 L 256,240" fill="none" stroke="black"/>
                            <path d="M 112,272 L 256,272" fill="none" stroke="black"/>
                            <path d="M 112,304 L 256,304" fill="none" stroke="black"/>
                            <path d="M 100,136 L 132,200" fill="none" stroke="black"/>
                            <path d="M 236,200 L 268,136" fill="none" stroke="black"/>
                            <polygon class="arrowhead" points="244,200 232,194.4 232,205.6" fill="black" transform="rotate(116.56505117707799,236,200)"/>
                            <polygon class="arrowhead" points="140,200 128,194.4 128,205.6" fill="black" transform="rotate(63.43494882292201,132,200)"/>
                            <g class="text">
                              <text x="80" y="52">Red</text>
                              <text x="284" y="52">Blue</text>
                              <text x="76" y="84">{}</text>
                              <text x="276" y="84">{}</text>
                              <text x="400" y="84">depth</text>
                              <text x="440" y="84">i-1</text>
                              <text x="52" y="116">{Gold,</text>
                              <text x="108" y="116">White}</text>
                              <text x="252" y="116">{Gold,</text>
                              <text x="312" y="116">Yellow}</text>
                              <text x="180" y="228">Gold</text>
                              <text x="180" y="260">{}</text>
                              <text x="304" y="260">depth</text>
                              <text x="336" y="260">i</text>
                              <text x="180" y="292">{Gold}</text>
                            </g>
                          </svg>
                        </artwork>
                        <artwork type="ascii-art"><![CDATA[
    +-----------------+      +-----------------+
    |       Red       |      |       Blue      |
    +-----------------+      +-----------------+
    |       {}        |      |       {}        |   depth i-1
    +-----------------+      +-----------------+
    |  {Gold, White}  |      |  {Gold, Yellow} |
    +-----------------+      +-----------------+
                \                   /
                 \                 /
                  \               /
                   v             v
                 +-----------------+
                 |      Gold       |
                 +-----------------+
                 |       {}        |   depth i
                 +-----------------+
                 |     {Gold}      |
                 +-----------------+
]]></artwork>
                      </artset>
                    </figure>
                  </li>
                  <li>
                    <t>If there was no match in step (i) and the <tt>valid_policy_graph</tt> includes a node of depth i-1 with the <tt>valid_policy</tt> anyPolicy,
generate a child node with the following values:
set the <tt>valid_policy</tt> to P-OID, set the <tt>qualifier_set</tt> to P-Q, set the <tt>expected_policy_set</tt> to {P-OID},
and set the parent node to the anyPolicy node at depth i-1.          </t>
                    <t>
For example, consider a <tt>valid_policy_graph</tt> with a node
of depth i-1 where the <tt>valid_policy</tt> is anyPolicy.
Assume the certificate policies Gold and Silver appear
in the certificate policies extension of certificate
i.  The Gold policy does not have a qualifier, but the
Silver policy has the qualifier Q-Silver.  If Gold and
Silver were not matched in (i) above, this rule will
generate two child nodes of depth i, one for each
policy.  The result is shown as <xref target="unmatched-anypolicy"/>.          </t>
                    <figure anchor="unmatched-anypolicy">
                      <name>Processing Unmatched Policies when a Leaf Node Specifies anyPolicy</name>
                      <artset>
                        <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="472" viewBox="0 0 472 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                            <path d="M 8,208 L 8,304" fill="none" stroke="black"/>
                            <path d="M 120,32 L 120,128" fill="none" stroke="black"/>
                            <path d="M 152,208 L 152,304" fill="none" stroke="black"/>
                            <path d="M 240,208 L 240,304" fill="none" stroke="black"/>
                            <path d="M 264,32 L 264,128" fill="none" stroke="black"/>
                            <path d="M 384,208 L 384,304" fill="none" stroke="black"/>
                            <path d="M 120,32 L 264,32" fill="none" stroke="black"/>
                            <path d="M 120,64 L 264,64" fill="none" stroke="black"/>
                            <path d="M 120,96 L 264,96" fill="none" stroke="black"/>
                            <path d="M 120,128 L 264,128" fill="none" stroke="black"/>
                            <path d="M 8,208 L 152,208" fill="none" stroke="black"/>
                            <path d="M 240,208 L 384,208" fill="none" stroke="black"/>
                            <path d="M 8,240 L 152,240" fill="none" stroke="black"/>
                            <path d="M 240,240 L 384,240" fill="none" stroke="black"/>
                            <path d="M 8,272 L 152,272" fill="none" stroke="black"/>
                            <path d="M 240,272 L 384,272" fill="none" stroke="black"/>
                            <path d="M 8,304 L 152,304" fill="none" stroke="black"/>
                            <path d="M 240,304 L 384,304" fill="none" stroke="black"/>
                            <path d="M 236,136 L 268,200" fill="none" stroke="black"/>
                            <path d="M 116,200 L 148,136" fill="none" stroke="black"/>
                            <polygon class="arrowhead" points="276,200 264,194.4 264,205.6" fill="black" transform="rotate(63.43494882292201,268,200)"/>
                            <polygon class="arrowhead" points="124,200 112,194.4 112,205.6" fill="black" transform="rotate(116.56505117707799,116,200)"/>
                            <g class="text">
                              <text x="192" y="52">anyPolicy</text>
                              <text x="188" y="84">{}</text>
                              <text x="312" y="100">depth</text>
                              <text x="352" y="100">i-1</text>
                              <text x="192" y="116">{anyPolicy}</text>
                              <text x="76" y="228">Gold</text>
                              <text x="308" y="228">Silver</text>
                              <text x="76" y="260">{}</text>
                              <text x="308" y="260">{Q-Silver}</text>
                              <text x="432" y="260">depth</text>
                              <text x="464" y="260">i</text>
                              <text x="76" y="292">{Gold}</text>
                              <text x="308" y="292">{Silver}</text>
                            </g>
                          </svg>
                        </artwork>
                        <artwork type="ascii-art"><![CDATA[
                  +-----------------+
                  |    anyPolicy    |
                  +-----------------+
                  |       {}        |
                  +-----------------+   depth i-1
                  |   {anyPolicy}   |
                  +-----------------+
                     /           \
                    /             \
                   /               \
                  v                 v
    +-----------------+          +-----------------+
    |      Gold       |          |     Silver      |
    +-----------------+          +-----------------+
    |       {}        |          |   {Q-Silver}    |   depth i
    +-----------------+          +-----------------+
    |     {Gold}      |          |    {Silver}     |
    +-----------------+          +-----------------+
]]></artwork>
                      </artset>
                    </figure>
                  </li>
                </ol>
              </li>
              <li>
                <t>If the certificate policies extension includes the policy anyPolicy with the qualifier set AP-Q and either (a)
<tt>inhibit_anyPolicy</tt> is greater than 0 or (b) i&lt;n and the certificate is self-issued, then:      </t>
                <t>
For each policy OID P-OID (including anyPolicy) which appears in the <tt>expected_policy_set</tt> of some node in the <tt>valid_policy_graph</tt> for depth i-1,
if P-OID does not appear as the <tt>valid_policy</tt> of some node at depth i, create a single child node with the following values:
set the <tt>valid_policy</tt> to P-OID, set the <tt>qualifier_set</tt> to AP-Q, set the <tt>expected_policy_set</tt> to {P-OID},
and set the parents to the nodes at depth i-1 where P-OID appears in <tt>expected_policy_set</tt>.      </t>
                <t>
This is equivalent to running step (1) above, as if the certificate policies extension contained a policy with OID P-OID and qualifier set AP-Q.      </t>
                <t>
For example, consider a <tt>valid_policy_graph</tt> with a node of depth i-1 where the <tt>expected_policy_set</tt> is {Gold, Silver},
and a second node of depth i-1 where the <tt>expected_policy_set</tt> is {Gold, Bronze}.
Assume anyPolicy appears in the certificate policies extension of certificate i with policy qualifiers AP-Q, but Gold and Silver do not appear.
This rule will generate two child nodes of depth i, one for each policy.
The result is shown below as <xref target="anypolicy-in-extension"/>.      </t>
                <figure anchor="anypolicy-in-extension">
                  <name>Processing Unmatched Policies When the Certificate Policies Extension Specifies anyPolicy</name>
                  <artset>
                    <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="368" width="432" viewBox="0 0 432 368" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                        <path d="M 8,32 L 8,128" fill="none" stroke="black"/>
                        <path d="M 8,240 L 8,336" fill="none" stroke="black"/>
                        <path d="M 72,136 L 72,232" fill="none" stroke="black"/>
                        <path d="M 152,32 L 152,128" fill="none" stroke="black"/>
                        <path d="M 152,240 L 152,336" fill="none" stroke="black"/>
                        <path d="M 184,32 L 184,128" fill="none" stroke="black"/>
                        <path d="M 184,240 L 184,336" fill="none" stroke="black"/>
                        <path d="M 256,136 L 256,232" fill="none" stroke="black"/>
                        <path d="M 328,32 L 328,128" fill="none" stroke="black"/>
                        <path d="M 328,240 L 328,336" fill="none" stroke="black"/>
                        <path d="M 8,32 L 152,32" fill="none" stroke="black"/>
                        <path d="M 184,32 L 328,32" fill="none" stroke="black"/>
                        <path d="M 8,64 L 152,64" fill="none" stroke="black"/>
                        <path d="M 184,64 L 328,64" fill="none" stroke="black"/>
                        <path d="M 8,96 L 152,96" fill="none" stroke="black"/>
                        <path d="M 184,96 L 328,96" fill="none" stroke="black"/>
                        <path d="M 8,128 L 152,128" fill="none" stroke="black"/>
                        <path d="M 184,128 L 328,128" fill="none" stroke="black"/>
                        <path d="M 8,240 L 152,240" fill="none" stroke="black"/>
                        <path d="M 184,240 L 328,240" fill="none" stroke="black"/>
                        <path d="M 8,272 L 152,272" fill="none" stroke="black"/>
                        <path d="M 184,272 L 328,272" fill="none" stroke="black"/>
                        <path d="M 8,304 L 152,304" fill="none" stroke="black"/>
                        <path d="M 184,304 L 328,304" fill="none" stroke="black"/>
                        <path d="M 8,336 L 152,336" fill="none" stroke="black"/>
                        <path d="M 184,336 L 328,336" fill="none" stroke="black"/>
                        <path d="M 148,136 L 196,232" fill="none" stroke="black"/>
                        <polygon class="arrowhead" points="264,232 252,226.4 252,237.6" fill="black" transform="rotate(90,256,232)"/>
                        <polygon class="arrowhead" points="204,232 192,226.4 192,237.6" fill="black" transform="rotate(63.43494882292201,196,232)"/>
                        <polygon class="arrowhead" points="80,232 68,226.4 68,237.6" fill="black" transform="rotate(90,72,232)"/>
                        <g class="text">
                          <text x="80" y="52">Red</text>
                          <text x="260" y="52">Blue</text>
                          <text x="76" y="84">{}</text>
                          <text x="252" y="84">{}</text>
                          <text x="376" y="84">depth</text>
                          <text x="416" y="84">i-1</text>
                          <text x="52" y="116">{Gold,</text>
                          <text x="112" y="116">Silver}</text>
                          <text x="228" y="116">{Gold,</text>
                          <text x="288" y="116">Bronze}</text>
                          <text x="76" y="260">Silver</text>
                          <text x="260" y="260">Gold</text>
                          <text x="76" y="292">{AP-Q}</text>
                          <text x="260" y="292">{AP-Q}</text>
                          <text x="376" y="292">depth</text>
                          <text x="408" y="292">i</text>
                          <text x="76" y="324">{Silver}</text>
                          <text x="260" y="324">{Gold}</text>
                        </g>
                      </svg>
                    </artwork>
                    <artwork type="ascii-art"><![CDATA[
    +-----------------+   +-----------------+
    |       Red       |   |       Blue      |
    +-----------------+   +-----------------+
    |       {}        |   |       {}        |   depth i-1
    +-----------------+   +-----------------+
    |  {Gold, Silver} |   |  {Gold, Bronze} |
    +-----------------+   +-----------------+
            |         \            |
            |          \           |
            |           \          |
            |            \         |
            |             \        |
            v              v       v
    +-----------------+   +-----------------+
    |     Silver      |   |       Gold      |
    +-----------------+   +-----------------+
    |     {AP-Q}      |   |      {AP-Q}     |   depth i
    +-----------------+   +-----------------+
    |    {Silver}     |   |      {Gold}     |
    +-----------------+   +-----------------+
]]></artwork>
                  </artset>
                </figure>
              </li>
              <li>
                <t>If there is a node in the <tt>valid_policy_graph</tt> of depth i-1 or less without any child nodes, delete that node.
Repeat this step until there are no nodes of depth i-1 or less without children.      </t>
                <t>
For example, consider the valid_policy_graph shown in <xref target="pruning"/> below.
The two nodes at depth i-1 that are marked with an 'X' have no children, and they are deleted.
Applying this rule to the resulting graph will cause the nodes at depth i-2 that is marked with a 'Y' to be deleted.
In the resulting graph, there are no nodes of depth i-1 or less without children, and this step is complete.      </t>
                <figure anchor="pruning">
                  <name>Pruning the valid_policy_graph</name>
                  <artset>
                    <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="384" width="416" viewBox="0 0 416 384" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                        <path d="M 8,128 L 8,160" fill="none" stroke="black"/>
                        <path d="M 8,224 L 8,256" fill="none" stroke="black"/>
                        <path d="M 8,320 L 8,352" fill="none" stroke="black"/>
                        <path d="M 56,168 L 56,216" fill="none" stroke="black"/>
                        <path d="M 104,128 L 104,160" fill="none" stroke="black"/>
                        <path d="M 104,224 L 104,256" fill="none" stroke="black"/>
                        <path d="M 104,320 L 104,352" fill="none" stroke="black"/>
                        <path d="M 120,32 L 120,64" fill="none" stroke="black"/>
                        <path d="M 120,128 L 120,160" fill="none" stroke="black"/>
                        <path d="M 120,224 L 120,256" fill="none" stroke="black"/>
                        <path d="M 120,320 L 120,352" fill="none" stroke="black"/>
                        <path d="M 168,72 L 168,120" fill="none" stroke="black"/>
                        <path d="M 168,168 L 168,216" fill="none" stroke="black"/>
                        <path d="M 168,264 L 168,312" fill="none" stroke="black"/>
                        <path d="M 216,32 L 216,64" fill="none" stroke="black"/>
                        <path d="M 216,128 L 216,160" fill="none" stroke="black"/>
                        <path d="M 216,224 L 216,256" fill="none" stroke="black"/>
                        <path d="M 216,320 L 216,352" fill="none" stroke="black"/>
                        <path d="M 232,128 L 232,160" fill="none" stroke="black"/>
                        <path d="M 232,224 L 232,256" fill="none" stroke="black"/>
                        <path d="M 232,320 L 232,352" fill="none" stroke="black"/>
                        <path d="M 280,168 L 280,216" fill="none" stroke="black"/>
                        <path d="M 328,128 L 328,160" fill="none" stroke="black"/>
                        <path d="M 328,224 L 328,256" fill="none" stroke="black"/>
                        <path d="M 328,320 L 328,352" fill="none" stroke="black"/>
                        <path d="M 120,32 L 216,32" fill="none" stroke="black"/>
                        <path d="M 120,64 L 216,64" fill="none" stroke="black"/>
                        <path d="M 8,128 L 104,128" fill="none" stroke="black"/>
                        <path d="M 120,128 L 216,128" fill="none" stroke="black"/>
                        <path d="M 232,128 L 328,128" fill="none" stroke="black"/>
                        <path d="M 8,160 L 104,160" fill="none" stroke="black"/>
                        <path d="M 120,160 L 216,160" fill="none" stroke="black"/>
                        <path d="M 232,160 L 328,160" fill="none" stroke="black"/>
                        <path d="M 8,224 L 104,224" fill="none" stroke="black"/>
                        <path d="M 120,224 L 216,224" fill="none" stroke="black"/>
                        <path d="M 232,224 L 328,224" fill="none" stroke="black"/>
                        <path d="M 8,256 L 104,256" fill="none" stroke="black"/>
                        <path d="M 120,256 L 216,256" fill="none" stroke="black"/>
                        <path d="M 232,256 L 328,256" fill="none" stroke="black"/>
                        <path d="M 8,320 L 104,320" fill="none" stroke="black"/>
                        <path d="M 120,320 L 216,320" fill="none" stroke="black"/>
                        <path d="M 232,320 L 328,320" fill="none" stroke="black"/>
                        <path d="M 8,352 L 104,352" fill="none" stroke="black"/>
                        <path d="M 120,352 L 216,352" fill="none" stroke="black"/>
                        <path d="M 232,352 L 328,352" fill="none" stroke="black"/>
                        <path d="M 100,168 L 124,216" fill="none" stroke="black"/>
                        <path d="M 212,264 L 236,312" fill="none" stroke="black"/>
                        <path d="M 212,72 L 236,120" fill="none" stroke="black"/>
                        <path d="M 100,120 L 124,72" fill="none" stroke="black"/>
                        <path d="M 100,312 L 124,264" fill="none" stroke="black"/>
                        <polygon class="arrowhead" points="288,216 276,210.4 276,221.6" fill="black" transform="rotate(90,280,216)"/>
                        <polygon class="arrowhead" points="244,312 232,306.4 232,317.6" fill="black" transform="rotate(63.43494882292201,236,312)"/>
                        <polygon class="arrowhead" points="244,120 232,114.4 232,125.6" fill="black" transform="rotate(63.43494882292201,236,120)"/>
                        <polygon class="arrowhead" points="176,312 164,306.4 164,317.6" fill="black" transform="rotate(90,168,312)"/>
                        <polygon class="arrowhead" points="176,216 164,210.4 164,221.6" fill="black" transform="rotate(90,168,216)"/>
                        <polygon class="arrowhead" points="176,120 164,114.4 164,125.6" fill="black" transform="rotate(90,168,120)"/>
                        <polygon class="arrowhead" points="132,216 120,210.4 120,221.6" fill="black" transform="rotate(63.43494882292201,124,216)"/>
                        <polygon class="arrowhead" points="108,312 96,306.4 96,317.6" fill="black" transform="rotate(116.56505117707799,100,312)"/>
                        <polygon class="arrowhead" points="108,120 96,114.4 96,125.6" fill="black" transform="rotate(116.56505117707799,100,120)"/>
                        <polygon class="arrowhead" points="64,216 52,210.4 52,221.6" fill="black" transform="rotate(90,56,216)"/>
                        <g class="text">
                          <text x="248" y="52">depth</text>
                          <text x="288" y="52">i-3</text>
                          <text x="280" y="148">Y</text>
                          <text x="360" y="148">depth</text>
                          <text x="400" y="148">i-2</text>
                          <text x="56" y="244">X</text>
                          <text x="280" y="244">X</text>
                          <text x="360" y="244">depth</text>
                          <text x="400" y="244">i-1</text>
                          <text x="360" y="340">depth</text>
                          <text x="392" y="340">i</text>
                        </g>
                      </svg>
                    </artwork>
                    <artwork type="ascii-art"><![CDATA[
                  +-----------+
                  |           | depth i-3
                  +-----------+
                  /     |     \
                 /      |      \
                v       v       v
    +-----------+ +-----------+ +-----------+
    |           | |           | |     Y     | depth i-2
    +-----------+ +-----------+ +-----------+
          |     \       |             |
          |      \      |             |
          v       v     v             v
    +-----------+ +-----------+ +-----------+
    |     X     | |           | |     X     | depth i-1
    +-----------+ +-----------+ +-----------+
                  /     |     \
                 /      |      \
                v       v       v
    +-----------+ +-----------+ +-----------+
    |           | |           | |           | depth i
    +-----------+ +-----------+ +-----------+
]]></artwork>
                  </artset>
                </figure>
              </li>
            </ol>
          </li>
          <li>
            <t>If the certificate policies extension is not present, set the <tt>valid_policy_graph</tt> to NULL.</t>
          </li>
          <li>
            <t>Verify that either <tt>explicit_policy</tt> is greater than 0 or the <tt>valid_policy_graph</tt> is not equal to NULL;</t>
          </li>
        </ol>
      </section>
      <section anchor="updates-to-section-614">
        <name>Updates to Section 6.1.4</name>
        <t>This update replaces step (b) of <xref section="6.1.4" sectionFormat="of" target="RFC5280"/> with the following text:</t>
        <ol spacing="normal" type="(%c)" start="2"><li>
            <t>If a policy mappings extension is present, then for each issuerDomainPolicy ID-P in the policy mappings extension:  </t>
            <ol spacing="normal" type="(%d)"><li>
                <t>If the policy_mapping variable is greater than 0 and there is a
node in the <tt>valid_policy_graph</tt> of depth i where ID-P is the
valid_policy, set <tt>expected_policy_set</tt> to the set of
subjectDomainPolicy values that are specified as
equivalent to ID-P by the policy mappings extension.</t>
              </li>
              <li>
                <t>If the policy_mapping variable is greater than 0,
no node of depth i in the <tt>valid_policy_graph</tt> has a
<tt>valid_policy</tt> of ID-P, but there is a node of depth i with a
<tt>valid_policy</tt> of anyPolicy, then generate a child node of
the node of depth i-1 that has a <tt>valid_policy</tt> of anyPolicy
as follows:      </t>
                <ol spacing="normal" type="(%i)"><li>
                    <t>set the <tt>valid_policy</tt> to ID-P;</t>
                  </li>
                  <li>
                    <t>set the <tt>qualifier_set</tt> to the qualifier set of the
policy anyPolicy in the certificate policies
extension of certificate i; and</t>
                  </li>
                  <li>
                    <t>set the <tt>expected_policy_set</tt> to the set of
subjectDomainPolicy values that are specified as
equivalent to ID-P by the policy mappings extension.</t>
                  </li>
                </ol>
              </li>
              <li>
                <t>If the <tt>policy_mapping</tt> variable is equal to 0:      </t>
                <ol spacing="normal" type="(%i)"><li>
                    <t>delete the node, if any, of depth i in the <tt>valid_policy_graph</tt> where ID-P is the <tt>valid_policy</tt>.</t>
                  </li>
                  <li>
                    <t>If there is a node in the <tt>valid_policy_graph</tt> of depth
i-1 or less without any child nodes, delete that
node.  Repeat this step until there are no nodes of
depth i-1 or less without children.</t>
                  </li>
                </ol>
              </li>
            </ol>
          </li>
        </ol>
      </section>
      <section anchor="updates-to-section-615">
        <name>Updates to Section 6.1.5</name>
        <t>This update replaces step (g) of <xref section="6.1.5" sectionFormat="of" target="RFC5280"/> with the following text:</t>
        <ol spacing="normal" type="(%c)" start="7"><li>
            <t>Calculate the <tt>user_constrained_policy_set</tt> as follows.
The <tt>user_constrained_policy_set</tt> is a set of policy OIDs, along with associated policy qualifiers.  </t>
            <ol spacing="normal" type="(%d)"><li>
                <t>If the <tt>valid_policy_graph</tt> is NULL, set <tt>valid_policy_node_set</tt> to the empty set.</t>
              </li>
              <li>
                <t>If the <tt>valid_policy_graph</tt> is not NULL, set <tt>valid_policy_node_set</tt> to the set of policy nodes
whose <tt>valid_policy</tt> is not anyPolicy and
whose parent list is a single node with <tt>valid_policy</tt> of anyPolicy.</t>
              </li>
              <li>
                <t>If the <tt>valid_policy_graph</tt> is not NULL and contains a node of depth n with the <tt>valid_policy</tt> anyPolicy, add it to <tt>valid_policy_node_set</tt>.</t>
              </li>
              <li>
                <t>Compute <tt>authority_constrained_policy_set</tt>, a set of policy OIDs and associated qualifiers as follows. For each node in <tt>valid_policy_node_set</tt>:      </t>
                <ol spacing="normal" type="(%i)"><li>
                    <t>Add the node's <tt>valid_policy</tt> to <tt>authority_constrained_policy_set</tt>.</t>
                  </li>
                  <li>
                    <t>Collect all qualifiers in the node, its ancestors, and descendants and associate them with <tt>valid_policy</tt>. Applications that do not use policy qualifiers MAY skip this step to simplify processing.</t>
                  </li>
                </ol>
              </li>
              <li>
                <t>Set <tt>user_constrained_policy_set</tt> to <tt>authority_constrained_policy_set</tt>.</t>
              </li>
              <li>
                <t>If the user-initial-policy-set is not anyPolicy:      </t>
                <ol spacing="normal" type="(%i)"><li>
                    <t>Remove any elements of <tt>user_constrained_policy_set</tt> which do not appear in user-initial-policy-set.</t>
                  </li>
                  <li>
                    <t>If anyPolicy appears in <tt>authority_constrained_policy_set</tt> with qualifiers AP-Q, for each OID P-OID in user-initial-policy-set which does not appear in <tt>user_constrained_policy_set</tt>, add P-OID with qualifiers AP-Q to <tt>user_constrained_policy_set</tt>.</t>
                  </li>
                </ol>
              </li>
            </ol>
          </li>
        </ol>
        <t>Additionally, this update replaces the final paragraph as follows:</t>
        <t>OLD:</t>
        <ul empty="true">
          <li>
            <t>If either (1) the value of <tt>explicit_policy</tt> variable is greater than
zero or (2) the <tt>valid_policy_tree</tt> is not NULL, then path processing
has succeeded.</t>
          </li>
        </ul>
        <t>NEW:</t>
        <ul empty="true">
          <li>
            <t>If either (1) the value of <tt>explicit_policy</tt> variable is greater than
zero or (2) the <tt>user_constrained_policy_set</tt> is not empty, then path processing
has succeeded.</t>
          </li>
        </ul>
      </section>
      <section anchor="update-outputs">
        <name>Updates to Section 6.1.6</name>
        <t>This update replaces <xref section="6.1.6" sectionFormat="of" target="RFC5280"/> with the following text:</t>
        <ul empty="true">
          <li>
            <t>If path processing succeeds, the procedure terminates, returning a
success indication together with final value of the <tt>user_constrained_policy_set</tt>,
the <tt>working_public_key</tt>, the <tt>working_public_key_algorithm</tt>, and the
<tt>working_public_key_parameters</tt>.</t>
            <t>Note the original procedure described in <xref target="RFC5280"/> included a
<tt>valid_policy_tree</tt> structure as part of the output. This structure grows
exponentially in the size of the input, so computing it risks
denial-of-service vulnerabilities in X.509-based applications, such as
<xref target="CVE-2023-0464"/> and <xref target="CVE-2023-23524"/>. Accordingly, this output is
deprecated. Computing this structure is NOT RECOMMENDED.</t>
            <t>An implementation which requires <tt>valid_policy_tree</tt> for compatibility with
legacy systems may compute it from <tt>valid_policy_graph</tt> by recursively
duplicating every multi-parent node. This may be done on-demand when the
calling application first requests this output. However, this computation may
consume exponential time and memory, so such implementations SHOULD mitigate
denial-of-service in other ways, such as limiting the depth or size of the
tree.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="other-mitigations">
      <name>Other Mitigations</name>
      <t>X.509 implementations that are unable switch to the policy graph structure
SHOULD mitigate the denial-of-service attack in other ways. This section
describes alternate mitigation and partial mitigation strategies.</t>
      <section anchor="limit-certificate-depth">
        <name>Limit Certificate Depth</name>
        <t>The policy tree grows exponentially in the depth of a certification path, so
limiting the depth and certificate size can mitigate the attack.</t>
        <t>However, this option may not be viable for all applications. Too low of a limit
may reject existing paths which the application wishes to accept. Too high of a
limit may still admit a DoS attack for the application. By modifying the example
in <xref target="exponential-growth"/> to increase the number of policies asserted in each
ertificate, an attacker could still achieve O(N^(depth/2)) scaling.</t>
      </section>
      <section anchor="limit-policy-tree-size">
        <name>Limit Policy Tree Size</name>
        <t>The attack can be mitigated by limiting the number of nodes in the policy tree,
and rejecting the certification path if this limit is reached. This limit should
be set high enough to still admit existing valid certification paths for the
application, but low enough to no longer admit a DoS attack.</t>
      </section>
      <section anchor="inhibit-policy-mapping">
        <name>Inhibit Policy Mapping</name>
        <t>If policy mapping is disabled via the initial-policy-mapping-inhibit setting
(see <xref section="6.1.1" sectionFormat="of" target="RFC5280"/>), the attack is mitigated. This also
significantly simplifies the X.509 implementation, which reduces the risk of
other security bugs. However, this will break compatibility with any existing
certification paths which rely on policy mapping.</t>
        <t>To facilitate this mitigation, certificate authorities SHOULD NOT issue
certificates with the policy mappings extension (<xref section="4.2.1.5" sectionFormat="of" target="RFC5280"/>). Applications maintaining policies for accepted trust anchors are
RECOMMENDED to forbid this extension in participating certificate authorities.</t>
      </section>
      <section anchor="disable-policy-checking">
        <name>Disable Policy Checking</name>
        <t>An X.509 validator can mitigate this attack by disabling policy validation
entirely. This may be viable for applications which do not require policy
validation. In this case, critical policy-related extensions, notably the policy
constraints (<xref section="4.2.1.11" sectionFormat="of" target="RFC5280"/>), MUST be treated as unrecognized
extensions as in <xref section="4.2" sectionFormat="of" target="RFC5280"/> and be rejected.</t>
      </section>
      <section anchor="verify-signatures-first">
        <name>Verify Signatures First</name>
        <t>X.509 validators SHOULD verify signatures in certification paths before or in
conjunction with policy verification. This limits the attack to entities in
control of CA certificates. For some applications, this may be sufficient to
mitigate the attack. However, other applications may still be impacted. For
example:</t>
        <ul spacing="normal">
          <li>
            <t>Any application that evaluates an untrusted PKI, such as a hosting provider
that evaluates a customer-supplied PKI</t>
          </li>
          <li>
            <t>Any application that evaluates an otherwise trusted PKI, but where untrusted
entities have technically-constrained intermediate certificates where policy
mapping and path length are unconstrained.</t>
          </li>
        </ul>
      </section>
    </section>
    <section removeInRFC="true" anchor="implementation-status">
      <name>Implementation Status</name>
      <t>This section records the status of known implementations of the
protocol defined by this specification at the time of posting of
this Internet-Draft, and is based on a proposal described in
RFC 7942.  The description of implementations in this section is
intended to assist the IETF in its decision processes in
progressing drafts to RFCs.  Please note that the listing of any
individual implementation here does not imply endorsement by the
IETF.  Furthermore, no effort has been spent to verify the
information presented here that was supplied by IETF contributors.
This is not intended as, and must not be construed to be, a
catalog of available implementations or their features.  Readers
are advised to note that other implementations may exist.</t>
      <t>According to RFC 7942, "this will allow reviewers and working
groups to assign due consideration to documents that have the
benefit of running code, which may serve as evidence of valuable
experimentation and feedback that have made the implemented
protocols more mature.  It is up to the individual working groups
to use this information as they see fit".</t>
      <t>The following projects adopted the concept outlined in this document:</t>
      <ul spacing="normal">
        <li>
          <t><xref target="BoringSSL"/></t>
        </li>
        <li>
          <t><xref target="LibreSSL"/></t>
        </li>
      </ul>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t><xref target="dos"/> discusses how <xref target="RFC5280"/>'s policy tree algorithm can lead to
denial-of-service vulnerabilities in X.509-based applications, such as
<xref target="CVE-2023-0464"/> and <xref target="CVE-2023-23524"/>.</t>
      <t><xref target="updates"/> replaces this algorithm to avoid this issue. As discussed in
<xref target="policy-graph"/>, the new structure scales linearly with the input. This means
input limits in X.509 validators will more naturally bound processing time,
thus avoiding these vulnerabilities.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC5280">
          <front>
            <title>Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile</title>
            <author fullname="D. Cooper" initials="D." surname="Cooper"/>
            <author fullname="S. Santesson" initials="S." surname="Santesson"/>
            <author fullname="S. Farrell" initials="S." surname="Farrell"/>
            <author fullname="S. Boeyen" initials="S." surname="Boeyen"/>
            <author fullname="R. Housley" initials="R." surname="Housley"/>
            <author fullname="W. Polk" initials="W." surname="Polk"/>
            <date month="May" year="2008"/>
            <abstract>
              <t>This memo profiles the X.509 v3 certificate and X.509 v2 certificate revocation list (CRL) for use in the Internet. An overview of this approach and model is provided as an introduction. The X.509 v3 certificate format is described in detail, with additional information regarding the format and semantics of Internet name forms. Standard certificate extensions are described and two Internet-specific extensions are defined. A set of required certificate extensions is specified. The X.509 v2 CRL format is described in detail along with standard and Internet-specific extensions. An algorithm for X.509 certification path validation is described. An ASN.1 module and examples are provided in the appendices. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5280"/>
          <seriesInfo name="DOI" value="10.17487/RFC5280"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="X.509">
          <front>
            <title>Information technology - Open Systems Interconnection - The Directory: Public-key and attribute certificate frameworks</title>
            <author>
              <organization>International Telecommunications Union</organization>
            </author>
            <date year="2019" month="October"/>
          </front>
          <seriesInfo name="ITU-T" value="Recommendation X.509"/>
        </reference>
        <reference anchor="CVE-2023-0464" target="https://www.cve.org/CVERecord?id=CVE-2023-0464">
          <front>
            <title>Excessive Resource Usage Verifying X.509 Policy Constraints</title>
            <author>
              <organization/>
            </author>
            <date year="2023" month="March"/>
          </front>
        </reference>
        <reference anchor="CVE-2023-23524" target="https://www.cve.org/CVERecord?id=CVE-2023-23524">
          <front>
            <title>Processing a maliciously crafted certificate may lead to a denial-of-service</title>
            <author>
              <organization/>
            </author>
            <date year="2023" month="February"/>
          </front>
        </reference>
        <reference anchor="BoringSSL" target="https://boringssl.googlesource.com/boringssl">
          <front>
            <title>BoringSSL</title>
            <author>
              <organization/>
            </author>
            <date year="2024" month="January"/>
          </front>
        </reference>
        <reference anchor="LibreSSL" target="https://www.libressl.org/">
          <front>
            <title>LibreSSL</title>
            <author>
              <organization/>
            </author>
            <date year="2024" month="January"/>
          </front>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
      </references>
    </references>
    <?line 802?>

<section numbered="false" anchor="acknowledgements">
      <name>Acknowledgements</name>
      <t>The author thanks Bob Beck, Adam Langley, Matt Mueller, and Ryan Sleevi for
many valuable discussions that led to discovering this issue, understanding it,
and developing the mitigation. The author also thanks Martin Thomson and Job
Snijders for feedback on this document.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
