Skip to main content

SlimMLS
draft-robert-mls-slim-00

Document Type Active Internet-Draft (individual)
Authors Raphael Robert , Konrad Kohbrok
Last updated 2026-05-29
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-robert-mls-slim-00
Messaging Layer Security                                       R. Robert
Internet-Draft                                                K. Kohbrok
Intended status: Informational                               Phoenix R&D
Expires: 30 November 2026                                    29 May 2026

                                SlimMLS
                        draft-robert-mls-slim-00

Abstract

   This document defines SlimMLS, an extension to the Messaging Layer
   Security (MLS) protocol for reducing wire and per-client storage
   overhead in groups that use ciphersuites with large public keys,
   ciphertexts, signatures, and credentials.  SlimMLS replaces many
   large objects that appear in MLS authenticated or transcript-hashed
   structures with typed hash references.  Clients resolve the
   referenced objects only when needed, using a per-message carrier, a
   local cache, or an application-specific retrieval channel.  The
   extension is most useful when an independent Delivery Service can
   assist with retrieval and per-recipient delivery, although local
   caching and delayed fetching also help without such assistance.
   SlimMLS defines slim variants of KeyPackage, Commit, Welcome,
   GroupInfo, and message framing.  When placing a signature outside an
   encrypted envelope would reveal the signer, SlimMLS keeps the
   signature inside the ciphertext.

About This Document

   This note is to be removed before publishing as an RFC.

   Status information for this document may be found at
   https://datatracker.ietf.org/doc/draft-robert-mls-slim/.

   Discussion of this document takes place on the Messaging Layer
   Security Working Group mailing list (mailto:mls@ietf.org), which is
   archived at https://mailarchive.ietf.org/arch/browse/mls/.  Subscribe
   at https://www.ietf.org/mailman/listinfo/mls/.

   Source for this draft and an issue tracker can be found at
   https://github.com/raphaelrobert/slim-mls.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

Robert & Kohbrok        Expires 30 November 2026                [Page 1]
Internet-Draft                   SlimMLS                        May 2026

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 30 November 2026.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
   2.  Conventions and Definitions . . . . . . . . . . . . . . . . .   4
   3.  Overview  . . . . . . . . . . . . . . . . . . . . . . . . . .   4
   4.  Reference Computation . . . . . . . . . . . . . . . . . . . .   5
   5.  SlimMLS Structs . . . . . . . . . . . . . . . . . . . . . . .   6
     5.1.  SlimLeafNode  . . . . . . . . . . . . . . . . . . . . . .   8
     5.2.  SlimParentNode and SlimParentHashInput  . . . . . . . . .  11
     5.3.  SlimGroupInfo . . . . . . . . . . . . . . . . . . . . . .  11
   6.  Large Object Retrieval  . . . . . . . . . . . . . . . . . . .  12
     6.1.  Large Object Carrier  . . . . . . . . . . . . . . . . . .  13
   7.  SlimKeyPackage  . . . . . . . . . . . . . . . . . . . . . . .  14
     7.1.  KeyPackage Batch Merkle Tree  . . . . . . . . . . . . . .  15
     7.2.  OuterKeyPackageHash component . . . . . . . . . . . . . .  16
     7.3.  Creation and Processing . . . . . . . . . . . . . . . . .  16
   8.  SlimWelcome . . . . . . . . . . . . . . . . . . . . . . . . .  18
     8.1.  Sender and DS Behavior  . . . . . . . . . . . . . . . . .  18
     8.2.  SlimEncryptedGroupSecrets . . . . . . . . . . . . . . . .  19
     8.3.  WelcomeGroupInfo  . . . . . . . . . . . . . . . . . . . .  19
   9.  SlimCommit  . . . . . . . . . . . . . . . . . . . . . . . . .  21
     9.1.  SlimUpdatePath  . . . . . . . . . . . . . . . . . . . . .  21

Robert & Kohbrok        Expires 30 November 2026                [Page 2]
Internet-Draft                   SlimMLS                        May 2026

     9.2.  Slim Framing  . . . . . . . . . . . . . . . . . . . . . .  22
     9.3.  SlimMessage . . . . . . . . . . . . . . . . . . . . . . .  26
     9.4.  Single Signature Construction . . . . . . . . . . . . . .  26
     9.5.  Sender, DS, and Recipient Behavior  . . . . . . . . . . .  28
   10. Optimizing Payload Sizes  . . . . . . . . . . . . . . . . . .  30
     10.1.  Storing Partial Trees  . . . . . . . . . . . . . . . . .  30
     10.2.  Omitting Cached Large Objects  . . . . . . . . . . . . .  30
     10.3.  Cross-group Credential Caching . . . . . . . . . . . . .  30
     10.4.  Delayed Fetching of Large Objects  . . . . . . . . . . .  31
   11. Wire Formats  . . . . . . . . . . . . . . . . . . . . . . . .  31
   12. The slim_mls Extension  . . . . . . . . . . . . . . . . . . .  31
   13. The slim_ratchet_tree Extension . . . . . . . . . . . . . . .  31
   14. The slim_external_pub Extension . . . . . . . . . . . . . . .  32
   15. Security Considerations . . . . . . . . . . . . . . . . . . .  32
   16. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  34
     16.1.  SlimMLS MLS Extension Types  . . . . . . . . . . . . . .  34
     16.2.  SlimMLS Wire Formats . . . . . . . . . . . . . . . . . .  35
   17. References  . . . . . . . . . . . . . . . . . . . . . . . . .  35
     17.1.  Normative References . . . . . . . . . . . . . . . . . .  35
     17.2.  Informative References . . . . . . . . . . . . . . . . .  35
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  36
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  36

1.  Introduction

   Post-quantum (PQ) signature and key encapsulation mechanism (KEM)
   primitives can have substantially larger keys, ciphertexts, and
   signatures than their classical counterparts.  Large credentials can
   create similar pressure, including in deployments that do not
   otherwise use large ciphersuite objects.  In an MLS group [RFC9420],
   these values appear as larger LeafNodes, parent nodes, Welcomes,
   Commits, GroupInfos, and messages.  The increase is visible both on
   the wire and in client storage.

   In MLS, many of these values are embedded in structures that are
   signed, covered by tree hashes or parent hashes, or fed into
   transcript hashes.  A Delivery Service (DS) can already choose how to
   route messages, but it cannot remove or replace authenticated bytes
   without invalidating the object.  This limits cache-aware delivery,
   server-assisted fanout, and operation with clients that hold only
   part of the group state.

   SlimMLS addresses this by separating object identity from object
   delivery.  The authenticated or transcript-hashed structure carries a
   typed hash reference, and the referenced object is delivered through
   a per-message carrier, a local cache, or an application-specific
   retrieval channel.  Recipients verify each object by recomputing the
   reference before using it.

Robert & Kohbrok        Expires 30 November 2026                [Page 3]
Internet-Draft                   SlimMLS                        May 2026

   The largest benefits come from deployments where the DS is an
   independent service that can assist clients.  In such deployments,
   the DS can omit objects a recipient already has, reduce update path
   ciphertexts to the subset each recipient needs, and supply GroupInfo
   separately from a SlimWelcome.  Deployments without an assisting DS
   still benefit from smaller authenticated state, local caches of
   credentials and keys, and the ability to defer fetching large objects
   until they are needed.

   The main protocol changes are:

   *  SlimKeyPackages replace KeyPackages and batch the signatures
      needed to authenticate multiple LeafNodes.

   *  SlimCommits carry commit content separately from update path
      delivery data, so the Delivery Service can deliver only the
      ciphertexts each recipient needs.

   *  SlimWelcomes adapt Welcome messages to slim KeyPackage references
      and server-assisted GroupInfo delivery.

   *  Slim message framing and SlimGroupInfo define when signatures are
      represented by references and when the raw signature must remain
      inside encrypted plaintext to avoid revealing the sender.

   This pattern is not new in MLS.  [RFC9420] already uses RefHash-based
   references such as KeyPackageRef and ProposalRef.  SlimMLS
   generalizes the mechanism.

   [[TODO: quantify wire and storage savings for representative PQ
   ciphersuites once the specification stabilizes.]]

2.  Conventions and Definitions

   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 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

   This document uses the TLS presentation language and notation of
   [RFC9420].  Familiarity with MLS [RFC9420] is assumed.

3.  Overview

   A SlimMLS group is an MLS group whose GroupContext carries the
   slim_mls extension (Section 12).  In such a group:

