<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.36 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-robert-mimi-delivery-service-03" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.17.4 -->
  <front>
    <title abbrev="MIMI">MIMI Delivery Service</title>
    <seriesInfo name="Internet-Draft" value="draft-robert-mimi-delivery-service-03"/>
    <author initials="R." surname="Robert" fullname="Raphael Robert">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>ietf@raphaelrobert.com</email>
      </address>
    </author>
    <author initials="K." surname="Kohbrok" fullname="Konrad Kohbrok">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>konrad.kohbrok@datashrine.de</email>
      </address>
    </author>
    <date year="2023" month="July" day="10"/>
    <area>Security</area>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 24?>

<t>This document describes the MIMI Delivery Service.</t>
    </abstract>
  </front>
  <middle>
    <?line 28?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>The MLS protocol document specifies a protocol between two or more clients. The
MLS architecture document introduces an abstract concept of a "Delivery Service"
(DS) that is specifically responsible for ordering handshake messages and more
generally for delivering messages to the intended recipients.</t>
      <t>This document describes a Delivery Service that performs the mandated ordering
of handshake messages and uses MLS to implement a variety of other features:</t>
      <ul spacing="normal">
        <li>A protocol between clients and the Delivery Service that allows clients to
interact with the Delivery Service, including the specific wire format of the
messages. The protocol is specifically designed to be operated in a
decentralized, federated architecture but can be used in single instances as
well.</li>
        <li>Discovery and connection establishment between clients: Clients can request
key material to establish an end-to-end encrypted channel to other clients.</li>
        <li>Assistance for new joiners of a group: The Delivery Service can keep and
update state such as the public ratchet tree, group extensions, etc.</li>
        <li>Message validation: The Delivery Service can inspect and validate handshake
messages and reject malformed, invalid or malicious messages.</li>
        <li>Built-in authentication of group members and policy enforcement: The Delivery
Service can authenticate group members, reject messages from non-members and
enforce group administration policies. Additionally, the Delivery Service can
be linked to the Authentication Service to enforce more policies and
validation rules.</li>
        <li>Message delivery with reduced metadata: The Delivery Service can deliver
messages to the intended recipients without learning the identity of group
members, in particular the sender or the recipients of messages. This feature
is optional and is compatible with all other features, such as assistance
and validation.</li>
        <li>Scalability: The protocol makes no assumption about whether the Delivery Service
runs as a single instance or as a cluster of instances.</li>
        <li>Network fluid: While the Delivery Service would typically run as a
server-side component, the only requirement is that it is accesible by all
clients.</li>
        <li>Transport agnostic: Messages between clients and the Delivery Service can be
sent via an arbitrary transport protocol. Additionally, in the federated
case, client messages to a guest Delivery Service can be forwarded by a
client's local instance of this service.</li>
        <li>Multi-device capable: The Delivery Service can be used by multiple devices
of the same users and supports adding and removing devices of a user.</li>
        <li>A Queueing Service subcomponent that can be used to implement a queueing
service for messages that are delivered asynchronously, particularly in
federated environments, as well as the protocol between the Delivery Service
and the Queueing Service.</li>
      </ul>
      <t>TODO: Make use of MUST/SHOULD, etc. throughout.</t>
      <t>The delivery service can operate in one of two modes: "Full Metadata" mode and
"Reduced Metadata" mode.</t>
      <t>In Full Metadata mode, the protocol does not attempt to hide or avoid collecting
any of the client's metadata. In Reduced Metadata mode, the individual
operations leak as little metadata as possible to the DS.</t>
      <t>The protocol defined in this document allows for both modes through the use of
enums and optional fields. A DS running in one specific mode has to validate
that the protocol messages conform with that mode. For simplicity, the main part
of this document specifies only the parts relevant for the normal mode, with the
remaining parts specified in <xref target="reduced-metadata-operating-mode"/>.</t>
    </section>
    <section anchor="terminology">
      <name>Terminology</name>
      <t>This document uses the terminology defined in <xref target="I-D.ietf-mls-protocol"/> with
the following additions:</t>
      <ul spacing="normal">
        <li>DS Domain: Fully qualified domain name as defined in RFC 2181 that represents
the DS. This does not necessarily have to be the domain under which the DS is
reachable on the network. Discovering that domain is the responsibility of the
MIMI transport protocol over which the MIMI DS protocol runs.
TODO: User/client/identifiers definitions are preliminary.</li>
        <li>User: The operator of one or more clients, identified by its
user identifier.</li>
        <li>User identifier: An identifier that is unique in the scope of its DS and that
allows resolution to the providers DS domain.</li>
        <li>Client: An MLS client with a unique client identifier.</li>
        <li>Client identifier: An octet string that uniquely identifies the client. A
client identifier includes the identifier of its user or otherwise allows the
association betwen the client and its user.</li>
        <li>Connection: An agreement between two users, where each user authorizes the
other to send them messages and to add them to groups.</li>
        <li>Connection establishment: The process by which a connection between two users
is established. The process is manually initiated by one user and involves the
discovery of the other user. The other user must be able to authenticate the
initiator and manually authorize the response.</li>
        <li>Connection group: An MLS group consisting of the clients of two users. For
each pair of users, there can only be one connection group between them. A
connection group is created when one user requests a connection with another
user, followed by that user's consent.</li>
      </ul>
    </section>
    <section anchor="architecture-and-protocol-overview">
      <name>Architecture and protocol overview</name>
      <t>The MIMI DS protocol allows interoperability between an owning DS which hosts a
group conversation and one or more guest DSs which are home to one or more of
the conversation's group members. Underlying each group conversation is an MLS
group that facilitates end-to-end encryption and authentication between group
members.</t>
      <t>The main purpose of the MIMI DS protocol thus is to ensure that guest clients
can participate in the group. With MLS as the underlying protocol, this means
that the MIMI DS protocol is primiarliy concerned with the fan-out of MLS
messages (both from and to guest clients), as well the assistance of guest
clients in joining MLS groups.</t>
      <t>The MIMI DS protocol requires clients to send MLS messages as PublicMessages
(with the exception of messages with content type <tt>application</tt>). This allows
the owning DS to track the MLS group state in the same way as a client would,
enabling it to keep an up-to-date and fully authenticated list of members, as
well as provide the full MLS group state to joining group members, even for
those joining via external commit. In addition, the DS can verify messages and
enforce access control policies on group operations.</t>
      <section anchor="c2s">
        <name>Client to server and server to server protocol</name>
        <t>MLS being a protocol for end-to-end encryption, a subset of MIMI DS protocol
messages have to originate from the clients rather than the interoperating
delivery services.</t>
        <t>The MIMI DS protocol consists of two parts: A client-to-server part that allows
guest clients to interact with the owning DS of one of their groups and a
server-to-server protocol that allows an owning DS to fan out messages to guest
DSs, which can subsequently store and forward messages to their respective
clients.</t>
        <t>Note that the client-to-server part of the protocol can optionally be proxied
via the guest DS of the sending client.</t>
      </section>
      <section anchor="transport-for-the-mimi-ds-protocol">
        <name>Transport for the MIMI DS protocol</name>
        <t>The MIMI DS protocol requires a transport protocol that provides confidentiality
of messages and that allows the discovery of a DS based on the DS domain in a
user identifier.</t>
        <t>Both the client-to-server part, as well as the server-to-server part of the MIMI
DS protocol provide sender authentication, leaving recipient authentication as
provided, for example, by the HTTPS protocol to the transport layer.</t>
        <t>TODO: If the transport layer provides mutual authentication, at least the
server-to-server part of the MIMI DS protocol can be changed accordingly.</t>
        <t>In the event that a guest DS proxies the client-server part of the MIMI DS
protocol, the transport protocol can be used to facilitate additional
functionality relevant to server-to-server communication, such as e.g.
server-to-server authentication.</t>
      </section>
      <section anchor="flow">
        <name>Flow</name>
        <figure anchor="full-sending-flow">
          <name>Architecture overview</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="272" width="480" viewBox="0 0 480 272" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,32 L 8,112" fill="none" stroke="black"/>
                <path d="M 120,32 L 120,112" fill="none" stroke="black"/>
                <path d="M 240,32 L 240,112" fill="none" stroke="black"/>
                <path d="M 240,176 L 240,256" fill="none" stroke="black"/>
                <path d="M 264,112 L 264,168" fill="none" stroke="black"/>
                <path d="M 336,120 L 336,176" fill="none" stroke="black"/>
                <path d="M 360,32 L 360,112" fill="none" stroke="black"/>
                <path d="M 360,176 L 360,256" fill="none" stroke="black"/>
                <path d="M 8,32 L 120,32" fill="none" stroke="black"/>
                <path d="M 240,32 L 360,32" fill="none" stroke="black"/>
                <path d="M 120,48 L 232,48" fill="none" stroke="black"/>
                <path d="M 128,96 L 240,96" fill="none" stroke="black"/>
                <path d="M 8,112 L 120,112" fill="none" stroke="black"/>
                <path d="M 240,112 L 360,112" fill="none" stroke="black"/>
                <path d="M 240,176 L 360,176" fill="none" stroke="black"/>
                <path d="M 240,256 L 360,256" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="344,120 332,114.4 332,125.6" fill="black" transform="rotate(270,336,120)"/>
                <polygon class="arrowhead" points="272,168 260,162.4 260,173.6" fill="black" transform="rotate(90,264,168)"/>
                <polygon class="arrowhead" points="240,48 228,42.4 228,53.6" fill="black" transform="rotate(0,232,48)"/>
                <polygon class="arrowhead" points="136,96 124,90.4 124,101.6" fill="black" transform="rotate(180,128,96)"/>
                <g class="text">
                  <text x="168" y="36">DSRequest</text>
                  <text x="48" y="68">Sending</text>
                  <text x="276" y="68">Owning</text>
                  <text x="316" y="68">DS</text>
                  <text x="44" y="84">Client</text>
                  <text x="172" y="116">DSResponse</text>
                  <text x="192" y="148">DSFanoutRequest</text>
                  <text x="412" y="148">DSFanoutResponse</text>
                  <text x="272" y="212">Guest</text>
                  <text x="308" y="212">DS</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
