Change:
This PR attempts to capture the spirit of the original key management provisions with a little more clarity about assumptions. It also adds a more more explicit construction for connecting SFrame to MLS.

Discussion:
4.3.1. <del> Each client creates a secret key "base_key" and shares it with the other participants via an E2E secure channel.  From "base_key", we derive the following values using HKDF RFC5869: </del> <ins> Each SFrame encryption or decryption operation is premised on a single secret "base_key", which is labeled with an integer KID value signaled in the SFrame header. The sender and receivers need to agree on which key should be used for a given KID.  The process for provisioning keys and their KID values is beyond the scope of this specification, but its security properties will bound the assurances that SFrame provides.  For example, if SFrame is used to provide E2E security against intermediary media nodes, then SFrame keys MUST be negotiated in a way that does not make them accessible to these intermediaries. For each known KID value, the client stores the corresponding symmetric key "base_key".  For keys that can be used for encryption, the client also stores the next counter value CTR to be used when encrypting (initially 0). When encrypting a frame, the application specifies which KID is to be used, and the counter is incremented after successful encryption. When decrypting, the "base_key" for decryption is selected from the available keys using the KID value in the SFrame Header. A given key MUST NOT be used for encryption by multiple senders. Such reuse would result in multiple encrypted frames being generated with the same (key, nonce) pair, which harms the protections provided by many AEAD algorithms.  Implementations SHOULD mark each key as usable for encryption or decryption, never both. Note that the set of available keys might change over the lifetime of a real-time session.  In such cases, the client will need to manage key usage to avoid media loss due to a key being used to encrypt before all receivers are able to use it to decrypt.  For example, an application may make decryption-only keys available immediately, but delay the use of encryption-only keys until (a) all receivers have acknowledged receipt of the new key or (b) a timeout expires. </ins> <del> A Salt key used to calculate the IV An encryption key to encrypt the media frame </del> <ins> 4.3.2. </ins> <del> An authentication key to authenticate the encrypted frame and the media metadata </del> <ins> SFrame encrytion and decryption use a key and salt derived from the "base_key" associated to a KID.  Given a "base_key" value, the key and salt are derived using HKDF RFC5869 as follows: </ins> <del> Each SFrame KID value identifies a "base_key", and thus both the "sframe_secret" and "sframe_salt" values to be used for encryption and decryption. </del> <ins> The hash function used for HKDF is determined by the ciphersuite in use. </ins> <del> 4.3.2. </del> <ins> 4.3.3. </ins> After encoding the frame and before packetizing it, the necessary media metadata will be moved out of the encoded frame buffer, to be

construct the RTP packets and encrypt it using SRTP keys for the HBH encryption to the media server. <del> 4.3.3. </del> <ins> 4.3.4. </ins> The receiving clients buffer all packets that belongs to the same frame using the frame beginning and ending marks in the generic RTP frame header extension, and once all packets are available, it passes <del> it to SFrame for decryption.  SFrame maintains multiple decryptor objects, one for each client in the call.  Initially the client might not have the mapping between the incoming streams the user's keys, in this case SFrame tries all unmapped keys until it finds one that passes the authentication verification and use it to decrypt the frame.  If the client has the mapping ready, it can push it down to SFrame later. The KeyId field in the SFrame header is used to find the right key for that user, which is incremented by the sender when they switch to a new key. For frames that are failed to decrypt because there is not key available yet, SFrame will buffer them and retries to decrypt them once a key is received. </del> <ins> it to SFrame for decryption.  The KID field in the SFrame header is used to find the right key for the encrypted frame. </ins> <del> 4.3.4. </del> <ins> For frames that are failed to decrypt because there is key available for the KID in the SFrame header, the client MAY buffer the frame and retry decryption once a key with that KID is received. 4.3.5. </ins> Unlike messaging application, in video calls, receiving a duplicate frame doesn't necessary mean the client is under a replay attack,

allows only older frame pithing a short interval to support out of order delivery. <del> 4.3.5. Because the E2EE keys could be rotated during the call when people join and leave, these new keys are exchanged using the same E2EE secure channel used in the initial key negotiation.  Sending new fresh keys is an expensive operation, so the key management component might chose to send new keys only when other clients leave the call and use hash ratcheting for the join case, so no need to send a new key to the clients who are already on the call.  SFrame supports both modes 4.3.5.1. When SFrame decryptor fails to decrypt one of the frames, it automatically ratchets the key forward and retries again until one ratchet succeed or it reaches the maximum allowed ratcheting window. If a new ratchet passed the decryption, all previous ratchets are deleted. 4.3.5.2. SFrame will set the key immediately on the decrypts when it is received and destroys the old key material, so if the key manager sends a new key during the call, it is recommended not to start using it immediately and wait for a short time to make sure it is delivered to all other clients before using it to decrease the number of decryption failure.  It is up to the application and the key manager to define how long this period is. </del> 4.4. Every client in the call knows the secret key for all other clients