Robert & Kohbrok        Expires 30 November 2026                [Page 4]
Internet-Draft                   SlimMLS                        May 2026

   *  In structures derived by mechanical substitution, each
      HPKEPublicKey, SignaturePublicKey, Credential, HPKECiphertext, or
      signature is replaced with a hash reference of the corresponding
      type.  Structures specified explicitly in this document define
      their own replacements and exceptions.

   *  The referenced large objects are retrieved per Section 6 if and
      when necessary.

4.  Reference Computation

   All new references are computed in the same style as KeyPackageRef in
   Section 5.2 of [RFC9420], i.e., using RefHash instantiated with the
   relevant ciphersuite hash function and a label unique to the
   referenced object type.  Inputs are TLS-encoded per [RFC9420].  For
   group-bound structures, the relevant ciphersuite is the group's
   ciphersuite.  For references contained in or computed over a
   SlimKeyPackage, the relevant ciphersuite is
   outer_key_package.cipher_suite of that SlimKeyPackage.

   The following reference types are defined:

   +====================+=======================+=====================+
   | Referenced value   | Reference type        | RefHash label       |
   +====================+=======================+=====================+
   | HPKEPublicKey      | HPKEPublicKeyRef      | "MLS 1.0 SlimMLS    |
   |                    |                       | HPKEPublicKey"      |
   +--------------------+-----------------------+---------------------+
   | SignaturePublicKey | SignaturePublicKeyRef | "MLS 1.0 SlimMLS    |
   |                    |                       | SignaturePublicKey" |
   +--------------------+-----------------------+---------------------+
   | Credential         | CredentialRef         | "MLS 1.0 SlimMLS    |
   |                    |                       | Credential"         |
   +--------------------+-----------------------+---------------------+
   | HPKECiphertext     | HPKECiphertextRef     | "MLS 1.0 SlimMLS    |
   |                    |                       | HPKECiphertext"     |
   +--------------------+-----------------------+---------------------+
   | Signature          | SignatureRef          | "MLS 1.0 SlimMLS    |
   |                    |                       | Signature"          |
   +--------------------+-----------------------+---------------------+
   | SlimKeyPackage     | SlimKeyPackageRef     | "MLS 1.0 SlimMLS    |
   |                    |                       | KeyPackage          |
   |                    |                       | Reference"          |
   +--------------------+-----------------------+---------------------+

                                 Table 1

Robert & Kohbrok        Expires 30 November 2026                [Page 5]
Internet-Draft                   SlimMLS                        May 2026

   Each reference is opaque<V> where V is the output length of the
   ciphersuite hash function.

   For a SlimKeyPackageRef, the value input is the TLS-encoded
   SlimKeyPackage.  SlimKeyPackageRef is used to identify the recipient
   of a SlimWelcome; it is not a large-object reference and has no
   corresponding LargeObjectCarrier entry.

   SignatureRef is used for signature fields that appear in slim
   structures unless this document requires the raw signature to remain
   inside an encrypted envelope.  It is also used for detached
   signatures referenced by slim structures, such as the SlimKeyPackage
   batch signature (Section 7).

   Some signature fields use SignatureOrRef, whose variant is
   constrained by the wire envelope that carries the structure:

   enum {
     reserved(0),
     signature(1),
     signature_ref(2),
     (255)
   } SignatureOrRefType;

   struct {
     SignatureOrRefType signature_type;
     select (SignatureOrRef.signature_type) {
       case signature:
         Signature signature;
       case signature_ref:
         SignatureRef signature_ref;
     };
   } SignatureOrRef;

   When signature_type = signature_ref, the raw signature bytes are
   resolved per Section 6.  When signature_type = signature, the raw
   signature bytes are carried inline and MUST NOT be sent outside the
   encrypted envelope in a LargeObjectCarrier.

5.  SlimMLS Structs

   For every [RFC9420] struct not given an explicit replacement in this
   document that embeds an HPKEPublicKey, SignaturePublicKey,
   Credential, HPKECiphertext, or signature, SlimMLS defines a
   corresponding "Slim*" struct that is identical to the original except
   that each occurrence of a large object is replaced by the reference
   type from Section 4 and that each occurrence of a struct for which
   there exists a Slim equivalent is replaced by that equivalent.  Tree

Robert & Kohbrok        Expires 30 November 2026                [Page 6]
Internet-Draft                   SlimMLS                        May 2026

   hashes and parent hashes are likewise computed over the slim
   encodings, so the reference values stand in for the corresponding
   large objects in these computations.

   The following signatures use SignatureOrRef because their correct
   presentation depends on whether the signature is carried inside an
   encrypted envelope:

   *  an encrypted GroupInfo carried in a SlimWelcome, whose signature
      remains inline inside the encrypted GroupInfo plaintext, and

   *  a SlimPrivateMessage framing signature, which remains inline
      inside the encrypted SlimPrivateMessageContent.

   When either signature is carried inside an encrypted envelope, it
   MUST use the signature variant.

   Welcome, KeyPackage, and Commit are not derived by mechanical
   substitution.  They are replaced by the SlimWelcome struct
   (Section 8), the SlimKeyPackage struct (Section 7), and the
   SlimCommit struct (Section 9) respectively.  As a consequence, the
   UpdatePath struct does not appear in a SlimMLS group.  Its contents
   are split between SlimCommit (which carries the committer's
   SlimLeafNode) and SlimUpdatePath (which carries the path nodes).

   In a SlimMLS group, the slim struct is sent on the wire wherever
   [RFC9420] would specify the original struct.  Validation rules of
   [RFC9420] apply in the same way.  References are only replaced by the
   corresponding large objects if functionally necessary (e.g. to verify
   a signature, encrypt a ciphertext, or retrieve referenced signature
   bytes).

   The [RFC9420] structs affected, the large objects they embed, and the
   SlimMLS replacements are listed below.  Structs whose only embedded
   large objects appear via a nested struct (e.g., proposals that carry
   a LeafNode or KeyPackage) inherit slim variants implicitly via the
   slim nested struct.

Robert & Kohbrok        Expires 30 November 2026                [Page 7]
Internet-Draft                   SlimMLS                        May 2026

   +===================+=====================+========================+
   | RFC 9420 struct   | Embedded large      | SlimMLS replacement(s) |
   |                   | object(s)           |                        |
   +===================+=====================+========================+
   | LeafNode          | HPKEPublicKey,      | HPKEPublicKeyRef,      |
   |                   | SignaturePublicKey, | SignaturePublicKeyRef, |
   |                   | Credential,         | CredentialRef,         |
   |                   | signature           | SignatureRef           |
   +-------------------+---------------------+------------------------+
   | ParentNode        | HPKEPublicKey       | HPKEPublicKeyRef       |
   +-------------------+---------------------+------------------------+
   | ParentHashInput   | HPKEPublicKey       | HPKEPublicKeyRef       |
   +-------------------+---------------------+------------------------+
   | UpdatePathNode    | HPKEPublicKey,      | HPKEPublicKeyRef,      |
   |                   | HPKECiphertext      | HPKECiphertextRef      |
   |                   | (vector)            | (vector)               |
   +-------------------+---------------------+------------------------+
   | Signature-bearing | signature           | SignatureRef           |
   | structs except    |                     |                        |
   | SignatureOrRef    |                     |                        |
   | cases             |                     |                        |
   +-------------------+---------------------+------------------------+
   | Add proposal      | KeyPackage          | SlimKeyPackage         |
   +-------------------+---------------------+------------------------+
   | Update proposal   | LeafNode            | SlimLeafNode           |
   +-------------------+---------------------+------------------------+
   | ratchet_tree      | LeafNode,           | slim_ratchet_tree      |
   | extension         | ParentNode          | extension with         |
   |                   |                     | SlimLeafNode,          |
   |                   |                     | SlimParentNode         |
   +-------------------+---------------------+------------------------+

                                 Table 2

   The exact TLS presentation of each remaining slim struct is obtained
   by mechanical substitution against [RFC9420] and is not repeated
   here.

   [[TODO: provide explicit TLS presentations for each slim variant in a
   later revision.]]

5.1.  SlimLeafNode

   SlimLeafNode replaces LeafNode.  SlimLeafNodeTBS replaces the
   LeafNodeTBS input defined in Section 7.2 of [RFC9420].

Robert & Kohbrok        Expires 30 November 2026                [Page 8]
Internet-Draft                   SlimMLS                        May 2026

   SlimMLS uses the app_data_dictionary extension specified in
   Section 7.2.1 of [I-D.ietf-mls-extensions] to carry SlimMLS-specific
   components in a SlimLeafNode's extensions field.

