<?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-03" 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-03"/>
    <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="05"/>
    <area>Security</area>
    <workgroup>Limited Additional Mechanisms for PKIX and SMIME</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 47?>

<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 54?>

<section anchor="introduction">
      <name>Introduction</name>
      <t><xref target="RFC5280"/> defines a suite of extensions for specifying certificate policies,
along with a mechanism for mapping policies between subject and issuer policy
domains in cross-certificates. This mechanism, when evaluated according to the
algorithm in <xref section="6.1" sectionFormat="comma" target="RFC5280"/> produces a policy tree, describing
policies asserted by each certificate, and mappings between them. This tree can
grow exponentially in the depth of the certification path. 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 object identifiers (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>
          <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>
        </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>
          <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>
        </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>
          <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>
        </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, 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>
              <artwork type="ascii-art"><![CDATA[
    +----------------+
    |   anyPolicy    |   <---- valid_policy
    +----------------+
    |       {}       |   <---- qualifier_set
    +----------------+
    |  {anyPolicy}   |   <---- expected_policy_set
    +----------------+
]]></artwork>
            </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>
                      <artwork type="ascii-art"><![CDATA[
    +-----------------+      +-----------------+
    |       Red       |      |       Blue      |
    +-----------------+      +-----------------+
    |       {}        |      |       {}        |   depth i-1
    +-----------------+      +-----------------+
    |  {Gold, White}  |      |  {Gold, Yellow} |
    +-----------------+      +-----------------+
                \                   /
                 \                 /
                  \               /
                   v             v
                 +-----------------+
                 |      Gold       |
                 +-----------------+
                 |       {}        |   depth i
                 +-----------------+
                 |     {Gold}      |
                 +-----------------+
]]></artwork>
                    </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>
                      <artwork type="ascii-art"><![CDATA[
                  +-----------------+
                  |    anyPolicy    |
                  +-----------------+
                  |       {}        |
                  +-----------------+   depth i-1
                  |   {anyPolicy}   |
                  +-----------------+
                     /           \
                    /             \
                   /               \
                  /                 \
    +-----------------+          +-----------------+
    |      Gold       |          |     Silver      |
    +-----------------+          +-----------------+
    |       {}        |          |   {Q-Silver}    |   depth i
    +-----------------+          +-----------------+
    |     {Gold}      |          |    {Silver}     |
    +-----------------+          +-----------------+
]]></artwork>
                    </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>
                  <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>
                </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>
                  <artwork type="ascii-art"><![CDATA[
                  +-----------+
                  |           | depth i-3
                  +-----------+
                  /     |     \
                 /      |      \
                /       |       \
    +-----------+ +-----------+ +-----------+
    |           | |           | |     Y     | depth i-2
    +-----------+ +-----------+ +-----------+
          |     \       |             |
          |      \      |             |
          |       \     |             |
    +-----------+ +-----------+ +-----------+
    |     X     | |           | |     X     | depth i-1
    +-----------+ +-----------+ +-----------+
                   /    |    \
                  /     |     \
                 /      |      \
    +-----------+ +-----------+ +-----------+
    |           | |           | |           | depth i
    +-----------+ +-----------+ +-----------+
]]></artwork>
                </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 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="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 750?>

<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.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
iQAA

-->

</rfc>
