<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.2 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-robert-mimi-delivery-service-06" category="info" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.18.2 -->
  <front>
    <title abbrev="MIMI">MIMI Delivery Service</title>
    <seriesInfo name="Internet-Draft" value="draft-robert-mimi-delivery-service-06"/>
    <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="November" day="06"/>
    <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>
          <t>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.</t>
        </li>
        <li>
          <t>Assistance for new joiners of a group: The Delivery Service can keep and
update state such as the public ratchet tree, group extensions, etc.</t>
        </li>
        <li>
          <t>Message validation: The Delivery Service can inspect and validate handshake
messages and reject malformed, invalid or malicious messages.</t>
        </li>
        <li>
          <t>Built-in authentication of group members and policy enforcement: The Delivery
Service can authenticate group members and reject messages from non-members.
Additionally, the Delivery Service can be linked to the Authentication
Service to enforce more policies and validation rules.</t>
        </li>
        <li>
          <t>Scalability: The protocol makes no assumption about whether the Delivery Service
runs as a single instance or as a cluster of instances.</t>
        </li>
        <li>
          <t>Network fluid: While the Delivery Service would typically run as a
server-side component, the only requirement is that it is accessible by all
clients.</t>
        </li>
        <li>
          <t>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.</t>
        </li>
      </ul>
      <t>TODO: Make use of MUST/SHOULD, etc. throughout.</t>
    </section>
    <section anchor="terminology">
      <name>Terminology</name>
      <t>This document uses the terminology defined in <xref target="RFC9420"/> with the following
additions:</t>
      <ul spacing="normal">
        <li>
          <t>DS Domain: Fully qualified domain name as defined in <xref target="RFC2181"/> 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 transport protocol over which the MIMI DS protocol runs.
TODO: client identifiers definitions are preliminary.</t>
        </li>
        <li>
          <t>Client: An MLS client with a unique client identifier.</t>
        </li>
        <li>
          <t>Client identifier: An octet string that uniquely identifies the client and
that maps to the DS domain of the client's DS.</t>
        </li>
      </ul>
    </section>
    <section anchor="interfaces">
      <name>Interfaces</name>
      <t>The MIMI DS protocol inherits the proposal-commit logic from MLS. Any party that
is either a group member, or that was added as an external sender can propose
changes to the group such as the addition, removal, or update of clients. Group
members can then change the group state in a commit operation. A commit MUST
include all valid previously received proposals, as well as any valid proposals
that the committing client wants to add to the commit.</t>
      <t>The MIMI DS tracks the state of individual MLS groups on a hub by storing
proposals and processing commits.</t>
      <t>Any party (including group members and external senders) can send requests for
the current group information (an MLS GroupInfo, required for clients to join
the group without the help of a group member) or request key material (MLS
KeyPackages, required by group members to add new group members) of the DS'
clients.</t>
      <t>Group members and external senders can send proposals to the group. The
MIMI DS protocol supports any MLS proposal supported by the specific group in
question. The proposals specified in <xref target="RFC9420"/> provide the baseline
operations:</t>
      <ul spacing="normal">
        <li>
          <t>Add proposals (to add new group members)</t>
        </li>
        <li>
          <t>Remove proposals (to remove existing group members)</t>
        </li>
        <li>
          <t>Update proposals (to update a group members's key material)</t>
        </li>
        <li>
          <t>PSK proposals (to inject additional key material into the group)</t>
        </li>
        <li>
          <t>Re-Init proposals (to re-initialize the group, e.g. with a new ciphersuite)</t>
        </li>
        <li>
          <t>Group Context Extensions (to modify data in GroupContext Extensions, e.g. to
add/remove/update external senders)</t>
        </li>
      </ul>
      <t>TODO: We might want to allow non-group members to propose adding themselves
(NewMemberProposal).</t>
      <t>Additional proposals may be added via MLS' extension mechanism.</t>
      <t>Group members can send commits (which can include any of the proposals listed
above), as well as application messages.</t>
      <t>Clients that are not group members can send an (external) commit to add
themselves to a group.</t>
      <t>Group members can send an external commit to re-join the group (e.g. if they
have previously lost state, or their group state was corrupted).</t>
      <t>The DS will verify all proposals, commits and application messages as described
in <xref target="RFC9420"/> and fan them out to the rest of the group.</t>
    </section>
    <section anchor="architecture-and-protocol-overview">
      <name>Architecture and protocol overview</name>
      <t>The MIMI DS protocol allows interoperability between a hub 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 primarily 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 hub 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, the MLS protocol messages that
many of the 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 hub of one of their groups and a
server-to-server protocol that allows a hub 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
client identifier.</t>
        <t>The client-to-server part of the MIMI DS protocol provide sender authentication.
Recipient authentication, as well as mutual server-to-server authentication is
left to the MIMI transport protocol.</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="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="216" y="148">DSRequest</text>
                  <text x="388" y="148">DSResponse</text>
                  <text x="264" y="212">Hub</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)  |              |