struct {
  opaque sibling_hash<V>;
} SlimKeyPackageMerkleProofNode;

struct {
  uint32                         leaf_index;
  uint32                         tree_size;
  SlimKeyPackageMerkleProofNode  path<V>;
} SlimKeyPackageMerkleProof;

struct {
  HPKEPublicKeyRef      encryption_key_ref;
  SignaturePublicKeyRef signature_key_ref;
  CredentialRef         credential_ref;
  Capabilities          capabilities;

  LeafNodeSource leaf_node_source;
  select (SlimLeafNodeTBS.leaf_node_source) {
    case key_package:
      Lifetime lifetime;

    case update:
      struct{};

    case commit:
      opaque parent_hash<V>;
  };

  Extension extensions<V>;

  select (SlimLeafNodeTBS.leaf_node_source) {
    case key_package:
      struct{};

    case update:
      opaque group_id<V>;
      uint32 leaf_index;

    case commit:
      opaque group_id<V>;
      uint32 leaf_index;
  };
} SlimLeafNodeTBS;

Robert & Kohbrok        Expires 30 November 2026                [Page 9]
Internet-Draft                   SlimMLS                        May 2026

struct {
  HPKEPublicKeyRef      encryption_key_ref;
  SignaturePublicKeyRef signature_key_ref;
  CredentialRef         credential_ref;
  Capabilities          capabilities;

  LeafNodeSource leaf_node_source;
  select (SlimLeafNode.leaf_node_source) {
    case key_package:
      Lifetime lifetime;

    case update:
      struct{};

    case commit:
      opaque parent_hash<V>;
  };

  Extension extensions<V>;

  /*
    For key_package leaves, this is a SignatureRef to the batch signature.
    For update and commit leaves, this is a SignatureRef to the normal
    SlimLeafNode signature over SlimLeafNodeTBS.
  */
  SignatureRef signature;

  select (SlimLeafNode.leaf_node_source) {
    case key_package:
      SlimKeyPackageMerkleProof proof;

    case update:
      struct{};

    case commit:
      struct{};
  };
} SlimLeafNode;

   The proof field is present only when leaf_node_source = key_package.
   It is not part of SlimLeafNodeTBS to avoid a circulare dependency.
   Update and commit leaf nodes do not carry this field.

   For leaf_node_source = key_package, the signature field references
   the SlimKeyPackage batch signature and validation MUST verify both
   this signature and the embedded proof as described in Section 7.1.
   This allows clients to validate a key-package SlimLeafNode even when
   it appears in a ratchet tree without the enclosing SlimKeyPackage.

Robert & Kohbrok        Expires 30 November 2026               [Page 10]
Internet-Draft                   SlimMLS                        May 2026

   For leaf nodes whose source is update or commit, the signature field
   is the normal SlimLeafNode signature over SlimLeafNodeTBS, verified
   as in Section 7.3 of [RFC9420] after applying the slim substitutions
   in this document.

5.2.  SlimParentNode and SlimParentHashInput

   The following slim tree structures are used in tree-hash and parent-
   hash computations:

   struct {
     HPKEPublicKeyRef encryption_key_ref;
     opaque           parent_hash<V>;
     uint32           unmerged_leaves<V>;
   } SlimParentNode;

   struct {
     HPKEPublicKeyRef encryption_key_ref;
     opaque           parent_hash<V>;
     opaque           original_sibling_tree_hash<V>;
   } SlimParentHashInput;

   SlimParentNode replaces ParentNode.  SlimParentHashInput replaces the
   ParentHashInput defined in Section 7.9 of [RFC9420].

5.3.  SlimGroupInfo

   SlimGroupInfo is the slim replacement for the [RFC9420] GroupInfo
   struct.  It uses the same fields and verification rules as GroupInfo,
   except that GroupInfo extensions use SlimMLS replacements and the
   signature is represented as SignatureOrRef.

Robert & Kohbrok        Expires 30 November 2026               [Page 11]
Internet-Draft                   SlimMLS                        May 2026

   struct {
     GroupContext group_context;
     Extension extensions<V>;
     MAC confirmation_tag;
     uint32 signer;
   } SlimGroupInfoTBS;

   struct {
     GroupContext group_context;
     Extension extensions<V>;
     MAC confirmation_tag;
     uint32 signer;

     /*
       SignWithLabel(., "GroupInfoTBS", SlimGroupInfoTBS)
     */
     SignatureOrRef signature;
   } SlimGroupInfo;

   The signature is computed and verified as in [RFC9420], except that
   the to-be-signed content is SlimGroupInfoTBS.  A standalone
   SlimGroupInfo, or a SlimGroupInfo carried in
   WelcomeGroupInfo.info_type = plaintext, MUST use signature_type =
   signature_ref.  A SlimGroupInfo encrypted into
   WelcomeGroupInfo.info_type = encrypted MUST use signature_type =
   signature so that the raw signature is protected by the SlimWelcome
   encryption.

6.  Large Object Retrieval

   References to large objects in SlimMLS structures, in their
   associated companion structures (e.g., SlimUpdatePath, Section 9),
   and in GroupInfo extensions defined by this document MUST be resolved
   to the corresponding large objects when necessary for MLS operations
   or validation checks.

   SlimMLS defines three retrieval channels:

   *  The LargeObjectCarrier (Section 6.1), specified in this document.

   *  A client-local cache of previously resolved objects.

   *  An application-specific fetch mechanism.

   Applications can decide how or if they use one or more retrieval
   channels.

   On receipt of a SlimMLS structure, a client:

Robert & Kohbrok        Expires 30 November 2026               [Page 12]
Internet-Draft                   SlimMLS                        May 2026

   1.  For every large-object *Ref it needs to process the structure or
       any associated companion structure, locates a candidate object
       through any of the three channels above.

   2.  Computes the reference of each candidate object under the
       appropriate label (Section 4) and verifies that it equals the
       *Ref being resolved.  A candidate object whose reference does not
       match MUST NOT be used for any cryptographic operation.

   3.  If a required *Ref cannot be resolved through any channel, the
       client MUST either request the missing object through an
       application-specific mechanism, for example from the DS, or drop
       the message.

6.1.  Large Object Carrier

   A client sending a SlimMLS struct over the wire MAY also send a
   LargeObjectCarrier struct that contains a subset of the large objects
   referenced by the SlimMLS struct or by an associated structure such
   as SlimUpdatePath (Section 9).

   This document does not define a single MLSMessage wrapper for
   LargeObjectCarrier.  When a carrier is sent on the wire, its
   encoding, multiplexing, and association with the SlimMLS message are
   provided by the application or DS protocol using SlimMLS.

   For each large-object reference type that appears in a slim structure
   or an associated structure, the LargeObjectCarrier contains a vector
   of the corresponding large objects:

   struct {
     HPKEPublicKey      hpke_public_keys<V>;
     SignaturePublicKey signature_public_keys<V>;
     Credential         credentials<V>;
     HPKECiphertext     hpke_ciphertexts<V>;
     Signature          signatures<V>;
   } LargeObjectCarrier;

   The carrier is NOT part of the signed structure.  The DS MAY add,
   remove, reorder, or substitute entries on a per-recipient basis,
   e.g., to omit objects the recipient already has cached, or to
   distribute SlimUpdatePath ciphertexts (see Section 9).  The
   LargeObjectCarrier is optional in the SlimMLS wire protocol.  The DS
   MAY reject a message based on a missing LargeObjectCarrier, or on a
   LargeObjectCarrier that is missing the large objects that clients
   will need to process a message, if its local deployment policy
   requires senders to provide those objects proactively.

Robert & Kohbrok        Expires 30 November 2026               [Page 13]
Internet-Draft                   SlimMLS                        May 2026

