Draft: draft-ietf-mls-protocol

Commentary: Basic idea : Application Key Schedule consists of a left balanced binary tree of secrets ( the " AS Tree " ) and one symmetric ratchet per group member . The AS Tree has the same node / edge structure as the ratchet tree for that epoch . Members are assigned the same leaves . Each node in the AS Tree is assigned a secret . The root 's secret = applicationsecret . The secrets of children are derived from that of their parent . The secret of a leaf is the initial secret of a symmetric hash ratchet . The ratchet generates the key / nonce sequence used by the leaf 's group member to encrypt messages during that epoch . Other comments : I included a " Deletion Schedule " : keys , nonces are ' consumed ' if they are used to encrypt or successfully decrypt a message . secrets are ' consumed ' if value derived from it is consumed . Any consumed value must be immediately deleted for reasons of forward secrecy . I was very generous with contexts for all calls to HKDF . E.g. I included Hash(GroupState[n ] ) in the context of every call to HKDF . True , I do nt think its neccesary to prove security against more coarse adversarial models ( e.g. that only do all - or - nothing state leakage ) . Still , as a matter of the " defense in depth " principle I think including as much relevant context as possible during all key / secret derivation is a good idea . Albeit only as long as the price ( in computation , complexity , etc ) is not to high . To that end , I purposefully use Hash(GroupState_[n ] ) in the context as it is short , needs only to be computed once at the start of the epoch and can then be used to very cheaply to construct all contexts needed for the rest of the new application key schedule . Disclaimer : I 'm a bit of a noob when it comes to Markdown , RFCs and  so forgive me ( and tell me ! ) if I 've done something wrong here . Co - contributors :   ,   ,   , 
 Merging this despite outstanding comments . and I will handle our requested edits in a couple of follow - up PRs . 
 Here 's the Weekly Digest for : This week , 8 issues were created . Of these , 4 issues have been closed and 4 issues are still open . : greenheart : , by : greenheart : , by : greenheart : , by : greenheart : , by : heart : , by : heart : , by : heart : , by : heart : , by The issue most discussed this week has been : : speaker : , by It received 9 comments . This week , no pull requests has been proposed by the users . This week , 4 users have contributed to this repository . They are , , , and . This week , no user has starred this repository . This week , there have been 4 commits in the repository . These are : : hammerandwrench : Merge pull request from rozbb / mlsplaintext - signature Multiple clarifications around Framing by : hammerandwrench : Merge pull request from rozbb / hpke - encrypt Clarify how HPKE ciphertexts are computed by : hammerandwrench : by : hammerand_wrench : by # RELEASES This week , no releases were published . That 's all for this week , please watch : eyes : and star : star : to receive next weekly updates . : smiley : 
 Here 's the Weekly Digest for : - - Last week 4 issues were created . Of these , 1 issues have been closed and 3 issues are still open . : greenheart : , by : greenheart : , by : greenheart : , by : heart : , by : speaker : , by It received 4 comments . - - Last week , 9 pull requests were created , updated or merged . Last week , 8 pull requests were updated . : yellowheart : , by : yellowheart : , by : yellowheart : , by : yellowheart : , by : yellowheart : , by : yellowheart : , by : yellowheart : , by : yellowheart : , by Last week , 1 pull request was merged . : purpleheart : , by - - Last week there were 4 commits . : hammerandwrench : by : hammerandwrench : by : hammerandwrench : by : hammerandwrench : by - - Last week there was 1 contributor . : bustinsilhouette : - - Last week there was 1 stargazer . : star : You are the star ! : star2 : - - Last week there were no releases . - - That 's all for last week , please < kbd : eyes : Watch</kbdand < kbd : star : Star</kbdthe repository to receive next weekly updates . : smiley : You can also . 
 We should ensure that there is adequate anti - replay protection for both Handshake and Application messages . ( In particular , we should define what anti - replay issues are a concern . ) Could be related to if we want to solve it at that framing layer . 
 It looks like application key schedule on its own may not be enough to prevent replay attacks if out - of - order messages are supported ( and it seems like they are supported according to section 9.2.1 ) . Lets say we are at epoch x , and the receiver derives applicationsecret[sender][0 ] for epoch x. Then , the receiver receives  ( generation = 1 ) first before  . In order to decrypt message1 , the receiver needs to advance the application secret forward once to applicationsecret[sender][1 ] to get message1 nonce and AEAD secret . The receiver then happily processes message 1 . However , the receiver can not forget applicationsecret[sender][0 ] at this time ; otherwise it will never be able to decrypt  so it has to keep applicationsecret[sender][0 ] around . If the receiver receives message1 again , it can compute applicationsecret[sender][1 ] from applicationsecret[sender][0 ] and process the message . Hence , it seems that key schedule on its own will not prevent replay attacks . The receiver needs to remember that it has already processed  . The same problem may apply to receiving a message from epoch N+1 while not all messages from epoch N have been received ( if such case is possible ) . Replay attack counter - measures may be implemented as part of key schedule logic or separately , but it looks like implementors need to pay attention to this . 
 Obviously , if you keep a previous application secret , you are breaking FS . This is forbidden by the protocol . The protocol mandates : " Receivers MUST delete an Application Secret once it has been used to derive the corresponding AEAD key and nonce as well as the next Application Secret . Receivers MAY keep the AEAD key and nonce around for some reasonable period . " 
 Cf . " Updating the Application Secret " 
 Does it mean that receiving out - of - order messages is not possible ? If I abandon applicationsecret[sender][0 ] and advance to applicationsecret[sender][2 ] after receiving message 1 before message 0 , I will never be able to process message 0 . Is this intended behavior or am I missing something ? 
 No , you can do out of order , but what you keep are the AEAD keys / nonces and not the Application Secrets . The idea is the following : 1 - Compute Application Secret[sender][0 ] 2 - Derive AEAD Key[Sender][0 ] and AEAD Nonce[Sender][0 ] from Application Secret[sender][0 ] 3 - Overwrite Application Secret[sender][0 ] with Application Secret[sender][1 ] Basically , you should see these 3 steps as a single operation Now , if you iterate over that you can get more AEAD Keys and nonces [ 0 ... N ] to receive out of order . Because of step 3 you have local Forward Secrecy . Note that you never store more than a single ( the latest ) Application Secret per sender and that you have the keys [ 0 ... N ] to decrypt out of order . 
 Makes sense . Thanks for explaining . I suspect receiving out of order messages from a different epoch works in a similar way . If I am at epoch 0 , and I receive a message from epoch 2 , I derive and keep applicationsecret for epoch 1 and roll the initsecret forward . From the implementation perspective , how do I know when I can safely discard an application secret for a particular epoch ? Or how do I know that no more messages are coming for a particular sender / epoch ? Do you think there is value in adding a paragraph clarifying how the key schedule ensures replay attack protection to the spec ? I know these are probably all implementation questions , but I suspect these may be the questions the implementors may be asking . 
 I have some text stashed for when to discard the previous application secrets after there is a new epoch , so I will handle that . The idea is that you " publish " the number of application messages you sent in the previous epoch , but that is to be discussed ... Regarding replay , if you asked , it means clarification might be helpful here , do you want to submit a PR and assign me for review ? Otherwise just tell me and I 'll handle it ... : ) 
 I think you should review the below and update the spec as you see fit : ) -- I would update section 9.2.1 with something like : If receiver 's application secret is at generation N , and the receiver receives an out of order message with generation N+x ( where  ) , the receiver MUST advance the application secret forward to application secret N+x+1 after processing the out of order message . For every message with generation between N and N+x-1 ( messages that have not been received ) , the receiver SHOULD derive AEAD nonce and AEAD key and store them in order to be able to decrypt these messages later . Application secret MUST NOT be kept at generation N in order allow for decryption of out - of - order messages . Instead , stored AEAD key and nonce will allow for decryption of out - of - order messages when received later . -- We may also introduce a short new section " Message Replay Protection " with something like : Application key schedule provides replay attack counter - measures . If a message is replayed , the receiver should not have the right AEAD key nor have the application secret that could be used for deriving the right AEAD key for the replayed message . Hence , replayed message will be rejected by the receiver . 
 I think this is adequately addressed by and