+-------------+ DSRequest    +--------------+
|             +------------->+              |
| Sending     |              | Owning DS    |
| Client      |              |              |
|             +<-------------+              |
+-------------+ DSResponse   +--+--------+--+
                                |        ^
                DSFanoutRequest |        | DSFanoutResponse
                                v        |
                             +--+--------+--+
                             |              |
                             | Guest DS     |
                             |              |
                             |              |
                             +--------------+
]]></artwork>
          </artset>
        </figure>
        <figure anchor="proxied-sending-flow">
          <name>Alternative with a guest DS as proxy</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="416" width="480" viewBox="0 0 480 416" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,32 L 8,112" fill="none" stroke="black"/>
                <path d="M 120,32 L 120,112" fill="none" stroke="black"/>
                <path d="M 240,32 L 240,112" fill="none" stroke="black"/>
                <path d="M 240,176 L 240,256" fill="none" stroke="black"/>
                <path d="M 240,320 L 240,400" fill="none" stroke="black"/>
                <path d="M 264,112 L 264,168" fill="none" stroke="black"/>
                <path d="M 264,256 L 264,312" fill="none" stroke="black"/>
                <path d="M 336,120 L 336,176" fill="none" stroke="black"/>
                <path d="M 336,264 L 336,320" fill="none" stroke="black"/>
                <path d="M 360,32 L 360,112" fill="none" stroke="black"/>
                <path d="M 360,176 L 360,256" fill="none" stroke="black"/>
                <path d="M 360,320 L 360,400" fill="none" stroke="black"/>
                <path d="M 8,32 L 120,32" fill="none" stroke="black"/>
                <path d="M 240,32 L 360,32" fill="none" stroke="black"/>
                <path d="M 120,48 L 232,48" fill="none" stroke="black"/>
                <path d="M 128,96 L 240,96" fill="none" stroke="black"/>
                <path d="M 8,112 L 120,112" fill="none" stroke="black"/>
                <path d="M 240,112 L 360,112" fill="none" stroke="black"/>
                <path d="M 240,176 L 360,176" fill="none" stroke="black"/>
                <path d="M 240,256 L 360,256" fill="none" stroke="black"/>
                <path d="M 240,320 L 360,320" fill="none" stroke="black"/>
                <path d="M 240,400 L 360,400" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="344,264 332,258.4 332,269.6" fill="black" transform="rotate(270,336,264)"/>
                <polygon class="arrowhead" points="344,120 332,114.4 332,125.6" fill="black" transform="rotate(270,336,120)"/>
                <polygon class="arrowhead" points="272,312 260,306.4 260,317.6" fill="black" transform="rotate(90,264,312)"/>
                <polygon class="arrowhead" points="272,168 260,162.4 260,173.6" fill="black" transform="rotate(90,264,168)"/>
                <polygon class="arrowhead" points="240,48 228,42.4 228,53.6" fill="black" transform="rotate(0,232,48)"/>
                <polygon class="arrowhead" points="136,96 124,90.4 124,101.6" fill="black" transform="rotate(180,128,96)"/>
                <g class="text">
                  <text x="48" y="68">Sending</text>
                  <text x="180" y="68">(proprietary</text>
                  <text x="272" y="68">Guest</text>
                  <text x="308" y="68">DS</text>
                  <text x="44" y="84">Client</text>
                  <text x="184" y="84">protocol)</text>
                  <text x="280" y="84">(proxy)</text>
                  <text x="216" y="148">DSRequest</text>
                  <text x="388" y="148">DSResponse</text>
                  <text x="276" y="212">Owning</text>
                  <text x="316" y="212">DS</text>
                  <text x="192" y="292">DSFanoutRequest</text>
                  <text x="412" y="292">DSFanoutResponse</text>
                  <text x="272" y="356">Guest</text>
                  <text x="308" y="356">DS</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
+-------------+              +--------------+
|             +------------->+              |
| Sending     | (proprietary | Guest DS     |
| Client      |   protocol)  | (proxy)      |
|             +<-------------+              |
+-------------+              +--+--------+--+
                                |        ^
                      DSRequest |        | DSResponse
                                v        |
                             +--+--------+--+
                             |              |
                             | Owning DS    |
                             |              |
                             |              |
                             +--+--------+--+
                                |        ^
                DSFanoutRequest |        | DSFanoutResponse
                                v        |
                             +--+--------+--+
                             |              |
                             | Guest DS     |
                             |              |
                             |              |
                             +--------------+
]]></artwork>
          </artset>
        </figure>
        <t><xref target="full-sending-flow"/> and <xref target="proxied-sending-flow"/> show example protocol flows,
where a client sends a request to the owning DS, followed by the owning DS
fanning out a message to a guest DS. In <xref target="proxied-sending-flow"/>, the request
sent by the client is proxied by the guest DS of that client.</t>
        <t>For the remainder of this document, we assume that clients send requests
directly to the owning DS. Proxying the requests over the client's own DS can
always be done and does not change the functionality.</t>
        <t>Both the message sending and the fanout parts of the protocol are designed in a
request/response pattern. In the first protocol part, the client sends a
DSRequest message to the Delivery Service and the Delivery Service responds with
a DSResponse message. This pattern can easily be used over e.g. RESTful APIs.</t>
        <figure>
          <name>Delivery Service Request/Response scheme</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="160" width="328" viewBox="0 0 328 160" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,144" fill="none" stroke="black"/>
                <path d="M 144,48 L 144,144" fill="none" stroke="black"/>
                <path d="M 8,80 L 136,80" fill="none" stroke="black"/>
                <path d="M 16,128 L 144,128" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="144,80 132,74.4 132,85.6" fill="black" transform="rotate(0,136,80)"/>
                <polygon class="arrowhead" points="24,128 12,122.4 12,133.6" fill="black" transform="rotate(180,16,128)"/>
                <g class="text">
                  <text x="28" y="36">Client</text>
                  <text x="164" y="36">Owning</text>
                  <text x="228" y="36">Delivery</text>
                  <text x="296" y="36">Service</text>
                  <text x="56" y="68">DSRequest</text>
                  <text x="60" y="116">DSResponse</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
Client           Owning Delivery Service
|                |
| DSRequest      |
+--------------->|
|                |
| DSResponse     |
|<---------------+
|                |
]]></artwork>
          </artset>
        </figure>
        <t>For the second part of the protocol the Delivery Service sends a DSFanoutRequest
to each guest DS. This happens whenever a message needs to be fanned out to all
other members of a group as a result of an incoming DSRequest. The guest DS in
turn responds with a DSFanoutResponse.</t>
        <figure>
          <name>Client/Delivery Service communication with fanout</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="592" viewBox="0 0 592 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,224" fill="none" stroke="black"/>
                <path d="M 144,48 L 144,224" fill="none" stroke="black"/>
                <path d="M 416,48 L 416,224" fill="none" stroke="black"/>
                <path d="M 8,80 L 136,80" fill="none" stroke="black"/>
                <path d="M 16,128 L 144,128" fill="none" stroke="black"/>
                <path d="M 144,160 L 408,160" fill="none" stroke="black"/>
                <path d="M 152,208 L 416,208" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="416,160 404,154.4 404,165.6" fill="black" transform="rotate(0,408,160)"/>
                <polygon class="arrowhead" points="160,208 148,202.4 148,213.6" fill="black" transform="rotate(180,152,208)"/>
                <polygon class="arrowhead" points="144,80 132,74.4 132,85.6" fill="black" transform="rotate(0,136,80)"/>
                <polygon class="arrowhead" points="24,128 12,122.4 12,133.6" fill="black" transform="rotate(180,16,128)"/>
                <g class="text">
                  <text x="28" y="36">Client</text>
                  <text x="164" y="36">Owning</text>
                  <text x="228" y="36">Delivery</text>
                  <text x="296" y="36">Service</text>
                  <text x="432" y="36">Guest</text>
                  <text x="492" y="36">Delivery</text>
                  <text x="560" y="36">Service</text>
                  <text x="56" y="68">DSRequest</text>
                  <text x="60" y="116">DSResponse</text>
                  <text x="216" y="148">DsFanoutRequest</text>
                  <text x="220" y="196">DsFanoutResponse</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
