Internet-Draft MIMI July 2023
Robert & Kohbrok Expires 11 January 2024 [Page]
Workgroup:
Network Working Group
Internet-Draft:
draft-robert-mimi-delivery-service-03
Published:
Intended Status:
Informational
Expires:
Authors:
R. Robert
Phoenix R&D
K. Kohbrok
Phoenix R&D

MIMI Delivery Service

Abstract

This document describes the MIMI Delivery Service.

Status of This Memo

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

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

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

This Internet-Draft will expire on 11 January 2024.

Table of Contents

1. Introduction

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.

This document describes a Delivery Service that performs the mandated ordering of handshake messages and uses MLS to implement a variety of other features:

TODO: Make use of MUST/SHOULD, etc. throughout.

The delivery service can operate in one of two modes: "Full Metadata" mode and "Reduced Metadata" mode.

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.

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 Section 11.

2. Terminology

This document uses the terminology defined in [I-D.ietf-mls-protocol] with the following additions:

3. Architecture and protocol overview

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.

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.

The MIMI DS protocol requires clients to send MLS messages as PublicMessages (with the exception of messages with content type application). 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.

3.1. Client to server and server to server protocol

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.

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.

Note that the client-to-server part of the protocol can optionally be proxied via the guest DS of the sending client.

3.2. Transport for the MIMI DS protocol

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.

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.

TODO: If the transport layer provides mutual authentication, at least the server-to-server part of the MIMI DS protocol can be changed accordingly.

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.

3.3. Flow

DSRequest Sending Owning DS Client DSResponse DSFanoutRequest DSFanoutResponse Guest DS
Figure 1: Architecture overview
Sending (proprietary Guest DS Client protocol) (proxy) DSRequest DSResponse Owning DS DSFanoutRequest DSFanoutResponse Guest DS
Figure 2: Alternative with a guest DS as proxy

Figure 1 and Figure 2 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 Figure 2, the request sent by the client is proxied by the guest DS of that client.

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.

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.

Client Owning Delivery Service DSRequest DSResponse
Figure 3: Delivery Service Request/Response scheme

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.

Client Owning Delivery Service Guest Delivery Service DSRequest DSResponse DsFanoutRequest DsFanoutResponse
Figure 4: Client/Delivery Service communication with fanout

3.4. Supported operations

The MIMI DS protocol allows guest clients to request a variety of operations for example to manage group membership, join groups, or send messages.

  • Group creation/deletion
  • Join a group from a Welcome message as a new member
  • 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)
  • Adding and removing users to/from a group
  • Adding and removing clients to/from a member of the group
  • Client updates (MLS leaf updates)
  • Sending application messages
  • Download of KeyPackages
  • Enqueueing of a message fanned out from an owning DS
  • Discovery of users and their clients
  • Download of connection-specific KeyPackages

3.5. Client removals induced by the Delivery Service

Independent of client requests, the Delivery Service itself can remove clients from a group by issuing remove proposals in the following cases:

  • A user has removed a client from its account
  • A user has been deleted
  • The client is removed from the group because it has been inactive for too long

3.6. Serialization format

MLS messages use the presentation language and encoding format defined in [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.

Octet strings resulting from serialization in this format are unambiguous and require no further canonicalization.

3.7. KeyPackages

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.

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.

TODO: KeyPackages of last resort should be marked. Ideally by using a KeyPackage extension.

3.7.1. Connection KeyPackages

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 Section 3.12) and differ from regular KeyPackages only in that they include a LeafNode extension marking them as such.

TODO: Such an extension would have to be specified in the context of the MLS WG.

3.8. Clients and users

TODO: This section needs to be revisited once identifiers and client/user authentication in general have been decided on by the MIMI WG.

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.

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.

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 Section 11.

3.9. Version agility

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 [I-D.ietf-mls-protocol]).

MLS DS protocol clients MUST make use of a LeafNode extension to advertise the MIMI DS protocol versions they support.

TODO: Such an extension would have to be specified in the context of the MLS WG.

3.10. Group lifecycle

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.

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.

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 [I-D.ietf-mls-protocol] to create a new group with a new set of parameters.

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.

If a group is no longer used, it can be deleted either by a client or the DS itself.

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.

3.11. Framing and processing overview

3.11.1. Client to server requests

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.

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;

A DS supports a variety of operations. For presentational reasons, we only define DSRequestType and the corresponding case statement in DSRequestBody partially here. A more complete definition with all operations relevant for the normal DS operating mode can be found in Section 6, while the full definition including the operations relevant for the Reduced Metadata operating mode and can be found in Section 11.

