Draft: draft-ietf-mls-protocol

Commentary: This is just a terminology change . ClientInitKey was feeling increasingly awkward , because ( 1 ) ClientInitKey structs are now used in leaves in addition to being used for initialization , and ( 2 ) there are some emerging cases where the " client " in an MLS sense might be a " server " ( or some other role ) in another application . " KeyPackage " is a more neutral term . Other than , the most invasive change was in Welcome , where we already had and . I just changed those to and , which seem more descriptive anyway . Depends on
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 and are
called their ClientInitKeys.
Paragraph (version A):
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 B):
A signed object describing a clients identity and capabilities,
and including an HPKE public key that can be used to encrypt to
that client.
Paragraph (version B):
A key package that is prepublished by a client, which other
clients can use to introduce the client to a new group.
Paragraph (version A):
A directory to which clients can publish initialization keys and
download initialization keys for other participants.
Paragraph (version B):
A directory to which clients can publish key packages and download
key packages for other participants.
Paragraph (version A):
Before the initialization of a group, clients publish ClientInitKey
objects to a directory provided by 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 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 A):
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 A):
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):
Before the initialization of a group, clients publish InitKeys (as
KeyPackage 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 KeyPackages for B and C.  It then initializes a group state
containing only itself and uses the KeyPackages 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 KeyPackage 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 KeyPackage
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 A):
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 generator of the Commit starts by using the HPKE secret key
"leaf_hpke_secret" associated with the new leaf ClientInitKey (see
initialization-keys) to compute "path_secret[0]" and generate a
sequence of "path secrets", one for each ancestor of its leaf.  That
is, path_secret[0] is used for the node directly above the leaf,
path_secret[1] for its parent, and so on.  At each step, the path
secret is used to derive a new secret value for the corresponding
node, from which the node's key pair is derived.
Paragraph (version B):
When performing a Commit, the leaf KeyPackage of the committer and
its direct path to the root are updated with new secret values.  The
HPKE leaf public key within the KeyPackage MUST be a freshly
generated value to provide post-compromise security.
Paragraph (version B):
The generator of the Commit starts by using the HPKE secret key
"leaf_hpke_secret" associated with the new leaf KeyPackage (see key-
packages) to compute "path_secret[0]" and generate a sequence of
"path secrets", one for each ancestor of its leaf.  That is,
path_secret[0] is used for the node directly above the leaf,
path_secret[1] for its parent, and so on.  At each step, the path
secret is used to derive a new secret value for the corresponding
node, from which the node's key pair is derived.
Paragraph (version A):
The signature algorithm specified in the ciphersuite is the mandatory
algorithm to be used for signatures in MLSPlaintext and the tree
signatures.  It MUST be the same as the signature algorithm specified
in the credential field of the ClientInitKey objects in the leaves of
the tree (including the ClientInitKeys used to add new members).
Paragraph (version B):
The signature algorithm specified in the ciphersuite is the mandatory
algorithm to be used for signatures in MLSPlaintext and the tree
signatures.  It MUST be the same as the signature algorithm specified
in the credential field of the KeyPackage objects in the leaves of
the tree (including the InitKeys used to add new members).
Paragraph (version A):
In order to facilitate asynchronous addition of clients to a group,
it is possible to pre-publish initialization keys that provide some
public information about a user.  ClientInitKey structures provide
information about a client that any existing member can use to add
this client to the group asynchronously.
Paragraph (version A):
A ClientInitKey object specifies a ciphersuite that the client
supports, as well as providing a public key that others can use for
key agreement.  The client's identity key can be updated throughout
the lifetime of the group by sending a new ClientInitKey with a new
identity; the new identity MUST be validated by the authentication
service.  ClientInitKeys are intended to be used only once and SHOULD
NOT be reused except in case of last resort.  (See init-key-reuse).
Clients MAY generate and publish multiple ClientInitKey objects to
support multiple ciphersuites.  ClientInitKeys contain a public key
chosen by the client, which the client MUST ensure uniquely
identifies a given ClientInitKey object among the set of
ClientInitKeys created by this client.
Paragraph (version A):
The value for hpke_init_key MUST be a public key for the asymmetric
encryption scheme defined by cipher_suite.  The whole structure is
signed using the client's identity key.  A ClientInitKey object with
an invalid signature field MUST be considered malformed.  The input
to the signature computation comprises all of the fields except for
the signature field.
Paragraph (version A):
ClientInitKey objects MUST contain at least two extensions, one of
type "supported_versions" and one of type "supported_ciphersuites".
These extensions allow MLS session establishment to be safe from
downgrade attacks on these two parameters (as discussed in group-
creation), while still only advertising one version / ciphersuite per
ClientInitKey.
Paragraph (version A):
As the "ClientInitKey" is a structure which is stored in the Ratchet
Tree and updated depending on the evolution of this tree, each
modification of its content MUST be reflected by a change of its
signature.  This allow other members to control the validity of the
ClientInitKey at any time and in particular in the case of a newcomer
joining the group.
Paragraph (version B):
In order to facilitate asynchronous addition of clients to a group,
it is possible to pre-publish key packages that provide some public
information about a user.  KeyPackage structures provide information
about a client that any existing member can use to add this client to
the group asynchronously.
Paragraph (version B):
A KeyPackage object specifies a ciphersuite that the client supports,
as well as providing a public key that others can use for key
agreement.  The client's identity key can be updated throughout the
lifetime of the group by sending a new KeyPackage with a new
identity; the new identity MUST be validated by the authentication
service.
Paragraph (version B):
When used as InitKeys, KeyPackages are intended to be used only once
and SHOULD NOT be reused except in case of last resort.  (See
initkey-reuse).  Clients MAY generate and publish multiple InitKeys
to support multiple ciphersuites.
Paragraph (version B):
KeyPackages contain a public key chosen by the client, which the
client MUST ensure uniquely identifies a given KeyPackage object
among the set of KeyPackages created by this client.
Paragraph (version B):
The value for hpke_init_key MUST be a public key for the asymmetric
encryption scheme defined by cipher_suite.  The whole structure is
signed using the client's identity key.  A KeyPackage object with an
invalid signature field MUST be considered malformed.  The input to
the signature computation comprises all of the fields except for the
signature field.
Paragraph (version B):
KeyPackage objects MUST contain at least two extensions, one of type
"supported_versions" and one of type "supported_ciphersuites".  These
extensions allow MLS session establishment to be safe from downgrade
attacks on these two parameters (as discussed in group-creation),
while still only advertising one version / ciphersuite per
KeyPackage.
Paragraph (version B):
As the "KeyPackage" is a structure which is stored in the Ratchet
Tree and updated depending on the evolution of this tree, each
modification of its content MUST be reflected by a change of its
signature.  This allow other members to control the validity of the
KeyPackage at any time and in particular in the case of a newcomer
joining the group.
Paragraph (version A):
These extensions MUST be always present in a ClientInitKey.
Paragraph (version A):
The "expiration" extension represents the time at which clients MUST
consider this ClientInitKey invalid.  This time is represented as an
absolute time, measured in seconds since the Unix epoch
(1970-01-01T00:00:00Z).  If a client receives a ClientInitKey that
contains an expiration extension at a time after its expiration time,
then it MUST consider the ClientInitKey invalid and not use it for
any further processing.
Paragraph (version A):
Applications that rely on "last resort" ClientInitKeys MAY set the
expiration to its maximum value even though this is NOT RECOMMENDED.
It is RECOMMENDED to rotate last resort keys at a pace chosen by the
application even though they can have much longer lifetimes than
other ClientInitKeys.
Paragraph (version A):
This extension MUST always be present in a ClientInitKey.
Paragraph (version A):
Within MLS, a ClientInitKey is identified by its hash (see, e.g.,
welcoming-new-members).  The "key_id" extension allows applications
to add an explicit, application-defined identifier to a
ClientInitKey.
Paragraph (version A):
The "parent_hash" extension serves to bind a ClientInitKey to all the
nodes above it in the group's ratchet tree.  This enforces the tree
invariant, meaning that malicious members can't lie about the state
of the ratchet tree when they send Welcome messages to new members.
Paragraph (version B):
These extensions MUST be always present in a KeyPackage.
Paragraph (version B):
The "expiration" extension represents the time at which clients MUST
consider this KeyPackage invalid.  This time is represented as an
absolute time, measured in seconds since the Unix epoch
(1970-01-01T00:00:00Z).  If a client receives a KeyPackage that
contains an expiration extension at a time after its expiration time,
then it MUST consider the KeyPackage invalid and not use it for any
further processing.
Paragraph (version B):
Applications that rely on "last resort" KeyPackages MAY set the
expiration to its maximum value even though this is NOT RECOMMENDED.
It is RECOMMENDED to rotate last resort keys at a pace chosen by the
application even though they can have much longer lifetimes than
other KeyPackages.
Paragraph (version B):
This extension MUST always be present in a KeyPackage.
Paragraph (version B):
Within MLS, a KeyPackage is identified by its hash (see, e.g.,
welcoming-new-members).  The "key_id" extension allows applications
to add an explicit, application-defined identifier to a KeyPackage.
Paragraph (version B):
The "parent_hash" extension serves to bind a KeyPackage to all the
nodes above it in the group's ratchet tree.  This enforces the tree
invariant, meaning that malicious members can't lie about the state
of the ratchet tree when they send Welcome messages to new members.
Paragraph (version A):
To allow group members to verify that they agree on the public
cryptographic state of the group, this section defines a scheme for
generating a hash value that represents the contents of the group's
ratchet tree and the members' ClientInitKeys.
Paragraph (version A):
Elements of the ratchet tree are called "Node" objects and the leaves
contain an optional "ClientInitKey", while the parents contain an
optional "ParentNode".
Paragraph (version B):
To allow group members to verify that they agree on the public
cryptographic state of the group, this section defines a scheme for
generating a hash value that represents the contents of the group's
ratchet tree and the members' KeyPackages.
Paragraph (version B):
Elements of the ratchet tree are called "Node" objects and the leaves
contain an optional "KeyPackage", while the parents contain an
optional "ParentNode".
Paragraph (version A):
As described in commit, each MLS Commit message needs to transmit a
ClientInitKey leaf and node values along its direct path.  The path
contains a public key and encrypted secret value for all intermediate
nodes in the path above the leaf.  The path is ordered from the
closest node to the leaf to the root; each node MUST be the parent of
its predecessor.
Paragraph (version B):
As described in commit, each MLS Commit message needs to transmit a
KeyPackage leaf and node values along its direct path.  The path
contains a public key and encrypted secret value for all intermediate
nodes in the path above the leaf.  The path is ordered from the
closest node to the leaf to the root; each node MUST be the parent of
its predecessor.
Paragraph (version A):
Fetch ClientInitKeys for the members to be added, and selects a
version and ciphersuite according to the capabilities of the
members.  To protect against downgrade attacks, the creator MUST
use the "supported_versions" and "supported_ciphersuites" fields
in these ClientInitKeys to verify that the chosen version and
ciphersuite is the best option supported by all members.
Paragraph (version B):
Fetch KeyPackages for the members to be added, and selects a
version and ciphersuite according to the capabilities of the
members.  To protect against downgrade attacks, the creator MUST
use the "supported_versions" and "supported_ciphersuites" fields
in these KeyPackages to verify that the chosen version and
ciphersuite is the best option supported by all members.
Paragraph (version A):
In principle, the above process could be streamlined by having the
creator directly create a tree and choose a random value for first
epoch's epoch secret.  We follow the steps above because it removes
unnecessary choices, by which, for example, bad randomness could be
introduced.  The only choices the creator makes here are its own
ClientInitKey, the leaf secret from which the Commit is built, and
the intermediate key pairs along the direct path to the root.
Paragraph (version B):
In principle, the above process could be streamlined by having the
creator directly create a tree and choose a random value for first
epoch's epoch secret.  We follow the steps above because it removes
unnecessary choices, by which, for example, bad randomness could be
introduced.  The only choices the creator makes here are its own
KeyPackage, the leaf secret from which the Commit is built, and the
intermediate key pairs along the direct path to the root.
Paragraph (version A):
An Add proposal requests that a client with a specified ClientInitKey
be added to the group.
Paragraph (version B):
An Add proposal requests that a client with a specified KeyPackage be
added to the group.
Paragraph (version A):
An Update proposal is a similar mechanism to Add with the distinction
that it is the sender's leaf ClientInitKey in the tree which would be
updated with a new ClientInitKey.
Paragraph (version B):
An Update proposal is a similar mechanism to Add with the distinction
that it is the sender's leaf KeyPackage in the tree which would be
updated with a new KeyPackage.
Paragraph (version A):
The "new_member" SenderType is used for clients proposing that they
themselves be added.  For this ID type the sender value MUST be zero.
Proposals with types other than Add MUST NOT be sent with this sender
type.  In such cases, the MLSPlaintext MUST be signed with the
private key corresponding to the ClientInitKey in the Add message.
Recipients MUST verify that the MLSPlaintext carrying the Proposal
message is validly signed with this key.
Paragraph (version B):
The "new_member" SenderType is used for clients proposing that they
themselves be added.  For this ID type the sender value MUST be zero.
Proposals with types other than Add MUST NOT be sent with this sender
type.  In such cases, the MLSPlaintext MUST be signed with the
private key corresponding to the KeyPackage in the Add message.
Recipients MUST verify that the MLSPlaintext carrying the Proposal
message is validly signed with this key.
Paragraph (version A):
Construct an initial Commit object with "updates", "removes", and
"adds" fields populated from Proposals received during the current
epoch, and empty "client_init_key" and "path" fields.
Paragraph (version B):
Construct an initial Commit object with "updates", "removes", and
"adds" fields populated from Proposals received during the current
epoch, and empty "key_package" and "path" fields.
Paragraph (version A):
Generate a new ClientInitKey for the Committer's own leaf, with a
"parent_hash" extension.  Store it in the ratchet tree and assign
it to the "client_init_key" field in the Commit object.
Paragraph (version B):
Generate a new KeyPackage for the Committer's own leaf, with a
"parent_hash" extension.  Store it in the ratchet tree and assign
it to the "key_package" field in the Commit object.
Paragraph (version A):
Compute an EncryptedKeyPackage object that encapsulates the
"init_secret" for the current epoch and the path secret for the
common ancestor.
Paragraph (version A):
Construct a Welcome message from the encrypted GroupInfo object
and the encrypted key packages.
Paragraph (version B):
Compute an EncryptedGroupSecrets object that encapsulates the
"init_secret" for the current epoch and the path secret for the
common ancestor.
Paragraph (version B):
Construct a Welcome message from the encrypted GroupInfo object
and the encrypted group secrets.
Paragraph (version A):
Apply the DirectPath to the tree, as described in
synchronizing-views-of-the-tree, and store "client_init_key" at
the Committer's leaf.
Paragraph (version A):
Verify that the ClientInitKey has a "parent_hash" extension and
that its value matches the new parent of the sender's leaf
node.
Paragraph (version B):
Apply the DirectPath to the tree, as described in
synchronizing-views-of-the-tree, and store "key_package" at the
Committer's leaf.
Paragraph (version B):
Verify that the KeyPackage has a "parent_hash" extension and
that its value matches the new parent of the sender's leaf
node.
Paragraph (version A):
In the description of the tree as a list of nodes, the
"client_init_key" field for a node MUST be populated if and only if
that node is a leaf in the tree.
Paragraph (version A):
Identify an entry in the "key_packages" array where the
"client_init_key_hash" value corresponds to one of this client's
ClientInitKeys, using the hash indicated by the "cipher_suite"
field.  If no such field exists, or if the ciphersuite indicated
in the ClientInitKey does not match the one in the Welcome
message, return an error.
Paragraph (version A):
Decrypt the "encrypted_key_package" using HPKE with the algorithms
indicated by the ciphersuite and the HPKE private key
corresponding to the ClientInitKey.
Paragraph (version A):
From the "epoch_secret" in the decrypted KeyPackage object, derive
the "welcome_secret", "welcome_key", and "welcome_nonce".  Use the
key and nonce to decrypt the "encrypted_group_info" field.
Paragraph (version B):
In the description of the tree as a list of nodes, the "key_package"
field for a node MUST be populated if and only if that node is a leaf
in the tree.
Paragraph (version B):
Identify an entry in the "secrets" array where the
"key_package_hash" value corresponds to one of this client's
KeyPackages, using the hash indicated by the "cipher_suite" field.
If no such field exists, or if the ciphersuite indicated in the
KeyPackage does not match the one in the Welcome message, return
an error.
Paragraph (version B):
Decrypt the "encrypted_group_secrets" using HPKE with the
algorithms indicated by the ciphersuite and the HPKE private key
corresponding to the GroupSecrets.
Paragraph (version B):
From the "epoch_secret" in the decrypted GroupSecrets object,
derive the "welcome_secret", "welcome_key", and "welcome_nonce".
Use the key and nonce to decrypt the "encrypted_group_info" field.
Paragraph (version A):
For each non-empty parent node, verify that exactly one of the
node's children are non-empty and have the hash of this node
set as their "parent_hash" value (if the child is another
parent) or has a "parent_hash" extension in the ClientInitKey
containing the same value (if the child is a leaf).
Paragraph (version A):
For each non-empty leaf node, verify the signature on the
ClientInitKey.
Paragraph (version A):
Identify a leaf in the "tree" array (any 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):
For each non-empty parent node, verify that exactly one of the
node's children are non-empty and have the hash of this node
set as their "parent_hash" value (if the child is another
parent) or has a "parent_hash" extension in the KeyPackage
containing the same value (if the child is a leaf).
Paragraph (version B):
For each non-empty leaf node, verify the signature on the
KeyPackage.
Paragraph (version B):
Identify a leaf in the "tree" array (any even-numbered node) whose
"key_package" field is identical to the the KeyPackage.  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):
In other words, clients advertise their capabilities in ClientInitKey
extensions, the creator of the group expresses its choices for the
group in Welcome extensions, and the GroupContext confirms that all
members of the group have the same view of the group's extensions.
Paragraph (version B):
In other words, clients advertise their capabilities in KeyPackage
extensions, the creator of the group expresses its choices for the
group in Welcome extensions, and the GroupContext confirms that all
members of the group have the same view of the group's extensions.
Paragraph (version A):
A client that posts a ClientInitKey MUST support all parameters
advertised in it.  Otherwise, another client might fail to
interoperate by selecting one of those parameters.
Paragraph (version B):
A client that posts a KeyPackage MUST support all parameters
advertised in it.  Otherwise, another client might fail to
interoperate by selecting one of those parameters.
Paragraph (version A):
A client adding a new member to a group MUST verify that the
ClientInitKey for the new member contains extensions that are
consistent with the group's extensions.  For each extension in the
GroupContext, the ClientInitKey MUST have an extension of the same
type, and the contents of the extension MUST be consistent with
the value of the extension in the GroupContext, according to the
semantics of the specific extension.
Paragraph (version B):
A client adding a new member to a group MUST verify that the
KeyPackage for the new member contains extensions that are
consistent with the group's extensions.  For each extension in the
GroupContext, the KeyPackage MUST have an extension of the same
type, and the contents of the extension MUST be consistent with
the value of the extension in the GroupContext, according to the
semantics of the specific extension.
Paragraph (version A):
A client joining a group MUST populate the GroupContext extensions
with exactly the contents of the extensions field in the Welcome
message.  If any extension is unrecognized (i.e., not contained in
the corresponding ClientInitKey), then the client MUST reject the
Welcome message and not join the group.
Paragraph (version B):
A client joining a group MUST populate the GroupContext extensions
with exactly the contents of the extensions field in the Welcome
message.  If any extension is unrecognized (i.e., not contained in
the corresponding KeyPackage), then the client MUST reject the
Welcome message and not join the group.
Paragraph (version A):
In the case where the client could have been compromised (device
loss...), the client SHOULD signal the delivery service to expire all
the previous ClientInitKeys and publish fresh ones for PCS.
Paragraph (version A):
Initialization keys are intended to be used only once and then
deleted.  Reuse of init keys can lead to replay attacks.
Paragraph (version B):
In the case where the client could have been compromised (device
loss...), the client SHOULD signal the delivery service to expire all
the previous KeyPackages and publish fresh ones for PCS.
Paragraph (version B):
InitKeys are intended to be used only once.  That is, once an InitKey
has been used to introduce the corresponding client to a group, it
SHOULD be deleted from the InitKey publication system.  Reuse of
InitKeys can lead to replay attacks.
Paragraph (version B):
An application MAY allow for reuse of a "last resort" InitKey in
order to prevent denial of service attacks.  Since an InitKey is
needed to add a client to a new group, an attacker could prevent a
client being added to new groups by exhausting all available
InitKeys.