Client           Owning Delivery Service           Guest Delivery Service
|                |                                 |
| DSRequest      |                                 |
+--------------->|                                 |
|                |                                 |
| DSResponse     |                                 |
|<---------------+                                 |
|                | DsFanoutRequest                 |
|                +-------------------------------->|
|                |                                 |
|                | DsFanoutResponse                |
|                |<--------------------------------+
|                |                                 |
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="supported-operations">
        <name>Supported operations</name>
        <t>The MIMI DS protocol allows guest clients to request a variety of operations for
example to manage group membership, join groups, or send messages.</t>
        <ul spacing="normal">
          <li>Group creation/deletion</li>
          <li>Join a group from a Welcome message as a new member</li>
          <li>Join a group through an External Commit message as a new member
or client of an existing member (e.g. Resync a client after state loss)</li>
          <li>Adding and removing users to/from a group</li>
          <li>Adding and removing clients to/from a member of the group</li>
          <li>Client updates (MLS leaf updates)</li>
          <li>Sending application messages</li>
          <li>Download of KeyPackages</li>
          <li>Enqueueing of a message fanned out from an owning DS</li>
          <li>Discovery of users and their clients</li>
          <li>Download of connection-specific KeyPackages</li>
        </ul>
      </section>
      <section anchor="client-removals-induced-by-the-delivery-service">
        <name>Client removals induced by the Delivery Service</name>
        <t>Independent of client requests, the Delivery Service itself can remove clients
from a group by issuing remove proposals in the following cases:</t>
        <ul spacing="normal">
          <li>A user has removed a client from its account</li>
          <li>A user has been deleted</li>
          <li>The client is removed from the group because it has been inactive for too
long</li>
        </ul>
      </section>
      <section anchor="serialization-format">
        <name>Serialization format</name>
        <t>MLS messages use the presentation language and encoding format defined in
<xref target="RFC8446"/> with the extensions defined in the MLS protocol specification. The
MIMI DS protocol uses the same serialization format, as both clients and DS
already have to support it to process MLS messages.</t>
        <t>Octet strings resulting from serialization in this format are unambiguous and
require no further canonicalization.</t>
      </section>
      <section anchor="keypackages">
        <name>KeyPackages</name>
        <t>Clients have to upload KeyPackages such that others can add them to groups. In
the context of interoperability, this means that clients have to be able to
download KeyPackages of clients belonging to other DSs.</t>
        <t>The MIMI DS protocol allows clients to download the KeyPackages of other
clients. Uploading KeyPackages is outside of the scope of this protocol, as it
is not relevant for interoperability.</t>
        <t>TODO: KeyPackages of last resort should be marked. Ideally by using a KeyPackage
extension.</t>
        <section anchor="connection-keypackages">
          <name>Connection KeyPackages</name>
          <t>In addition to regular KeyPackages, the MIMI DS protocol requires clients to
provide connection KeyPackages for other clients to download. Connection
KeyPackages are meant for use in the connection establishment process (explained
in more detail in <xref target="connection-establishment-flow"/>) and differ from regular
KeyPackages only in that they include a LeafNode extension marking them as such.</t>
          <t>TODO: Such an extension would have to be specified in the context of the MLS WG.</t>
        </section>
      </section>
      <section anchor="clients-and-users">
        <name>Clients and users</name>
        <t>TODO: This section needs to be revisited once identifiers and client/user
authentication in general have been decided on by the MIMI WG.</t>
        <t>Secure messaging applications typically have a notion of users, where each user
has one or more clients. As MLS does not have a native notion of users, it has
to be provided by the MIMI DS protocol.</t>
        <t>For the Full Metadata mode, the MIMI DS protocol only requires that the user
identifier can be derived from the client identifier. Authentication of a client
is then assumed to imply authentication of the user.</t>
        <t>In the Reduced Metadata mode, the DS does not see real client or user
identifiers, but instead has to work with pseudonyms. Here, the DS introduces
its own notion of users. For more information see
<xref target="reduced-metadata-operating-mode"/>.</t>
      </section>
      <section anchor="version-agility">
        <name>Version agility</name>
        <t>MLS provides version, ciphersuite and extension agility. The versions,
ciphersuites and extensions a client supports are advertised in its LeafNodes,
both in all of the client's groups, as well as in its KeyPackages through the
Capabilities field (Section 7.2 of <xref target="I-D.ietf-mls-protocol"/>).</t>
        <t>MLS DS protocol clients MUST make use of a LeafNode extension to advertise the
MIMI DS protocol versions they support.</t>
        <t>TODO: Such an extension would have to be specified in the context of the MLS WG.</t>
      </section>
      <section anchor="group-lifecycle">
        <name>Group lifecycle</name>
        <t>Upon creation MLS groups are parameterized by a GroupID, an MLS version number,
as well as a ciphersuite. All three parameters are fixed and cannot be changed
throughout the lifetime of a group.</t>
        <t>Groups capable of interoperability with the MIMI DS protocol MUST use a
GroupContext extension that indicates the MIMI DS protocol version with which it
was created. This extension MUST NOT be changed throughout the lifetime of the
group.</t>
        <t>While all these parameters cannot be changed throughout a group's lifetime, the
group can be re-initialized as described in Section 11.2. of
<xref target="I-D.ietf-mls-protocol"/> to create a new group with a new set of parameters.</t>
        <t>The MIMI DS protocol supports re-initializations of groups using the
corresponding ReInitialization operation under the condition that all MLS
parameters are compatible with the MIMI DS protocol version.</t>
        <t>If a group is no longer used, it can be deleted either by a client or the DS
itself.</t>
        <t>TODO: Each MIMI DS protocol version should probably fix a set of ciphersuites,
MLS protocol versions and maybe even extensions it supports. New ones can be
added with protocol version upgrades.</t>
      </section>
      <section anchor="framing-and-processing-overview">
        <name>Framing and processing overview</name>
        <section anchor="client-to-server-requests">
          <name>Client to server requests</name>
          <t>All client to server requests consist of a MIMI DS specific protocol wrapper
called DSRequst. DSRequest contains the MIMI DS protocol version, a body with
operation-specific data, as well as authentication information.</t>
          <artwork><![CDATA[
enum {
  ds_request_group_id(0),
  ds_create_group(1),
  ds_delete_group(2),
  ...
} DSRequestType;

struct {
  DSRequestType request_type;
  select (DSRequestBody.request_type) {
    case ds_delete_group:
      DeleteGroupRequest delete_group_request;
    ...
  }
} DSRequestBody;

struct {
  DSProtocolVersion version;
  DSRequestBody request_body;
  DSAuthData authentication_data;
} DSRequest;
]]></artwork>
          <t>A DS supports a variety of operations. For presentational reasons, we only
define DSRequestType and the corresponding <tt>case</tt> statement in DSRequestBody
partially here. A more complete definition with all operations relevant for the
normal DS operating mode can be found in <xref target="operations"/>, while the full
definition including the operations relevant for the Reduced Metadata
operating mode and can be found in <xref target="reduced-metadata-operating-mode"/>.</t>
          <t>The <tt>authentication_data</tt> field of a DSRequest depends on the request type and
contains the data necessary for the DS to authenticate the request.</t>
          <artwork><![CDATA[
enum {
  Anonymous,
  ClientSignature,
  ...
} DSAuthType;

struct {
  DSAuthType auth_type;
  select (DSAuthData.auth_type) {
    case Anonymous:
      struct {};
    case ClientSignature:
      uint32 sender_index;
      opaque signature<0..255>;
    ...
  }
} DSAuthData;
]]></artwork>
          <t>For the normal DS operating mode, Anonymous and ClientSignature are the only
relevant authentication types. The complete specification of DSAuthType and
DSAuthBody can be found in <xref target="reduced-metadata-operating-mode"/>.</t>
          <t>Before the DS performs the requested operation, it performs an authentication
operation depending on the DSAuthType.</t>
          <ul spacing="normal">
            <li>Anonymous: No authentication required</li>
            <li>ClientSignature: The DS uses the public signature key of the MLS client in
leaf with the leaf index <tt>sender_index</tt> to verify the signature over the
following struct:</li>
          </ul>
          <artwork><![CDATA[
struct {
  DSProtocolVersion protocol_version;
  DSRequestBody request_body;
  u32 sender_index
} ClientSignatureTBS
]]></artwork>
          <t>Note that all group operations additionally contain an MLSMessage the content
of which mirrors the request type, e.g., an AddUsers request wraps an MLS commit
that in turn contains the Add proposals for the users' clients. In that case,
the DS uses the GroupID inside the MLSMessage to determine which group the
request refers to and verifies the MLSMessage in the same way an MLS client
would (including the signature).</t>
          <t>Depending on the nature of the request, clients can also include data in the AAD
field of the MLSMessage, where it can be read and authenticated by both DS and
all other group members.</t>
          <t>After performing the desired operation using the data in DSRequestBody the DS
