Internet-Draft | MIMI | July 2023 |
Robert & Kohbrok | Expires 11 January 2024 | [Page] |
This document describes the MIMI Delivery Service.¶
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.¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
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.¶
This document uses the terminology defined in [I-D.ietf-mls-protocol] with the following additions:¶
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.¶
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.¶
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.¶
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.¶
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.¶
The MIMI DS protocol allows guest clients to request a variety of operations for example to manage group membership, join groups, or send messages.¶
Independent of client requests, the Delivery Service itself can remove clients from a group by issuing remove proposals in the following cases:¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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¶
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¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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:¶
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:¶
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:¶
commit
field must contain a PublicMessage with a
commit that contains only Add proposals.¶
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:¶
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:¶
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:¶
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:¶
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:¶
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.¶
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:¶
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:¶
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.¶
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:¶
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:¶
A request from a client to re-initialize a group with different parameters as outlined in Section 3.10.¶
struct { MLSGroupUpdate commit; } ReInitializeGroupRequest;¶
Validation:¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.)¶
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¶
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.¶
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.¶
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;¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