7.  SlimKeyPackage

   SlimKeyPackage applies the slim reference replacement to KeyPackage
   and amortizes KeyPackage authentication across a batch of KeyPackages
   uploaded by the same client.  The signature around the KeyPackage is
   omitted, and the per-KeyPackage LeafNode signature is replaced by a
   detached batch signature over the root of a Merkle tree.  The leaves
   of this tree are the SlimLeafNodeTBS values of the SlimKeyPackages in
   the batch.

   In a SlimMLS group, an [RFC9420] KeyPackage MUST NOT be used to add a
   new member: Add proposals MUST carry a SlimKeyPackage, and standalone
   KeyPackage publication MUST use the mls_slim_key_package wire format
   (Section 11).  A recipient MUST reject any Add proposal or wire-
   format message carrying an [RFC9420] KeyPackage in the context of a
   group with the slim_mls extension.

   SlimLeafNodeTBS is the unsigned part of a SlimLeafNode.  It carries
   neither the signature field nor the key-package Merkle proof.

   A SlimKeyPackage is partitioned into an OuterSlimKeyPackage (the
   fields of a KeyPackage other than the LeafNode and signature) and a
   SlimLeafNode.  The SlimLeafNode carries the SignatureRef of the
   detached batch signature and its Merkle inclusion proof:

   struct {
     ProtocolVersion  version;
     CipherSuite      cipher_suite;
     HPKEPublicKeyRef init_key_ref;
     Extension        extensions<V>;
   } OuterSlimKeyPackage;

   struct {
     ProtocolVersion       version;
     CipherSuite           cipher_suite;
     SignaturePublicKeyRef signature_key_ref;
     uint32                tree_size;
     opaque                merkle_root<V>;
   } SlimKeyPackageBatchTBS;

   struct {
     OuterSlimKeyPackage              outer_key_package;
     SlimLeafNode                     leaf_node;
   } SlimKeyPackage;

   A SlimKeyPackage carries no outer signature and no per-package
   LeafNode signature.  Authenticity of outer_key_package is provided by
   an OuterKeyPackageHash component (Section 7.2) placed in the

Robert & Kohbrok        Expires 30 November 2026               [Page 14]
Internet-Draft                   SlimMLS                        May 2026

   SlimLeafNode's app_data_dictionary extension.  Authenticity of the
   SlimLeafNodeTBS, including this component, is provided by the batch
   signature referenced by leaf_node.signature and the Merkle inclusion
   proof in leaf_node.proof.

   The HPKEPublicKey corresponding to init_key_ref, together with any
   large objects referenced by the SlimLeafNode, is resolved per
   Section 6.

7.1.  KeyPackage Batch Merkle Tree

   The Merkle tree for a SlimKeyPackage batch is computed under the hash
   function of the SlimKeyPackage ciphersuite.  A batch MUST contain at
   least one leaf.  All SlimKeyPackages in a batch MUST have the same
   version, cipher_suite, and signature_key_ref.

   The leaf hash for a SlimLeafNodeTBS is computed over the TLS-encoded
   SlimLeafNodeTBS:

   HashWithLabel("SlimKeyPackageLeaf", SlimLeafNodeTBS)

   The parent hash for two child hashes is computed over their TLS-
   encoded ordered pair:

   struct {
     opaque left<V>;
     opaque right<V>;
   } SlimKeyPackageMerkleParentInput;

   HashWithLabel("SlimKeyPackageNode", SlimKeyPackageMerkleParentInput)

   The tree is built bottom-up from the ordered list of leaf hashes.  At
   each level, adjacent nodes are paired from left to right.  If the
   final node at a level has no sibling, it is promoted unchanged to the
   next level.  The single node remaining after this process is the
   Merkle root.

Robert & Kohbrok        Expires 30 November 2026               [Page 15]
Internet-Draft                   SlimMLS                        May 2026

   The path entries in SlimKeyPackageMerkleProof are ordered from the
   leaf level toward the root.  To verify a proof, a recipient starts
   with the leaf hash of leaf_node_tbs, leaf_index, and tree_size.  At
   each level, if the current level width is odd and the current index
   is width - 1, the current hash is promoted unchanged and no path
   entry is consumed.  Otherwise, the next path entry is consumed as the
   sibling hash and the parent hash is computed with the sibling on the
   left when the current index is odd, and on the right when the current
   index is even.  The index is then divided by two, rounding down, and
   the level width is divided by two, rounding up.  A proof is valid
   only if tree_size is nonzero, leaf_index < tree_size, all path
   entries are consumed, and the final computed hash is the Merkle root.

   The batch signature is computed over:

   SignWithLabel(., "SlimKeyPackageBatchTBS", SlimKeyPackageBatchTBS)

   where version and cipher_suite are taken from outer_key_package,
   signature_key_ref is taken from leaf_node_tbs, tree_size is taken
   from the proof in leaf_node, and merkle_root is the Merkle root
   computed as above.

7.2.  OuterKeyPackageHash component

   struct {
     opaque outer_key_package_hash<V>;
   } OuterKeyPackageHash;

   outer_key_package_hash is the hash, under the SlimKeyPackage's
   ciphersuite hash function, of the TLS-encoded outer_key_package of
   the SlimKeyPackage in which the SlimLeafNode appears.

   An OuterKeyPackageHash is valid only if the SlimLeafNode's
   leaf_node_source is key_package and outer_key_package_hash equals the
   hash of the enclosing SlimKeyPackage's outer_key_package.

   The app_data_dictionary extension MUST contain exactly one
   OuterKeyPackageHash component under component identifier TBD.  A
   missing, malformed, or duplicated OuterKeyPackageHash component makes
   the enclosing SlimKeyPackage invalid.

7.3.  Creation and Processing

   A sender constructs a SlimKeyPackage as follows:

   1.  Construct an OuterSlimKeyPackage with the desired version,
       cipher_suite, HPKEPublicKeyRef for the init key, and extensions.

Robert & Kohbrok        Expires 30 November 2026               [Page 16]
Internet-Draft                   SlimMLS                        May 2026

   2.  Construct a SlimLeafNodeTBS with leaf_node_source = key_package.
       Add an app_data_dictionary extension containing an
       OuterKeyPackageHash whose value is the hash of the
       OuterSlimKeyPackage from step 1.

   3.  Construct all other SlimLeafNodeTBS values in the batch in the
       same way.

   4.  Build the KeyPackage batch Merkle tree over the SlimLeafNodeTBS
       values.

   5.  Construct a SlimKeyPackageBatchTBS for the root, sign it with the
       signature private key corresponding to signature_key_ref, and
       compute the SignatureRef over the raw signature bytes.

   6.  Emit each SlimKeyPackage with the common SignatureRef in
       leaf_node.signature and the leaf's inclusion proof in
       leaf_node.proof, optionally accompanied by a LargeObjectCarrier
       holding the referenced HPKEPublicKey and the large objects
       referenced by the SlimLeafNode and the batch signature bytes.

   A recipient processes a SlimKeyPackage like a KeyPackage with the
   following exceptions:

   *  There is no outer signature to verify.

   *  There is no per-package LeafNode signature to verify.

   *  The SlimLeafNode MUST contain an app_data_dictionary extension
      with a valid OuterKeyPackageHash component.

   *  The SlimLeafNode MUST have leaf_node_source = key_package and
      therefore carry a proof field.

   *  The recipient resolves the batch signature bytes using
      leaf_node.signature, computes SignatureRef over those bytes, and
      verifies that it equals leaf_node.signature.

   *  The recipient verifies the Merkle inclusion proof in
      leaf_node.proof, reconstructs the SlimKeyPackageBatchTBS, resolves
      the SignaturePublicKey corresponding to signature_key_ref, and
      verifies the raw batch signature bytes identified by
      leaf_node.signature using VerifyWithLabel label
      "SlimKeyPackageBatchTBS".

   *  All large-object *Ref values are resolved per Section 6.

Robert & Kohbrok        Expires 30 November 2026               [Page 17]
Internet-Draft                   SlimMLS                        May 2026

8.  SlimWelcome

   SlimWelcome makes two changes relative to the [RFC9420] Welcome:

   1.  The per-recipient EncryptedGroupSecrets is replaced by a
       SlimEncryptedGroupSecrets (Section 8.2), which permits the
       recipient to be identified either by SlimKeyPackageRef or by leaf
       index.

   2.  The encrypted_group_info field is replaced by an
       optional<WelcomeGroupInfo> (Section 8.3), where WelcomeGroupInfo
       is a tagged union over an encrypted form and a plaintext form.

   With the exception of changes described in this section, SlimWelcomes
   are processed just like regular Welcome messages.

   struct {
     CipherSuite                cipher_suite;
     SlimEncryptedGroupSecrets  secrets<V>;
     optional<WelcomeGroupInfo> group_info;
   } SlimWelcome;