Paragraph (version A):
The primary purpose of the handshake protocol is to provide an
authenticated group key exchange to clients.  In order to protect
Application messages sent among those members of a group, the
Application secret provided by the handshake key schedule is used to
derive encryption keys for the Message Protection Layer.
Paragraph (version B):
The primary purpose of the Handshake protocol is to provide an
authenticated group key exchange to clients.  In order to protect
Application messages sent among the members of a group, the
Application secret provided by the Handshake key schedule is used to
derive nonces and encryption keys for the Message Protection Layer
according to the Application Key Schedule.  That is, each epoch is
equipped with a fresh Application Key Schedule which consist of a
tree of Application Secrets as well as one symmetric ratchet per
group member.
Paragraph (version B):
Each client maintains their own local copy of (parts of) the
Application Key Schedule for each epoch during which they are a group
member.  They derive new keys, nonces and secrets as needed while
deleting old ones as soon as they have been used.
Paragraph (version A):
Each member maintains their own chain of Application secrets, where
the first one is derived based on a secret chained from the Epoch
secret.  As shown in key-schedule, the initial Application secret is
bound to the identity of each client to avoid collisions and allow
support for decryption of reordered messages.
Paragraph (version A):
Subsequent Application secrets MUST be rotated for each message sent
in order to provide stronger cryptographic security guarantees.  The
Application Key Schedule use this rotation to generate fresh AEAD
encryption keys and nonces used to encrypt and decrypt future
Application messages.  In all cases, a participant MUST NOT encrypt
more than expected by the security bounds of the AEAD scheme used.
Paragraph (version A):
Note that each change to the Group through a handshake message will
cause a change of the group Secret.  Hence this change MUST be
applied before encrypting any new Application message.  This is
required for confidentiality reasons in order for members to avoid
receiving messages from the group after leaving, being added to, or
excluded from the group.
Paragraph (version A):
The group identifier and epoch allow a recipient to know which group
secrets should be used and from which Epoch secret to start computing
other secrets and keys.  The "sender" identifier is used to derive
the member's Application secret chain from the initial group
Application secret.  The application generation field is used to
determine which Application secret should be used from the chain to
compute the correct AEAD keys before performing decryption.
Paragraph (version B):
The Application schedule begins with the Application secrets which
are arranged in an "Application Secret Tree" or AS Tree for short; a
left balanced binary tree with the same set of nodes and edges as the
epoch's ratchet tree.  Each leaf in the AS Tree is associated with
the same group member as the corresponding leaf in the ratchet tree.
Nodes are also assigned an index according to their position in the
array representation of the tree (described in tree-math).  If V is a
node in the AS Tree then IndexOf(V) denotes it's index while
V.leftChild and V.rightChild denote the children of V (if they
exist).
Paragraph (version B):
The secret of any other node in the tree is derived from its parent's
secret using a call to Derive-Secret.  The context for the call is
the (hash of the) Group state of the epoch and the index of the node
whose secret is being derived.
Paragraph (version B):
Note that fixing concrete values for GroupState_[n] and
application_secret completely defines all secrets in the AS Tree.
Paragraph (version B):
The secret of a leaf in the AS Tree is used to initiate a symmetric
hash ratchet which generates a sequence of keys and nonces.  The
group member assigned to that leaf uses the j-th key/nonce pair in
the sequence to encrypt (using the AEAD) the j-th message they send
during that epoch.  In particular, each key/nonce pair MUST NOT be
used to encrypt more than one message.
Paragraph (version B):
More precisely, the initial secret of the ratchet for the group
member assigned to the leaf with index i is simply the secret of that
leaf.
Paragraph (version B):
Keys, nonces and secrets of ratchets are derived using HKDF-Expand-
Label.  The context in a given call consists of (a hash of) the
current Group state, the index of the sender's leaf in the ratchet
tree and the position in the ratchet.  In particular, the index of
the sender's leaf in the ratchet tree is the same as the index of the
leaf in the AS Tree used to initialize the sender's ratchet.
Paragraph (version B):
Ratchet_position is initialized to 1 for the first HKDF-Expand-Label
call of a new ratchet and incremented for each subsequent call in
that ratchet.
Paragraph (version B):
Here, AEAD.nonceLen and AEAD.keyLength denote the lengths in bytes of
the nonce and key for the AEAD scheme defined by the ciphersuite.
Paragraph (version B):
It is important to delete all security sensitive values as soon as
they, or another value derived from them, is used for encryption or
decryption.
Paragraph (version B):
if a key, nonce or secret derived from S has been consumed.  (This
goes both for values derived via Derive-Secret and HKDF-Expand-
Label).
Paragraph (version B):
Here, S may be the init_secret, update_secret, epoch_secret,
application_secret as well as any secret in the AS Tree or one of the
ratchets.
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 even if
their generating secret was already consumed (e.g. due to out of
order message delivery).
Paragraph (version B):
the init_secret, update_secret, epoch_secret, application_secret
of that epoch,
Paragraph (version B):
all node secrets in the AS Tree on the path from the root to the
leaf with index i,
Paragraph (version B):
application_[i]_[j]_key and application_[i]_[j]_nonce.
Paragraph (version B):
Concretely, suppose we have the following AS Tree.
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
update_secret and init_secret used to derive G (i.e. the
application_secret).
Paragraph (version B):
During each epoch senders MUST NOT encrypt more messages than
permitted by the security bounds of the AEAD scheme used.
Paragraph (version B):
Note that each change to the Group through a Handshake message will
also set a new application_secret.  Hence this change MUST be applied
before encrypting any new Application message.  This is required both
to ensure that any users removed from the group can no longer receive
messages and to (potentially) recover confidentiality and
authenticity for future messages despite a past state compromise.
Paragraph (version B):
The group identifier and epoch allow a recipient to know which group
secrets should be used and from which Epoch secret to start computing
other secrets and keys.  The sender identifier is used to identify
the member's symmetric ratchet from the initial group Application
secret.  The application generation field is used to determine how
far into the ratchet to iterate in order to reproduce the required
AEAD keys and nonce for performing decryption.