5. <del> SFrame must be integrated with an E2EE key management framework to exchange and rotate the encryption keys.  This framework will maintain a group of participant endpoints who are in the call.  At call setup time, each endpoint will create a fresh key material and optionally signing key pair for that call and encrypt the key material and the public signing key to every other endpoints.  They encrypted keys are delivered by the messaging delivery server using a reliable channel. The KMS will monitor the group changes, and exchange new keys when necessary.  It is up to the application to define this group, for example one application could have ephemeral group for every call and keep rotating key when end points joins or leave the call, while another application could have a persisted group that can be used for multiple calls and exchange keys with all group endpoints for every call. When a new key material is created during the call, we recommend not to start using it immediately in SFrame to give time for the new keys to be delivered.  If the application supports delivery receipts, it can be used to track if the key is delivered to all other endpoints on the call before using it. Keys must have a sequential id starting from 0 and incremented eery time a new key is generated for this endpoint.  The key id will be added in the SFrame header during encryption, so the recipient know which key to use for the decryption. </del> <ins> SFrame must be integrated with an E2E key management framework to exchange and rotate the keys used for SFrame encryption and/or signing.  The key management framework provides the following functions: Provisioning KID/"base_key" mappings to participating clients (optional) Provisioning clients with a list of trusted signing keys Updating the above data as clients join or leave It is up to the application to define a rotation schedule for keys. For example, one application might have an ephemeral group for every call and keep rotating key when end points joins or leave the call, while another application could have a persistent group that can be used for multiple calls and simply derives ephemeral symmetric keys for a specific call. </ins> 5.1. <del> While any other E2EE KMS can be used with SFrame, there is a big advantage if it is used with I-D.ietf-mls-architecture which natively supports very large groups efficiently.  When I-D.ietf-mls-protocol is used, the endpoints keys (AKA Application secret) can be used directly for SFrame without the need to exchange separate key material.  The application secret is rotated automatically by I- D.ietf-mls-protocol when group membership changes. </del> <ins> If the participants in a call have a pre-existing E2E-secure channel, they can use it to distribute SFrame keys.  Each client participating in a call generates a fresh encryption key and optionally a signing key pair.  The client then uses the E2E-secure channel to send their encryption key and signing public key to the other participants. In this scheme, it is assumed that receivers have a signal outside of SFrame for which client has sent a given frame, for example the RTP SSRC.  SFrame KID values are then used to distinguish generations of the sender's key.  At the beginning of a call, each sender encrypts with KID=0.  Thereafter, the sender can ratchet their key forward for forward secrecy: The sender signals such an update by incrementing their KID value.  A receiver who receives from a sender with a new KID computes the new key as above.  The old key may be kept for some time to allow for out-of-order delivery, but should be deleted promptly. If a new participant joins mid-call, they will need to receive from each sender (a) the current sender key for that sender, (b) the signing key for the sender, if used, and (c) the current KID value for the sender.  Evicting a participant requires each sender to send a fresh sender key to all receivers. 5.2. The Messaging Layer Security (MLS) protocol provides group authenticated key exchange I-D.ietf-mls-architecture I-D.ietf-mls- protocol.  In principle, it could be used to instantiate the sender key scheme above, but it can also be used more efficiently directly. MLS creates a linear sequence of keys, each of which is shared among the members of a group at a given point in time.  When a member joins or leaves the group, a new key is produced that is known only to the augmented or reduced group.  Each step in the lifetime of the group is know as an "epoch", and each member of the group is assigned an "index" that is constant for the time they are in the group. In SFrame, we derive per-sender "base_key" values from the group secret for an epoch, and use the KID field to signal the epoch and sender index.  First, we use the MLS exporter to compute a shared SFrame secret for the epoch. For compactness, do not send the whole epoch number.  Instead, we send only its low-order E bits.  Note that E effectively defines a re-ordering window, since no more than 2^E epoch can be active at a given time.  Receivers MUST be prepared for the epoch counter to roll over, removing an old epoch when a new epoch with the same E lower bits is introduced.  (Sender indices cannot be similarly compressed.) Once an SFrame stack has been provisioned with the "sframe_epoch_secret" for an epoch, it can compute the required KIDs and "sender_base_key" values on demand, as it needs to encrypt/ decrypt for a given member. MLS also provides an authenticated signing key pair for each participant.  When SFrame uses signatures, these are the keys used to generate SFrame signatures. </ins> 6.