8.1.  Sender and DS Behavior

   The sender MUST construct SlimWelcome.secrets to contain one
   SlimEncryptedGroupSecrets for every recipient it intends to add, in
   the same order it would use under [RFC9420].

   The DS MAY remove entries from SlimWelcome.secrets on a per-recipient
   basis, e.g., to deliver to each recipient only its own entry.

   If the sender omits the group_info field (presence octet 0), the DS
   MUST populate it with a plaintext WelcomeGroupInfo before delivering
   the SlimWelcome to a recipient (Section 8.3).  In this mode, the
   GroupInfo used by the sender to encrypt the SlimEncryptedGroupSecrets
   and the GroupInfo populated by the DS MUST be byte-for-byte identical
   SlimGroupInfo objects.

   A DS that supplies large objects alongside a SlimWelcome can
   distinguish between basic-processing delivery and update-capable
   delivery.  Basic-processing delivery contains the large objects
   needed for the recipient to validate the SlimWelcome, derive the
   epoch secrets, receive subsequent MLS messages, and send application
   messages.  It can omit HPKE public keys that are only needed to
   construct a future Commit with an update path.  Update-capable
   delivery additionally includes enough HPKE public keys for the
   recipient to construct an update path without a later fetch, such as
   the HPKE public keys for the recipient's copath resolution in the

Robert & Kohbrok        Expires 30 November 2026               [Page 18]
Internet-Draft                   SlimMLS                        May 2026

   delivered tree.  A recipient that has only basic-processing state
   MUST resolve the missing HPKEPublicKeyRefs before sending a Commit
   with an update path.

8.2.  SlimEncryptedGroupSecrets

   SlimEncryptedGroupSecrets extends the [RFC9420] EncryptedGroupSecrets
   to allow either of two recipient identifiers:

   enum {
     reserved(0),
     slim_key_package_ref(1),
     leaf_node_index(2),
     (255)
   } RecipientIdentifierType;

   struct {
     RecipientIdentifierType recipient_type;
     select (SlimEncryptedGroupSecrets.recipient_type) {
       case slim_key_package_ref:
         SlimKeyPackageRef new_member;
       case leaf_node_index:
         uint32 leaf_node_index;
     };
     HPKECiphertext encrypted_group_secrets;
   } SlimEncryptedGroupSecrets;

   A recipient locates the entry intended for it by matching either its
   own SlimKeyPackageRef or its leaf in the group's ratchet tree via the
   leaf index.

   The leaf_node_index recipient type MUST be used only when the
   SlimEncryptedGroupSecrets is encrypted using a plaintext
   SlimGroupInfo as context and the delivered SlimWelcome carries
   WelcomeGroupInfo.info_type = plaintext.  Otherwise, the sender MUST
   use slim_key_package_ref.

8.3.  WelcomeGroupInfo

   WelcomeGroupInfo is a tagged union over two presentations of the
   SlimGroupInfo: an encrypted form or a plaintext form:

Robert & Kohbrok        Expires 30 November 2026               [Page 19]
Internet-Draft                   SlimMLS                        May 2026

   enum {
     reserved(0),
     encrypted(1),
     plaintext(2),
     (255)
   } WelcomeGroupInfoType;

   struct {
     WelcomeGroupInfoType info_type;
     select (WelcomeGroupInfo.info_type) {
       case encrypted:
         opaque encrypted_group_info<V>;
       case plaintext:
         SlimGroupInfo group_info;
     };
   } WelcomeGroupInfo;

   The encrypted variant is encrypted under a key derived from the
   joiner secret, as in the encrypted_group_info field of the [RFC9420]
   Welcome.  Its plaintext is a SlimGroupInfo whose SignatureOrRef uses
   signature_type = signature.  A sender MUST NOT encrypt a
   SlimGroupInfo with signature_type = signature_ref into this field.

   The plaintext variant carries a SlimGroupInfo in the clear.  Its
   SignatureOrRef MUST use signature_type = signature_ref, which is
   resolved per Section 6 before signature verification.

   The HPKE context used to encrypt and decrypt
   SlimEncryptedGroupSecrets.encrypted_group_secrets depends on the
   GroupInfo presentation.  For the encrypted variant, the context is
   the encrypted_group_info value, as in [RFC9420].  For the plaintext
   variant, and for SlimWelcomes sent with group_info absent, the
   context is the TLS-encoded SlimGroupInfo.

   The outer optional<WelcomeGroupInfo> in the SlimWelcome additionally
   allows the sender to omit the GroupInfo.  This mode is intended for
   server-assisted deployments where the sender and recipient can obtain
   the exact GroupInfo by some channel other than the SlimWelcome.

   A recipient that receives a SlimWelcome whose group_info field is
   absent MUST consider the SlimWelcome invalid.

Robert & Kohbrok        Expires 30 November 2026               [Page 20]
Internet-Draft                   SlimMLS                        May 2026

9.  SlimCommit

   SlimCommit enables split delivery for SlimMLS Commits.  The DS can
   deliver to each recipient only the HPKECiphertextRefs and
   HPKECiphertexts intended for that recipient.  It also saves one
   signature when a commit contains a path but does not rotate the
   sender's signature key.

   A SlimMLS-aware sender MUST use a SlimCommit in place of an MLS
   Commit in a group with the slim_mls extension.

   A SlimCommit is carried in either a SlimPublicMessage or
   SlimPrivateMessage (Section 9.2).  These message structures allow the
   unsigned SlimUpdatePath to be carried alongside the framed SlimCommit
   without being included in the transcript hash, the membership tag, or
   the framing signature.

   A SlimCommit carries the normal [RFC9420] confirmation tag in its
   SlimFramedContentAuthData.  When the single-signature construction of
   Section 9.4 applies, the authentication data contains the
   confirmation tag but omits the framing signature field.  Otherwise,
   the authentication data contains the confirmation tag and a
   SignatureOrRef whose variant is determined by the message envelope.

   struct {
     ProposalOrRef          proposals<V>;
     optional<SlimLeafNode> leaf_node;
   } SlimCommit;

   leaf_node, when present, is the committer's new SlimLeafNode.

9.1.  SlimUpdatePath

   The path is conveyed separately from the framed SlimCommit:

   struct {
     HPKEPublicKeyRef  encryption_key_ref;
     HPKECiphertextRef encrypted_path_secret_refs<V>;
   } SlimUpdatePathNode;

   struct {
     SlimUpdatePathNode nodes<V>;
   } SlimUpdatePath;

   Each SlimUpdatePathNode carries an HPKEPublicKeyRef for the new
   ParentNode public key and a vector of HPKECiphertextRefs.  In the
   sender-to-DS SlimUpdatePath, the encrypted_path_secret_refs vector
   has the same order and cardinality as the encrypted_path_secret

Robert & Kohbrok        Expires 30 November 2026               [Page 21]
Internet-Draft                   SlimMLS                        May 2026

   vector in the corresponding [RFC9420] UpdatePathNode.  In a DS-to-
   recipient SlimUpdatePath, the DS MAY reduce each
   encrypted_path_secret_refs vector to the subset the recipient needs.
   The reduced path MUST contain enough HPKECiphertextRefs for the
   recipient to decrypt one path secret and derive the remaining path
   secrets it needs to process the Commit.  The corresponding
   HPKECiphertexts, and any HPKEPublicKeys that are functionally needed,
   are resolved per Section 6.

   The SlimUpdatePath is not signed.  Its HPKEPublicKeyRefs are
   authenticated by the parent hash in the committer's SlimLeafNode, as
   in Section 7.9 of [RFC9420], with HPKEPublicKeyRef replacing
   HPKEPublicKey in the parent-hash computation.  Its HPKECiphertextRefs
   are unauthenticated delivery objects: a recipient validates them by
   decrypting the referenced HPKECiphertext, deriving the path public
   keys, checking that the derived public keys hash to the authenticated
   HPKEPublicKeyRefs, and verifying the Commit confirmation tag.