responds to the client (or the proxying guest DS) with a DSResponse.</t>
          <artwork><![CDATA[
struct {
  DSProtocolVersion protocol_version;
  DSResponseBody response_body;
} DSResponse

enum DSResponseType {
  Ok,
  Error,
  GroupID,
  WelcomeInfo,
  ExternalCommitInfo
  SignaturePublicKey,
  KeyPackages,
  ConnectionKeyPackages,
}

struct DSResponseBody {
  DSResponseType response_type;
  select (DSResponseBody.response_type) {
    case Ok:
      struct {};
    case Error:
      DSError error;
    case GroupID:
      opaque group_id<V>;
    case WelcomeInfo:
      optional<Node> ratchet_tree<V>;
    case ExternalCommit:
      MLSMessage: group_info;
      optional<Node> ratchet_tree<V>;
    case SignaturePublicKey:
      SignaturePublicKey signature_public_key;
    case KeyPackages:
      AddPackage add_packages<V>;
    case ConnectionKeyPackages:
      AddPackage add_packages<V>;
  }
}

struct {
  TODO: Operation specific errors.
} DSError
]]></artwork>
        </section>
        <section anchor="server-to-server-requests">
          <name>Server to server requests</name>
          <t>After sending the response, and depending on the operation the DS might fan out
messages to one or more guest DSs.</t>
          <t>To that end, it wraps the MLSMessage to be fanned out into a DSFanoutRequest.
In addition to the MLSMessage, the DSFanoutRequest contains the protocol
version, the FQDN of the sending DS and the identifiers of all clients on DS
that the message is meant to be fanned out to.</t>
          <t>If the message needs to be fanned out to more than one guest DS, the DS prepares
different messages for each destination DS with each message containing only the
DSFanoutRecipients of that DS.</t>
          <artwork><![CDATA[
enum {
  ClientIdentifier,
  ...
} DSFanoutRecipientType;

struct {
  DSRecipientType recipient_type;
  select (DSRecipient.recipient_type) {
    case ClientIdentifier:
      opaque client_id<0..255>;
    ...
  }
} DSFanoutRecipient;

struct {
  DSProtocolVersion protocol_version;
  FQDN sender;
  DSFanoutRecipient recipients<V>;
  MLSMessage mls_message;
  // Signature over the above fields
  opaque signature<0..255>;
} DSFanoutRequest

]]></artwork>
          <t>The DS receiving a DSFanoutRequest can then store and forward the contained MLS
message to the clients indicated in the <tt>recipients</tt> field.</t>
          <t>For presentational reasons, we only define DSRecipientType and the corresponding
<tt>case</tt> statement in DSRecipient partially here. The rest of the definition is
relevant only for the Reduced Metadata operating mode and can be found in
<xref target="reduced-metadata-operating-mode"/>.</t>
          <t>The receiving DS verifies the signature using the sending DS' public signature
key, process the message and sends a DSFanoutResponse.</t>
          <artwork><![CDATA[
enum {
  Ok,
  Error,
} DSFanoutResponseType

struct {
  TODO: Fanout error types
} DSFanoutError

struct DSFanoutResponseBody {
  DSFanoutResponseType response_type;
  select (DSFanoutResponseBody.response_type) {
    case Ok:
      struct {};
    case Error:
      DSFanoutError error;
  }
}

struct {
  DSProtocolVersion protocol_version;
  DSResponseBody response_body;
} DSFanoutResponse
]]></artwork>
        </section>
        <section anchor="addpackages">
          <name>AddPackages</name>
          <t>As noted in <xref target="keypackages"/>, clients must upload KeyPackages such that other
clients can add them to groups. For the Full Metadata operating mode, a regular
KeyPackage is sufficient. However, as the Reduced Metadata mode requires
additional data, the DS stores AddPackages instead for clients to download.</t>
          <artwork><![CDATA[
struct {
  KeyPackage key_package;
  optional<RMAddPackageData> rm_data;
} AddPackage
]]></artwork>
          <t>AddPackages are also used to wrap connection KeyPackages. An AddPackage that
contains a connection KeyPackages is also called a connection AddPackage.</t>
        </section>
      </section>
      <section anchor="connection-establishment-flow">
        <name>Connection establishment flow</name>
        <t>A user can establish a connection to another user by creating a connection
group, fetching connection AddPackage of the target user's clients from its DS
and inviting that user to the connection group. The receiving user can process
the Welcome and figure out from the group state who the sender is. Additional
information can either be attached to the group via an extension, or via MLS
application messages within that group.</t>
        <t>TODO: This is a sketch for a simple connection establishment flow that allows
the recipient to identify and authenticate the sender and that establishes an
initial communication channel between the two users. More functionality can be
added via additional messages or MLS extensions.</t>
        <figure>
          <name>Example flow for connection establishment</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="632" viewBox="0 0 632 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,48 L 8,304" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,88" fill="none" stroke="black"/>
                <path d="M 240,104 L 240,136" fill="none" stroke="black"/>
                <path d="M 240,152 L 240,304" fill="none" stroke="black"/>
                <path d="M 448,48 L 448,304" fill="none" stroke="black"/>
                <path d="M 608,48 L 608,304" fill="none" stroke="black"/>
                <path d="M 8,96 L 440,96" fill="none" stroke="black"/>
                <path d="M 16,144 L 448,144" fill="none" stroke="black"/>
                <path d="M 8,192 L 232,192" fill="none" stroke="black"/>
                <path d="M 8,240 L 232,240" fill="none" stroke="black"/>
                <path d="M 240,256 L 440,256" fill="none" stroke="black"/>
                <path d="M 448,272 L 600,272" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="608,272 596,266.4 596,277.6" fill="black" transform="rotate(0,600,272)"/>
                <polygon class="arrowhead" points="448,256 436,250.4 436,261.6" fill="black" transform="rotate(0,440,256)"/>
                <polygon class="arrowhead" points="448,96 436,90.4 436,101.6" fill="black" transform="rotate(0,440,96)"/>
                <polygon class="arrowhead" points="240,240 228,234.4 228,245.6" fill="black" transform="rotate(0,232,240)"/>
                <polygon class="arrowhead" points="240,192 228,186.4 228,197.6" fill="black" transform="rotate(0,232,192)"/>
                <polygon class="arrowhead" points="24,144 12,138.4 12,149.6" fill="black" transform="rotate(180,16,144)"/>
                <g class="text">
                  <text x="24" y="36">Alice</text>
                  <text x="260" y="36">Owning</text>
                  <text x="300" y="36">DS</text>
                  <text x="464" y="36">Guest</text>
                  <text x="500" y="36">DS</text>
                  <text x="616" y="36">Bob</text>
                  <text x="48" y="68">Request</text>
                  <text x="124" y="68">Connection</text>
                  <text x="64" y="84">AddPackages</text>
                  <text x="60" y="132">Connection</text>
                  <text x="152" y="132">AddPackages</text>
                  <text x="44" y="180">Create</text>
                  <text x="116" y="180">Connection</text>
                  <text x="184" y="180">group</text>
                  <text x="32" y="228">Add</text>
                  <text x="88" y="228">Responder</text>
                  <text x="488" y="228">Deliver</text>
                  <text x="552" y="228">Welcome</text>
                  <text x="264" y="244">Fan</text>
                  <text x="296" y="244">out</text>
                  <text x="344" y="244">Welcome</text>
                  <text x="508" y="244">(proprietary</text>
                  <text x="504" y="260">protocol)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
Alice                        Owning DS                 Guest DS            Bob
+                            +                         +                   +
| Request Connection         |                         |                   |
| AddPackages                |                         |                   |
+----------------------------------------------------->+                   |
|                            |                         |                   |
| Connection AddPackages     |                         |                   |
+<-----------------------------------------------------+                   |
|                            |                         |                   |
| Create Connection group    |                         |                   |
+--------------------------->+                         |                   |
|                            |                         |                   |
| Add Responder              |                         | Deliver Welcome   |
+--------------------------->+ Fan out Welcome         | (proprietary      |
|                            +------------------------>+  protocol)        |
|                            |                         +------------------>+
|                            |                         |                   |
+                            +                         +                   +

]]></artwork>
          </artset>
        </figure>
      </section>
    </section>
    <section anchor="ds-assisted-joining">
      <name>DS assisted joining</name>
      <t>To verify and deliver messages, authenticate clients as members of a group and
to assist clients that want to join a group, the DS keeps track of the state of
each group it owns. More specifically, it keeps track of the group's ratchet
tree, the group's GroupContext and other information required to produce a valid
GroupInfo for the current group epoch. It does this by processing incoming MLS
messages in the same way a member of that group would, except of course that the
DS doesn't hold any private key material.</t>
      <t>While MLS messages are sufficient to keep track of most of the group information,
it is not quite enough to create a GroupInfo. To allow the DS to provide a valid
GroupInfo to externally joining clients, it additionally requires clients to
provide the remaining required information. Concretely, it requires clients to
upload the Signature and the GroupInfo extensions. Clients need to send this
information whenever they send an MLS message (i.e. an MLSMessage struct) that
contains a commit.</t>
      <artwork><![CDATA[
struct {
  Extension group_info_extensions<V>;
  opaque Signature<V>;
} PartialGroupInfo
]]></artwork>
      <t>The combination of a commit and a partial group info is called an
