<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     ipr="trust200902"
     docName="draft-premont-lamps-drl-stapling-00"
     category="exp"
     submissionType="IETF"
     consensus="true"
     version="3">

  <front>
    <title abbrev="DRL TLS Stapling">TLS Extension for Distributed Revocation Ledger (DRL) Stapling using a Sparse Merkle Tree</title>
    <seriesInfo name="Internet-Draft" value="draft-premont-lamps-drl-stapling-00"/>

    <author initials="A." surname="Premont" fullname="Arthur Premont">
      <organization>IP Paris</organization>
      <address>
        <email>arthur.premont@ip-paris.fr</email>
      </address>
    </author>
    <author initials="H." surname="Afifi" fullname="Hossam Afifi">
      <organization>Telecom SudParis</organization>
      <address>
        <email>hossam.afifi@telecom-sudparis.eu</email>
      </address>
    </author>

    <date/>
    <workgroup>LAMPS</workgroup>
    <keyword>Internet-Draft</keyword>
    <keyword>Revocation</keyword>
    <keyword>TLS</keyword>
    <keyword>Sparse Merkle Tree</keyword>
    <keyword>PKI</keyword>
    <keyword>BFT</keyword>

    <abstract>
      <t>Managing certificate revocation remains a recurring challenge in the Web
      Public Key Infrastructure (WebPKI). Existing solutions such as Certificate
      Revocation Lists (CRLs) and the Online Certificate Status Protocol (OCSP)
      involve compromises in terms of propagation latency, availability, and user
      privacy. With the planned deprecation of OCSP by some major Certificate
      Authorities (CAs), there is renewed interest in alternatives.</t>

      <t>This document specifies a decentralized certificate revocation
      architecture based on a Distributed Revocation Ledger (DRL) managed
      collectively by CAs. The ledger state is maintained as a Sparse Merkle Tree
      (SMT) in which only revoked certificates occupy non-default leaves, so that a
      valid certificate is attested by a compact non-membership proof and no prior
      registration of valid certificates is required. This document further defines
      a new Transport Layer Security (TLS) extension enabling "DRL Stapling", which
      allows a server to provide a client with a cryptographic proof of a
      certificate's status, consisting of a Sparse Merkle audit path and an M-of-N
      threshold signature from the CA consortium. The approach builds on the
      Revocation Transparency proposal of Laurie and Kasper and on subsequent
      formalizations of Sparse Merkle Trees; its novel contributions are the
      decentralized threshold-signature trust model with deterministic finality and
      the concrete TLS wire format.</t>
    </abstract>
  </front>

  <middle>

    <section anchor="introduction">
      <name>Introduction</name>
      <t>The Web Public Key Infrastructure (WebPKI) relies heavily on the reliable
      dissemination of certificate revocation information. Standardized mechanisms
      show significant limitations:</t>
      <ul>
        <li>CRLs <xref target="RFC5280"/> suffer from high issuance latency,
        massive file sizes, and high bandwidth consumption for clients.</li>
        <li>OCSP <xref target="RFC6960"/> introduces a single point of failure,
        adds blocking latency during the TLS handshake, and leaks privacy by
        exposing browsing habits to the responder.</li>
      </ul>

      <t>To address latency and privacy, OCSP Stapling <xref target="RFC6066"/> was
      introduced, but it still relies on centralized OCSP infrastructure.
      Proprietary mechanisms like CRLite address privacy and availability but rely
      on a single trusted aggregator without distributed cryptographic proof.</t>

      <t>This work is directly inspired by, and builds upon, the Revocation
      Transparency (RT) proposal of Laurie and Kasper
      <xref target="RevocationTransparency"/>, which first proposed storing
      certificate revocation status in a Sparse Merkle Tree and stapling a recent
      proof alongside the certificate. It also builds on the subsequent
      formalization of Sparse Merkle Trees and their (non-)membership proofs by
      Dahlberg, Pulls, and Peeters <xref target="SMT"/>. RT deliberately left the
      trust model out of scope. The novel contribution of this document is
      twofold: (1) a decentralized trust model in which the ledger root is signed
      by an M-of-N threshold signature produced by a consortium of CAs operating a
      consensus with deterministic finality, replacing RT's reliance on an
      auxiliary transparency log for accountability; and (2) a concrete TLS wire
      format for stapling the resulting proof.</t>

      <t>Because the ledger is a Sparse Merkle Tree in which only revoked
      certificates occupy non-default leaves, a valid certificate is proven by a
      compact non-membership proof, and CAs need not register valid certificates.
      The server fetches the proof from a local DRL node and staples it; the client
      verifies it as a purely local cryptographic operation.</t>
    </section>

    <section anchor="related-work">
      <name>Related Work</name>
      <t>The idea of maintaining certificate revocation status in a Sparse Merkle
      Tree and serving a recent proof to relying parties originates in Revocation
      Transparency <xref target="RevocationTransparency"/>. That proposal focuses on
      transparency, i.e., ensuring that the revocation list a client sees is the
      same one everyone else sees, and explicitly leaves open the questions of who
      may revoke and under which trust model. The Sparse Merkle Tree data structure
      and its secure (non-)membership proofs, including precomputable default
      digests and node encodings that prevent second-preimage confusion, are
      formalized in <xref target="SMT"/>.</t>

      <t>DRL Stapling differs from these works by replacing the transparency/auxiliary-log
      accountability model with an M-of-N threshold signature produced by an
      identifiable CA consortium under a consensus protocol with deterministic
      finality, and by specifying an interoperable TLS wire format. It builds on
      OCSP Stapling <xref target="RFC6066"/> and the Must-Staple concept
      <xref target="RFC7633"/>, and is inspired by Certificate Transparency
      <xref target="RFC6962"/> <xref target="RFC9162"/>. It is complementary to,
      and distinct from, Merkle Tree Certificates
      <xref target="I-D.davidben-tls-merkle-tree-certs"/>, which target certificate
      issuance rather than revocation. Unlike Decentralized PKI (DPKI), DRL retains
      the existing X.509 trust hierarchy and decentralizes only the dissemination
      of revocation status among already-trusted CAs.</t>
    </section>

    <section anchor="conventions">
      <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>
      <dl>
        <dt>DRL (Distributed Revocation Ledger):</dt>
        <dd>An append-only, cryptographically verifiable ledger of revocations,
        collectively managed by a consortium of CAs and represented as a Sparse
        Merkle Tree.</dd>
        <dt>Consortium:</dt>
        <dd>The set of CAs that operate as validators of the DRL and collectively
        produce threshold signatures over the ledger root.</dd>
        <dt>Threshold Signature:</dt>
        <dd>A signature scheme where at least M of N authorized signers must
        cooperate to produce a valid signature.</dd>
        <dt>Sparse Merkle Tree (SMT):</dt>
        <dd>A Merkle tree of intractable size (one leaf per possible key digest) in
        which the vast majority of leaves are empty (default), enabling efficient
        membership and non-membership proofs.</dd>
        <dt>Epoch:</dt>
        <dd>A strictly monotonically increasing sequence number identifying a
        finalized SMT root, associated with a UNIX timestamp of finalization.</dd>
        <dt>DRL Node:</dt>
        <dd>A network peer maintaining a replica of the SMT state and serving
        proofs to TLS servers.</dd>
      </dl>
    </section>

    <section anchor="architecture">
      <name>Architecture Overview</name>
      <t>The DRL is a Sparse Merkle Tree collectively maintained by participating
      CAs acting as consensus validators. Only revocations are inserted; a
      certificate that has never been revoked corresponds to a default (empty) leaf.
      The consortium signs the SMT root of each Epoch with a threshold signature.</t>

      <t>While the exact ledger implementation is outside the scope of this TLS
      extension, the underlying network MUST guarantee:</t>
      <ol>
        <li><t><strong>Deterministic Finality:</strong> Once committed, a revocation
        cannot be reverted or forked. Proof-of-Work and probabilistic
        Proof-of-Stake are NOT RECOMMENDED; permissioned Byzantine Fault Tolerant
        (BFT) / Proof-of-Authority consensus is RECOMMENDED.</t></li>
        <li><t><strong>Authority Accountability:</strong> The validator set MUST
        consist of identifiable and accountable entities, such as CAs present in
        existing root trust stores.</t></li>
      </ol>

      <section anchor="validators">
        <name>Consortium Validators and Epoch Generation</name>
        <t>When a CA revokes a certificate, it submits a signed revocation
        transaction. Upon consensus, the corresponding SMT leaf transitions from
        default to a revoked value, a new Epoch is finalized, and the validators
        produce a collective threshold signature over the new SMT root together with
        the epoch metadata. The following properties are RECOMMENDED for the
        underlying DRL protocol:</t>
        <ul>
          <li>A revocation transaction SHOULD only be accepted if it originates from
          (or is endorsed by) the issuing CA.</li>
          <li>The consensus mechanism SHOULD ensure that no single compromised CA
          can unilaterally alter the status of certificates it did not issue.</li>
        </ul>
        <t>Note that, because only revocations are stored, no registration of valid
        certificates is required.</t>
      </section>

      <section anchor="edge-nodes">
        <name>Edge Nodes and Proof Computation</name>
        <t>To limit latency and distribute load, DRL Nodes may be deployed close to
        servers. (Edge topologies such as Multi-Access Edge Computing are one
        possible non-normative realization.) A node holds a synchronized replica of
        the SMT and computes, on demand, either a membership proof (for a revoked
        certificate) or a non-membership proof (for a certificate absent from the
        tree), attaching the consortium threshold signature for the current Epoch.
        This yields the <tt>DRLProof</tt>.</t>
      </section>
    </section>

    <section anchor="smt-construction">
      <name>Sparse Merkle Tree Construction</name>
      <t>The DRL is a Sparse Merkle Tree of depth D, where D equals the output
      length in bits of the tree hash algorithm (256 for SHA-256). Each certificate
      is mapped to a unique leaf whose position is the digest of its identifier. A
      valid (never-revoked) certificate maps to a default leaf; a revoked
      certificate maps to a non-default leaf carrying its revocation reason.</t>

      <section anchor="leaf-index">
        <name>Leaf Index</name>
        <t>The leaf index for a certificate is computed as
        <tt>leaf_index = Hash(CertificateID)</tt>, where <tt>Hash</tt> is the
        algorithm identified by <tt>hash_algo</tt> and <tt>CertificateID</tt> is
        serialized as defined in <xref target="leaf-struct"/>. The index is
        interpreted as a bit string b[0..D-1] with b[0] the most significant bit;
        b[0] selects the direction at the root and b[D-1] at the leaf's parent.</t>
      </section>

      <section anchor="encoding">
        <name>Node Encoding and Default Digests</name>
        <t>To prevent second-preimage confusion between leaves, internal nodes, and
        empty subtrees, hashing employs distinct one-byte domain separation
        prefixes:</t>
        <ul>
          <li>Empty leaf digest: <tt>E[0] = Hash(0x00)</tt>.</li>
          <li>Default digest of an empty subtree of height k
          (1 &lt;= k &lt;= D): <tt>E[k] = Hash(0x01 || E[k-1] || E[k-1])</tt>.</li>
          <li>Revoked (non-default) leaf digest:
          <tt>RevokedLeaf = Hash(0x02 || reason_code)</tt>, where
          <tt>reason_code</tt> is a single byte.</li>
          <li>Internal node digest:
          <tt>Hash(0x01 || left_child || right_child)</tt>.</li>
        </ul>
        <t>The default digests E[0..D] are deterministic and MUST be precomputed by
        all implementations. Because empty subtrees share these digests, only the
        non-default siblings along a path need to be transmitted; the resulting
        SMT root is deterministic and history-independent.</t>
      </section>
    </section>

    <section anchor="agility">
      <name>Cryptographic Agility</name>
      <t>This specification defines a <tt>DRLHashAlgorithm</tt> enumeration for the
      SMT and leverages the <tt>SignatureScheme</tt> registry of TLS 1.3
      <xref target="RFC8446"/> for the threshold signature. The tree depth D is
      determined by the chosen hash algorithm.</t>
    </section>

    <section anchor="data-structures">
      <name>Data Structures</name>
      <t>All structures use the TLS presentation language <xref target="RFC8446"/>.</t>

      <section anchor="hash-algo">
        <name>Hash Algorithm</name>
        <t>The <tt>hash_algo</tt> field identifies the hash algorithm used for the
        SMT. Values are defined in the "DRL Hash Algorithm" registry established by
        this document (<xref target="iana"/>).</t>
        <sourcecode type="tls"><![CDATA[
enum {
    sha256(1),   /* D = 256 */
    sha384(2),   /* D = 384 */
    sha512(3),   /* D = 512 */
    (255)
} DRLHashAlgorithm;
]]></sourcecode>
        <t>Implementations MUST support <tt>sha256(1)</tt>. Support for
        <tt>sha384(2)</tt> and <tt>sha512(3)</tt> is RECOMMENDED.</t>
      </section>

      <section anchor="leaf-struct">
        <name>Certificate Identifier and Status</name>
        <sourcecode type="tls"><![CDATA[
enum {
    valid(0),      /* proven by a non-membership proof */
    revoked(1),    /* proven by a membership proof     */
    (255)
} CertificateStatus;

enum {
    unspecified(0),
    keyCompromise(1),
    cACompromise(2),
    affiliationChanged(3),
    superseded(4),
    cessationOfOperation(5),
    certificateHold(6),
    /* 7 reserved; 8 (removeFromCRL) intentionally omitted */
    privilegeWithdrawn(9),
    aACompromise(10),
    (255)
} CRLReason;

struct {
    opaque issuer_hash<32..64>;
    opaque serial_number<1..32>;
} CertificateID;
]]></sourcecode>
        <t>The <tt>CRLReason</tt> values are drawn from
        <xref target="RFC5280"/> Section 5.3.1; <tt>removeFromCRL(8)</tt> is omitted
        as it pertains to delta-CRL processing.</t>
        <ul>
          <li><tt>issuer_hash</tt>: the hash of the DER-encoded Subject Public Key
          Info (SPKI) of the issuer's certificate, using <tt>hash_algo</tt>; its
          length MUST equal the output length of that algorithm (32, 48, or 64
          bytes).</li>
          <li><tt>serial_number</tt>: the raw value bytes of the ASN.1 INTEGER
          serial number (without tag/length), in network byte order. Formatting
          characters (e.g., ':') MUST NOT be used.</li>
        </ul>
        <t>The canonical serialization of <tt>CertificateID</tt> is its
        TLS-presentation-language encoding per <xref target="RFC8446"/> Section 3,
        with length-prefixed <tt>opaque</tt> vectors. The leaf index is computed
        over exactly these bytes.</t>
      </section>

      <section anchor="proof-struct">
        <name>The DRL Proof</name>
        <t>A DRL Proof carries everything the client needs to recompute the SMT root
        and evaluate the status. The audit path transmits only non-default
        siblings; a bitmap indicates, for each of the D levels (bottom to top),
        whether the sibling is non-default (present in <tt>audit_path</tt>) or is the
        precomputed default digest for that level.</t>
        <sourcecode type="tls"><![CDATA[
struct {
    opaque node_hash<20..64>;
} MerkleNode;

struct {
    CertificateID cert_id;
    CertificateStatus status;
    CRLReason reason_code;        /* meaningful only if status == revoked */
    DRLHashAlgorithm hash_algo;
    SignatureScheme sig_scheme;
    opaque key_id<4..32>;
    opaque path_bitmap<0..2^16-1>; /* D bits, ceil(D/8) bytes, bit j = level j */
    MerkleNode audit_path<0..2^16-1>; /* non-default siblings, bottom to top */
    uint64 epoch_number;
    uint64 epoch_timestamp;
    opaque root_signature<1..2^16-1>;
} DRLProof;
]]></sourcecode>
        <ul>
          <li><tt>status</tt>: <tt>valid(0)</tt> denotes a non-membership proof (the
          leaf at <tt>leaf_index</tt> is empty); <tt>revoked(1)</tt> denotes a
          membership proof (the leaf holds <tt>RevokedLeaf</tt>).</li>
          <li><tt>path_bitmap</tt>: exactly ceil(D/8) bytes. Bit j (j = 0 is the
          bottom/leaf level) set means the sibling at level j is non-default and
          appears next in <tt>audit_path</tt>; unset means the sibling is the
          default digest E[j].</li>
          <li><tt>audit_path</tt>: the non-default siblings in bottom-to-top order,
          in the same order as the set bits of <tt>path_bitmap</tt>.</li>
          <li><tt>key_id</tt>: identifier of the consortium aggregated public
          threshold key, computed as the leading 20 bytes of the SHA-256 hash of the
          serialized aggregated public key. If unrecognized, the client MUST reject
          the proof.</li>
          <li><tt>epoch_number</tt>: strictly monotonically increasing 64-bit epoch
          counter; ensures ordering, uniqueness, and rollback detection.</li>
          <li><tt>epoch_timestamp</tt>: UNIX timestamp (seconds) of epoch
          finalization, used for freshness.</li>
          <li><tt>root_signature</tt>: the M-of-N threshold signature over
          <tt>ComputedRoot || epoch_number || epoch_timestamp</tt>, with the two
          integers encoded as 8 bytes each in network byte order.</li>
        </ul>
      </section>

      <section anchor="bls">
        <name>Threshold Signatures and Baseline Mode</name>
        <t>To ensure interoperability in the absence of a standardized threshold
        signature code point, implementations MUST support a baseline mode in which
        <tt>root_signature</tt> carries the concatenation of individual
        <tt>SignatureScheme</tt> signatures (using a mandatory-to-implement scheme
        such as <tt>ecdsa_secp256r1_sha256</tt>), of which at least M MUST verify
        against consortium member keys in the client's trust store. BLS threshold
        aggregation, following <xref target="I-D.irtf-cfrg-bls-signature"/>, is an
        OPTIONAL optimization; once an IANA code point is assigned it MUST be used in
        <tt>sig_scheme</tt>. Any threshold scheme used MUST prevent rogue-key
        attacks.</t>
      </section>
    </section>

    <section anchor="tls-extension">
      <name>TLS Extension for DRL Stapling</name>
      <t>We define a new Certificate Status Type for the <tt>status_request</tt>
      extension <xref target="RFC6066"/>.</t>
      <sourcecode type="tls"><![CDATA[
enum {
    ocsp(1),
    drl_proof(TBD),
    (255)
} CertificateStatusType;
]]></sourcecode>

      <section anchor="client-hello">
        <name>Client Hello</name>
        <t>A client wishing to receive a DRL Proof includes a
        <tt>status_request</tt> extension with <tt>status_type</tt> set to
        <tt>drl_proof</tt>. A client MAY advertise both <tt>drl_proof</tt> and
        <tt>ocsp</tt>.</t>
      </section>

      <section anchor="server-cert">
        <name>Server Certificate Message</name>
        <t>If the server holds a valid <tt>DRLProof</tt> for its end-entity
        certificate and the client advertised <tt>drl_proof</tt>, the server MUST
        include the <tt>DRLProof</tt> in the <tt>CertificateStatus</tt> structure.
        In TLS 1.3 <xref target="RFC8446"/> it is carried in the <tt>extensions</tt>
        of the relevant <tt>CertificateEntry</tt>; in TLS 1.2 it follows
        <xref target="RFC6066"/> in a <tt>CertificateStatus</tt> message. The server
        MUST NOT send an empty <tt>drl_proof</tt> status; it MAY fall back to
        <tt>ocsp</tt>.</t>
      </section>

      <section anchor="fallback">
        <name>Fallback and Coexistence</name>
        <ul>
          <li><strong>Server:</strong> If it cannot obtain a fresh proof, the server
          SHOULD fall back to OCSP Stapling if supported.</li>
          <li><strong>Client:</strong> If it advertised <tt>drl_proof</tt> but
          receives none, it SHOULD apply its local revocation policy.</li>
          <li><strong>Hard-fail:</strong> Deployments MAY define a Must-Staple-like
          policy extension (analogous to <xref target="RFC7633"/>); such a
          definition is out of scope here.</li>
        </ul>
      </section>
    </section>

    <section anchor="validation">
      <name>Client Validation</name>
      <t>Upon receiving a <tt>DRLProof</tt>, the client MUST perform the following
      steps. If any fails, the proof is invalid. The client MUST NOT act on
      <tt>status</tt> until steps 1 through 5 succeed, to prevent an attacker from
      forcing a handshake abort via an unauthenticated <tt>revoked</tt> claim.</t>
      <ol>
        <li><t><strong>Identifier and index:</strong> Verify that <tt>cert_id</tt>
        matches the server certificate (issuer SPKI hash and serial number), then
        compute <tt>leaf_index = Hash(cert_id)</tt> using <tt>hash_algo</tt>.</t></li>
        <li><t><strong>Leaf digest:</strong> If <tt>status</tt> is <tt>valid</tt>,
        set <tt>cur = E[0]</tt>. If <tt>revoked</tt>, set
        <tt>cur = Hash(0x02 || reason_code)</tt>.</t></li>
        <li><t><strong>Root reconstruction:</strong> For j from 0 to D-1: let the
        controlling bit be <tt>b[D-1-j]</tt> of <tt>leaf_index</tt>; obtain the
        sibling S = <tt>audit_path</tt> next entry if <tt>path_bitmap</tt> bit j is
        set, else S = E[j]. If the controlling bit is 0, set
        <tt>cur = Hash(0x01 || cur || S)</tt>; else
        <tt>cur = Hash(0x01 || S || cur)</tt>. After D iterations,
        <tt>ComputedRoot = cur</tt>. Implementations MUST verify that the number of
        set bits in <tt>path_bitmap</tt> equals the number of entries in
        <tt>audit_path</tt>.</t></li>
        <li><t><strong>Signature:</strong> Look up the aggregated key for
        <tt>key_id</tt>; if absent, reject. Verify <tt>root_signature</tt> using
        <tt>sig_scheme</tt> over
        <tt>ComputedRoot || epoch_number || epoch_timestamp</tt>. It MUST be a valid
        M-of-N threshold signature.</t></li>
        <li><t><strong>Freshness:</strong> <tt>epoch_timestamp</tt> MUST be within
        the acceptable freshness window; stale proofs MUST be rejected. Stateful
        clients MAY reject proofs whose <tt>epoch_number</tt> is lower than the
        highest previously seen.</t></li>
        <li><t><strong>Status evaluation:</strong> If <tt>status</tt> is
        <tt>revoked</tt>, abort with a <tt>certificate_revoked</tt> alert.</t></li>
      </ol>
    </section>

    <section anchor="perf">
      <name>Privacy and Performance Considerations</name>
      <t>The client performs no outbound status query, so browsing habits and IP
      address are never exposed to third-party responders. For SHA-256 (D = 256),
      the average number of non-default siblings on a path is O(log N) where N is
      the number of revoked certificates <xref target="RevocationTransparency"/>
      <xref target="SMT"/>; the remaining siblings are default and omitted, kept
      implicit via <tt>path_bitmap</tt>.</t>
    </section>

    <section anchor="operational">
      <name>Operational Considerations</name>
      <t>Servers SHOULD refresh their cached <tt>DRLProof</tt> at an interval shorter
      than the client freshness window (a RECOMMENDED value is half the window), with
      exponential-backoff retry. The consortium SHOULD generate epochs at a regular
      cadence; for Web PKI, an epoch interval between 1 minute and 1 hour is
      RECOMMENDED.</t>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>

      <section anchor="byzantine">
        <name>Byzantine Consortium and Threshold Signatures</name>
        <t>Security relies on the assumption that compromised authorities do not
        exceed the fault-tolerance threshold f (typically M = 2f + 1 with
        N = 3f + 1). Unlike OCSP, a single compromised CA cannot forge a root
        signature; an adversary must compromise M authorities to subvert the system.
        This replaces the auxiliary-log accountability of Revocation Transparency
        with cryptographic threshold accountability.</t>
      </section>

      <section anchor="replay">
        <name>Freshness, Rollback and Equivocation</name>
        <t>Because the SMT represents a mutable current state, an evil node could
        attempt to present a stale root in which a currently revoked certificate
        still appears valid, as described in
        <xref target="RevocationTransparency"/>. The <tt>epoch_number</tt> and
        <tt>epoch_timestamp</tt> strictly couple the signature to one epoch. Clients
        MUST enforce a freshness threshold and therefore MUST maintain a reasonably
        accurate clock; stateful clients SHOULD additionally enforce monotonicity of
        <tt>epoch_number</tt> to detect rollback and equivocation.</t>
      </section>

      <section anchor="second-preimage">
        <name>Node Encoding</name>
        <t>Distinct domain separation prefixes for empty leaves, revoked leaves, and
        internal nodes prevent an interior digest from being reinterpreted as a leaf,
        following the encoding rationale of <xref target="SMT"/>. Because the tree
        depth is fixed by <tt>hash_algo</tt>, the position of a leaf is uniquely
        determined by <tt>Hash(cert_id)</tt>, binding a revocation to its
        certificate.</t>
      </section>

      <section anchor="partition">
        <name>Network Partitioning</name>
        <t>A partitioned DRL Node freezes at an old epoch. Servers SHOULD fail over
        to an alternative node; otherwise clients reject the stale proof once the
        freshness threshold expires, providing a fail-safe.</t>
      </section>

      <section anchor="governance">
        <name>Governance and Trust Model Assumptions</name>
        <t>This specification assumes a functioning CA consortium willing to operate
        validators and produce threshold signatures. Establishing such a consortium
        (membership, liability, key-share custody, edge funding) is a governance
        problem out of scope here and is expected to require coordination with root
        program operators and the CA/Browser Forum.</t>
      </section>

      <section anchor="trust-bootstrap">
        <name>Trust Bootstrap and Key Rotation</name>
        <t>Clients are provisioned with the consortium aggregated public key via
        their trust store, analogous to a root CA. Each key is identified by
        <tt>key_id</tt> (leading 20 bytes of SHA-256 of the serialized key). On
        membership changes, a new key is distributed; during a transition period the
        consortium signs each root with both old and new keys, and clients accepting
        either <tt>key_id</tt> validate either proof. After the transition, the old
        key is retired.</t>
      </section>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <section anchor="iana-status">
        <name>CertificateStatusType Registry</name>
        <t>IANA is requested to assign a new value for <tt>drl_proof</tt> in the
        "TLS Certificate Status Types" registry <xref target="RFC6066"/>.</t>
        <table>
          <thead><tr><th>Value</th><th>Description</th><th>Reference</th></tr></thead>
          <tbody><tr><td>TBD</td><td>DRL Sparse Merkle Proof</td><td>This document</td></tr></tbody>
        </table>
      </section>
      <section anchor="iana-hash">
        <name>DRL Hash Algorithm Registry</name>
        <t>IANA is requested to create a "DRL Hash Algorithm" registry with a
        "Specification Required" policy.</t>
        <table>
          <thead><tr><th>Value</th><th>Description</th><th>Reference</th></tr></thead>
          <tbody>
            <tr><td>0</td><td>Reserved</td><td>This document</td></tr>
            <tr><td>1</td><td>sha256</td><td>This document</td></tr>
            <tr><td>2</td><td>sha384</td><td>This document</td></tr>
            <tr><td>3</td><td>sha512</td><td>This document</td></tr>
            <tr><td>4-254</td><td>Unassigned</td><td></td></tr>
            <tr><td>255</td><td>Reserved</td><td>This document</td></tr>
          </tbody>
        </table>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>Normative References</name>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6066.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8446.xml"/>
    </references>

    <references>
      <name>Informative References</name>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5280.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6960.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6962.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7633.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9162.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.irtf-cfrg-bls-signature.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.davidben-tls-merkle-tree-certs.xml"/>

      <reference anchor="RevocationTransparency"
                 target="https://www.links.org/files/RevocationTransparency.pdf">
        <front>
          <title>Revocation Transparency</title>
          <author initials="B." surname="Laurie" fullname="Ben Laurie"/>
          <author initials="E." surname="Kasper" fullname="Emilia Kasper"/>
          <date year="2012"/>
        </front>
        <refcontent>Google Research</refcontent>
      </reference>

      <reference anchor="SMT" target="https://eprint.iacr.org/2016/683">
        <front>
          <title>Efficient Sparse Merkle Trees: Caching Strategies and Secure
          (Non-)Membership Proofs</title>
          <author initials="R." surname="Dahlberg" fullname="Rasmus Dahlberg"/>
          <author initials="T." surname="Pulls" fullname="Tobias Pulls"/>
          <author initials="R." surname="Peeters" fullname="Roel Peeters"/>
          <date year="2016"/>
        </front>
        <refcontent>NordSec 2016</refcontent>
      </reference>
    </references>

    <section anchor="appendix-example">
      <name>Example DRL Proof Verification</name>
      <t>This non-normative example uses a toy depth of D = 4 for readability
      (a real deployment uses D = 256 for SHA-256). Suppose the certificate maps to
      <tt>leaf_index = 1011</tt> (b[0]=1, b[1]=0, b[2]=1, b[3]=1) and is
      <tt>valid</tt>, i.e., its leaf is empty.</t>
      <artwork><![CDATA[
Precompute defaults:
  E[0] = Hash(0x00)
  E[1] = Hash(0x01 || E[0] || E[0])
  E[2] = Hash(0x01 || E[1] || E[1])
  E[3] = Hash(0x01 || E[2] || E[2])

Start (status = valid):
  cur = E[0]

Walk bottom (j=0) to top (j=3); controlling bit = b[3-j]:
  j=0: bit b[3]=1 -> cur is right child.
       sibling S0 = (bitmap bit0 set ? audit_path[.] : E[0])
       cur = Hash(0x01 || S0 || cur)
  j=1: bit b[2]=1 -> cur is right child.
       cur = Hash(0x01 || S1 || cur)
  j=2: bit b[1]=0 -> cur is left child.
       cur = Hash(0x01 || cur || S2)
  j=3: bit b[0]=1 -> cur is right child.
       cur = Hash(0x01 || S3 || cur)

ComputedRoot = cur

Verify root_signature over
  (ComputedRoot || epoch_number || epoch_timestamp)
using the consortium aggregated key selected by key_id,
then check freshness. Since status = valid, the handshake proceeds.
]]></artwork>
    </section>
  </back>
</rfc>