9.2.  Slim Framing

   In a SlimMLS group, public and private message framing uses dedicated
   SlimMLS structures.  They are the same as [RFC9420] PublicMessage and
   PrivateMessage, except that:

   *  the framed content carries a SlimCommit or SlimProposal where
      [RFC9420] carries a Commit or Proposal,

   *  the authentication data is a SlimFramedContentAuthData, and

   *  when the content is a SlimCommit, the unsigned SlimUpdatePath is
      carried alongside the framed content, outside the authenticated
      content.

   SlimProposal is the slim variant of the [RFC9420] Proposal struct
   obtained by the mechanical-substitution rule of Section 5: an Add
   proposal carries a SlimKeyPackage and an Update proposal carries a
   SlimLeafNode.  Other proposal variants are unchanged.

   struct {
     opaque group_id<V>;
     uint64 epoch;
     Sender sender;
     opaque authenticated_data<V>;

     ContentType content_type;
     select (SlimFramedContent.content_type) {
       case application:
         opaque application_data<V>;

Robert & Kohbrok        Expires 30 November 2026               [Page 22]
Internet-Draft                   SlimMLS                        May 2026

       case proposal:
         SlimProposal proposal;
       case commit:
         SlimCommit commit;
     };
   } SlimFramedContent;

   struct {
     /*
       SignWithLabel(., "FramedContentTBS", SlimFramedContentTBS)
     */
     optional<SignatureOrRef> signature;

     select (SlimFramedContent.content_type) {
       case commit:
         /*
           MAC(confirmation_key,
               GroupContext.confirmed_transcript_hash)
         */
         MAC confirmation_tag;
       case application:
       case proposal:
         struct{};
     };
   } SlimFramedContentAuthData;

   struct {
     ProtocolVersion    version = mls10;
     WireFormat         wire_format;
     SlimFramedContent  content;
     select (SlimFramedContentTBS.content.sender.sender_type) {
       case member:
       case new_member_commit:
         GroupContext context;
       case external:
       case new_member_proposal:
         struct{};
     };
   } SlimFramedContentTBS;

   struct {
     WireFormat         wire_format;
     SlimFramedContent  content;
     SlimFramedContentAuthData auth;
   } SlimAuthenticatedContent;

   struct {
     SlimFramedContent         content;

Robert & Kohbrok        Expires 30 November 2026               [Page 23]
Internet-Draft                   SlimMLS                        May 2026

     SlimFramedContentAuthData auth;
     select (SlimPublicMessage.content.sender.sender_type) {
       case member:
         MAC membership_tag;
       case external:
       case new_member_commit:
       case new_member_proposal:
         struct{};
     };
     select (SlimPublicMessage.content.content_type) {
       case commit:
         optional<SlimUpdatePath> path;
       case application:
       case proposal:
         struct{};
     };
   } SlimPublicMessage;

   struct {
     select (SlimPrivateMessage.content_type) {
       case application:
         opaque application_data<V>;
       case proposal:
         SlimProposal proposal;
       case commit:
         SlimCommit commit;
     };
     SlimFramedContentAuthData auth;
     opaque                    padding[length_of_padding];
   } SlimPrivateMessageContent;

   struct {
     opaque group_id<V>;
     uint64 epoch;
     ContentType content_type;
     opaque authenticated_data<V>;
     opaque encrypted_sender_data<V>;
     opaque ciphertext<V>;
     select (SlimPrivateMessage.content_type) {
       case commit:
         optional<SlimUpdatePath> path;
       case application:
       case proposal:
         struct{};
     };
   } SlimPrivateMessage;

Robert & Kohbrok        Expires 30 November 2026               [Page 24]
Internet-Draft                   SlimMLS                        May 2026

   The optional signature field in SlimFramedContentAuthData MUST be
   present whenever content_type is application or proposal.  For
   content_type = commit, signature MUST be absent if and only if the
   single-signature construction of Section 9.4 applies.

   When present in a SlimPublicMessage, signature MUST use
   signature_type = signature_ref.  When present in a
   SlimPrivateMessage, signature MUST use signature_type = signature.
   This ensures that a SlimPrivateMessage framing signature is encrypted
   as part of SlimPrivateMessageContent.

   When a framing signature is present, it is computed and verified as
   in [RFC9420], except that the to-be-signed content is
   SlimFramedContentTBS and the WireFormat is either
   mls_slim_public_message or mls_slim_private_message.

   For SlimPrivateMessage, the ciphertext field encrypts a
   SlimPrivateMessageContent.  The sender data encryption, content
   encryption, padding, and decryption rules are otherwise the same as
   for PrivateMessage in [RFC9420].

   After decrypting a SlimPrivateMessage, the recipient reconstructs the
   SlimFramedContent from the outer group_id, epoch, content_type, and
   authenticated_data fields, the decrypted sender, and the decrypted
   content.  The reconstructed SlimFramedContent is used with the
   decrypted SlimFramedContentAuthData for signature verification and,
   for commits, for OuterUpdateHash verification, transcript hash
   computation, and confirmation tag verification.

   For SlimPublicMessage, the membership tag is computed over the
   following structure:

   struct {
     SlimFramedContentTBS       content_tbs;
     SlimFramedContentAuthData  auth;
   } SlimAuthenticatedContentTBM;

   For commits, the input to the confirmed transcript hash is:

   struct {
     WireFormat        wire_format;
     SlimFramedContent content;
   } SlimConfirmedTranscriptHashInput;

Robert & Kohbrok        Expires 30 November 2026               [Page 25]
Internet-Draft                   SlimMLS                        May 2026

   The SlimUpdatePath is not part of SlimFramedContent,
   SlimAuthenticatedContentTBM, or SlimConfirmedTranscriptHashInput.  It
   is therefore not authenticated by the membership tag, the framing
   signature, or the transcript hash.  In a SlimPrivateMessage carrying
   a commit, the path is carried outside the ciphertext so the DS can
   reduce it per recipient.

9.3.  SlimMessage

   SlimMessage is the generic term for the two concrete wire
   presentations, SlimPublicMessage and SlimPrivateMessage.  Both
   presentations are used for sender-to-DS transport and for DS-to-
   recipient delivery.  For commits, the difference between the two is
   the cardinality of the HPKECiphertextRef vectors in path.

   In a SlimMLS group, the [RFC9420] PublicMessage and PrivateMessage
   wire formats MUST NOT be used.  A SlimMLS-aware sender MUST emit a
   SlimPublicMessage or SlimPrivateMessage in their place.

9.4.  Single Signature Construction

   When a SlimCommit is sent by a member, contains a SlimLeafNode, and
   the sender's signature key is unchanged, the framing signature is
   omitted, and authenticity is provided by the SlimLeafNode's own
   signature in combination with an OuterUpdateHash component placed in
   the SlimLeafNode's app_data_dictionary extension.  The confirmation
   tag is still present and processed as in [RFC9420].

   The OuterUpdateHash binds the framed SlimCommit (excluding the
   SlimLeafNode itself, to avoid a circular dependency) and the
   GroupContext to the SlimLeafNode:

Robert & Kohbrok        Expires 30 November 2026               [Page 26]
Internet-Draft                   SlimMLS                        May 2026

   struct {
     opaque outer_update_hash<V>;
   } OuterUpdateHash;

   struct {
     opaque       group_id<V>;
     uint64       epoch;
     Sender       sender;
     opaque       authenticated_data<V>;
     ContentType  content_type;
     select (OuterFramedContent.content_type) {
       case commit:
         ProposalOrRef proposals<V>;
     };
   } OuterFramedContent;

   struct {
     ProtocolVersion    version = mls10;
     WireFormat         wire_format;
     OuterFramedContent content;
     GroupContext       context;
   } SlimFramedContentTBH;

   outer_update_hash is the hash, under the group's ciphersuite hash
   function, of the TLS-encoded SlimFramedContentTBH.  Fields of
   OuterFramedContent are populated from the SlimCommit being framed.
   The SlimLeafNode is omitted to prevent the circular dependency that
   would arise from including the very component being computed.

   The app_data_dictionary extension MUST contain exactly one
   OuterUpdateHash component under component identifier TBD.  A missing,
   malformed, or duplicated OuterUpdateHash component makes the single-
   signature construction invalid.

   The OuterUpdateHash authenticates the non-path commit contents that
   the omitted framing signature would otherwise cover.  The path's
   HPKEPublicKeyRefs are authenticated separately by parent hash
   validation.  The path's HPKECiphertextRefs are not authenticated by
   the signature and do not contribute to the group state.  Tampering
   with them can only cause decryption, derived-key, or confirmation-tag
   validation to fail.

   When the construction applies, the SignaturePublicKeyRef in the
   SlimLeafNode MUST equal the sender's current SignaturePublicKeyRef.
   A sender that wishes to change its signature key MUST instead emit a
   SlimCommit whose authentication data carries a framing signature, so
   that the new key is bound by a signature under the old one.

Robert & Kohbrok        Expires 30 November 2026               [Page 27]
Internet-Draft                   SlimMLS                        May 2026

   A SlimCommit without a SlimLeafNode (e.g., a commit containing only
   Add or Remove proposals) does not use this construction.  Its
   authentication data carries a framing signature.

   A SlimCommit whose sender type is not member does not use this
   construction.  Its authentication data carries a framing signature.