The authentication_data field of a DSRequest depends on the request type and contains the data necessary for the DS to authenticate the request.

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;

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 Section 11.

Before the DS performs the requested operation, it performs an authentication operation depending on the DSAuthType.

  • Anonymous: No authentication required
  • ClientSignature: The DS uses the public signature key of the MLS client in leaf with the leaf index sender_index to verify the signature over the following struct:
struct {
  DSProtocolVersion protocol_version;
  DSRequestBody request_body;
  u32 sender_index
} ClientSignatureTBS

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).

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.

After performing the desired operation using the data in DSRequestBody the DS responds to the client (or the proxying guest DS) with a DSResponse.

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

3.11.2. Server to server requests

After sending the response, and depending on the operation the DS might fan out messages to one or more guest DSs.

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.

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.

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

The DS receiving a DSFanoutRequest can then store and forward the contained MLS message to the clients indicated in the recipients field.

For presentational reasons, we only define DSRecipientType and the corresponding case statement in DSRecipient partially here. The rest of the definition is relevant only for the Reduced Metadata operating mode and can be found in Section 11.

The receiving DS verifies the signature using the sending DS' public signature key, process the message and sends a DSFanoutResponse.

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

3.11.3. AddPackages

As noted in Section 3.7, 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.

struct {
  KeyPackage key_package;
  optional<RMAddPackageData> rm_data;
} AddPackage

AddPackages are also used to wrap connection KeyPackages. An AddPackage that contains a connection KeyPackages is also called a connection AddPackage.

3.12. Connection establishment flow

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.

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.

Alice Owning DS Guest DS Bob Request Connection AddPackages Connection AddPackages Create Connection group Add Responder Deliver Welcome Fan out Welcome (proprietary protocol)
Figure 5: Example flow for connection establishment

4. DS assisted joining

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.

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.

struct {
  Extension group_info_extensions<V>;
  opaque Signature<V>;
} PartialGroupInfo

The combination of a commit and a partial group info is called an MLSGroupUpdate.

struct {
  MLSMessage commit;
  PartialGroupInfo partial_group_info;
} MLSGroupUpdate

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.

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.

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.

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.

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.

5. Handling of standalone MLS Proposals

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.

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.

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.

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.

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.

Such an additional proposal MUST be committed by reference.

To allow the DS to send proposals, all groups MUST contain an external_senders extension as defined in Section 12.1.8.1. of [I-D.ietf-mls-protocol] that includes the DS' credential and its signature public key.

TODO: Details of the DS credential. A BasicCredential with the FQDN of the DS would probably be sufficient.

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.

6. Operations

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.

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;

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.

Additional variants specific to the privacy preserving mode, as well as the corresponding rest of the case statement can be found in Section 11.

6.1. Request group id

Clients can use this operation to request a group id. This group ID can subsequently used to create a group on this DS.

After receiving this request, the DS generates a unique group id and responds with a DSResponse struct of type GroupID.

6.2. Create group

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.

The client sends the following CreateGroupRequest to the Delivery Service:

struct {
  opaque group_id<V>;
  LeafNode LeafNode;
  MLSMessage group_info;
  optional<RMCreateGroupData>
} CreateGroupRequest;

The Delivery Service internally creates and stores the group based on the information in the request and responds with a CreateGroupResponse:

enum {
  invalid_group_id(0),
  invalid_leaf_node(1),
  invalid_group_info(2),
} CreateGroupResponse;

TODO: How to mark connection groups? Have the creator include a connection extension in the LeafNode?

Validation:

The Delivery Service validates the request as follows:

  • The group ID is not empty and is not already in use.
  • The LeafNode is valid, according to [I-D.ietf-mls-protocol] 7.3. Leaf Node validation.
  • The GroupInfo is valid, according to [I-D.ietf-mls-protocol] 12.4.3. Adding Members to the Group.

6.3. Delete group

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.

struct {
  MLSGroupUpdate group_update;
} DeleteGroupRequest;

Validation:

The Delivery Service validates the request as follows:

  • The MLSGroupUpdate must contain a PublicMessage with a commit that contains remove proposals for every member of the group except the committer.

6.4. Add users to a group

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.

To obtain the AddPackages required to add the users' clients, the sender must first fetch the clients' AddPackages from their DS.

