title: "Using Messaging Layer Security to Synchronize Application State" abbrev: "MLS AppSync" category: info
docname: draft-barnes-mls-appsync-latest submissiontype: IETF number: date: consensus: true v: 3 area: "Security" workgroup: "Messaging Layer Security" keyword:
- messaging layer security
- end-to-end encryption venue: group: "Messaging Layer Security" type: "Working Group" mail: "mls@ietf.org" arch: "https://mailarchive.ietf.org/arch/browse/mls/" github: "bifurcation/mls-appsync" latest: "https://bifurcation.github.io/mls-appsync/draft-barnes-mls-appsync.html"
fullname: Richard Barnes
organization: Cisco
email: rlb@ipv.sx
- fullname: Rohan Mahy organization: Rohan Mahy Consulting Services email: rohan.ietf@gmail.com
normative:
informative:
--- abstract
One feature that the Messaging Layer Security (MLS) protocol provides is that it allows the members of a group to confirm that they agree on certain data. In this document, we define a mechanism for applications using MLS to exploit this feature of MLS to ensure that the group members are in agreement on the state of the application in addition to MLS-related state. We define a GroupContext extension that captures the state of the application and an AppSync proposal that can be used to update the application state.
--- middle
Messaging Layer Security (MLS) allows a group of clients to authenticate each other and establish shared secret state {{!RFC9420}}. One of the primary security benefits of MLS is that the MLS key schedule confirms that the group agrees on certain metadata, such as the membership of the group. Members that disagree on the relevant metadata will arrive at different keys and be unable to communicate. Applications based on MLS can integrate their state into this metadata in order to confirm that the members of an MLS group agree on application state as well as MLS metadata.
Here, we define two extensions to MLS to facilitate this application design:
- A GroupContext extension
application_states
that confirms agreement on application state from potentially multiple sources. - A new proposal type AppSync that allows MLS group members to propose changes to the agreed application state.
{::boilerplate bcp14-tagged}
This document defines a new AppSync proposal. AppSync is a Safe Extension as
defined in {{Section 2 of !I-D.ietf-mls-extensions}}, of type
extension_external_proposal
.
The application_states
extension allows the application to inject state
objects into the MLS key schedule. Changes to this state can be made out of
band, or using the AppSync proposal. Using the AppSync proposal ensures that
members of the MLS group have received the relevant state changes before they
are reflected in the group's application_states
.
NOTE: This design exposes the high-level structure of the application state to MLS. An alternative design would be to have the application state be opaque to MLS. There is a trade-off between generality and the complexity of the API between the MLS implementation and the application. An opaque design would give the application more freedom, but require the MLS stack to call out to the application to get the updated state as part of Commit processing. This design allows the updates to happen within the MLS stack, so that no callback is needed, at the cost of forcing the application state to fit a certain structure. It also potentially can result in smaller state updates in large groups.
The state for Each applicationId
in the application_states
needs to conform
to one of four basic types: an ordered array, an unordered array, a map, or an
irreducible blob. This allows the AppSync proposal to efficiently modify a large
application state object.
The content of the application_states
extension and the AppSync
proposal are
structured as follows:
enum {
irreducible(0),
map(1),
unorderedList(2),
orderedArray(3),
(255)
} StateType;
struct {
opaque element<V>;
} OpaqueElement;
struct {
opaque elementName<V>;
opaque elementValue<V>;
} OpaqueMapElement;
struct {
uint32 applicationId;
StateType stateType;
select (stateType) {
case irreducible:
OpaqueElement state;
case map:
OpaqueMapElement mapEntries<V>;
case unorderedList:
OpaqueElement unorderedEntries<V>;
case orderedArray:
OpaqueElement orderedEntries<V>;
};
} ApplicationState;
struct {
ApplicationState applicationStates<V>;
} ApplicationStatesExtension;
{: #fig-app-state title="The application_state
extension" }
struct {
uint32 index;
opaque element<V>;
} ElementWithIndex;
struct {
uint32 applicationId;
StateType stateType;
select (stateType) {
case irreducible:
OpaqueElement newState;
case map:
OpaqueElement removedKeys<V>;
OpaqueMapElement newOrUpdatedElements<V>;
case unorderedList:
uint32 removedIndices<V>;
OpaqueElement addedEntries<V>;
case orderedArray:
ElementWithIndex replacedElements<V>;
uint32 removedIndices<V>;
ElementWithIndex insertedElements<V>;
OpaqueElement appenededEntries<V>;
};
} AppSync;
{: #fig-app-sync title="The AppSync proposal type" }
The applicationId
determines the structure and interpretation of the contents.
of an ApplicationState object. AppSync proposals
contain changes to this state, which the client uses to update the
representation of the state in application_states
.
A client receiving an AppSync proposal applies it in the following way:
- Identify an
application_states
GroupContext extension which contains the sameapplication_id
state as the AppSync proposal - Apply the relevant operations (replace, remove, update, append, insert)
according to the
stateType
to the relevant parts of the ApplicationState object inapplication_states
extension.
An AppSync for an irreducible state replaces its state
element with a new
(possibly empty) newState
. An AppSync for a map-based ApplicationState first
removes all the keys in removedKeys
and than replaces or adds the elements in
newOrUpdatedElements
. An AppSync for an unorderedList ApplicationState first
removes all the indexes in removedIndices
, then adds the elements in
addedEntries
. Finally an AppSync for an orderedArray, replaces all the
elements (index-by-index) in replacedElements
, the removes the elements in
removedIndices
according to the then order of the array, then inserts all the
elements in insertedElements
according to the then order of the array, then
finally appends the appendedEntries
(in order). All indices are zero-based.
Note that the application_states
extension is updated directly by AppSync
proposals; a GroupContextExtensions proposal is not necessary. A proposal list
that contains both an AppSync proposal and a GroupContextExtensions proposal
is invalid.
Likewise a proposal list in a Commit MAY contain more than one AppSync proposal,
but no more than one AppSync proposal per applicationId
. The proposals are
applied in the order that they are sent in the Commit.
AppSync proposals do not need to contain an UpdatePath. An AppSync proposal can be sent by an authorized external sender.
The mechanism defined in this document provides strong authenticity, integrity, and change control properties to the application state information it manages. Nobody outside the group can make changes to the application state, and the identity of the group member making each change is authenticated.
The application data synchronized via this mechanism may or may not be confidential to the group, depending on whether the AppSync proposal is sent as an MLS PublicMessage or PrivateMessage. As with application data, applications should generally prefer the use of Private Message. There may be cases, however, where it is useful for intermediaries to inspect application state updates, e.g., to enforce policy.
TODO: Register new extension and proposal types.
TODO: IANA registry for
application_id
; register extension and proposal types as safe extensions
--- back
{:numbered="false"}
TODO: Acknowledgements.