9.5.  Sender, DS, and Recipient Behavior

   A committer constructs a SlimMessage carrying a SlimCommit as
   follows:

   1.  Perform the steps of an [RFC9420] commit, deriving the path's
       HPKEPublicKeys, HPKECiphertexts, parent hashes, and the new
       epoch's key schedule.  Parent hashes are computed over the slim
       parent-hash inputs, with HPKEPublicKeyRef replacing
       HPKEPublicKey.

   2.  Build a SlimCommit containing the committed proposals and, if the
       commit contains a path, the committer's new SlimLeafNode.  The
       SlimLeafNode's parent hash MUST authenticate the
       HPKEPublicKeyRefs in the SlimUpdatePath.

   3.  Compute the confirmation tag for the new epoch as in [RFC9420].

   4.  If the single-signature construction applies, include a valid
       OuterUpdateHash in the SlimLeafNode and leave the optional
       signature field absent.  If the construction does not apply,
       include the normal framing signature in
       SlimFramedContentAuthData, using signature_type = signature_ref
       for SlimPublicMessage and signature_type = signature for
       SlimPrivateMessage.

   5.  Build a SlimUpdatePath whose SlimUpdatePathNodes carry the
       HPKEPublicKeyRefs and HPKECiphertextRefs of the path, and emit a
       SlimPublicMessage or SlimPrivateMessage, optionally accompanied
       by a LargeObjectCarrier holding the corresponding HPKEPublicKeys,
       HPKECiphertexts, and any public-message framing signature
       referenced by the SignatureOrRef.

   The DS, knowing the ratchet tree before and after the commit,
   produces a per-recipient SlimMessage by reducing each
   SlimUpdatePathNode's HPKECiphertextRef vector to the subset needed by
   that recipient.  The DS MUST retain the HPKEPublicKeyRef in every
   SlimUpdatePathNode, and MUST retain enough HPKECiphertextRefs for the
   recipient to decrypt one path secret and derive the remaining path
   secrets it needs to process the Commit.  If a LargeObjectCarrier is
   present, the DS reduces it accordingly, retaining only any

Robert & Kohbrok        Expires 30 November 2026               [Page 28]
Internet-Draft                   SlimMLS                        May 2026

   HPKEPublicKeys the recipient must receive and the HPKECiphertexts
   corresponding to the retained HPKECiphertextRefs.  If the commit
   removes the recipient, path is omitted.

   For basic-processing delivery of a Commit with an update path, a
   recipient needs enough ciphertext material to derive the epoch
   secrets and verify the Commit, but does not necessarily need every
   HPKE public key referenced by the path.  Such a recipient can process
   the Commit, receive subsequent MLS messages, and send application
   messages, but might not be able to construct its own Commit with an
   update path until it resolves additional HPKEPublicKeyRefs.  To make
   the recipient immediately update-capable, the DS MAY include any
   updated HPKE public keys in the recipient's copath that the recipient
   cannot derive from its retained path secret.  In a full tree with no
   blank nodes, this is one HPKE public key for each non-committing
   recipient.

   A recipient processes a SlimMessage carrying a SlimCommit by:

   1.  Resolving the HPKECiphertextRefs required for the recipient and
       any HPKEPublicKeyRefs that are functionally needed, per
       Section 6.  For SlimPublicMessage, this also includes any
       SignatureRef in the SlimFramedContentAuthData SignatureOrRef.
       For SlimPrivateMessage, the recipient decrypts
       SlimPrivateMessageContent and uses the inline SignatureOrRef
       value when one is present.

   2.  If the authentication data contains a framing signature,
       verifying it per [RFC9420] using SlimFramedContentTBS.  If the
       SignatureOrRef uses signature_type = signature_ref, the recipient
       first resolves the referenced signature.  If it uses
       signature_type = signature, the recipient uses the inline
       signature.  If the framing signature is absent, verifying the
       SlimLeafNode signature and OuterUpdateHash per Section 9.4.

   3.  Decrypting the resolved HPKECiphertext, deriving the path public
       keys, and verifying that the derived public keys hash to the
       authenticated HPKEPublicKeyRefs.

   4.  Applying the path update and verifying parent hashes over the
       slim encodings per Section 7.9.2 of [RFC9420].

   5.  Processing the commit per Section 12.4 of [RFC9420], deriving the
       new epoch, and verifying the confirmation tag.  If confirmation
       tag validation fails, the recipient MUST reject the commit.

Robert & Kohbrok        Expires 30 November 2026               [Page 29]
Internet-Draft                   SlimMLS                        May 2026

   The input to the confirmed transcript hash is
   SlimConfirmedTranscriptHashInput (Section 9.2).  The interim
   transcript hash is computed from the confirmed transcript hash and
   the confirmation tag as in [RFC9420].

   DSs that do not maintain the ratchet tree cannot perform the per-
   recipient reduction described above.  Strategies for such deployments
   are out of scope.

10.  Optimizing Payload Sizes

   The separation of large objects and their references in structs that
   are sent over the wire or stored locally allows a few performance
   optimizations.  They are up to the application to implement.

10.1.  Storing Partial Trees

   SlimMLS clients need the slim public tree for MLS tree computations,
   but they do not need to fetch every large object referenced by that
   tree.  Tree hashes, parent hashes, and GroupInfo validation are
   computed over SlimLeafNode and SlimParentNode encodings, so the
   references to public keys and credentials are the values committed to
   by those computations.  A client can therefore defer fetching large
   objects that are not functionally needed, such as HPKE public keys
   outside the client's copath.  This is especially relevant when
   joining a group, where the DS can selectively include the public keys
   and credentials the joiner needs immediately.

10.2.  Omitting Cached Large Objects

   If the DS keeps track of the group's public state, clients that send
   a commit with an update path only need to proactively provide the
   signature public key and credential if either of them change as part
   of the commit.

10.3.  Cross-group Credential Caching

   If clients use the same credential across multiple groups, other
   clients can cache them and pull new credentials selectively when they
   encounter credential references they can't resolve.  Whether this is
   a performance increase depends on the context of the application.

   The DS can similarly deduplicate stored credentials.

Robert & Kohbrok        Expires 30 November 2026               [Page 30]
Internet-Draft                   SlimMLS                        May 2026

10.4.  Delayed Fetching of Large Objects

   A client that has been offline for some time can fetch and process
   slim messages first.  It can wait to fetch large objects that are not
   relevant for processing (such as HPKE public keys) until it has
   arrived at the current group state.  The client thus avoids
   downloading stale, intermediate large objects.

11.  Wire Formats

   SlimMLS defines new WireFormat values for the SlimMLS variants of
   each [RFC9420] wire format.  The MLSMessage struct defined in
   [RFC9420] is correspondingly extended with the following cases:

struct {
  ProtocolVersion version = mls10;
  WireFormat wire_format;
  select (MLSMessage.wire_format) {
    case mls_slim_welcome:          SlimWelcome        slim_welcome;
    case mls_slim_key_package:      SlimKeyPackage     slim_key_package;
    case mls_slim_group_info:       SlimGroupInfo      slim_group_info;
    case mls_slim_public_message:   SlimPublicMessage  slim_public_message;
    case mls_slim_private_message:  SlimPrivateMessage slim_private_message;
  };
} MLSMessage;

   In a SlimMLS group, the [RFC9420] wire formats mls_public_message,
   mls_private_message, mls_welcome, mls_group_info, and mls_key_package
   MUST NOT be used.  A SlimMLS-aware sender MUST emit the corresponding
   SlimMLS wire format instead: mls_slim_public_message or
   mls_slim_private_message for member-originated messages,
   mls_slim_welcome for Welcomes, mls_slim_group_info for standalone
   GroupInfos, and mls_slim_key_package for KeyPackages.  A recipient
   MUST reject any RFC 9420 wire format received in the context of a
   group that carries the slim_mls extension.

12.  The slim_mls Extension

   SlimMLS is signaled by a GroupContext extension named slim_mls.
   Presence of this extension in the GroupContext means that all wire
   formats within the group use SlimMLS replacements (Section 11).

13.  The slim_ratchet_tree Extension

   The [RFC9420] ratchet_tree GroupInfo extension carries LeafNode and
   ParentNode objects.  SlimMLS defines a slim_ratchet_tree GroupInfo
   extension that conveys the same tree using SlimLeafNode and
   SlimParentNode objects:

Robert & Kohbrok        Expires 30 November 2026               [Page 31]
Internet-Draft                   SlimMLS                        May 2026

   struct {
       NodeType node_type;
       select (SlimNode.node_type) {
           case leaf:   SlimLeafNode leaf_node;
           case parent: SlimParentNode parent_node;
       };
   } SlimNode;

   optional<SlimNode> slim_ratchet_tree<V>;

   The ordering, truncation, and validation rules are the same as for
   the ratchet_tree extension in Section 12.4.3.3 of [RFC9420], except
   that tree hash and parent hash computations use the slim node
   encodings.  The large objects referenced by the slim nodes are
   resolved per Section 6.

   In a SlimMLS group, the [RFC9420] ratchet_tree extension MUST NOT be
   used.  A sender that would include ratchet_tree MUST instead include
   the slim_ratchet_tree extension.