MLSGroupUpdate.</t>
      <artwork><![CDATA[
struct {
  MLSMessage commit;
  PartialGroupInfo partial_group_info;
} MLSGroupUpdate
]]></artwork>
      <t>Whenever the DS receives an MLSGroupUpdate, it must verify that the
MLSMessage contains a PublicMessage with a commit and that commit and partial
group info are valid relative to the existing group state according to the MLS
specification.</t>
      <t>TODO: For now there is no distinct endpoint to obtain authentication material
that allows the DS to authenticate clients. This would be part of the AS design.</t>
      <t>By tracking the group information in this way, the DS can help clients that join
via external commit by providing them with a ratchet tree and a group into.</t>
      <t>Similary, clients that wish to join a group via a regular invite (i.e. a Welcome
message) have already received a GroupInfo and can obtain a ratchet tree from
the DS.</t>
      <t>In the time between a client being added to a group by a commit and the client
wanting to join the group, the group state can have progressed by one or more
epochs. As a consequence, the DS MUST keep track of epochs in which clients are
added and store the corresponding group states until each client has
successfully joined.</t>
    </section>
    <section anchor="proposals-by-reference">
      <name>Handling of standalone MLS Proposals</name>
      <t>MLS relies on a proposal-commit logic, where the proposals encode the specific
action the sending client intends to take and the commit then performs the
actions of a set of commits.</t>
      <t>The advantage of this approach is that the sender of the proposal does not have
to be the committer, which allows, for example, the DS to propose the removal of
a client, or a client to propose that it be removed from the group. Note that
the latter example is the only way that a client can remove itself from a group.</t>
      <t>In MLS proposals can be committed "by reference" (if the proposal was sent
separately before the commit), or "by value" if the proposal is sent as part of
the commit itself.</t>
      <t>In all operations specified in the follow sections, the proposals in the commit
that is included in the DSRequest MUST match the semantics of the operation and
all of those proposals MUST be committed by reference. For example, the commit
in the AddUsersRequest MUST only contain Add proposals.</t>
      <t>However, in addition, each commit MAY also include an arbitrary number of valid
proposal that were sent previously in the same epoch, such as server-initiated
Remove proposals, or proposals sent as part of a self-remove operation.</t>
      <t>Such an additional proposal MUST be committed by reference.</t>
      <t>To allow the DS to send proposals, all groups MUST contain an <tt>external_senders</tt>
extension as defined in Section 12.1.8.1. of <xref target="I-D.ietf-mls-protocol"/> that
includes the DS' credential and its signature public key.</t>
      <t>TODO: Details of the DS credential. A BasicCredential with the FQDN of the DS
would probably be sufficient.</t>
      <t>TODO: Proposals by reference pose a problem in the context of external commits,
as, even if the external committer had access to all proposals in an epoch, it
wouldn't be able to verify them, thus potentially leading to an invalid external
commit. A solution could be introduced either as part of the MIMI DS protocol,
or as an MLS extension. The latter would be preferable, as other users of MLS
are likely going to encounter the same problem.</t>
    </section>
    <section anchor="operations">
      <name>Operations</name>
      <t>The DS supports a number of operations, each of which is represented by a
variant of the DSRequestType enum and has its own request body.</t>
      <artwork><![CDATA[
enum {
  ds_request_group_id(0),
  ds_create_group(1),
  ds_delete_group(2),
  ds_add_users(3),
  ds_remove_users(4),
  ds_add_clients(5),
  ds_remove_clients(6),
  ds_self_remove_client(7),
  ds_update_client(8),
  ds_external_join(9),
  ds_send_message(10),
  ds_signature_public_key(11),
  ds_add_packages(12),
  ds_connection_add_packages(13),
  ds_re_initialize_group(14),
  ...
} DSRequestType;

struct {
  DSRequestType request_type;
  select (DSRequestBody.request_type) {
    case ds_request_group_id:
      struct {};
    case ds_create_group:
      CreateGroupRequest create_group_request;
    case ds_delete_group:
      DeleteGroupRequest delete_group_request;
    case ds_add_users:
      AddUsersRequest add_users_request;
    case ds_remove_users:
      RemoveUsersRequest remove_users_request;
    case ds_add_clients:
      AddClientsRequest add_clients_request;
    case ds_remove_clients:
      RemoveClientsRequest remove_clients_request;
    case ds_self_remove_clients:
      SelfRemoveClientsRequest self_remove_clients_request;
    case ds_update_client:
      UpdateClientRequest update_client_request;
    case ds_external_join:
      ExternalJoinRequest external_join_request;
    case ds_send_message:
      SendMessageRequest send_message_request;
    case ds_signature_public_key:
      struct {};
    case ds_add_packages:
      AddPackagesRequest add_packages_request;
    case ds_connection_add_packages:
      ConnectionAddPackagesRequest connection_add_packages_request;
    case ds_re_initialize_group:
      ReInitializeGroupRequest re_initialize_group_request;
    ...
  }
  optional<RMGroupStateEARKey> rn_data<0..255>;
} DSRequestBody;
]]></artwork>
      <t>A number of these operations require either slightly different or additional
parameters in the privacy preserving operational mode. If the parameter is
different, it will be defined as an enum with one variant for each mode. If
additional parameters are required, a field with an optional type is included
that contains a type prefixed with "RM" to indicate that it is relevant only for
the privacy preserving mode.</t>
      <t>Additional variants specific to the privacy preserving mode, as well as the
corresponding rest of the <tt>case</tt> statement can be found in
<xref target="reduced-metadata-operating-mode"/>.</t>
      <section anchor="request-group-id">
        <name>Request group id</name>
        <t>Clients can use this operation to request a group id. This group ID can
subsequently used to create a group on this DS.</t>
        <t>After receiving this request, the DS generates a unique group id and responds
with a DSResponse struct of type GroupID.</t>
      </section>
      <section anchor="create-group">
        <name>Create group</name>
        <t>A request from the client to create a new group on the Delivery Service. This
operation can be used both for the creation of regular groups and for the
creation of connection groups.</t>
        <t>The client sends the following CreateGroupRequest to the Delivery Service:</t>
        <artwork><![CDATA[
struct {
  opaque group_id<V>;
  LeafNode LeafNode;
  MLSMessage group_info;
  optional<RMCreateGroupData>
} CreateGroupRequest;
]]></artwork>
        <t>The Delivery Service internally creates and stores the group based on the
information in the request and responds with a CreateGroupResponse:</t>
        <artwork><![CDATA[
enum {
  invalid_group_id(0),
  invalid_leaf_node(1),
  invalid_group_info(2),
} CreateGroupResponse;
]]></artwork>
        <t>TODO: How to mark connection groups? Have the creator include a connection
extension in the LeafNode?</t>
        <t><strong>Validation:</strong></t>
        <t>The Delivery Service validates the request as follows:</t>
        <ul spacing="normal">
          <li>The group ID is not empty and is not already in use.</li>
          <li>The LeafNode is valid, according to <xref target="I-D.ietf-mls-protocol"/> 7.3. Leaf Node
validation.</li>
          <li>The GroupInfo is valid, according to <xref target="I-D.ietf-mls-protocol"/> 12.4.3. Adding
Members to the Group.</li>
        </ul>
      </section>
      <section anchor="delete-group">
        <name>Delete group</name>
        <t>A request from the client to delete a group from the Delivery Service. This
operation allows clients to delete a group from the DS. Clients can of course
keep a copy of the group state locally for archival purposes.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
} DeleteGroupRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <t>The Delivery Service validates the request as follows:</t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage with a commit that contains
remove proposals for every member of the group except the committer.</li>
        </ul>
      </section>
      <section anchor="add-users-to-a-group">
        <name>Add users to a group</name>
        <t>A request from a client to add one or more users to a group. For each user, one
or more of the user's clients are added to the group. The Welcome messages in
the request are then fanned out to the user's DSs.</t>
        <t>To obtain the AddPackages required to add the users' clients, the sender must
first fetch the clients' AddPackages from their DS.</t>
        <artwork><![CDATA[
struct {
  MLSMessage welcome;
  optional<RMWelcomeData> rm_data;
} WelcomePackage

struct {
  MLSGroupUpdate group_update;
  WelcomePackage welcome_packages<V>;
  optional<RMAddClientsData> rm_data;
} AddUsersRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate in the <tt>commit</tt> field must contain a PublicMessage with a
commit that contains only Add proposals.</li>
          <li>The commit MUST NOT change the sender's client credential.</li>
          <li>Add proposals must not contain clients of existing group members.</li>
          <li>Add proposals must not contain connection AddPackages, except if the group is
a connection group.</li>
          <li>If guest users are added as part of the request, there has to be a distinct
Welcome message for each guest DS involved.</li>
        </ul>
      </section>
      <section anchor="remove-users-from-a-group">
        <name>Remove users from a group</name>
        <t>A request from a client to remove one or more users from a group. The DS will
still fan out the request to the users. The commit contained in the message will
allow the users to recognize that they were removed.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
} RemoveUsersRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage with a commit that contains only
remove proposals.</li>
          <li>The commit MUST NOT change the sender's client credential.</li>
          <li>The remove proposals in the commit MUST always remove all clients of one or
more users.</li>
        </ul>
      </section>
      <section anchor="add-clients-to-a-group">
        <name>Add clients to a group</name>
        <t>A request from a client to add one or more clients of the same user. This
operation allows users to add new clients to an existing group. Alternatively,
new clients can add themselves by joining via external commit.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
  WelcomePackage welcome_packages<V>;
  optional<RMAddClientsData> rm_data;
} AddClientsRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage with a commit that contains only
add proposals.</li>
          <li>The commit MUST NOT change the sender's client credential.</li>
          <li>All Add proposals must contain clients of the same user as an existing group