struct {
  MLSMessage welcome;
  optional<RMWelcomeData> rm_data;
} WelcomePackage

struct {
  MLSGroupUpdate group_update;
  WelcomePackage welcome_packages<V>;
  optional<RMAddClientsData> rm_data;
} AddUsersRequest;

Validation:

  • The MLSGroupUpdate in the commit field must contain a PublicMessage with a commit that contains only Add proposals.
  • The commit MUST NOT change the sender's client credential.
  • Add proposals must not contain clients of existing group members.
  • Add proposals must not contain connection AddPackages, except if the group is a connection group.
  • If guest users are added as part of the request, there has to be a distinct Welcome message for each guest DS involved.

6.5. Remove users from a group

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.

struct {
  MLSGroupUpdate group_update;
} RemoveUsersRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage with a commit that contains only remove proposals.
  • The commit MUST NOT change the sender's client credential.
  • The remove proposals in the commit MUST always remove all clients of one or more users.

6.6. Add clients to a group

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.

struct {
  MLSGroupUpdate group_update;
  WelcomePackage welcome_packages<V>;
  optional<RMAddClientsData> rm_data;
} AddClientsRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage with a commit that contains only add proposals.
  • The commit MUST NOT change the sender's client credential.
  • All Add proposals must contain clients of the same user as an existing group member.

6.7. Remove clients from a group

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.

struct {
  MLSGroupUpdate group_update;
} RemoveClientsRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage with a commit that contains only remove proposals.
  • The commit MUST NOT change the sender's client credential.
  • All remove proposals must target clients of the same user as the sending client.

6.8. Self remove a client from a group

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 Section 5 for more details.

struct {
  MLSMessage proposal;
} SelfRemoveClientRequest;

Validation:

  • The MLSMessage must contain a PublicMessage that contains a single remove proposal.
  • The remove proposal must target the sending client.

6.9. Update a client in a group

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.

struct {
  MLSGroupUpdate group_update;
  optional<RMUpdateClientData> rm_data;
} UpdateClientRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage that contains a commit with an UpdatePath, but without other proposals.
  • If the leaf credential is changed by the update, the DS must validate the new credential.

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.

6.10. Join the group using an external commit

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.

To retrieve the information necessary to create the external commit, the joiner has to fetch the external commit information from the DS.

struct {
  MLSGroupUpdate group_update;
  optional<RMExternalJoinData> rm_data;
} ExternalJoinRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage that contains a commit with sender type NewMemberCommit.
  • The sender of the ExternalJoinRequest must be a client that belongs to a user that is already in the group.

6.11. Send an application message to a group

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).

struct {
  MLSMessage application_message;
} SendMessageRequest;

Validation:

  • The MLSMessage must contain a PrivateMessage with ContentType application.

6.12. Fetch the DS' signature public key

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 Section 5), clients should use the signature key included in the group's external_senders extension to validate those.

The DS responds with a DSResponse of type SignaturePublicKey that contains the signature public key of this DS.

6.13. Fetch AddPackages of one or more clients

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.

struct {
  ClientID client_identifiers<V>;
} AddPackagesRequest;

The DS responds with the AddPackages of all clients listed in the request.

Validation:

  • All client identifiers must refer to clients native to this DS.
  • 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).

6.14. Fetch connection AddPackages of one or more clients

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.

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.

struct {
  UserID user_identifier;
} ConnectionAddPackagesRequest;

The DS responds with connection AddPackages of all clients of the user corresponding to the identifier in the request.

Validation:

  • All client identifiers must refer to clients native to this DS.
  • All clients referred to by the identifiers must belong to the same user.

6.15. ReInitialize a group

A request from a client to re-initialize a group with different parameters as outlined in Section 3.10.

struct {
  MLSGroupUpdate commit;
} ReInitializeGroupRequest;

Validation:

  • The MLSGroupUpdate must contain a PublicMessage that contains a commit with a re-init proposal.
  • 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.

7. DSFanoutRequests and DS-to-DS authentication

After the DS has processed an incoming MLSMessage, it prepars a DSFanoutRequest as described in Section 3.11.

To authenticate these messages, an additional layer of DS-to-DS authentication is required. As defined in Section 3.11, 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.

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.

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.

8. Role-based access control in groups

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.

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.

struct {
  uint32 admins<V>;
} RBACExtension

The RBACExtension supports two roles: Members and Admins. Since all group members are Members by default, the extension only lists admins.

Any client the leaf node index of which is listed in the admins 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.

