Draft: draft-ietf-mls-protocol

Commentary: Merge+Squash from  and apply editorial fixes
Paragraph (version A):
An agent that uses this protocol to establish shared cryptographic
state with other clients.  A client is defined by the
cryptographic keys it holds.  An application or user may use one
client per device (keeping keys local to each device) or sync keys
among a user's devices so that each user appears as a single
client.  In the scenario where multiple devices share the
cryptographic material the client is referred to as a "virtual"
client.
Paragraph (version B):
An agent that uses this protocol to establish shared cryptographic
state with other clients.  A client is defined by the
cryptographic keys it holds.  An application or user may use one
client per device (keeping keys local to each device) or sync keys
among a user's devices so that each user appears as a single
client.
Paragraph (version A):
A short-lived HPKE key pair used to introduce a new client to a
group.  Initialization keys are published for each client
(ClientInitKey).
Paragraph (version A):
A secret that represents a member's contribution to the group
secret (so called because the members' leaf keys are the leaves in
the group's ratchet tree).
Paragraph (version B):
A short-lived HPKE key pair used to introduce a new client to a
group.  Initialization keys are published for each client and are
called their ClientInitKeys.
Paragraph (version B):
An HPKE key pair that can be used to encrypt to a specific client,
so called because members' leaf keys are the leaves in the group's
ratchet tree.
Paragraph (version A):
The goal of this protocol is to allow a group of clients to exchange
confidential and authenticated messages.  It does so by deriving a
sequence of secrets and keys known only to members.  Those should be
secret against an active network adversary and should have both
forward and post-compromise secrecy with respect to compromise of a
participant.
Paragraph (version A):
We describe the information stored by each client as a _state_, which
includes both public and private data.  An initial state, including
an initial set of clients, is set up by a group creator using the
_Init_ algorithm and based on information pre-published by clients.
The creator sends the _Init_ message to the clients, who can then set
up their own group state and derive the same shared secret.  Clients
then exchange messages to produce new shared states which are
causally linked to their predecessors, forming a logical Directed
Acyclic Graph (DAG) of states.  Members can send _Commit_ messages
for post-compromise secrecy and new clients can be added or existing
members removed from the group.
Paragraph (version B):
The goal of this protocol is to allow a group of clients to exchange
confidential and authenticated messages.  It does so by deriving a
sequence of secrets and keys known only to members.  Those should be
secret against an active network adversary and should have both
forward secrecy and post-compromise security with respect to
compromise of any members.
Paragraph (version B):
We describe the information stored by each client as _state_, which
includes both public and private data.  An initial state is set up by
a group creator, which is a group containing only themself.  The
creator then sends _Add_ proposals for each client in the initial set
of members, followed by a _Commit_ message which incorporates all of
the _Adds_ into the group state.  Finally, the group creator
generates a _Welcome_ message corresponding to the Commit and sends
this directly to all the new members, who can use the information it
contains to set up their own group state and derive a shared secret.
Members exchange Commit messages for post-compromise security, to add
new members, and to remove existing members.  These messages produce
new shared secrets which are causally linked to their predecessors,
forming a logical Directed Acyclic Graph (DAG) of states.
Paragraph (version A):
Before the initialization of a group, clients publish ClientInitKey
objects to a directory provided to the Messaging Service.
Paragraph (version A):
When a client A wants to establish a group with B and C, it first
downloads ClientInitKeys for B and C.  It then initializes a group
state containing only itself and uses the ClientInitKeys to compute
Welcome and Add messages to add B and C, in a sequence chosen by A.
The Welcome messages are sent directly to the new members (there is
no need to send them to the group).  The Add messages are broadcasted
to the group, and processed in sequence by B and C.  Messages
received before a client has joined the group are ignored.  Only
after A has received its Add messages back from the server does it
update its state to reflect their addition.
Paragraph (version A):
Subsequent additions of group members proceed in the same way.  Any
member of the group can download an ClientInitKey for a new client
and broadcast an Add message that the current group can use to update
their state and the new client can use to initialize its state.
Paragraph (version A):
To enforce forward secrecy and post-compromise security of messages,
each member periodically updates its leaf secret which represents its
contribution to the group secret and its member information.  Any
member can update this information at any time by generating a fresh
ClientInitKey and sending a Commit message.  Once all members have
processed this message, the group's secrets will be unknown to an
attacker that had compromised the sender's prior leaf secret.
Paragraph (version A):
It is left to the application to determine the interval of time
between Commit messages.  This policy could require a Commit with
each message, or require sending an update regularly.
Paragraph (version A):
Members are removed from the group in a similar way, as a Commit is
effectively removing the old leaf from the group.  Any member of the
group can generate a Remove proposal followed by a Commit message
that adds new entropy to the group state that is known to all members
except the removed member.  After other participants have processed
this message, the group's secrets will be unknown to the removed
participant.  Note that this does not necessarily imply that any
member is actually allowed to evict other members; groups can layer
authentication-based access control policies on top of these basic
mechanism.
Paragraph (version B):
Before the initialization of a group, clients publish ClientInitKey
objects to a directory provided by the Messaging Service.
Paragraph (version B):
When a client A wants to establish a group with B and C, it first
downloads ClientInitKeys for B and C.  It then initializes a group
state containing only itself and uses the ClientInitKeys to compute
Welcome and Add messages to add B and C, in a sequence chosen by A.
The Welcome messages are sent directly to the new members (there is
no need to send them to the group).  The Add messages are broadcast
to the group, and processed in sequence by B and C.  Messages
received before a client has joined the group are ignored.  Only
after A has received its Add messages back from the server does it
update its state to reflect their addition.
Paragraph (version B):
Subsequent additions of group members proceed in the same way.  Any
member of the group can download a ClientInitKey for a new client and
broadcast an Add message that the current group can use to update
their state and a Welcome message that the new client can use to
initialize its state.
Paragraph (version B):
To enforce forward secrecy and post-compromise security of messages,
each member periodically updates their leaf secret.  Any member can
update this information at any time by generating a fresh
ClientInitKey and sending an Update message followed by a Commit
message.  Once all members have processed both, the group's secrets
will be unknown to an attacker that had compromised the sender's
prior leaf secret.
Paragraph (version B):
It is left to the application to determine a policy for regularly
sending Update messages.  This policy can be as strong as requiring
an Update+Commit after each application message, or weaker, such as
once every hour, day...
Paragraph (version B):
Members are removed from the group in a similar way.  Any member of
the group can send a Remove proposal followed by a Commit message,
which adds new entropy to the group state that's known to all except
the removed member.  Note that this does not necessarily imply that
any member is actually allowed to evict other members; groups can
enforce access control policies on top of these basic mechanism.
Paragraph (version A):
A binary tree is _left-balanced_ if for every parent, either the
parent is balanced, or the left subtree of that parent is the largest
full subtree that could be constructed from the leaves present in the
parent's own subtree.  Note that given a list of "n" items, there is
a unique left-balanced binary tree structure with these elements as
leaves.  In such a left-balanced tree, the "k-th" leaf node refers to
the "k-th" leaf node in the tree when counting from the left,
starting from 0.
Paragraph (version B):
A binary tree is _left-balanced_ if for every parent, either the
parent is balanced, or the left subtree of that parent is the largest
full subtree that could be constructed from the leaves present in the
parent's own subtree.  Given a list of "n" items, there is a unique
left-balanced binary tree structure with these elements as leaves.
In such a left-balanced tree, the "k-th" leaf node refers to the
"k-th" leaf node in the tree when counting from the left, starting
from 0.
Paragraph (version A):
A Derive-Key-Pair function that produces an asymmetric key pair
for the specified KEM from a symmetric secret, using the specified
hash function.
Paragraph (version A):
No participant in an MLS group has full knowledge of the secret state
of the tree, i.e., private keys associated with the nodes.  Instead,
each member is assigned to a leaf of the tree, which determines the
set of secret state known to the member.  The credential stored at
that leaf is one provided by the member.
Paragraph (version A):
In other words, if a node is not blank, then it holds a key pair, and
the private key of that key pair is known only to members holding
leaves below that node.
Paragraph (version B):
No participant in an MLS group knows the private key associated with
every node in the tree.  Instead, each member is assigned to a leaf
of the tree, which determines the subset of private keys it knows.
The credential stored at that leaf is one provided by the member.
Paragraph (version B):
In other words, if a node is not blank, then it holds a public key.
The corresponding private key is known only to members occupying
leaves below that node.
Paragraph (version A):
When performing a Commit, the leaf ClientInitKey of the commiter and
its direct path to the root are updated with new secret values.  The
HPKE leaf public key within the ClientInitKey MUST be a freshly
generated value to provide better Post-Compromise Secrecy.
Paragraph (version B):
When performing a Commit, the leaf ClientInitKey of the committer and
its direct path to the root are updated with new secret values.  The
HPKE leaf public key within the ClientInitKey MUST be a freshly
generated value to provide post-compromise security.
Paragraph (version A):
The path secret value for a given node is encrypted for the subtree
corresponding to the parent's non-updated child, i.e., the child on
the copath of the leaf node.  There is one encrypted path secret for
each public key in the resolution of the non-updated child.  In
particular, for the leaf node, there are no encrypted secrets, since
a leaf node has no children.
Paragraph (version B):
The path secret value for a given node is encrypted for the subtree
corresponding to the parent's non-updated child, that is, the child
on the copath of the leaf node.  There is one encrypted path secret
for each public key in the resolution of the non-updated child.  In
particular, for the leaf node, there are no encrypted secrets, since
a leaf node has no children.
Paragraph (version A):
The "confirmed_transcript_hash" field contains a running hash over
the handshake messages that led to this state.
Paragraph (version B):
The "confirmed_transcript_hash" field contains a running hash over
the messages that led to this state.
Paragraph (version A):
Thus the "confirmed_transcript_hash" field in a GroupContext object
represents a transcript over the whole history of MLSPlaintext Commit
messages, up to the confirmation field in the current MLSPlaintext
message.  The confirmation and signature fields are then included in
the transcript for the next epoch.  The interim transcript hash is
passed to new members in the WelcomeInfo struct, and enables existing
members to incorporate a handshake message into the transcript
without having to store the whole MLSPlaintextCommitAuthData
structure.
Paragraph (version B):
Thus the "confirmed_transcript_hash" field in a GroupContext object
represents a transcript over the whole history of MLSPlaintext Commit
messages, up to the confirmation field in the current MLSPlaintext
message.  The confirmation and signature fields are then included in
the transcript for the next epoch.  The interim transcript hash is
passed to new members in the WelcomeInfo struct, and enables existing
members to incorporate a Commit message into the transcript without
having to store the whole MLSPlaintextCommitAuthData structure.
Paragraph (version A):
The signature field in an MLSPlaintext object is computed using the
signing private key corresponding to the credential at the leaf in
the tree indicated by the sender field.  The signature covers the
plaintext metadata and message content, i.e., all fields of
MLSPlaintext except for the "signature" field.  The signature also
covers the GroupContext for the current epoch, so that signatures are
specific to a given group and epoch.
Paragraph (version B):
The signature field in an MLSPlaintext object is computed using the
signing private key corresponding to the credential at the leaf in
the tree indicated by the sender field.  The signature covers the
plaintext metadata and message content, which is all of MLSPlaintext
except for the "signature" field.  The signature also covers the
GroupContext for the current epoch, so that signatures are specific
to a given group and epoch.
Paragraph (version A):
The sender of a Commit message MUST include in it all valid Proposals
that the sender has received during the current epoch.  Invalid
Proposals include, for example, Proposals with an invalid signature
or Proposals that are semantically inconsistent, such as a Remove
proposal for an unoccupied leaf.  The Commit MUST NOT combine
Proposals sent within different epochs.  Despite these requirements,
it is still possible for a valid Proposal not to be covered by a
Commit, e.g., because the sender of the Commit did not receive the
Proposal.  In such cases, the sender of the proposal can retransmit
the Proposal in the new epoch.  In the case where a committer is
processing Proposals where an Update proposal or a Remove proposal
exists for herself, this proposal MUST be ignored and added to the
list of discarded proposals in the Commit.
Paragraph (version B):
The sender of a Commit message MUST include in it all valid Proposals
that the sender has received during the current epoch.  Invalid
Proposals include, for example, Proposals with an invalid signature
or Proposals that are semantically inconsistent, such as a Remove
proposal for an unoccupied leaf.  The Commit MUST NOT combine
Proposals sent within different epochs.  Despite these requirements,
it is still possible for a valid Proposal not to be covered by a
Commit, for example, because the sender of the Commit did not receive
the Proposal.  In such cases, the sender of the proposal can
retransmit the Proposal in the new epoch.  In the case where a
committer is processing Proposals where an Update proposal or a
Remove proposal exists for herself, this proposal MUST be ignored and
added to the list of discarded proposals in the Commit.
Paragraph (version A):
Identify a leaf in the "tree" array (i.e., an even-numbered node)
whose "public_key" and "credential" fields are identical to the
corresponding fields in the ClientInitKey.  If no such field
exists, return an error.  Let "index" represent the index of this
node among the leaves in the tree, namely the index of the node in
the "tree" array divided by two.
Paragraph (version B):
Identify a leaf in the "tree" array whose "public_key" and
"credential" fields are identical to the corresponding fields in
the ClientInitKey.  If no such field exists, return an error.  Let
"index" represent the index of this node among the leaves in the
tree, namely the index of the node in the "tree" array divided by
two.
Paragraph (version A):
Each handshake message is premised on a given starting state,
indicated in its "prior_epoch" field.  If the changes implied by a
handshake messages are made starting from a different state, the
results will be incorrect.
Paragraph (version A):
This need for sequencing is not a problem as long as each time a
group member sends a handshake message, it is based on the most
current state of the group.  In practice, however, there is a risk
that two members will generate handshake messages simultaneously,
based on the same state.
Paragraph (version A):
As long as handshake messages cannot be merged, there is a risk of
starvation.  In a sufficiently busy group, a given member may never
be able to send a handshake message, because he always loses to other
members.  The degree to which this is a practical problem will depend
on the dynamics of the application.
Paragraph (version A):
It might be possible, because of the non-contributivity of
intermediate nodes, that Commit messages could be applied one after
the other without the Delivery Service having to reject any handshake
message, which would make MLS more resilient regarding the
concurrency of handshake messages.  The Messaging system can decide
to choose the order for applying the state changes.  Note that there
are certain cases (if no total ordering is applied by the Delivery
Service) where the ordering is important for security, ie. all
updates must be executed before removes.
Paragraph (version A):
Regardless of how messages are kept in sequence, implementations MUST
only update their cryptographic state when valid handshake messages
are received.  Generation of handshake messages MUST be stateless,
since the endpoint cannot know at that time whether the change
implied by the handshake message will succeed or not.
Paragraph (version B):
Each Commit message is premised on a given starting state, indicated
in its "prior_epoch" field.  If the changes implied by a Commit
messages are made starting from a different state, the results will
be incorrect.
Paragraph (version B):
This need for sequencing is not a problem as long as each time a
group member sends a Commit message, it is based on the most current
state of the group.  In practice, however, there is a risk that two
members will generate Commit messages simultaneously, based on the
same state.
Paragraph (version B):
As long as Commit messages cannot be merged, there is a risk of
starvation.  In a sufficiently busy group, a given member may never
be able to send a Commit message, because he always loses to other
members.  The degree to which this is a practical problem will depend
on the dynamics of the application.
Paragraph (version B):
It might be possible, because of the non-contributivity of
intermediate nodes, that Commit messages could be applied one after
the other without the Delivery Service having to reject any Commit
message, which would make MLS more resilient regarding the
concurrency of Commit messages.  The Messaging system can decide to
choose the order for applying the state changes.  Note that there are
certain cases (if no total ordering is applied by the Delivery
Service) where the ordering is important for security, ie. all
updates must be executed before removes.
Paragraph (version B):
Regardless of how messages are kept in sequence, implementations MUST
only update their cryptographic state when valid Commit messages are
received.  Generation of handshake messages MUST be stateless, since
the endpoint cannot know at that time whether the change implied by
the handshake message will succeed or not.
Paragraph (version A):
As soon as a group member consumes a value they MUST immediately
delete (all representations of) that value.  This is crucial to
ensuring Forward Secrecy for past messages.  Members MAY keep
unconsumed values around for some reasonable amount of time even if
their generating secret was already consumed (e.g. due to out of
order message delivery).
Paragraph (version B):
As soon as a group member consumes a value they MUST immediately
delete (all representations of) that value.  This is crucial to
ensuring forward secrecy for past messages.  Members MAY keep
unconsumed values around for some reasonable amount of time to handle
out-of-order message delivery.
Paragraph (version A):
Then if a client uses key KD1 and nonce ND1 during epoch n then it
must consume (at least) values G, F, D0, D1, KD1, ND1 as well as the
"commit_secret" and init_secret used to derive G (i.e. the
application_secret).  The client MAY retain (i.e., not consume) the
values KD0 and ND0 to allow for out-of-order delivery, and SHOULD
retain D2 to allow for processing future messages.
Paragraph (version B):
Then if a client uses key KD1 and nonce ND1 during epoch n then it
must consume (at least) values G, F, D0, D1, KD1, ND1 as well as the
"commit_secret" and init_secret used to derive G (the
application_secret).  The client MAY retain (not consume) the values
KD0 and ND0 to allow for out-of-order delivery, and SHOULD retain D2
to allow for processing future messages.