member.</li>
        </ul>
      </section>
      <section anchor="remove-clients-from-a-group">
        <name>Remove clients from a group</name>
        <t>A request from a client to remove one or more other clients of the same user
from a group. This operation allows users to remove their own clients from a
group. Note that this operation cannot be used by a client to remove itself from
the group. For that purpose, the SelfRemoveClientRequest should be used instead.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
} RemoveClientsRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage with a commit that contains only
remove proposals.</li>
          <li>The commit MUST NOT change the sender's client credential.</li>
          <li>All remove proposals must target clients of the same user as the sending
client.</li>
        </ul>
      </section>
      <section anchor="self-remove-a-client-from-a-group">
        <name>Self remove a client from a group</name>
        <t>A request from a client to remove itself from the group. If it's the last client
of a user, this effectively removes the user from the group. Note that this
request only contains a proposal, so the client is not effectively removed from
the group until another group member commits that proposal. See
<xref target="proposals-by-reference"/> for more details.</t>
        <artwork><![CDATA[
struct {
  MLSMessage proposal;
} SelfRemoveClientRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSMessage must contain a PublicMessage that contains a single
remove proposal.</li>
          <li>The remove proposal must target the sending client.</li>
        </ul>
      </section>
      <section anchor="update-a-client-in-a-group">
        <name>Update a client in a group</name>
        <t>A request from a client to update its own leaf in an MLS group. This operation
can be used to update any information in the sender's leaf node. For example,
the sender could use this operation to update its key material to achieve
post-compromise security, update its Capabilities extension, or its leaf
credential.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
  optional<RMUpdateClientData> rm_data;
} UpdateClientRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage that contains a commit with an
UpdatePath, but without other proposals.</li>
          <li>If the leaf credential is changed by the update, the DS must validate the new
credential.</li>
        </ul>
        <t>TODO: The discussion around identity and credentials should yield a method to
judge if a new credential is a valid update to an existing one.</t>
      </section>
      <section anchor="join-the-group-using-an-external-commit">
        <name>Join the group using an external commit</name>
        <t>A request from a client to join a group using an external commit, i.e. without
the help of an existing group member. This operation can be used, for example,
by new clients of a user that already has clients in the group, or by existing
group members that have to recover from state loss.</t>
        <t>To retrieve the information necessary to create the external commit, the joiner
has to fetch the external commit information from the DS.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
  optional<RMExternalJoinData> rm_data;
} ExternalJoinRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage that contains a commit with sender
type NewMemberCommit.</li>
          <li>The sender of the ExternalJoinRequest must be a client that belongs to a user
that is already in the group.</li>
        </ul>
      </section>
      <section anchor="send-an-application-message-to-a-group">
        <name>Send an application message to a group</name>
        <t>A request from a client to fan out an application message to a group. This