The SetRole operation is an additional operation available to groups that have an RBACExtension.

struct {
  MLSGroupUpdate group_update;
} SetRoleRequest

The group_update needs to contain a commit which commits to a single RBACProposal.

struct {
  uint32 promoted_members;
  uint32 demoted_members;
} SetRole

The DS (and all clients) process this proposal by changing the role of the group members with the leaf indices listed in the promoted_members and demoted_members fields and change the admins field of the group's RBACExtension accordingly. For example, if the leaf index admin is listed in the changed_members field of the proposal, it is demoted to Member and removed from the admins field. Similarly, if a Member is listed, it is promoted to Admin and added to the admins field.

9. Rate-limiting and spam prevention

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.

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.

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.

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.

10. Abusive and illegal content

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.

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.

11. Reduced metadata operating mode

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:

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.

11.1. Connection key material

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.

struct {
  opaque connection_token<0..255>;
  opaque welcome_data_encryption_key<0..255>;
  opaque de_pseudonymization_key<0..255>;
} ConnectionKeyMaterial

The exact nature of the keys and what they are used for will become apparent in the following sections.

11.2. Group-level encryption keys

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.

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.

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

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.

11.3. Pseudonymous client identifiers and authentication

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.

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.

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.

Since the signature would reveal which client has signed a pseudonymized credential, that signature MUST be encrypted symmetrically using a signature encryption key.

TODO: The authenticated encryption scheme used for the encryption should be determined by the MIMI DS protocol version.

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.

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 Section 11.9 for more details.)

11.3.1. Signature encryption key management

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.

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.

struct {
  opaque encrypted_signature_encryption_key<0..255>;
} EncryptedSignatureEncryptionKey

11.3.2. Client credential encryption

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.

struct {
  opaque encrypted_client_credential<0..255>;
} EncryptedClientCredential

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.

struct {
  EncryptedSignatureEncryptionKey encrypted_signature_encryption_keys<V>;
  EncryptedClientCredential encrypted_client_credentials<V>;
} RMAddClientsData

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.

11.4. Pseudonymous user identifiers and authentication

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.

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.

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.

11.5. AddPackage retrieval

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.

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.

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;

11.6. Pseudonymized fan-out

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.

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.

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;

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.

Additionally, clients can update their FanoutPseudonym whenever they perform an update operation.

struct {
  optional<EncryptedSignatureEncryptionKey> encrypted_signature_encryption_key;
  optional<EncryptedClientCredential> encrypted_client_credential;
  optional<opaque> user_authentication_key;
  optional<FanoutPseudonym> fan_out_pseudonym
} RMUpdateClientData

TODO: This extension would have to be defined in the context of the MLS WG.

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 destination_address 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.

11.7. Group state encryption at rest

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.

struct {
  opaque group_state_ear_key<0..255>;
} RMGroupStateEARKey

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.

11.8. External joins

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.

11.9. Reduced metadata connection establishment

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.

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 hpke_init_key in that KeyPackage.

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

The recipient_identifier represents the real client identifier of the responding client.

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.

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 key_package_ref and the encrypted_connection_establishment_info to the client identified by the recipient_identifier.

The recipient can then determine the hpke_init_key of which KeyPackage to use and decrypt the ConnectionEstablishmentInfo. It can then perform an external join operation on the group indicated by the connection_group_id using the group_level_keys.

The users can then exchange information like the connection token via the connection group.

12. Security considerations

TODO: There is currently no consensus in the MIMI w.r.t. the security goals we want to reach.

The underlying MLS protocol provides end-to-end encryption and authentication for all MLSMessages, as well as group state agreement.

12.1. Transport Security

Transport of DSFanoutRequests, as well as their responses MUST use a recipient authenticated transport. This is to ensure that these messages are mutually authenticated.

To protect the metadata in all request-response flows, requests and responses SHOULD be secured using an encrypted transport channel.

13. Normative References

[I-D.ietf-mls-protocol]
Barnes, R., Beurdouche, B., Robert, R., Millican, J., Omara, E., and K. Cohn-Gordon, "The Messaging Layer Security (MLS) Protocol", Work in Progress, Internet-Draft, draft-ietf-mls-protocol-20, , <https://datatracker.ietf.org/doc/html/draft-ietf-mls-protocol-20>.
[RFC8446]
Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/rfc/rfc8446>.

Authors' Addresses

Raphael Robert
Phoenix R&D
Konrad Kohbrok
Phoenix R&D