|             +<-------------+              |
+-------------+              +--+--------+--+
                                |        ^
                      DSRequest |        | DSResponse
                                v        |
                             +--+--------+--+
                             |              |
                             | Hub          |
                             |              |
                             |              |
                             +--+--------+--+
                                |        ^
                DSFanoutRequest |        | DSFanoutResponse
                                v        |
                             +--+--------+--+
                             |              |
                             | Guest DS     |
                             |              |
                             |              |
                             +--------------+
]]></artwork>
          </artset>
        </figure>
        <t><xref target="full-sending-flow"/> shows an example protocol flow, where a client sends a
request to its own guest DS, which in turn makes a request to the hub. The
hub then fans out a message to another guest DS.</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="168" viewBox="0 0 168 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="152" y="36">Hub</text>
                  <text x="56" y="68">DSRequest</text>
                  <text x="60" y="116">DSResponse</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
Client           Hub
|                |
| 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="152" y="36">Hub</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           Hub                               Guest Delivery Service
|                |                                 |
| DSRequest      |                                 |
+--------------->|                                 |
|                |                                 |
| DSResponse     |                                 |
|<---------------+                                 |
|                | DSFanoutRequest                 |
|                +-------------------------------->|
|                |                                 |
|                | DSFanoutResponse                |
|                |<--------------------------------+
|                |                                 |
]]></artwork>
          </artset>
        </figure>
      </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>
      <section anchor="enqueue-authorization">
        <name>Enqueue authorization</name>
        <t>TODO: This section sketches an authorization mechanism based on a KeyPackage
extension. That extension would have to be defined in the context of the MLS WG.</t>
        <t>Each KeyPackage that a client publishes also carries a FanoutAuthToken inside
a FanoutAuth KeyPackage extension.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  opaque token<V>;
} FanoutAuthToken
]]></sourcecode>
        <t>Whenever a client is added to a group (or when a new group is created), the DS
checks that the KeyPackages of all joiners contain a FanoutAuth extension and
stores the contained token alongside the group state.</t>
        <t>The FanoutAuthToken is included in DSFanoutRequests and allows the receiving
DS to check whether the sender is authorized to enqueue messages for the
recipient.</t>
        <t>Clients can change their FanoutAuthToken by sending a new token with an
update operation.</t>
        <t>TODO: Details on the cryptographic scheme underlying the token.</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="RFC9420"/> 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>
    <section anchor="security-properties-overview">
      <name>Security properties overview</name>
      <t>The MIMI DS protocol provides a number of security guarantees.</t>
      <section anchor="mls-based-security-properties">
        <name>MLS-based security properties</name>
        <t>The MLS protocol underlying the MIMI DS protocol provides a number of security
guarantees that primarily affect end-to-end communication between clients such
as authentication and confidentiality with forward- as well as post-compromise
security (although the latter only holds for application messages). While the
MIMI DS protocol acts as a layer around the MLS protocol it inherits some of
MLSs security guarantees.</t>
        <t>More concretely, the DS can verify client signatures on MLS messages and thus