operation is meant to send arbitrary data to the rest of the group. Since the
application message is a PrivateMessage, the DS can not verify its content or
authenticate its sender (even though it does authenticate the sender of the
surrounding DSRequest).</t>
        <artwork><![CDATA[
struct {
  MLSMessage application_message;
} SendMessageRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSMessage must contain a PrivateMessage with ContentType application.</li>
        </ul>
      </section>
      <section anchor="fetch-the-ds-signature-public-key">
        <name>Fetch the DS' signature public key</name>
        <t>A request from a remote DS to retrieve the signature public key of this DS. The
signature public key can be used by other DSs to verify DSFanoutRequests sent by
the DS. While the DS also uses its signature private key to sign proposals (see
<xref target="proposals-by-reference"/>), clients should use the signature key included in
the group's <tt>external_senders</tt> extension to validate those.</t>
        <t>The DS responds with a DSResponse of type SignaturePublicKey that contains the
signature public key of this DS.</t>
      </section>
      <section anchor="fetch-addpackages-of-one-or-more-clients">
        <name>Fetch AddPackages of one or more clients</name>
        <t>A request from a client to retrieve the AddPackage(s) of one or more clients of
this DS. AddPackages are required to add other clients (and thus other users) to
a group.</t>
        <artwork><![CDATA[
struct {
  ClientID client_identifiers<V>;
} AddPackagesRequest;
]]></artwork>
        <t>The DS responds with the AddPackages of all clients listed in the request.</t>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>All client identifiers must refer to clients native to this DS.</li>
          <li>The DS SHOULD verify that the sender of the request is authorized to retrieve
the DSAddPackages of the clients in question. For example, it could check if
the user of the sending client has a connection with the user of the target
client(s).</li>
        </ul>
      </section>
      <section anchor="fetch-connection-addpackages-of-one-or-more-clients">
        <name>Fetch connection AddPackages of one or more clients</name>
        <t>A request from a client to retrieve the AddPackage(s) of all clients of a user
of this DS. AddPackages obtained via this operation can only be used to add
clients to a connection group.</t>
        <t>Connection AddPackages are available separately from regular AddPackages, as
they are meant to be accessed by clients of users with which the owning user has
no connection.</t>
        <artwork><![CDATA[
struct {
  UserID user_identifier;
} ConnectionAddPackagesRequest;
]]></artwork>
        <t>The DS responds with connection AddPackages of all clients of the user
corresponding to the identifier in the request.</t>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>All client identifiers must refer to clients native to this DS.</li>
          <li>All clients referred to by the identifiers must belong to the same user.</li>
        </ul>
      </section>
      <section anchor="reinitialize-a-group">
        <name>ReInitialize a group</name>
        <t>A request from a client to re-initialize a group with different parameters as
outlined in <xref target="group-lifecycle"/>.</t>
        <artwork><![CDATA[
struct {
  MLSGroupUpdate commit;
} ReInitializeGroupRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>The MLSGroupUpdate must contain a PublicMessage that contains a commit with a
re-init proposal.</li>
          <li>The GroupID in the re-init proposal must point to another group owned by the
DS, which has a MIMI DS protocol version that is greater or equal than this
group.</li>
        </ul>
      </section>
    </section>
    <section anchor="dsfanoutrequests-and-ds-to-ds-authentication">
      <name>DSFanoutRequests and DS-to-DS authentication</name>
      <t>After the DS has processed an incoming MLSMessage, it prepars a DSFanoutRequest
as described in <xref target="framing-and-processing-overview"/>.</t>
      <t>To authenticate these messages, an additional layer of DS-to-DS authentication
is required. As defined in <xref target="framing-and-processing-overview"/>, DSFanoutRequests
are signed using signing key of the sending DS. The receiving DS can obtain the
corresponding signature public key by sending a DSRequest to the sender
indicated in the DSFanoutRequest.</t>
      <t>The request for the signature public key MUST be sent via an HTTPS secured channel, or
otherwise authenticated using a root of trust present on the DS.</t>
      <t>TODO: If the transport provides server-to-server authentication this section and
the signature on the DSFanoutRequest can be removed.
TODO: Details on key management, caching etc. We can probably get away with
using very small lifetimes for these keys, as they can be re-fetched cheaply and
essentially at any time.</t>
    </section>
    <section anchor="role-based-access-control-in-groups">
      <name>Role-based access control in groups</name>
      <t>TODO: Access control is beyond the charter. However, to show how easily
implementable it is with MLS, this is section sketches a possible MLS extension
to handle access control in groups that is enforcible and verifiable by both
clients and DS. It is just an example and details can be changed later.</t>
      <t>As group operations are handled by MLS PublicMessages, the DS can enforce access
control policies on groups. The privileges of clients in a group are determined
by the group's RBAC GroupContext Extension.</t>
      <artwork><![CDATA[
struct {
  uint32 admins<V>;
} RBACExtension
]]></artwork>
      <t>The RBACExtension supports two roles: Members and Admins. Since all group
members are Members by default, the extension only lists admins.</t>
      <t>Any client the leaf node index of which is listed in the <tt>admins</tt> field of the
RBACExtension in a given group is considered as an Admin role and allowed to
perform the following operations in the context of this group.</t>
      <ul spacing="normal">
        <li>AddUsers, RemoveUsers, DeleteGroup, SetRole</li>
      </ul>
      <t>The SetRole operation is an additional operation available to groups that have
an RBACExtension.</t>
      <artwork><![CDATA[
struct {
  MLSGroupUpdate group_update;
} SetRoleRequest
]]></artwork>
      <t>The <tt>group_update</tt> needs to contain a commit which commits to a single
RBACProposal.</t>
      <artwork><![CDATA[
struct {
  uint32 promoted_members;
  uint32 demoted_members;
} SetRole
]]></artwork>
      <t>The DS (and all clients) process this proposal by changing the role of the group
members with the leaf indices listed in the <tt>promoted_members</tt> and
<tt>demoted_members</tt> fields and change the <tt>admins</tt> field of the group's
RBACExtension accordingly. For example, if the leaf index admin is listed in the
<tt>changed_members</tt> field of the proposal, it is demoted to Member and removed
from the <tt>admins</tt> field. Similarly, if a Member is listed, it is promoted to
Admin and added to the <tt>admins</tt> field.</t>
    </section>
    <section anchor="rate-limiting-and-spam-prevention">
      <name>Rate-limiting and spam prevention</name>
      <t>All requests (with the exception of the VerificationKeyRequest) can be
explicitly authenticated by the recipient through the verification of a
signature. This means that recipients can follow a rate-limiting strategy of
their choice based on the sender's identity.</t>
      <t>For DSRequests, the DS can rate-limit on a per group-level, per-DS level
(reducing the messages from all clients or users belonging to a single DS), or
even based on individual clients or users.</t>
      <t>For DSFanoutRequests, rate-limiting or blocking can happen based on the identity
of the sending DS, or it can happen on a per-group basis, where the recipient
only blocks messages from a particular group.</t>
      <t>Such rate-limiting can happen by decision of the DS itself, or on the request of
its local users. For example, a user might wish to block connection requests
from one specific other user without blocking connection requests from all other
users of that DS.</t>
    </section>
    <section anchor="abusive-and-illegal-content">
      <name>Abusive and illegal content</name>
      <t>As all application messages are encrypted, the DS has no way of analyzing their
content for illegal or abusive content. It may make use of a message franking
scheme to allow its users to report such content, although this is beyond the
scope of this document.</t>
      <t>Additionally, in the same way as a DS might allow its users to block certain
messages from specific users in the context of spam prevention, it may do the
same based on abusive or illegal content.</t>
    </section>
    <section anchor="reduced-metadata-operating-mode">
      <name>Reduced metadata operating mode</name>
      <t>If the desired mode of operation is for the Delivery Service to learn as little
as possible about the groups it owns and their individual members, the protocol
can operate in a mode that protects the group state on the Delivery Service.
This can happen through two complementary mechanisms:</t>
      <ul spacing="normal">
        <li>Unlinking member credentials from credentials issued by the Authentication
Service, providing pseudonymity at the Delivery Service level</li>
        <li>Encrypting the group state with a key that is only known to the group
members, providing encryption at rest</li>
      </ul>
      <t>In practice, the requests from clients to the Delivery Server are extended with
additional parameters, such as decryption keys for the group state and
additional pseudonymous user-level authentication.</t>
      <section anchor="connection-key-material">
        <name>Connection key material</name>
        <t>After the responder in a connection establishment process has joined the
connection group created by the initiator, they MUST exchange their connection
key material. This key material consists of keys that both users can use to hide
metadata from the DS, or to authenticate themselves to the DS without revealing
their identity when fetching KeyPackages for the other user.</t>
        <artwork><![CDATA[
struct {
  opaque connection_token<0..255>;
  opaque welcome_data_encryption_key<0..255>;
  opaque de_pseudonymization_key<0..255>;
} ConnectionKeyMaterial
]]></artwork>
        <t>The exact nature of the keys and what they are used for will become apparent in
the following sections.</t>
      </section>
      <section anchor="group-level-encryption-keys">
        <name>Group-level encryption keys</name>
        <t>Some of the metadata in the context of a group has to be encrypted to prevent
the DS from seeing it. Since the members of that group should still be able to
process the data fully, the protocol needs key material that is known to group
members, but not to the DS. In theory, such key material could be derived from
the Exporter key of the MLS group. However, this key changes with each epoch, so
all data encrypted in this way would have to be re-encrypted every epoch.</t>
        <t>Instead, these group keys are randomly generated and distributed to new group
members as part of the WelcomePackages. Instead of sending them in the clear,
the sender of the Welcome encrypts them under the welcome data encryption key of
each receiving user.</t>
        <artwork><![CDATA[
struct {
  opaque de_pseudonymization_key<0..255>;
  opaque credential_encryption_key<0..255>;
  opaque group_state_encryption_key<0..255>;
} GroupLevelKeys

struct {
  opaque encrypted_group_level_keys;
} RMWelcomeData
]]></artwork>
        <t>TODO: Lifecycle of these keys. Rotation of such key material is tricky, as any
member who has not joined yet via a Welcome message, or who is going to try to
join via external commit with the old key is going to fail. Then how to retrieve
that key? Our preferred solution would be to introduce a maximum time that
clients can be offline. Then it would be possible to have an overlapping
rotation window that ensures that anyone that wants to join can join.</t>
      </section>
      <section anchor="pseudonymous-client-identifiers-and-authentication">
        <name>Pseudonymous client identifiers and authentication</name>
        <t>As a general rule, clients MUST NOT use their real identifiers in credentials
that they include in LeafNodes, be it in KeyPackages or as part of updates in
their groups.</t>
        <t>Instead, clients use per-group pseudonyms, where each pseudonym consists is a
randomly generated UUID. Once a user is added to a group, the pseudonym remains
the same throughout the lifetime of that group.</t>
        <t>Despite this pseudonymization, clients must still be able to tie other group
members to real client and user identities. To that end, clients sign their
pseudonymized credentials with their client-level signature key material.</t>
        <t>Since the signature would reveal which client has signed a pseudonymized
credential, that signature MUST be encrypted symmetrically using a signature
encryption key.</t>
        <t>TODO: The authenticated encryption scheme used for the encryption should be
determined by the MIMI DS protocol version.</t>
        <t>Whenever the client uses a pseudonymized credential, it attaches the symmetric
encryption key encrypted under another key that in turn known to everyone who is
meant to be able to authenticate the client in that context.</t>
        <t>There are two contexts in which a client needs to authenticate the credential of
another client: In the context of a group and when a client fetches a KeyPackage
from another client. (Note that there are no connection Key- or AddPackages in
Reduced Metadata mode. See <xref target="reduced-metadata-connection-establishment"/> for
more details.)</t>
        <section anchor="signature-encryption-key-management">
          <name>Signature encryption key management</name>
          <t>All groups operated in the Reduced Metadata mode have a de-pseudonymization key
(DPK) associated with them that is known to all group members, but not the DS.
It is randomly generated at group creation and is sent to new group members when
they join the group as part of the optional data in the WelcomePackage. This key
is then used to encrypt all signature encryption keys attached to credentials
used in that group.</t>
          <t>For credentials in KeyPackages, clients use a DPK that they distribute to users
they have a connection with as part of the connection establishment process.
When those users then want to use the KeyPackages, they have to re-encrypt the
signature encryption key under the DPK of the group they want to add the owner
of the KeyPackage to.</t>
          <artwork><![CDATA[
struct {
  opaque encrypted_signature_encryption_key<0..255>;
} EncryptedSignatureEncryptionKey
]]></artwork>
        </section>
        <section anchor="client-credential-encryption">
          <name>Client credential encryption</name>
          <t>For clients to authenticate other group members, they do not only need to
decrypt the encrypted signatures that accompany the credential of each member,
they also need to know the client credentials that produced those signatures to
verify them. To this end, whenever a client is added to the group (or joins it
via an external commit), its client credential is uploaded to the group.
However, since this data, too, is not meant to be visible by the DS, it is
encrypted with a group level encryption key, the client credential encryption
key.</t>
          <artwork><![CDATA[
struct {
  opaque encrypted_client_credential<0..255>;
} EncryptedClientCredential
]]></artwork>
          <t>Thus both the encrypted signature encryption key, as well as the encrypted
client credential need to be uploaded to the group whenever a group client is
added.</t>
          <artwork><![CDATA[
struct {
  EncryptedSignatureEncryptionKey encrypted_signature_encryption_keys<V>;
  EncryptedClientCredential encrypted_client_credentials<V>;
} RMAddClientsData
]]></artwork>
          <t>The encrypted signature encryption key and the encrypted client credential also
need to be maintained across updates, which means that whenever a client
performs an update operation and changes its client credential it MAY update its
encrypted signature encryption key and it MAY update its encrypted client
credential.</t>
        </section>
      </section>
      <section anchor="pseudonymous-user-identifiers-and-authentication">
        <name>Pseudonymous user identifiers and authentication</name>
        <t>Pseudonymous per-group client identifiers mean that the DS can not determine
which client belongs to which user. Instead, whenever a user is added, that user
has to supply the DS with a public signature key called the user authentication
key.</t>
        <t>Since these user authentication keys are unique, per-group values, a user that
was added to a group has to set them explicitly before it performs any other
operation. User authentication keys are set using the regular update operation,
which means that a newly added user MUST perform an update operation with one of
its clients to set that key.</t>
        <t>Client then use the user authentication key to authenticate operations that
require user level authentication, specifically client addition and removal, as
well as joining via external commit.</t>
      </section>
      <section anchor="addpackage-retrieval">
        <name>AddPackage retrieval</name>
        <t>Since the DS can potentially observe which KeyPackage is added to which group,
KeyPackages need to be published pseudonymously as well. This should be taken
into account in the design of the DS' local client-to-server protocol.</t>
        <t>Similarly, clients should be able to retrieve AddPackages of other users without
revealing their identity. On the one hand, this means that they cannot
authenticate using their client-level authentication key material. Instead, each
user has a connection token that it distributes to all users that they have a
connection with. They also upload it to the DS s.t. clients can show that they
are authorized to fetch AddPackages by showing the connection token.</t>
        <artwork><![CDATA[
enum {
  Anonymous,
  ClientSignature,
  PseudonymousUserAuth,
  ConnectionToken,
} DSAuthType;

struct {
  DSAuthType auth_type;
  select (DSAuthData.auth_type) {
    case Anonymous:
      struct {};
    case ClientSignature:
      uint32 sender_index;
      opaque signature<0..255>;
    case PseudonymousUserAuth:
      opaque user_auth_hash<0..255>;
      opaque signature<0..255>;
    case ConnectionToken:
      opaque connection_token<0..255>
  }
} DSAuthData;
]]></artwork>
      </section>
      <section anchor="pseudonymized-fan-out">
        <name>Pseudonymized fan-out</name>
        <t>If DS cannot see the real identifiers of group members, it needs more
information to determine where to fan messages out to. To this end, clients
supply the DS with group-specific FanoutPseudonyms.</t>
        <t>A FanoutPseudonym consists of the FQDN of the client's DS, as well as an octet
string that allows the client's DS to further associate the message with the
client. The local client-to-server protocol SHOULD ensure that that identifier
is not tied to the client's real identifier.</t>
        <artwork><![CDATA[
struct {
  opaque ds_domain_name<0..255>;
  opaque destination_address<0..255>
} FanoutPseudonym

enum {
  ClientIdentifier,
  Pseudonym
} DSFanoutRecipientType;

struct {
  DSRecipientType recipient_type;
  select (DSRecipient.recipient_type) {
    case ClientIdentifier:
      opaque client_id<0..255>;
    case Pseudonym:
      FanoutPseudonym fanout_pseudonym
  }
} DSFanoutRecipient;
]]></artwork>
        <t>To allow for the delivery of messages immmediately after clients were added to a
group, clients need to include a FanoutPseudonym extension in their KeyPackages.</t>
        <t>Additionally, clients can update their FanoutPseudonym whenever they perform an
update operation.</t>
        <artwork><![CDATA[
struct {
  optional<EncryptedSignatureEncryptionKey> encrypted_signature_encryption_key;
  optional<EncryptedClientCredential> encrypted_client_credential;
  optional<opaque> user_authentication_key;
  optional<FanoutPseudonym> fan_out_pseudonym
} RMUpdateClientData
]]></artwork>
        <t>TODO: This extension would have to be defined in the context of the MLS WG.</t>
        <t>TODO: The intended way to use the destination address is for the client to have
a queue pseudonymously registered to it on its own DS. The <tt>destination_address</tt>
is then the identifier of the queue HPKE-encrypted to the client's DS, where for
each group/KeyPackage, the client freshly encrypts the identifier to create
unique ciphertexts.</t>
      </section>
      <section anchor="group-state-encryption-at-rest">
        <name>Group state encryption at rest</name>
        <t>To additionally protect persisted metadata on the DS, the DS MUST encrypt the
group state before it stores it in persistent state. The key used for encryption
and decryption is another group-level key that clients send to the DS with
DSRequest.</t>
        <artwork><![CDATA[
struct {
  opaque group_state_ear_key<0..255>;
} RMGroupStateEARKey
]]></artwork>
        <t>Whenever a client sends a DSRequest that is concerned with a specific group, it
includes the group state encryption key in the DSRequestBody. The DS then
decrypts the group state, performs the operation and re-encrypts it.</t>
      </section>
      <section anchor="external-joins">
        <name>External joins</name>
        <t>For a client to perform an external join successfully, it needs all group-level
keys. Since external join operations are only allowed for clients that belong to
a user that is already in the group, those clients need to obtain the relevant
key material from other clients of that user first.</t>
      </section>
      <section anchor="reduced-metadata-connection-establishment">
        <name>Reduced metadata connection establishment</name>
        <t>The only major change to the protocol that is required in the Metadata Reduced
mode of operation is moving the connection establishment flow from a Welcome
based one to one based on external commits. While this change prevents the
initiator from immediately sending messages after creating the connection group,
it is necessary, because the use of KeyPackages allows the DS to track which
group is used as the connection group.</t>
        <t>In this changed flow, the initiating client fetches a connection AddPackage, but
instead of using it to add the clients of the responding user to the group, it
encrypts a ConnectionEstablishmentInfo to the <tt>hpke_init_key</tt> in that
KeyPackage.</t>
        <artwork><![CDATA[
struct {
  opaque initiator_client_credential<0..255>;
  opaque connection_group_id<0..255>;
  GroupLevelKeys group_level_keys;
  // Signature over the above fields using the signature key in the client
  // credential
  opaque signature<0..255>
} ConnectionEstablishmentInfo

struct {
  opaque recipient_identifier<0..255>;
  KeyPackageRef key_package_reference;
  opaque encrypted_connection_establishment_info<0..255>;
} ConnectionEstablishmentPackage
]]></artwork>
        <t>The <tt>recipient_identifier</tt> represents the real client identifier of the
responding client.</t>
        <t>TODO: "client_credential" is a place holder for whatever the key material would
look like that binds an authentication key to the sender's identity.</t>
        <t>The delivery of ConnectionEstablishmentPackages necessitates a new DS request
type ds_fanout_cep, where the DSRequestBody contains a
ConnectionEstablishmentPackage. The DS then stores and forwards the
<tt>key_package_ref</tt> and the <tt>encrypted_connection_establishment_info</tt> to the
client identified by the <tt>recipient_identifier</tt>.</t>
        <t>The recipient can then determine the <tt>hpke_init_key</tt> of which KeyPackage to use
and decrypt the ConnectionEstablishmentInfo. It can then perform an external
join operation on the group indicated by the <tt>connection_group_id</tt> using the
<tt>group_level_keys</tt>.</t>
        <t>The users can then exchange information like the connection token via the
connection group.</t>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security considerations</name>
      <t>TODO: There is currently no consensus in the MIMI w.r.t. the security goals we
want to reach.</t>
      <t>The underlying MLS protocol provides end-to-end encryption and authentication
for all MLSMessages, as well as group state agreement.</t>
      <section anchor="transport-security">
        <name>Transport Security</name>
        <t>Transport of DSFanoutRequests, as well as their responses MUST use a recipient
authenticated transport. This is to ensure that these messages are mutually
authenticated.</t>
        <t>To protect the metadata in all request-response flows, requests and responses
SHOULD be secured using an encrypted transport channel.</t>
      </section>
    </section>
  </middle>
  <back>
    <references>
      <name>Normative References</name>
      <reference anchor="I-D.ietf-mls-protocol">
        <front>
          <title>The Messaging Layer Security (MLS) Protocol</title>
          <author fullname="Richard Barnes" initials="R." surname="Barnes">
            <organization>Cisco</organization>
          </author>
          <author fullname="Benjamin Beurdouche" initials="B." surname="Beurdouche">
            <organization>Inria &amp; Mozilla</organization>
          </author>
          <author fullname="Raphael Robert" initials="R." surname="Robert">
            <organization>Phoenix R&amp;D</organization>
          </author>
          <author fullname="Jon Millican" initials="J." surname="Millican">
            <organization>Meta Platforms</organization>
          </author>
          <author fullname="Emad Omara" initials="E." surname="Omara">
            <organization>Google</organization>
          </author>
          <author fullname="Katriel Cohn-Gordon" initials="K." surname="Cohn-Gordon">
            <organization>University of Oxford</organization>
          </author>
          <date day="27" month="March" year="2023"/>
          <abstract>
            <t>   Messaging applications are increasingly making use of end-to-end
   security mechanisms to ensure that messages are only accessible to
   the communicating endpoints, and not to any servers involved in
   delivering messages.  Establishing keys to provide such protections
   is challenging for group chat settings, in which more than two
   clients need to agree on a key but may not be online at the same
   time.  In this document, we specify a key establishment protocol that
   provides efficient asynchronous group key establishment with forward
   secrecy and post-compromise security for groups in size ranging from
   two to thousands.

            </t>
          </abstract>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-ietf-mls-protocol-20"/>
      </reference>
      <reference anchor="RFC8446">
        <front>
          <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
          <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
          <date month="August" year="2018"/>
          <abstract>
            <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
            <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8446"/>
        <seriesInfo name="DOI" value="10.17487/RFC8446"/>
      </reference>
    </references>
  </back>
  <!-- ##markdown-source:
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
lWX4PxCH5P+38QAA

-->

</rfc>