14.  The slim_external_pub Extension

   The [RFC9420] external_pub GroupInfo extension carries an
   HPKEPublicKey that external joiners use when issuing an External Init
   proposal (Section 12.4.3.2 of [RFC9420]).  SlimMLS defines a
   slim_external_pub GroupInfo extension that conveys the same
   information using an HPKEPublicKeyRef:

   struct {
     HPKEPublicKeyRef external_pub_ref;
   } SlimExternalPub;

   In a SlimMLS group, the [RFC9420] external_pub extension MUST NOT be
   used.  A sender that would include external_pub MUST instead include
   the slim_external_pub extension, populated with the reference to the
   relevant HPKEPublicKey.  The actual public key is resolved per
   Section 6, as for any other HPKEPublicKeyRef.

15.  Security Considerations

   Outside the SlimCommit split path described below, the signing and
   transcript-hashing rules of [RFC9420] are preserved by SlimMLS: every
   struct that was authenticated under [RFC9420] remains authenticated,
   with large objects bound through the collision-resistant hash
   references defined in Section 4.  The strength of the binding is
   therefore at most the collision resistance of the ciphersuite hash.

Robert & Kohbrok        Expires 30 November 2026               [Page 32]
Internet-Draft                   SlimMLS                        May 2026

   SlimCommit (Section 9) changes the exact authentication surface of
   Commits with paths.  The path's HPKEPublicKeyRefs are not covered
   directly by the framing signature or OuterUpdateHash, but are
   authenticated by the parent hash chain rooted in the signed
   SlimLeafNode.  The path's HPKECiphertextRefs are not authenticated by
   the signature and are treated as delivery objects.  Tampering with an
   HPKECiphertextRef or the referenced HPKECiphertext can only cause the
   recipient to fail reference resolution, decryption, derived-public-
   key matching, parent-hash validation, or confirmation-tag validation.

   Large-object retrieval channels (Section 6) may be unauthenticated.
   The hash-reference verification in step 2 of that section is what
   provides authentication of the resolved objects, and is what binds
   them to the signed and transcript-hashed slim structures.  A Delivery
   Service or network attacker that withholds, modifies, or substitutes
   entries in any channel can only cause a recipient to fail to resolve
   a reference, which is functionally equivalent to dropping the
   message, which the DS can already do under [RFC9420].  An attacker
   may also surface unsolicited or malformed objects through any
   channel.  Recipients MUST NOT treat the contents of any retrieval
   channel as authoritative metadata and MUST ignore objects whose hash
   does not match any reference the recipient needs to resolve.

   A client that caches resolved large objects across groups MUST index
   its cache by the tuple (reference type, ciphersuite hash function,
   reference value).  The same underlying object yields different
   reference values under different hash functions, and a cached object
   MUST NOT be treated as authoritative across ciphersuites whose hash
   functions differ.

   SlimKeyPackage batch signatures (Section 7) replace independent
   LeafNode signatures with one signature over a Merkle root.  A
   recipient MUST verify both the Merkle inclusion proof and the batch
   signature before treating the SlimLeafNodeTBS as authenticated.  The
   signed SlimKeyPackageBatchTBS binds the protocol version,
   ciphersuite, tree size, Merkle root, and SignaturePublicKeyRef.
   Together with the SignWithLabel label and the Merkle leaf and parent
   hash labels, this prevents a valid batch signature from being
   replayed across protocols, ciphersuites, or signing keys.  The Merkle
   proof is carried in the SlimLeafNode only for leaf_node_source =
   key_package, so group members that later validate the ratchet tree
   can verify the authenticity of the leaf without having received the
   original SlimKeyPackage.

   All SlimKeyPackages whose key-package SlimLeafNodes share the same
   signature field are linkable as members of the same publication
   batch.  Deployments that consider this linkability sensitive can
   reduce batch sizes or publish independently signed batches.

Robert & Kohbrok        Expires 30 November 2026               [Page 33]
Internet-Draft                   SlimMLS                        May 2026

   SlimWelcome (Section 8) introduces two confidentiality changes
   relative to the [RFC9420] Welcome:

   *  When WelcomeGroupInfo.info_type is plaintext, the GroupInfo is
      visible to the DS and to anyone observing the SlimWelcome on the
      wire.  This variant is appropriate only in deployments where the
      GroupInfo is not considered confidential with respect to those
      parties (e.g., where the DS already maintains group state).

   *  When SlimWelcome.group_info is absent (presence octet 0), the DS
      chooses which WelcomeGroupInfo a joiner ultimately receives.

   In both cases authenticity is unchanged: the joiner MUST verify the
   SlimGroupInfo signature as under [RFC9420], and a SlimWelcome that
   reaches a recipient with group_info still absent MUST be rejected
   (Section 8.3).

   SlimPrivateMessage and encrypted SlimWelcome GroupInfo signatures are
   carried inside the encrypted plaintext using the SignatureOrRef
   signature variant.  This prevents a visible LargeObjectCarrier
   signature from being tested against known signature public keys to
   identify the hidden signer.

16.  IANA Considerations

16.1.  SlimMLS MLS Extension Types

   IANA is requested to add the following entries to the "MLS Extension
   Types" registry defined in Section 17.3 of [RFC9420]:

    +======+===================+============+=============+===========+
    |Value | Name              | Message(s) | Recommended | Reference |
    +======+===================+============+=============+===========+
    |0x000C| slim_mls          | GC         | Y           | RFC XXXX  |
    +------+-------------------+------------+-------------+-----------+
    |0x000D| slim_ratchet_tree | GI         | Y           | RFC XXXX  |
    +------+-------------------+------------+-------------+-----------+
    |0x000E| slim_external_pub | GI         | Y           | RFC XXXX  |
    +------+-------------------+------------+-------------+-----------+

                                  Table 3

   (Values are SlimMLS's suggested allocations.  IANA may pick others.)

   The "Message(s)" abbreviations are those used in Section 17.3 of
   [RFC9420].  "GC" denotes a GroupContext extension and "GI" denotes a
   GroupInfo extension.  RFC XXXX is to be replaced with the RFC number
   assigned to this document upon publication.

Robert & Kohbrok        Expires 30 November 2026               [Page 34]
Internet-Draft                   SlimMLS                        May 2026

16.2.  SlimMLS Wire Formats

   IANA is requested to add the following entries to the "MLS Wire
   Formats" registry defined in Section 17.2 of [RFC9420]:

      +========+==========================+=============+===========+
      | Value  | Name                     | Recommended | Reference |
      +========+==========================+=============+===========+
      | 0x0007 | mls_slim_welcome         | Y           | RFC XXXX  |
      +--------+--------------------------+-------------+-----------+
      | 0x0008 | mls_slim_key_package     | Y           | RFC XXXX  |
      +--------+--------------------------+-------------+-----------+
      | 0x0009 | mls_slim_group_info      | Y           | RFC XXXX  |
      +--------+--------------------------+-------------+-----------+
      | 0x000A | mls_slim_public_message  | Y           | RFC XXXX  |
      +--------+--------------------------+-------------+-----------+
      | 0x000B | mls_slim_private_message | Y           | RFC XXXX  |
      +--------+--------------------------+-------------+-----------+

                                  Table 4

   (Values are SlimMLS's suggested allocations.  IANA may pick others.)

17.  References

17.1.  Normative References

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC9420]  Barnes, R., Beurdouche, B., Robert, R., Millican, J.,
              Omara, E., and K. Cohn-Gordon, "The Messaging Layer
              Security (MLS) Protocol", RFC 9420, DOI 10.17487/RFC9420,
              July 2023, <https://www.rfc-editor.org/rfc/rfc9420>.

17.2.  Informative References

Robert & Kohbrok        Expires 30 November 2026               [Page 35]
Internet-Draft                   SlimMLS                        May 2026

   [I-D.ietf-mls-extensions]
              Robert, R., "The Messaging Layer Security (MLS)
              Extensions", Work in Progress, Internet-Draft, draft-ietf-
              mls-extensions-09, 2 March 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-mls-
              extensions-09>.

Acknowledgments

   TODO acknowledge.

Authors' Addresses

   Raphael Robert
   Phoenix R&D
   Email: ietf@raphaelrobert.com

   Konrad Kohbrok
   Phoenix R&D
   Email: konrad@ratchet.ing

Robert & Kohbrok        Expires 30 November 2026               [Page 36]