ensure that end-to-end authentication holds. Since the DS uses MLS messages to
track the group state (including group membership), it is guaranteed to have the
same view of that state as the group members.</t>
      </section>
    </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>
        <sourcecode type="tls"><![CDATA[
enum {
  ds_delete_group(0),
  ...
} 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;
]]></sourcecode>
        <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. The full definition with all operations relevant for the
normal DS operating mode can be found in <xref target="operations"/>.</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>
        <sourcecode type="tls"><![CDATA[
enum {
  Unauthenticated,
  ClientSignature,
} DSAuthType;

struct {
  DSAuthType auth_type;
  select (DSAuthData.auth_type) {
    case Unauthenticated:
      struct {};
    case ClientSignature:
      uint32 sender_index;
      opaque signature<0..255>;
  }
} DSAuthData;
]]></sourcecode>
        <t>Before the DS performs the requested operation, it performs an authentication
operation depending on the DSAuthType.</t>
        <ul spacing="normal">
          <li>
            <t>Anonymous: No authentication required</t>
          </li>
          <li>
            <t>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:</t>
          </li>
        </ul>
        <sourcecode type="tls"><![CDATA[
struct {
  DSProtocolVersion protocol_version;
  DSRequestBody request_body;
  u32 sender_index
} ClientSignatureTBS
]]></sourcecode>
        <t>Note that all group operations additionally contain an MLSMessage the content of
which mirrors the request type, e.g., an AddClients request wraps an MLS commit
that in turn contains the Add proposals for the clients to be added. 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>
        <sourcecode type="tls"><![CDATA[
struct {
  DSProtocolVersion protocol_version;
  DSResponseBody response_body;
} DSResponse

enum DSResponseType {
  Ok,
  Error,
  WelcomeInfo,
  ExternalCommitInfo
  KeyPackages,
}

struct DSResponseBody {
  DSResponseType response_type;
  select (DSResponseBody.response_type) {
    case Ok:
      struct {};
    case Error:
      DSError error;
    case WelcomeInfo:
      optional<Node> ratchet_tree<V>;
    case ExternalCommit:
      MLSMessage: group_info;
      optional<Node> ratchet_tree<V>;
    case KeyPackages:
      KeyPackage key_packages<V>;
  }
}

struct {
  TODO: Operation specific errors.
} DSError
]]></sourcecode>
      </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, a
list of client ids representing the clients for which the payload is meant, a
FanoutAuthToken (see <xref target="enqueue-authorization"/>) for each of the clients, as well
as the payload to be fanned out.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  DSProtocolVersion protocol_version;
  opaque recipient_ids<V>;
  FanoutAuthToken fanout_auth_tokens<V>;
  MLSMessage mls_message;
} DSFanoutRequest
]]></sourcecode>
        <t>The receiving DS first verifies the signature using the sending DS' public
signature key and then further validates the message by performing the following
checks:</t>
        <ul spacing="normal">
          <li>
            <t>That the protocol version is compatible with its configuration</t>
          </li>
          <li>
            <t>That the <tt>recipient_ids</tt> are all clients of this DS</t>
          </li>
          <li>
            <t>The the <tt>fanout_auth_tokens</tt> are all valid tokens for the individual
recipients</t>
          </li>
        </ul>
        <t>The recieving DS can then store and forward the contained MLS message to the
clients indicated in the <tt>recipient_ids</tt> field and send a DSFanoutResponse.</t>
        <sourcecode type="tls"><![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
]]></sourcecode>
      </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 for which it is the hub. 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>
      <sourcecode type="tls"><![CDATA[
struct {
  Extension group_info_extensions<V>;
  opaque Signature<V>;
} PartialGroupInfo
]]></sourcecode>
      <t>The combination of a commit and a partial group info is called an
MLSGroupUpdate.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  MLSMessage commit;
  PartialGroupInfo partial_group_info;
} MLSGroupUpdate
]]></sourcecode>
      <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>Proposals and DS-initiated operations</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 (i.e. leave)
from a group.</t>
      <t>Such proposals, where the original sender differs from the sender of the commit
are called "proposal by reference", or "proposal by value" if the proposal is
sent by the committer as part of the commit itself.</t>
      <t>The following sections detail operations that can be performed by clients, so
each operation that entails a change to the group state (with the exception of
the self remove operation) require the sender to perform a commit, where the
semantics of the operation are reflected as proposals by value. For example, the
commit in the AddClientsRequest must only contain Add proposals.</t>
      <t>If a client receives a valid standalone proposal, it MUST store it and verify
that the next commit includes said proposal.</t>
      <t>TODO: Be more specific about proposal validation. Also, we might want to allow
the server to rescind a proposal.</t>
      <t>Whenever a client sends a commit as part of an operation, it MUST include all
stored proposals by reference, such as server-initiated Remove proposals, or
proposals sent as part of a self-remove operation.</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>
      <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="RFC9420"/> that includes the DS'
credential and its signature public key.</t>
      <t>TODO: We might also want to mandate that the group includes credentials of guest
DSs involved in the group. However, for them to be able to send proposals, we'd
need an additional operation/endpoint that the DS exposes.</t>
      <t>TODO: Details of the DS credential, distribution, etc. A BasicCredential with
the FQDN of the DS would probably be sufficient.</t>
      <t>The DS can simply create such proposals itself based on the group information
and distribute it to all group members via regular DSFanoutRequests.</t>
    </section>
    <section anchor="operations">
      <name>Client-initiated 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>
      <sourcecode type="tls"><![CDATA[
enum {
  ds_delete_group,
  ds_proposals,
  ds_commits,
  ds_send_message,
  ds_key_packages,
  ds_group_info,
} DSRequestType;

struct {
  DSRequestType request_type;
  select (DSRequestBody.request_type) {
    case ds_delete_group:
      DeleteGroupRequest delete_group_request;
    case ds_proposals:
      ProposalRequest proposal_request;
    case ds_commits:
      CommitRequest commit_request;
    case ds_send_message:
      SendMessageRequest send_message_request;
    case ds_key_packages:
      KeyPackagesRequest key_packages_request;
    case ds_key_packages:
      GroupInfoRequest group_info_request;
  }
} DSRequestBody;
]]></sourcecode>
      <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>
        <sourcecode type="tls"><![CDATA[
struct {
  MLSGroupUpdate group_update;
} DeleteGroupRequest;
]]></sourcecode>
        <t><strong>Validation:</strong></t>
        <t>The Delivery Service validates the request as follows:</t>
        <ul spacing="normal">
          <li>
            <t>The MLSGroupUpdate MUST contain a PublicMessage with a commit that contains
Remove proposals for every member of the group except the committer.</t>
          </li>
        </ul>
      </section>
      <section anchor="propose-group-state-changes">
        <name>Propose group state changes</name>
        <t>A request from a client or an external sender to propose one ore more changes to
the group state. Each change is encoded as an MLS proposal.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  MLSMessage proposals<V>;
} AddClientsRequest;
]]></sourcecode>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>
            <t>The MLSMessages MUST contain PublicMessages with proposals.</t>
          </li>
          <li>
            <t>All proposals MUST be valid according to <xref target="RFC9420"/>.</t>
          </li>
        </ul>
      </section>
      <section anchor="commit-group-state-changes">
        <name>Commit group state changes</name>
        <t>A request from a client to change the group state via one or more commits as
proposed by previously sent proposals, or proposals included in the commits.
Note that this operation cannot be used by a group member to remove itself from
the group. Group members can only propose their own removal and wait for another
group member to commit the change.</t>
        <t>Clients that are not yet group members can use a commit to add themselves to a
group.</t>
        <t>Group members can re-add themselves to a group via a commit (e.g. in case of
lost group state).</t>
        <sourcecode type="tls"><![CDATA[
struct {
  MLSGroupUpdate group_updates<V>;
  MLSMessage welcome_messages<V>;
} RemoveClientsRequest;
]]></sourcecode>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>
            <t>The MLSGroupUpdates MUST contain PublicMessages that contain commits.</t>
          </li>
        </ul>
      </section>
      <section anchor="send-application-messages-to-a-group">
        <name>Send application messages to a group</name>
        <t>A request from a client to fan out one or more application messages 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<V>;
} SendMessageRequest;
]]></artwork>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>
            <t>The MLSMessages MUST contain PrivateMessages with ContentType application.</t>
          </li>
        </ul>
      </section>
      <section anchor="fetch-keypackages-of-one-or-more-clients">
        <name>Fetch KeyPackages of one or more clients</name>
        <t>A request from a client to retrieve the KeyPackage(s) of one or more clients of
this DS. KeyPackages are required to add other clients (and thus other users) to
a group.</t>
        <artwork><![CDATA[
struct {
  ClientID client_identifiers<V>;
} KeyPackagesRequest;
]]></artwork>
        <t>The DS responds with the KeyPackages of all clients listed in the request.</t>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>
            <t>All client identifiers MUST refer to clients native to this DS.</t>
          </li>
          <li>
            <t>The DS SHOULD verify that the sender of the request is authorized to retrieve
the DSKeyPackages of the clients in question.</t>
          </li>
        </ul>
      </section>
      <section anchor="fetch-group-information">
        <name>Fetch group information</name>
        <t>A request from a client to retrieve the group's GroupInfo. KeyPackages are
required for clients to add themselves to a group via a commit and for group
members to re-add themselves to a group.</t>
        <artwork><![CDATA[
struct {} GroupInfoRequest;
]]></artwork>
        <t>The DS responds with the group's current GroupInfo.</t>
        <t><strong>Validation:</strong></t>
        <ul spacing="normal">
          <li>
            <t>The DS MUST verify that the sender of the request is authorized to retrieve
the group's GroupInfo.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="dsfanoutrequests">
      <name>DSFanoutRequests</name>
      <t>After the DS has processed an incoming MLSMessage, it prepares a DSFanoutRequest
as described in <xref target="framing-and-processing-overview"/>.</t>
      <t>For DS to DS communication, the MIMI DS protocol relies on the underlying
transport protocol to provide mutual authentication.</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 belonging to a single DS), or even based
on individual clients.</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 clients. For example, a client might wish to block connection requests
from one specific other client without blocking connection requests from all other
clients of that DS.</t>
    </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 anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="RFC9420">
        <front>
          <title>The Messaging Layer Security (MLS) Protocol</title>
          <author fullname="R. Barnes" initials="R." surname="Barnes"/>
          <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
          <author fullname="R. Robert" initials="R." surname="Robert"/>
          <author fullname="J. Millican" initials="J." surname="Millican"/>
          <author fullname="E. Omara" initials="E." surname="Omara"/>
          <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
          <date month="July" 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 (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="9420"/>
        <seriesInfo name="DOI" value="10.17487/RFC9420"/>
      </reference>
      <reference anchor="RFC2181">
        <front>
          <title>Clarifications to the DNS Specification</title>
          <author fullname="R. Elz" initials="R." surname="Elz"/>
          <author fullname="R. Bush" initials="R." surname="Bush"/>
          <date month="July" year="1997"/>
          <abstract>
            <t>This document considers some areas that have been identified as problems with the specification of the Domain Name System, and proposes remedies for the defects identified. [STANDARDS-TRACK]</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="2181"/>
        <seriesInfo name="DOI" value="10.17487/RFC2181"/>
      </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>
      <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 (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.
            </t>
          </abstract>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-ietf-mls-protocol-20"/>
      </reference>
    </references>
  </back>
  <!-- ##markdown-source:
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
DK0Eg7bQIVq1IiC+ALmvta0W5v8APxm3P7p4AAA=

-->

</rfc>
