From 4bfd864f10b68b71482b35c818559068ef8d5797 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Wed, 27 Nov 2024 20:54:24 +0100 Subject: doc: Add RFC documents --- doc/rfc/rfc9605.txt | 3210 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3210 insertions(+) create mode 100644 doc/rfc/rfc9605.txt (limited to 'doc/rfc/rfc9605.txt') diff --git a/doc/rfc/rfc9605.txt b/doc/rfc/rfc9605.txt new file mode 100644 index 0000000..8f3f014 --- /dev/null +++ b/doc/rfc/rfc9605.txt @@ -0,0 +1,3210 @@ + + + + +Internet Engineering Task Force (IETF) E. Omara +Request for Comments: 9605 Apple +Category: Standards Track J. Uberti +ISSN: 2070-1721 Fixie.ai + S. G. Murillo + CoSMo Software + R. Barnes, Ed. + Cisco + Y. Fablet + Apple + August 2024 + + + Secure Frame (SFrame): Lightweight Authenticated Encryption for + Real-Time Media + +Abstract + + This document describes the Secure Frame (SFrame) end-to-end + encryption and authentication mechanism for media frames in a + multiparty conference call, in which central media servers (Selective + Forwarding Units or SFUs) can access the media metadata needed to + make forwarding decisions without having access to the actual media. + + This mechanism differs from the Secure Real-Time Protocol (SRTP) in + that it is independent of RTP (thus compatible with non-RTP media + transport) and can be applied to whole media frames in order to be + more bandwidth efficient. + +Status of This Memo + + This is an Internet Standards Track document. + + This document is a product of the Internet Engineering Task Force + (IETF). It represents the consensus of the IETF community. It has + received public review and has been approved for publication by the + Internet Engineering Steering Group (IESG). Further information on + Internet Standards is available in Section 2 of RFC 7841. + + Information about the current status of this document, any errata, + and how to provide feedback on it may be obtained at + https://www.rfc-editor.org/info/rfc9605. + +Copyright Notice + + Copyright (c) 2024 IETF Trust and the persons identified as the + document authors. All rights reserved. + + This document is subject to BCP 78 and the IETF Trust's Legal + Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info) in effect on the date of + publication of this document. Please review these documents + carefully, as they describe your rights and restrictions with respect + to this document. Code Components extracted from this document must + include Revised BSD License text as described in Section 4.e of the + Trust Legal Provisions and are provided without warranty as described + in the Revised BSD License. + +Table of Contents + + 1. Introduction + 2. Terminology + 3. Goals + 4. SFrame + 4.1. Application Context + 4.2. SFrame Ciphertext + 4.3. SFrame Header + 4.4. Encryption Schema + 4.4.1. Key Selection + 4.4.2. Key Derivation + 4.4.3. Encryption + 4.4.4. Decryption + 4.5. Cipher Suites + 4.5.1. AES-CTR with SHA2 + 5. Key Management + 5.1. Sender Keys + 5.2. MLS + 6. Media Considerations + 6.1. Selective Forwarding Units + 6.1.1. RTP Stream Reuse + 6.1.2. Simulcast + 6.1.3. Scalable Video Coding (SVC) + 6.2. Video Key Frames + 6.3. Partial Decoding + 7. Security Considerations + 7.1. No Header Confidentiality + 7.2. No Per-Sender Authentication + 7.3. Key Management + 7.4. Replay + 7.5. Risks Due to Short Tags + 8. IANA Considerations + 8.1. SFrame Cipher Suites + 9. Application Responsibilities + 9.1. Header Value Uniqueness + 9.2. Key Management Framework + 9.3. Anti-Replay + 9.4. Metadata + 10. References + 10.1. Normative References + 10.2. Informative References + Appendix A. Example API + Appendix B. Overhead Analysis + B.1. Assumptions + B.2. Audio + B.3. Video + B.4. Conferences + B.5. SFrame over RTP + Appendix C. Test Vectors + C.1. Header Encoding/Decoding + C.2. AEAD Encryption/Decryption Using AES-CTR and HMAC + C.3. SFrame Encryption/Decryption + Acknowledgements + Contributors + Authors' Addresses + +1. Introduction + + Modern multiparty video call systems use Selective Forwarding Unit + (SFU) servers to efficiently route media streams to call endpoints + based on factors such as available bandwidth, desired video size, + codec support, and other factors. An SFU typically does not need + access to the media content of the conference, which allows the media + to be encrypted "end to end" so that it cannot be decrypted by the + SFU. In order for the SFU to work properly, though, it usually needs + to be able to access RTP metadata and RTCP feedback messages, which + is not possible if all RTP/RTCP traffic is end-to-end encrypted. + + As such, two layers of encryption and authentication are required: + + 1. Hop-by-hop (HBH) encryption of media, metadata, and feedback + messages between the endpoints and SFU + + 2. End-to-end (E2E) encryption (E2EE) of media between the endpoints + + The Secure Real-Time Protocol (SRTP) is already widely used for HBH + encryption [RFC3711]. The SRTP "double encryption" scheme defines a + way to do E2E encryption in SRTP [RFC8723]. Unfortunately, this + scheme has poor efficiency and high complexity, and its entanglement + with RTP makes it unworkable in several realistic SFU scenarios. + + This document proposes a new E2EE protection scheme known as SFrame, + specifically designed to work in group conference calls with SFUs. + SFrame is a general encryption framing that can be used to protect + media payloads, agnostic of transport. + +2. Terminology + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and + "OPTIONAL" in this document are to be interpreted as described in + BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all + capitals, as shown here. + + MAC: Message Authentication Code + + E2EE: End-to-End Encryption + + HBH: Hop-by-Hop + + We use "Selective Forwarding Unit (SFU)" and "media stream" in a less + formal sense than in [RFC7656]. An SFU is a selective switching + function for media payloads, and a media stream is a sequence of + media payloads, regardless of whether those media payloads are + transported over RTP or some other protocol. + +3. Goals + + SFrame is designed to be a suitable E2EE protection scheme for + conference call media in a broad range of scenarios, as outlined by + the following goals: + + 1. Provide a secure E2EE mechanism for audio and video in conference + calls that can be used with arbitrary SFU servers. + + 2. Decouple media encryption from key management to allow SFrame to + be used with an arbitrary key management system. + + 3. Minimize packet expansion to allow successful conferencing in as + many network conditions as possible. + + 4. Decouple the media encryption framework from the underlying + transport, allowing use in non-RTP scenarios, e.g., WebTransport + [WEBTRANSPORT]. + + 5. When used with RTP and its associated error-resilience + mechanisms, i.e., RTX and Forward Error Correction (FEC), require + no special handling for RTX and FEC packets. + + 6. Minimize the changes needed in SFU servers. + + 7. Minimize the changes needed in endpoints. + + 8. Work with the most popular audio and video codecs used in + conferencing scenarios. + +4. SFrame + + This document defines an encryption mechanism that provides effective + E2EE, is simple to implement, has no dependencies on RTP, and + minimizes encryption bandwidth overhead. This section describes how + the mechanism works and includes details of how applications utilize + SFrame for media protection as well as the actual mechanics of E2EE + for protecting media. + +4.1. Application Context + + SFrame is a general encryption framing, intended to be used as an + E2EE layer over an underlying HBH-encrypted transport such as SRTP or + QUIC [RFC3711][MOQ-TRANSPORT]. + + The scale at which SFrame encryption is applied to media determines + the overall amount of overhead that SFrame adds to the media stream + as well as the engineering complexity involved in integrating SFrame + into a particular environment. Two patterns are common: using SFrame + to encrypt either whole media frames (per frame) or individual + transport-level media payloads (per packet). + + For example, Figure 1 shows a typical media sender stack that takes + media from some source, encodes it into frames, divides those frames + into media packets, and then sends those payloads in SRTP packets. + The receiver stack performs the reverse operations, reassembling + frames from SRTP packets and decoding. Arrows indicate two different + ways that SFrame protection could be integrated into this media + stack: to encrypt whole frames or individual media packets. + + Applying SFrame per frame in this system offers higher efficiency but + may require a more complex integration in environments where + depacketization relies on the content of media packets. Applying + SFrame per packet avoids this complexity at the cost of higher + bandwidth consumption. Some quantitative discussion of these trade- + offs is provided in Appendix B. + + As noted above, however, SFrame is a general media encapsulation and + can be applied in other scenarios. The important thing is that the + sender and receivers of an SFrame-encrypted object agree on that + object's semantics. SFrame does not provide this agreement; it must + be arranged by the application. + + +------------------------------------------------------+ + | | + | +--------+ +-------------+ +-----------+ | + .-. | | | | | | HBH | | +| | | | Encode |----->| Packetize |----->| Protect |----------+ + '+' | | | ^ | | ^ | | | | + /|\ | +--------+ | +-------------+ | +-----------+ | | +/ + \ | | | ^ | | + / \ | SFrame SFrame | | | +/ \ | Protect Protect | | | +Alice | (per frame) (per packet) | | | + | ^ ^ | | | + | | | | | | + +---------------|-------------------|---------|--------+ | + | | | v + | | | +------+-+ + | E2E Key | HBH Key | Media | + +---- Management ---+ Management | Server | + | | | +------+-+ + | | | | + +---------------|-------------------|---------|--------+ | + | | | | | | + | V V | | | + .-. | SFrame SFrame | | | +| | | Unprotect Unprotect | | | + '+' | (per frame) (per packet) | | | + /|\ | | | V | | +/ + \ | +--------+ | +-------------+ | +-----------+ | | + / \ | | | V | | V | HBH | | | +/ \ | | Decode |<-----| Depacketize |<-----| Unprotect |<---------+ + Bob | | | | | | | | + | +--------+ +-------------+ +-----------+ | + | | + +------------------------------------------------------+ + +Figure 1: Two Options for Integrating SFrame in a Typical Media Stack + + Like SRTP, SFrame does not define how the keys used for SFrame are + exchanged by the parties in the conference. Keys for SFrame might be + distributed over an existing E2E-secure channel (see Section 5.1) or + derived from an E2E-secure shared secret (see Section 5.2). The key + management system MUST ensure that each key used for encrypting media + is used by exactly one media sender in order to avoid reuse of + nonces. + +4.2. SFrame Ciphertext + + An SFrame ciphertext comprises an SFrame header followed by the + output of an Authenticated Encryption with Associated Data (AEAD) + encryption of the plaintext [RFC5116], with the header provided as + additional authenticated data (AAD). + + The SFrame header is a variable-length structure described in detail + in Section 4.3. The structure of the encrypted data and + authentication tag are determined by the AEAD algorithm in use. + + +-+----+-+----+--------------------+--------------------+<-+ + |K|KLEN|C|CLEN| Key ID | Counter | | + +->+-+----+-+----+--------------------+--------------------+ | + | | | | + | | | | + | | | | + | | | | + | | Encrypted Data | | + | | | | + | | | | + | | | | + | | | | + +->+-------------------------------------------------------+<-+ + | | Authentication Tag | | + | +-------------------------------------------------------+ | + | | + | | + +--- Encrypted Portion Authenticated Portion ---+ + + Figure 2: Structure of an SFrame Ciphertext + + When SFrame is applied per packet, the payload of each packet will be + an SFrame ciphertext. When SFrame is applied per frame, the SFrame + ciphertext representing an encrypted frame will span several packets, + with the header appearing in the first packet and the authentication + tag in the last packet. It is the responsibility of the application + to reassemble an encrypted frame from individual packets, accounting + for packet loss and reordering as necessary. + +4.3. SFrame Header + + The SFrame header specifies two values from which encryption + parameters are derived: + + * A Key ID (KID) that determines which encryption key should be used + + * A Counter (CTR) that is used to construct the nonce for the + encryption + + Applications MUST ensure that each (KID, CTR) combination is used for + exactly one SFrame encryption operation. A typical approach to + achieve this guarantee is outlined in Section 9.1. + + Config Byte + | + .-----' '-----. + | | + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+------------+------------+ + |X| K |Y| C | KID... | CTR... | + +-+-+-+-+-+-+-+-+------------+------------+ + + Figure 3: SFrame Header + + The SFrame header has the overall structure shown in Figure 3. The + first byte is a "config byte", with the following fields: + + Extended KID Flag (X, 1 bit): Indicates if the K field contains the + KID or the KID length. + + KID or KID Length (K, 3 bits): If the X flag is set to 0, this field + contains the KID. If the X flag is set to 1, then it contains the + length of the KID, minus one. + + Extended CTR Flag (Y, 1 bit): Indicates if the C field contains the + CTR or the CTR length. + + CTR or CTR Length (C, 3 bits): This field contains the CTR if the Y + flag is set to 0, or the CTR length, minus one, if set to 1. + + The KID and CTR fields are encoded as compact unsigned integers in + network (big-endian) byte order. If the value of one of these fields + is in the range 0-7, then the value is carried in the corresponding + bits of the config byte (K or C) and the corresponding flag (X or Y) + is set to zero. Otherwise, the value MUST be encoded with the + minimum number of bytes required and appended after the config byte, + with the KID first and CTR second. The header field (K or C) is set + to the number of bytes in the encoded value, minus one. The value + 000 represents a length of 1, 001 a length of 2, etc. This allows a + 3-bit length field to represent the value lengths 1-8. + + The SFrame header can thus take one of the four forms shown in + Figure 4, depending on which of the X and Y flags are set. + + KID < 8, CTR < 8: + +-+-----+-+-----+ + |0| KID |0| CTR | + +-+-----+-+-----+ + + KID < 8, CTR >= 8: + +-+-----+-+-----+------------------------+ + |0| KID |1|CLEN | CTR... (length=CLEN) | + +-+-----+-+-----+------------------------+ + + KID >= 8, CTR < 8: + +-+-----+-+-----+------------------------+ + |1|KLEN |0| CTR | KID... (length=KLEN) | + +-+-----+-+-----+------------------------+ + + KID >= 8, CTR >= 8: + +-+-----+-+-----+------------------------+------------------------+ + |1|KLEN |1|CLEN | KID... (length=KLEN) | CTR... (length=CLEN) | + +-+-----+-+-----+------------------------+------------------------+ + + Figure 4: Forms of Encoded SFrame Header + +4.4. Encryption Schema + + SFrame encryption uses an AEAD encryption algorithm and hash function + defined by the cipher suite in use (see Section 4.5). We will refer + to the following aspects of the AEAD and the hash algorithm below: + + * AEAD.Encrypt and AEAD.Decrypt - The encryption and decryption + functions for the AEAD. We follow the convention of RFC 5116 + [RFC5116] and consider the authentication tag part of the + ciphertext produced by AEAD.Encrypt (as opposed to a separate + field as in SRTP [RFC3711]). + + * AEAD.Nk - The size in bytes of a key for the encryption algorithm + + * AEAD.Nn - The size in bytes of a nonce for the encryption + algorithm + + * AEAD.Nt - The overhead in bytes of the encryption algorithm + (typically the size of a "tag" that is added to the plaintext) + + * AEAD.Nka - For cipher suites using the compound AEAD described in + Section 4.5.1, the size in bytes of a key for the underlying + encryption algorithm + + * Hash.Nh - The size in bytes of the output of the hash function + +4.4.1. Key Selection + + 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 base_key should be + used for a given KID. Moreover, senders and receivers need to agree + on whether a base_key will be used for encryption or decryption only. + The process for provisioning base_key values 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 need to 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 CTR value to be used when encrypting + (initially 0). + + When encrypting a plaintext, the application specifies which KID is + to be used, and the CTR value 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 base_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 MUST mark each base_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 keys for encryption until (a) all receivers have + acknowledged receipt of the new key, or (b) a timeout expires. + +4.4.2. Key Derivation + + SFrame encryption and decryption use a key and salt derived from the + base_key associated with a KID. Given a base_key value, the key and + salt are derived using HMAC-based Key Derivation Function (HKDF) + [RFC5869] as follows: + + def derive_key_salt(KID, base_key): + sframe_secret = HKDF-Extract("", base_key) + + sframe_key_label = "SFrame 1.0 Secret key " + KID + cipher_suite + sframe_key = + HKDF-Expand(sframe_secret, sframe_key_label, AEAD.Nk) + + sframe_salt_label = "SFrame 1.0 Secret salt " + KID + cipher_suite + sframe_salt = + HKDF-Expand(sframe_secret, sframe_salt_label, AEAD.Nn) + + return sframe_key, sframe_salt + + In the derivation of sframe_secret: + + * The + operator represents concatenation of byte strings. + + * The KID value is encoded as an 8-byte big-endian integer, not the + compressed form used in the SFrame header. + + * The cipher_suite value is a 2-byte big-endian integer representing + the cipher suite in use (see Section 8.1). + + The hash function used for HKDF is determined by the cipher suite in + use. + +4.4.3. Encryption + + SFrame encryption uses the AEAD encryption algorithm for the cipher + suite in use. The key for the encryption is the sframe_key. The + nonce is formed by first XORing the sframe_salt with the current CTR + value, and then encoding the result as a big-endian integer of length + AEAD.Nn. + + The encryptor forms an SFrame header using the CTR and KID values + provided. The encoded header is provided as AAD to the AEAD + encryption operation, together with application-provided metadata + about the encrypted media (see Section 9.4). + + def encrypt(CTR, KID, metadata, plaintext): + sframe_key, sframe_salt = key_store[KID] + + # encode_big_endian(x, n) produces an n-byte string encoding the + # integer x in big-endian byte order. + ctr = encode_big_endian(CTR, AEAD.Nn) + nonce = xor(sframe_salt, CTR) + + # encode_sframe_header produces a byte string encoding the + # provided KID and CTR values into an SFrame header. + header = encode_sframe_header(CTR, KID) + aad = header + metadata + + ciphertext = AEAD.Encrypt(sframe_key, nonce, aad, plaintext) + return header + ciphertext + + For example, the metadata input to encryption allows for frame + metadata to be authenticated when SFrame is applied per frame. After + encoding the frame and before packetizing it, the necessary media + metadata will be moved out of the encoded frame buffer to be sent in + some channel visible to the SFU (e.g., an RTP header extension). + + +---------------+ + | | + | | + | plaintext | + | | + | | + +-------+-------+ + | + .- +-----+ | + | | +--+--> sframe_key ----->| Key + Header | | KID | | | + | | | +--> sframe_salt --+ | + +--+ +-----+ | | + | | | +---------------------+->| Nonce + | | | CTR | | + | | | | | + | '- +-----+ | + | | + | +----------------+ | + | | metadata | | + | +-------+--------+ | + | | | + +------------------+----------------->| AAD + | | + | AEAD.Encrypt + | | + | SFrame Ciphertext | + | +---------------+ | + +-------------->| SFrame Header | | + +---------------+ | + | | | + | |<----+ + | ciphertext | + | | + | | + +---------------+ + + Figure 5: Encrypting an SFrame Ciphertext + +4.4.4. Decryption + + Before decrypting, a receiver needs to assemble a full SFrame + ciphertext. When an SFrame ciphertext is fragmented into multiple + parts for transport (e.g., a whole encrypted frame sent in multiple + SRTP packets), the receiving client collects all the fragments of the + ciphertext, using appropriate sequencing and start/end markers in the + transport. Once all of the required fragments are available, the + client reassembles them into the SFrame ciphertext and passes the + ciphertext to SFrame for decryption. + + The KID field in the SFrame header is used to find the right key and + salt for the encrypted frame, and the CTR field is used to construct + the nonce. The SFrame decryption procedure is as follows: + + def decrypt(metadata, sframe_ciphertext): + KID, CTR, header, ciphertext = parse_ciphertext(sframe_ciphertext) + + sframe_key, sframe_salt = key_store[KID] + + ctr = encode_big_endian(CTR, AEAD.Nn) + nonce = xor(sframe_salt, ctr) + aad = header + metadata + + return AEAD.Decrypt(sframe_key, nonce, aad, ciphertext) + + If a ciphertext fails to decrypt because there is no key available + for the KID in the SFrame header, the client MAY buffer the + ciphertext and retry decryption once a key with that KID is received. + If a ciphertext fails to decrypt for any other reason, the client + MUST discard the ciphertext. Invalid ciphertexts SHOULD be discarded + in a way that is indistinguishable (to an external observer) from + having processed a valid ciphertext. In other words, the SFrame + decrypt operation should take the same amount of time regardless of + whether decryption succeeds or fails. + + SFrame Ciphertext + +---------------+ + +---------------| SFrame Header | + | +---------------+ + | | | + | | |-----+ + | | ciphertext | | + | | | | + | | | | + | +---------------+ | + | | + | .- +-----+ | + | | | +--+--> sframe_key ----->| Key + | | | KID | | | + | | | | +--> sframe_salt --+ | + +->+ +-----+ | | + | | | +---------------------+->| Nonce + | | | CTR | | + | | | | | + | '- +-----+ | + | | + | +----------------+ | + | | metadata | | + | +-------+--------+ | + | | | + +------------------+----------------->| AAD + | + AEAD.Decrypt + | + V + +---------------+ + | | + | | + | plaintext | + | | + | | + +---------------+ + + Figure 6: Decrypting an SFrame Ciphertext + +4.5. Cipher Suites + + Each SFrame session uses a single cipher suite that specifies the + following primitives: + + * A hash function used for key derivation + + * An AEAD encryption algorithm [RFC5116] used for frame encryption, + optionally with a truncated authentication tag + + This document defines the following cipher suites, with the constants + defined in Section 4.4: + + +============================+====+=====+====+====+====+ + | Name | Nh | Nka | Nk | Nn | Nt | + +============================+====+=====+====+====+====+ + | AES_128_CTR_HMAC_SHA256_80 | 32 | 16 | 48 | 12 | 10 | + +----------------------------+----+-----+----+----+----+ + | AES_128_CTR_HMAC_SHA256_64 | 32 | 16 | 48 | 12 | 8 | + +----------------------------+----+-----+----+----+----+ + | AES_128_CTR_HMAC_SHA256_32 | 32 | 16 | 48 | 12 | 4 | + +----------------------------+----+-----+----+----+----+ + | AES_128_GCM_SHA256_128 | 32 | n/a | 16 | 12 | 16 | + +----------------------------+----+-----+----+----+----+ + | AES_256_GCM_SHA512_128 | 64 | n/a | 32 | 12 | 16 | + +----------------------------+----+-----+----+----+----+ + + Table 1: SFrame Cipher Suite Constants + + Numeric identifiers for these cipher suites are defined in the IANA + registry created in Section 8.1. + + In the suite names, the length of the authentication tag is indicated + by the last value: "_128" indicates a 128-bit tag, "_80" indicates an + 80-bit tag, "_64" indicates a 64-bit tag, and "_32" indicates a + 32-bit tag. + + In a session that uses multiple media streams, different cipher + suites might be configured for different media streams. For example, + in order to conserve bandwidth, a session might use a cipher suite + with 80-bit tags for video frames and another cipher suite with + 32-bit tags for audio frames. + +4.5.1. AES-CTR with SHA2 + + In order to allow very short tag sizes, we define a synthetic AEAD + function using the authenticated counter mode of AES together with + HMAC for authentication. We use an encrypt-then-MAC approach, as in + SRTP [RFC3711]. + + Before encryption or decryption, encryption and authentication + subkeys are derived from the single AEAD key. The overall length of + the AEAD key is Nka + Nh, where Nka represents the key size for the + AES block cipher in use and Nh represents the output size of the hash + function (as in Section 4.4). The encryption subkey comprises the + first Nka bytes and the authentication subkey comprises the remaining + Nh bytes. + + def derive_subkeys(sframe_key): + # The encryption key comprises the first Nka bytes + enc_key = sframe_key[..Nka] + + # The authentication key comprises Nh remaining bytes + auth_key = sframe_key[Nka..] + + return enc_key, auth_key + + The AEAD encryption and decryption functions are then composed of + individual calls to the CTR encrypt function and HMAC. The resulting + MAC value is truncated to a number of bytes Nt fixed by the cipher + suite. + + def truncate(tag, n): + # Take the first `n` bytes of `tag` + return tag[..n] + + def compute_tag(auth_key, nonce, aad, ct): + aad_len = encode_big_endian(len(aad), 8) + ct_len = encode_big_endian(len(ct), 8) + tag_len = encode_big_endian(Nt, 8) + auth_data = aad_len + ct_len + tag_len + nonce + aad + ct + tag = HMAC(auth_key, auth_data) + return truncate(tag, Nt) + + def AEAD.Encrypt(key, nonce, aad, pt): + enc_key, auth_key = derive_subkeys(key) + initial_counter = nonce + 0x00000000 # append four zero bytes + ct = AES-CTR.Encrypt(enc_key, initial_counter, pt) + tag = compute_tag(auth_key, nonce, aad, ct) + return ct + tag + + def AEAD.Decrypt(key, nonce, aad, ct): + inner_ct, tag = split_ct(ct, tag_len) + + enc_key, auth_key = derive_subkeys(key) + candidate_tag = compute_tag(auth_key, nonce, aad, inner_ct) + if !constant_time_equal(tag, candidate_tag): + raise Exception("Authentication Failure") + + initial_counter = nonce + 0x00000000 # append four zero bytes + return AES-CTR.Decrypt(enc_key, initial_counter, inner_ct) + +5. Key Management + + SFrame must be integrated with an E2E key management framework to + exchange and rotate the keys used for SFrame encryption. The key + management framework provides the following functions: + + * Provisioning KID / base_key mappings to participating clients + + * Updating the above data as clients join or leave + + It is the responsibility of the application to provide the key + management framework, as described in Section 9.2. + +5.1. Sender Keys + + If the participants in a call have a preexisting E2E-secure channel, + they can use it to distribute SFrame keys. Each client participating + in a call generates a fresh base_key value that it will use to + encrypt media. The client then uses the E2E-secure channel to send + their encryption 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 (e.g., an RTP + synchronization source (SSRC)). SFrame KID values are then used to + distinguish between versions of the sender's base_key. + + KID values in this scheme have two parts: a "key generation" and a + "ratchet step". Both are unsigned integers that begin at zero. The + key generation increments each time the sender distributes a new key + to receivers. The ratchet step is incremented each time the sender + ratchets their key forward for forward secrecy: + + base_key[i+1] = HKDF-Expand( + HKDF-Extract("", base_key[i]), + "SFrame 1.0 Ratchet", CipherSuite.Nh) + + For compactness, we do not send the whole ratchet step. Instead, we + send only its low-order R bits, where R is a value set by the + application. Different senders may use different values of R, but + each receiver of a given sender needs to know what value of R is used + by the sender so that they can recognize when they need to ratchet + (vs. expecting a new key). R effectively defines a reordering + window, since no more than 2^R ratchet steps can be active at a given + time. The key generation is sent in the remaining 64 - R bits of the + KID. + + KID = (key_generation << R) + (ratchet_step % (1 << R)) + + 64-R bits R bits + <---------------> <------------> + +-----------------+--------------+ + | Key Generation | Ratchet Step | + +-----------------+--------------+ + + Figure 7: Structure of a KID in the Sender Keys Scheme + + The sender signals such a ratchet step update by sending with a KID + value in which the ratchet step has been incremented. 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 in the middle of a session, they will need + to receive from each sender (a) the current sender key for that + sender and (b) the current KID value for the sender. Evicting a + participant requires each sender to send a fresh sender key to all + receivers. + + It is the application's responsibility to decide when sender keys are + updated. A sender key may be updated by sending a new base_key + (updating the key generation) or by hashing the current base_key + (updating the ratchet step). Ratcheting the key forward is useful + when adding new receivers to an SFrame-based interaction, since it + ensures that the new receivers can't decrypt any media encrypted + before they were added. If a sender wishes to assure the opposite + property when removing a receiver (i.e., ensuring that the receiver + can't decrypt media after they are removed), then the sender will + need to distribute a new sender key. + +5.2. MLS + + The Messaging Layer Security (MLS) protocol provides group + authenticated key exchange [MLS-ARCH] [MLS-PROTO]. 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 known as an "epoch", and each member of the group is assigned an + "index" that is constant for the time they are in the group. + + To generate keys and nonces for SFrame, we use the MLS exporter + function to generate a base_key value for each MLS epoch. Each + member of the group is assigned a set of KID values so that each + member has a unique sframe_key and sframe_salt that it uses to + encrypt with. Senders may choose any KID value within their assigned + set of KID values, e.g., to allow a single sender to send multiple, + uncoordinated outbound media streams. + + base_key = MLS-Exporter("SFrame 1.0 Base Key", "", AEAD.Nk) + + For compactness, we do not send the whole epoch number. Instead, we + send only its low-order E bits, where E is a value set by the + application. E effectively defines a reordering window, since no + more than 2^E epochs can be active at a given time. To handle + rollover of the epoch counter, receivers MUST remove an old epoch + when a new epoch with the same low-order E bits is introduced. + + Let S be the number of bits required to encode a member index in the + group, i.e., the smallest value such that group_size <= (1 << S). + The sender index is encoded in the S bits above the epoch. The + remaining 64 - S - E bits of the KID value are a context value chosen + by the sender (context value 0 will produce the shortest encoded + KID). + + KID = (context << (S + E)) + (sender_index << E) + (epoch % (1 << E)) + + 64-S-E bits S bits E bits + <-----------> <------> <------> + +-------------+--------+-------+ + | Context ID | Index | Epoch | + +-------------+--------+-------+ + + Figure 8: Structure of a KID for an MLS Sender + + Once an SFrame stack has been provisioned with the + sframe_epoch_secret for an epoch, it can compute the required KID + values on demand (as well as the resulting SFrame keys/nonces derived + from the base_key and KID) as it needs to encrypt or decrypt for a + given member. + + ... + | + | + Epoch 14 +--+-- index=3 ---> KID = 0x3e + | | + | +-- index=7 ---> KID = 0x7e + | | + | +-- index=20 --> KID = 0x14e + | + | + Epoch 15 +--+-- index=3 ---> KID = 0x3f + | | + | +-- index=5 ---> KID = 0x5f + | + | + Epoch 16 +----- index=2 --+--> context = 2 --> KID = 0x820 + | | + | +--> context = 3 --> KID = 0xc20 + | + | + Epoch 17 +--+-- index=33 --> KID = 0x211 + | | + | +-- index=51 --> KID = 0x331 + | + | + ... + + Figure 9: An Example Sequence of KIDs for an MLS-based SFrame + Session (E=4; S=6, Allowing for 64 Group Members) + +6. Media Considerations + +6.1. Selective Forwarding Units + + SFUs (e.g., those described in Section 3.7 of [RFC7667]) receive the + media streams from each participant and select which ones should be + forwarded to each of the other participants. There are several + approaches for stream selection, but in general, the SFU needs to + access metadata associated with each frame and modify the RTP + information of the incoming packets when they are transmitted to the + received participants. + + This section describes how these normal SFU modes of operation + interact with the E2EE provided by SFrame. + +6.1.1. RTP Stream Reuse + + The SFU may choose to send only a certain number of streams based on + the voice activity of the participants. To avoid the overhead + involved in establishing new transport streams, the SFU may decide to + reuse previously existing streams or even pre-allocate a predefined + number of streams and choose in each moment in time which participant + media will be sent through it. + + This means that the same transport-level stream (e.g., an RTP stream + defined by either SSRC or Media Identification (MID)) may carry media + from different streams of different participants. Because each + participant uses a different key to encrypt their media, the receiver + will be able to verify the sender of the media within the RTP stream + at any given point in time. Thus the receiver will correctly + associate the media with the sender indicated by the authenticated + SFrame KID value, irrespective of how the SFU transmits the media to + the client. + + Note that in order to prevent impersonation by a malicious + participant (not the SFU), a mechanism based on digital signature + would be required. SFrame does not protect against such attacks. + +6.1.2. Simulcast + + When using simulcast, the same input image will produce N different + encoded frames (one per simulcast layer), which would be processed + independently by the frame encryptor and assigned an unique CTR value + for each. + +6.1.3. Scalable Video Coding (SVC) + + In both temporal and spatial scalability, the SFU may choose to drop + layers in order to match a certain bitrate or to forward specific + media sizes or frames per second. In order to support the SFU + selectively removing layers, the sender MUST encapsulate each layer + in a different SFrame ciphertext. + +6.2. Video Key Frames + + Forward security and post-compromise security require that the E2EE + keys (base keys) are updated any time a participant joins or leaves + the call. + + The key exchange happens asynchronously and on a different path than + the SFU signaling and media. So it may happen that when a new + participant joins the call and the SFU side requests a key frame, the + sender generates the E2EE frame with a key that is not known by the + receiver, so it will be discarded. When the sender updates his + sending key with the new key, it will send it in a non-key frame, so + the receiver will be able to decrypt it, but not decode it. + + The new receiver will then re-request a key frame, but due to sender + and SFU policies, that new key frame could take some time to be + generated. + + If the sender sends a key frame after the new E2EE key is in use, the + time required for the new participant to display the video is + minimized. + + Note that this issue does not arise for media streams that do not + have dependencies among frames, e.g., audio streams. In these + streams, each frame is independently decodable, so a frame never + depends on another frame that might be on the other side of a key + rotation. + +6.3. Partial Decoding + + Some codecs support partial decoding, where individual packets can be + decoded without waiting for the full frame to arrive. When SFrame is + applied per frame, partial decoding is not possible because the + decoder cannot access data until an entire frame has arrived and has + been decrypted. + +7. Security Considerations + +7.1. No Header Confidentiality + + SFrame provides integrity protection to the SFrame header (the KID + and CTR values), but it does not provide confidentiality protection. + Parties that can observe the SFrame header may learn, for example, + which parties are sending SFrame payloads (from KID values) and at + what rates (from CTR values). In cases where SFrame is used for end- + to-end security on top of hop-by-hop protections (e.g., running over + SRTP as described in Appendix B.5), the hop-by-hop security + mechanisms provide confidentiality protection of the SFrame header + between hops. + +7.2. No Per-Sender Authentication + + SFrame does not provide per-sender authentication of media data. Any + sender in a session can send media that will be associated with any + other sender. This is because SFrame uses symmetric encryption to + protect media data, so that any receiver also has the keys required + to encrypt packets for the sender. + +7.3. Key Management + + The specifics of key management are beyond the scope of this + document. However, every client SHOULD change their keys when new + clients join or leave the call for forward secrecy and post- + compromise security. + +7.4. Replay + + The handling of replay is out of the scope of this document. + However, senders MUST reject requests to encrypt multiple times with + the same key and nonce since several AEAD algorithms fail badly in + such cases (see, e.g., Section 5.1.1 of [RFC5116]). + +7.5. Risks Due to Short Tags + + The SFrame cipher suites based on AES-CTR allow for the use of short + authentication tags, which bring a higher risk that an attacker will + be able to cause an SFrame receiver to accept an SFrame ciphertext of + the attacker's choosing. + + Assuming that the authentication properties of the cipher suite are + robust, the only attack that an attacker can mount is an attempt to + find an acceptable (ciphertext, tag) combination through brute force. + Such a brute-force attack will have an expected success rate of the + following form: + + attacker_success_rate = attempts_per_second / 2^(8*Nt) + + For example, a gigabit Ethernet connection is able to transmit + roughly 2^20 packets per second. If an attacker saturated such a + link with guesses against a 32-bit authentication tag (Nt=4), then + the attacker would succeed on average roughly once every 2^12 + seconds, or about once an hour. + + In a typical SFrame usage in a real-time media application, there are + a few approaches to mitigating this risk: + + * Receivers only accept SFrame ciphertexts over HBH-secure channels + (e.g., SRTP security associations or QUIC connections). If this + is the case, only an entity that is part of such a channel can + mount the above attack. + + * The expected packet rate for a media stream is very predictable + (and typically far lower than the above example). On the one + hand, attacks at this rate will succeed even less often than the + high-rate attack described above. On the other hand, the + application may use an elevated packet arrival rate as a signal of + a brute-force attack. This latter approach is common in other + settings, e.g., mitigating brute-force attacks on passwords. + + * Media applications typically do not provide feedback to media + senders as to which media packets failed to decrypt. When media- + quality feedback mechanisms are used, decryption failures will + typically appear as packet losses, but only at an aggregate level. + + * Anti-replay mechanisms (see Section 7.4) prevent the attacker from + reusing valid ciphertexts (either observed or guessed by the + attacker). A receiver applying anti-replay controls will only + accept one valid plaintext per CTR value. Since the CTR value is + covered by SFrame authentication, an attacker has to do a fresh + search for a valid tag for every forged ciphertext, even if the + encrypted content is unchanged. In other words, when the above + brute-force attack succeeds, it only allows the attacker to send a + single SFrame ciphertext; the ciphertext cannot be reused because + either it will have the same CTR value and be discarded as a + replay, or else it will have a different CTR value and its tag + will no longer be valid. + + Nonetheless, without these mitigations, an application that makes use + of short tags will be at heightened risk of forgery attacks. In many + cases, it is simpler to use full-size tags and tolerate slightly + higher bandwidth usage rather than to add the additional defenses + necessary to safely use short tags. + +8. IANA Considerations + + IANA has created a new registry called "SFrame Cipher Suites" + (Section 8.1) under the "SFrame" group registry heading. + +8.1. SFrame Cipher Suites + + The "SFrame Cipher Suites" registry lists identifiers for SFrame + cipher suites as defined in Section 4.5. The cipher suite field is + two bytes wide, so the valid cipher suites are in the range 0x0000 to + 0xFFFF. Except as noted below, assignments are made via the + Specification Required policy [RFC8126]. + + The registration template is as follows: + + * Value: The numeric value of the cipher suite + + * Name: The name of the cipher suite + + * Recommended: Whether support for this cipher suite is recommended + by the IETF. Valid values are "Y", "N", and "D" as described in + Section 17.1 of [MLS-PROTO]. The default value of the + "Recommended" column is "N". Setting the Recommended item to "Y" + or "D", or changing an item whose current value is "Y" or "D", + requires Standards Action [RFC8126]. + + * Reference: The document where this cipher suite is defined + + * Change Controller: Who is authorized to update the row in the + registry + + Initial contents: + + +========+============================+===+===========+============+ + | Value | Name | R | Reference | Change | + | | | | | Controller | + +========+============================+===+===========+============+ + | 0x0000 | Reserved | - | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0x0001 | AES_128_CTR_HMAC_SHA256_80 | Y | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0x0002 | AES_128_CTR_HMAC_SHA256_64 | Y | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0x0003 | AES_128_CTR_HMAC_SHA256_32 | Y | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0x0004 | AES_128_GCM_SHA256_128 | Y | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0x0005 | AES_256_GCM_SHA512_128 | Y | RFC 9605 | IETF | + +--------+----------------------------+---+-----------+------------+ + | 0xF000 | Reserved for Private Use | - | RFC 9605 | IETF | + | - | | | | | + | 0xFFFF | | | | | + +--------+----------------------------+---+-----------+------------+ + + Table 2: SFrame Cipher Suites + +9. Application Responsibilities + + To use SFrame, an application needs to define the inputs to the + SFrame encryption and decryption operations, and how SFrame + ciphertexts are delivered from sender to receiver (including any + fragmentation and reassembly). In this section, we lay out + additional requirements that an application must meet in order for + SFrame to operate securely. + + In general, an application using SFrame is responsible for + configuring SFrame. The application must first define when SFrame is + applied at all. When SFrame is applied, the application must define + which cipher suite is to be used. If new versions of SFrame are + defined in the future, it will be the application's responsibility to + determine which version should be used. + + This division of responsibilities is similar to the way other media + parameters (e.g., codecs) are typically handled in media + applications, in the sense that they are set up in some signaling + protocol and not described in the media. Applications might find it + useful to extend the protocols used for negotiating other media + parameters (e.g., Session Description Protocol (SDP) [RFC8866]) to + also negotiate parameters for SFrame. + +9.1. Header Value Uniqueness + + Applications MUST ensure that each (base_key, KID, CTR) combination + is used for at most one SFrame encryption operation. This ensures + that the (key, nonce) pairs used by the underlying AEAD algorithm are + never reused. Typically this is done by assigning each sender a KID + or set of KIDs, then having each sender use the CTR field as a + monotonic counter, incrementing for each plaintext that is encrypted. + In addition to its simplicity, this scheme minimizes overhead by + keeping CTR values as small as possible. + + In applications where an SFrame context might be written to + persistent storage, this context needs to include the last-used CTR + value. When the context is used later, the application should use + the stored CTR value to determine the next CTR value to be used in an + encryption operation, and then write the next CTR value back to + storage before using the CTR value for encryption. Storing the CTR + value before usage (vs. after) helps ensure that a storage failure + will not cause reuse of the same (base_key, KID, CTR) combination. + +9.2. Key Management Framework + + The application is responsible for provisioning SFrame with a mapping + of KID values to base_key values and the resulting keys and salts. + More importantly, the application specifies which KID values are used + for which purposes (e.g., by which senders). An application's KID + assignment strategy MUST be structured to assure the non-reuse + properties discussed in Section 9.1. + + The application is also responsible for defining a rotation schedule + for keys. For example, one application might have an ephemeral group + for every call and keep rotating keys when endpoints join 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. + + It should be noted that KID values are not encrypted by SFrame and + are thus visible to any application-layer intermediaries that might + handle an SFrame ciphertext. If there are application semantics + included in KID values, then this information would be exposed to + intermediaries. For example, in the scheme of Section 5.1, the + number of ratchet steps per sender is exposed, and in the scheme of + Section 5.2, the number of epochs and the MLS sender ID of the SFrame + sender are exposed. + +9.3. Anti-Replay + + It is the responsibility of the application to handle anti-replay. + Replay by network attackers is assumed to be prevented by network- + layer facilities (e.g., TLS, SRTP). As mentioned in Section 7.4, + senders MUST reject requests to encrypt multiple times with the same + key and nonce. + + It is not mandatory to implement anti-replay on the receiver side. + Receivers MAY apply time- or counter-based anti-replay mitigations. + For example, Section 3.3.2 of [RFC3711] specifies a counter-based + anti-replay mitigation, which could be adapted to use with SFrame, + using the CTR field as the counter. + +9.4. Metadata + + The metadata input to SFrame operations is an opaque byte string + specified by the application. As such, the application needs to + define what information should go in the metadata input and ensure + that it is provided to the encryption and decryption functions at the + appropriate points. A receiver MUST NOT use SFrame-authenticated + metadata until after the SFrame decrypt function has authenticated + it, unless the purpose of such usage is to prepare an SFrame + ciphertext for SFrame decryption. Essentially, metadata may be used + "upstream of SFrame" in a processing pipeline, but only to prepare + for SFrame decryption. + + For example, consider an application where SFrame is used to encrypt + audio frames that are sent over SRTP, with some application data + included in the RTP header extension. Suppose the application also + includes this application data in the SFrame metadata, so that the + SFU is allowed to read, but not modify, the application data. A + receiver can use the application data in the RTP header extension as + part of the standard SRTP decryption process since this is required + to recover the SFrame ciphertext carried in the SRTP payload. + However, the receiver MUST NOT use the application data for other + purposes before SFrame decryption has authenticated the application + data. + +10. References + +10.1. Normative References + + [MLS-PROTO] + Barnes, R., Beurdouche, B., Robert, R., Millican, J., + Omara, E., and K. Cohn-Gordon, "The Messaging Layer + Security (MLS) Protocol", RFC 9420, DOI 10.17487/RFC9420, + July 2023, . + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, + DOI 10.17487/RFC2119, March 1997, + . + + [RFC5116] McGrew, D., "An Interface and Algorithms for Authenticated + Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008, + . + + [RFC5869] Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand + Key Derivation Function (HKDF)", RFC 5869, + DOI 10.17487/RFC5869, May 2010, + . + + [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for + Writing an IANA Considerations Section in RFCs", BCP 26, + RFC 8126, DOI 10.17487/RFC8126, June 2017, + . + + [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC + 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, + May 2017, . + +10.2. Informative References + + [MLS-ARCH] Beurdouche, B., Rescorla, E., Omara, E., Inguva, S., and + A. Duric, "The Messaging Layer Security (MLS) + Architecture", Work in Progress, Internet-Draft, draft- + ietf-mls-architecture-15, 3 August 2024, + . + + [MOQ-TRANSPORT] + Curley, L., Pugin, K., Nandakumar, S., Vasiliev, V., and + I. Swett, Ed., "Media over QUIC Transport", Work in + Progress, Internet-Draft, draft-ietf-moq-transport-05, 8 + July 2024, . + + [RFC3711] Baugher, M., McGrew, D., Naslund, M., Carrara, E., and K. + Norrman, "The Secure Real-time Transport Protocol (SRTP)", + RFC 3711, DOI 10.17487/RFC3711, March 2004, + . + + [RFC6716] Valin, JM., Vos, K., and T. Terriberry, "Definition of the + Opus Audio Codec", RFC 6716, DOI 10.17487/RFC6716, + September 2012, . + + [RFC7656] Lennox, J., Gross, K., Nandakumar, S., Salgueiro, G., and + B. Burman, Ed., "A Taxonomy of Semantics and Mechanisms + for Real-Time Transport Protocol (RTP) Sources", RFC 7656, + DOI 10.17487/RFC7656, November 2015, + . + + [RFC7667] Westerlund, M. and S. Wenger, "RTP Topologies", RFC 7667, + DOI 10.17487/RFC7667, November 2015, + . + + [RFC8723] Jennings, C., Jones, P., Barnes, R., and A.B. Roach, + "Double Encryption Procedures for the Secure Real-Time + Transport Protocol (SRTP)", RFC 8723, + DOI 10.17487/RFC8723, April 2020, + . + + [RFC8866] Begen, A., Kyzivat, P., Perkins, C., and M. Handley, "SDP: + Session Description Protocol", RFC 8866, + DOI 10.17487/RFC8866, January 2021, + . + + [RTP-PAYLOAD] + Murillo, S. G., Fablet, Y., and A. Gouaillard, "Codec + agnostic RTP payload format for video", Work in Progress, + Internet-Draft, draft-gouaillard-avtcore-codec-agn-rtp- + payload-01, 9 March 2021, + . + + [TestVectors] + "SFrame Test Vectors", commit 025d568, September 2023, + . + + [WEBTRANSPORT] + Vasiliev, V., "The WebTransport Protocol Framework", Work + in Progress, Internet-Draft, draft-ietf-webtrans-overview- + 08, 25 August 2024, + . + +Appendix A. Example API + + *This section is not normative.* + + This section describes a notional API that an SFrame implementation + might expose. The core concept is an "SFrame context", within which + KID values are meaningful. In the key management scheme described in + Section 5.1, each sender has a different context; in the scheme + described in Section 5.2, all senders share the same context. + + An SFrame context stores mappings from KID values to "key contexts", + which are different depending on whether the KID is to be used for + sending or receiving (an SFrame key should never be used for both + operations). A key context tracks the key and salt associated to the + KID, and the current CTR value. A key context to be used for sending + also tracks the next CTR value to be used. + + The primary operations on an SFrame context are as follows: + + * *Create an SFrame context:* The context is initialized with a + cipher suite and no KID mappings. + + * *Add a key for sending:* The key and salt are derived from the + base key and used to initialize a send context, together with a + zero CTR value. + + * *Add a key for receiving:* The key and salt are derived from the + base key and used to initialize a send context. + + * *Encrypt a plaintext:* Encrypt a given plaintext using the key for + a given KID, including the specified metadata. + + * *Decrypt an SFrame ciphertext:* Decrypt an SFrame ciphertext with + the KID and CTR values specified in the SFrame header, and the + provided metadata. + + Figure 10 shows an example of the types of structures and methods + that could be used to create an SFrame API in Rust. + + type KeyId = u64; + type Counter = u64; + type CipherSuite = u16; + + struct SendKeyContext { + key: Vec, + salt: Vec, + next_counter: Counter, + } + + struct RecvKeyContext { + key: Vec, + salt: Vec, + } + + struct SFrameContext { + cipher_suite: CipherSuite, + send_keys: HashMap, + recv_keys: HashMap, + } + + trait SFrameContextMethods { + fn create(cipher_suite: CipherSuite) -> Self; + fn add_send_key(&self, kid: KeyId, base_key: &[u8]); + fn add_recv_key(&self, kid: KeyId, base_key: &[u8]); + fn encrypt(&mut self, kid: KeyId, metadata: &[u8], + plaintext: &[u8]) -> Vec; + fn decrypt(&self, metadata: &[u8], ciphertext: &[u8]) -> Vec; + } + + Figure 10: An Example SFrame API + +Appendix B. Overhead Analysis + + Any use of SFrame will impose overhead in terms of the amount of + bandwidth necessary to transmit a given media stream. Exactly how + much overhead will be added depends on several factors: + + * The number of senders involved in a conference (length of KID) + + * The duration of the conference (length of CTR) + + * The cipher suite in use (length of authentication tag) + + * Whether SFrame is used to encrypt packets, whole frames, or some + other unit + + Overall, the overhead rate in kilobits per second can be estimated + as: + + OverheadKbps = (1 + |CTR| + |KID| + |TAG|) * 8 * CTPerSecond / 1024 + + Here the constant value 1 reflects the fixed SFrame header; |CTR| + and |KID| reflect the lengths of those fields; |TAG| reflects the + cipher overhead; and CTPerSecond reflects the number of SFrame + ciphertexts sent per second (e.g., packets or frames per second). + + In the remainder of this section, we compute overhead estimates for a + collection of common scenarios. + +B.1. Assumptions + + In the below calculations, we make conservative assumptions about + SFrame overhead so that the overhead amounts we compute here are + likely to be an upper bound of those seen in practice. + + +==============+=======+============================+ + | Field | Bytes | Explanation | + +==============+=======+============================+ + | Config byte | 1 | Fixed | + +--------------+-------+----------------------------+ + | Key ID (KID) | 2 | >255 senders; or MLS epoch | + | | | (E=4) and >16 senders | + +--------------+-------+----------------------------+ + | Counter | 3 | More than 24 hours of | + | (CTR) | | media in common cases | + +--------------+-------+----------------------------+ + | Cipher | 16 | Full authentication tag | + | overhead | | (longest defined here) | + +--------------+-------+----------------------------+ + + Table 3: Overhead Analysis Assumptions + + In total, then, we assume that each SFrame encryption will add 22 + bytes of overhead. + + We consider two scenarios: applying SFrame per frame and per packet. + In each scenario, we compute the SFrame overhead in absolute terms + (kbps) and as a percentage of the base bandwidth. + +B.2. Audio + + In audio streams, there is typically a one-to-one relationship + between frames and packets, so the overhead is the same whether one + uses SFrame at a per-packet or per-frame level. + + Table 4 considers three scenarios that are based on recommended + configurations of the Opus codec [RFC6716] (where "fps" stands for + "frames per second"): + + +==============+==============+=====+======+==========+==========+ + | Scenario | Frame length | fps | Base | Overhead | Overhead | + | | | | kbps | kbps | % | + +==============+==============+=====+======+==========+==========+ + | Narrow-band | 120 ms | 8.3 | 8 | 1.4 | 17.9% | + | speech | | | | | | + +--------------+--------------+-----+------+----------+----------+ + | Full-band | 20 ms | 50 | 32 | 8.6 | 26.9% | + | speech | | | | | | + +--------------+--------------+-----+------+----------+----------+ + | Full-band | 10 ms | 100 | 128 | 17.2 | 13.4% | + | stereo music | | | | | | + +--------------+--------------+-----+------+----------+----------+ + + Table 4: SFrame Overhead for Audio Streams + +B.3. Video + + Video frames can be larger than an MTU and thus are commonly split + across multiple frames. Tables 5 and 6 show the estimated overhead + of encrypting a video stream, where SFrame is applied per frame and + per packet, respectively. The choices of resolution, frames per + second, and bandwidth roughly reflect the capabilities of modern + video codecs across a range from very low to very high quality. + + +=============+=====+===========+===============+============+ + | Scenario | fps | Base kbps | Overhead kbps | Overhead % | + +=============+=====+===========+===============+============+ + | 426 x 240 | 7.5 | 45 | 1.3 | 2.9% | + +-------------+-----+-----------+---------------+------------+ + | 640 x 360 | 15 | 200 | 2.6 | 1.3% | + +-------------+-----+-----------+---------------+------------+ + | 640 x 360 | 30 | 400 | 5.2 | 1.3% | + +-------------+-----+-----------+---------------+------------+ + | 1280 x 720 | 30 | 1500 | 5.2 | 0.3% | + +-------------+-----+-----------+---------------+------------+ + | 1920 x 1080 | 60 | 7200 | 10.3 | 0.1% | + +-------------+-----+-----------+---------------+------------+ + + Table 5: SFrame Overhead for a Video Stream Encrypted per + Frame + + +==========+=====+==============+======+==========+==========+ + | Scenario | fps | Packets per | Base | Overhead | Overhead | + | | | Second (pps) | kbps | kbps | % | + +==========+=====+==============+======+==========+==========+ + | 426 x | 7.5 | 7.5 | 45 | 1.3 | 2.9% | + | 240 | | | | | | + +----------+-----+--------------+------+----------+----------+ + | 640 x | 15 | 30 | 200 | 5.2 | 2.6% | + | 360 | | | | | | + +----------+-----+--------------+------+----------+----------+ + | 640 x | 30 | 60 | 400 | 10.3 | 2.6% | + | 360 | | | | | | + +----------+-----+--------------+------+----------+----------+ + | 1280 x | 30 | 180 | 1500 | 30.9 | 2.1% | + | 720 | | | | | | + +----------+-----+--------------+------+----------+----------+ + | 1920 x | 60 | 780 | 7200 | 134.1 | 1.9% | + | 1080 | | | | | | + +----------+-----+--------------+------+----------+----------+ + + Table 6: SFrame Overhead for a Video Stream Encrypted per + Packet + + In the per-frame case, the SFrame percentage overhead approaches zero + as the quality of the video improves since bandwidth is driven more + by picture size than frame rate. In the per-packet case, the SFrame + percentage overhead approaches the ratio between the SFrame overhead + per packet and the MTU (here 22 bytes of SFrame overhead divided by + an assumed 1200-byte MTU, or about 1.8%). + +B.4. Conferences + + Real conferences usually involve several audio and video streams. + The overhead of SFrame in such a conference is the aggregate of the + overhead across all the individual streams. Thus, while SFrame + incurs a large percentage overhead on an audio stream, if the + conference also involves a video stream, then the audio overhead is + likely negligible relative to the overall bandwidth of the + conference. + + For example, Table 7 shows the overhead estimates for a two-person + conference where one person is sending low-quality media and the + other is sending high-quality media. (And we assume that SFrame is + applied per frame.) The video streams dominate the bandwidth at the + SFU, so the total bandwidth overhead is only around 1%. + + +=====================+===========+===============+============+ + | Stream | Base Kbps | Overhead Kbps | Overhead % | + +=====================+===========+===============+============+ + | Participant 1 audio | 8 | 1.4 | 17.9% | + +---------------------+-----------+---------------+------------+ + | Participant 1 video | 45 | 1.3 | 2.9% | + +---------------------+-----------+---------------+------------+ + | Participant 2 audio | 32 | 9 | 26.9% | + +---------------------+-----------+---------------+------------+ + | Participant 2 video | 1500 | 5 | 0.3% | + +---------------------+-----------+---------------+------------+ + | Total at SFU | 1585 | 16.5 | 1.0% | + +---------------------+-----------+---------------+------------+ + + Table 7: SFrame Overhead for a Two-Person Conference + +B.5. SFrame over RTP + + SFrame is a generic encapsulation format, but many of the + applications in which it is likely to be integrated are based on RTP. + This section discusses how an integration between SFrame and RTP + could be done, and some of the challenges that would need to be + overcome. + + As discussed in Section 4.1, there are two natural patterns for + integrating SFrame into an application: applying SFrame per frame or + per packet. In RTP-based applications, applying SFrame per packet + means that the payload of each RTP packet will be an SFrame + ciphertext, starting with an SFrame header, as shown in Figure 11. + Applying SFrame per frame means that different RTP payloads will have + different formats: The first payload of a frame will contain the + SFrame headers, and subsequent payloads will contain further chunks + of the ciphertext, as shown in Figure 12. + + In order for these media payloads to be properly interpreted by + receivers, receivers will need to be configured to know which of the + above schemes the sender has applied to a given sequence of RTP + packets. SFrame does not provide a mechanism for distributing this + configuration information. In applications that use SDP for + negotiating RTP media streams [RFC8866], an appropriate extension to + SDP could provide this function. + + Applying SFrame per frame also requires that packetization and + depacketization be done in a generic manner that does not depend on + the media content of the packets, since the content being packetized + or depacketized will be opaque ciphertext (except for the SFrame + header). In order for such a generic packetization scheme to work + interoperably, one would have to be defined, e.g., as proposed in + [RTP-PAYLOAD]. + + +---+-+-+-------+-+-----------+------------------------------+<-+ + |V=2|P|X| CC |M| PT | sequence number | | + +---+-+-+-------+-+-----------+------------------------------+ | + | timestamp | | + +------------------------------------------------------------+ | + | synchronization source (SSRC) identifier | | + +============================================================+ | + | contributing source (CSRC) identifiers | | + | .... | | + +------------------------------------------------------------+ | + | RTP extension(s) (OPTIONAL) | | + +->+-------------------+----------------------------------------+ | + | | SFrame header | | | + | +-------------------+ | | + | | | | + | | SFrame encrypted and authenticated payload | | + | | | | + +->+------------------------------------------------------------+<-+ + | | SRTP authentication tag | | + | +------------------------------------------------------------+ | + | | + +--- SRTP Encrypted Portion SRTP Authenticated Portion ---+ + + Figure 11: SRTP Packet with SFrame-Protected Payload + + +----------------+ +---------------+ + | frame metadata | | | + +-------+--------+ | | + | | frame | + | | | + | | | + | +-------+-------+ + | | + | | + V V + +--------------------------------------+ + | SFrame Encrypt | + +--------------------------------------+ + | | + | | + | V + | +-------+-------+ + | | | + | | | + | | encrypted | + | | frame | + | | | + | | | + | +-------+-------+ + | | + | generic RTP packetize + | | + | +----------------------+--------.....--------+ + | | | | + V V V V + +---------------+ +---------------+ +---------------+ + | SFrame header | | | | | + +---------------+ | | | | + | | | payload 2/N | ... | payload N/N | + | payload 1/N | | | | | + | | | | | | + +---------------+ +---------------+ +---------------+ + + Figure 12: Encryption Flow with per-Frame Encryption for RTP + +Appendix C. Test Vectors + + This section provides a set of test vectors that implementations can + use to verify that they correctly implement SFrame encryption and + decryption. In addition to test vectors for the overall process of + SFrame encryption/decryption, we also provide test vectors for header + encoding/decoding, and for AEAD encryption/decryption using the AES- + CTR construction defined in Section 4.5.1. + + All values are either numeric or byte strings. Numeric values are + represented as hex values, prefixed with 0x. Byte strings are + represented in hex encoding. + + Line breaks and whitespace within values are inserted to conform to + the width requirements of the RFC format. They should be removed + before use. + + These test vectors are also available in JSON format at + [TestVectors]. In the JSON test vectors, numeric values are JSON + numbers and byte string values are JSON strings containing the hex + encoding of the byte strings. + +C.1. Header Encoding/Decoding + + For each case, we provide: + + * kid: A KID value + + * ctr: A CTR value + + * header: An encoded SFrame header + + An implementation should verify that: + + * Encoding a header with the KID and CTR results in the provided + header value + + * Decoding the provided header value results in the provided KID and + CTR values + + kid: 0x0000000000000000 + ctr: 0x0000000000000000 + header: 00 + + kid: 0x0000000000000000 + ctr: 0x0000000000000001 + header: 01 + + kid: 0x0000000000000000 + ctr: 0x00000000000000ff + header: 08ff + + kid: 0x0000000000000000 + ctr: 0x0000000000000100 + header: 090100 + + kid: 0x0000000000000000 + ctr: 0x000000000000ffff + header: 09ffff + + kid: 0x0000000000000000 + ctr: 0x0000000000010000 + header: 0a010000 + + kid: 0x0000000000000000 + ctr: 0x0000000000ffffff + header: 0affffff + + kid: 0x0000000000000000 + ctr: 0x0000000001000000 + header: 0b01000000 + + kid: 0x0000000000000000 + ctr: 0x00000000ffffffff + header: 0bffffffff + + kid: 0x0000000000000000 + ctr: 0x0000000100000000 + header: 0c0100000000 + + kid: 0x0000000000000000 + ctr: 0x000000ffffffffff + header: 0cffffffffff + + kid: 0x0000000000000000 + ctr: 0x0000010000000000 + header: 0d010000000000 + + kid: 0x0000000000000000 + ctr: 0x0000ffffffffffff + header: 0dffffffffffff + + kid: 0x0000000000000000 + ctr: 0x0001000000000000 + header: 0e01000000000000 + + kid: 0x0000000000000000 + ctr: 0x00ffffffffffffff + header: 0effffffffffffff + + kid: 0x0000000000000000 + ctr: 0x0100000000000000 + header: 0f0100000000000000 + + kid: 0x0000000000000000 + ctr: 0xffffffffffffffff + header: 0fffffffffffffffff + + kid: 0x0000000000000001 + ctr: 0x0000000000000000 + header: 10 + + kid: 0x0000000000000001 + ctr: 0x0000000000000001 + header: 11 + + kid: 0x0000000000000001 + ctr: 0x00000000000000ff + header: 18ff + + kid: 0x0000000000000001 + ctr: 0x0000000000000100 + header: 190100 + + kid: 0x0000000000000001 + ctr: 0x000000000000ffff + header: 19ffff + + kid: 0x0000000000000001 + ctr: 0x0000000000010000 + header: 1a010000 + + kid: 0x0000000000000001 + ctr: 0x0000000000ffffff + header: 1affffff + + kid: 0x0000000000000001 + ctr: 0x0000000001000000 + header: 1b01000000 + + kid: 0x0000000000000001 + ctr: 0x00000000ffffffff + header: 1bffffffff + + kid: 0x0000000000000001 + ctr: 0x0000000100000000 + header: 1c0100000000 + + kid: 0x0000000000000001 + ctr: 0x000000ffffffffff + header: 1cffffffffff + + kid: 0x0000000000000001 + ctr: 0x0000010000000000 + header: 1d010000000000 + + kid: 0x0000000000000001 + ctr: 0x0000ffffffffffff + header: 1dffffffffffff + + kid: 0x0000000000000001 + ctr: 0x0001000000000000 + header: 1e01000000000000 + + kid: 0x0000000000000001 + ctr: 0x00ffffffffffffff + header: 1effffffffffffff + + kid: 0x0000000000000001 + ctr: 0x0100000000000000 + header: 1f0100000000000000 + + kid: 0x0000000000000001 + ctr: 0xffffffffffffffff + header: 1fffffffffffffffff + + kid: 0x00000000000000ff + ctr: 0x0000000000000000 + header: 80ff + + kid: 0x00000000000000ff + ctr: 0x0000000000000001 + header: 81ff + + kid: 0x00000000000000ff + ctr: 0x00000000000000ff + header: 88ffff + + kid: 0x00000000000000ff + ctr: 0x0000000000000100 + header: 89ff0100 + + kid: 0x00000000000000ff + ctr: 0x000000000000ffff + header: 89ffffff + + kid: 0x00000000000000ff + ctr: 0x0000000000010000 + header: 8aff010000 + + kid: 0x00000000000000ff + ctr: 0x0000000000ffffff + header: 8affffffff + + kid: 0x00000000000000ff + ctr: 0x0000000001000000 + header: 8bff01000000 + + kid: 0x00000000000000ff + ctr: 0x00000000ffffffff + header: 8bffffffffff + + kid: 0x00000000000000ff + ctr: 0x0000000100000000 + header: 8cff0100000000 + + kid: 0x00000000000000ff + ctr: 0x000000ffffffffff + header: 8cffffffffffff + + kid: 0x00000000000000ff + ctr: 0x0000010000000000 + header: 8dff010000000000 + + kid: 0x00000000000000ff + ctr: 0x0000ffffffffffff + header: 8dffffffffffffff + + kid: 0x00000000000000ff + ctr: 0x0001000000000000 + header: 8eff01000000000000 + + kid: 0x00000000000000ff + ctr: 0x00ffffffffffffff + header: 8effffffffffffffff + + kid: 0x00000000000000ff + ctr: 0x0100000000000000 + header: 8fff0100000000000000 + + kid: 0x00000000000000ff + ctr: 0xffffffffffffffff + header: 8fffffffffffffffffff + + kid: 0x0000000000000100 + ctr: 0x0000000000000000 + header: 900100 + + kid: 0x0000000000000100 + ctr: 0x0000000000000001 + header: 910100 + + kid: 0x0000000000000100 + ctr: 0x00000000000000ff + header: 980100ff + + kid: 0x0000000000000100 + ctr: 0x0000000000000100 + header: 9901000100 + + kid: 0x0000000000000100 + ctr: 0x000000000000ffff + header: 990100ffff + + kid: 0x0000000000000100 + ctr: 0x0000000000010000 + header: 9a0100010000 + + kid: 0x0000000000000100 + ctr: 0x0000000000ffffff + header: 9a0100ffffff + + kid: 0x0000000000000100 + ctr: 0x0000000001000000 + header: 9b010001000000 + + kid: 0x0000000000000100 + ctr: 0x00000000ffffffff + header: 9b0100ffffffff + + kid: 0x0000000000000100 + ctr: 0x0000000100000000 + header: 9c01000100000000 + + kid: 0x0000000000000100 + ctr: 0x000000ffffffffff + header: 9c0100ffffffffff + + kid: 0x0000000000000100 + ctr: 0x0000010000000000 + header: 9d0100010000000000 + + kid: 0x0000000000000100 + ctr: 0x0000ffffffffffff + header: 9d0100ffffffffffff + + kid: 0x0000000000000100 + ctr: 0x0001000000000000 + header: 9e010001000000000000 + + kid: 0x0000000000000100 + ctr: 0x00ffffffffffffff + header: 9e0100ffffffffffffff + + kid: 0x0000000000000100 + ctr: 0x0100000000000000 + header: 9f01000100000000000000 + + kid: 0x0000000000000100 + ctr: 0xffffffffffffffff + header: 9f0100ffffffffffffffff + + kid: 0x000000000000ffff + ctr: 0x0000000000000000 + header: 90ffff + + kid: 0x000000000000ffff + ctr: 0x0000000000000001 + header: 91ffff + + kid: 0x000000000000ffff + ctr: 0x00000000000000ff + header: 98ffffff + + kid: 0x000000000000ffff + ctr: 0x0000000000000100 + header: 99ffff0100 + + kid: 0x000000000000ffff + ctr: 0x000000000000ffff + header: 99ffffffff + + kid: 0x000000000000ffff + ctr: 0x0000000000010000 + header: 9affff010000 + + kid: 0x000000000000ffff + ctr: 0x0000000000ffffff + header: 9affffffffff + + kid: 0x000000000000ffff + ctr: 0x0000000001000000 + header: 9bffff01000000 + + kid: 0x000000000000ffff + ctr: 0x00000000ffffffff + header: 9bffffffffffff + + kid: 0x000000000000ffff + ctr: 0x0000000100000000 + header: 9cffff0100000000 + + kid: 0x000000000000ffff + ctr: 0x000000ffffffffff + header: 9cffffffffffffff + + kid: 0x000000000000ffff + ctr: 0x0000010000000000 + header: 9dffff010000000000 + + kid: 0x000000000000ffff + ctr: 0x0000ffffffffffff + header: 9dffffffffffffffff + + kid: 0x000000000000ffff + ctr: 0x0001000000000000 + header: 9effff01000000000000 + + kid: 0x000000000000ffff + ctr: 0x00ffffffffffffff + header: 9effffffffffffffffff + + kid: 0x000000000000ffff + ctr: 0x0100000000000000 + header: 9fffff0100000000000000 + + kid: 0x000000000000ffff + ctr: 0xffffffffffffffff + header: 9fffffffffffffffffffff + + kid: 0x0000000000010000 + ctr: 0x0000000000000000 + header: a0010000 + + kid: 0x0000000000010000 + ctr: 0x0000000000000001 + header: a1010000 + + kid: 0x0000000000010000 + ctr: 0x00000000000000ff + header: a8010000ff + + kid: 0x0000000000010000 + ctr: 0x0000000000000100 + header: a90100000100 + + kid: 0x0000000000010000 + ctr: 0x000000000000ffff + header: a9010000ffff + + kid: 0x0000000000010000 + ctr: 0x0000000000010000 + header: aa010000010000 + + kid: 0x0000000000010000 + ctr: 0x0000000000ffffff + header: aa010000ffffff + + kid: 0x0000000000010000 + ctr: 0x0000000001000000 + header: ab01000001000000 + + kid: 0x0000000000010000 + ctr: 0x00000000ffffffff + header: ab010000ffffffff + + kid: 0x0000000000010000 + ctr: 0x0000000100000000 + header: ac0100000100000000 + + kid: 0x0000000000010000 + ctr: 0x000000ffffffffff + header: ac010000ffffffffff + + kid: 0x0000000000010000 + ctr: 0x0000010000000000 + header: ad010000010000000000 + + kid: 0x0000000000010000 + ctr: 0x0000ffffffffffff + header: ad010000ffffffffffff + + kid: 0x0000000000010000 + ctr: 0x0001000000000000 + header: ae01000001000000000000 + + kid: 0x0000000000010000 + ctr: 0x00ffffffffffffff + header: ae010000ffffffffffffff + + kid: 0x0000000000010000 + ctr: 0x0100000000000000 + header: af0100000100000000000000 + + kid: 0x0000000000010000 + ctr: 0xffffffffffffffff + header: af010000ffffffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000000000000 + header: a0ffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000000000001 + header: a1ffffff + + kid: 0x0000000000ffffff + ctr: 0x00000000000000ff + header: a8ffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000000000100 + header: a9ffffff0100 + + kid: 0x0000000000ffffff + ctr: 0x000000000000ffff + header: a9ffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000000010000 + header: aaffffff010000 + + kid: 0x0000000000ffffff + ctr: 0x0000000000ffffff + header: aaffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000001000000 + header: abffffff01000000 + + kid: 0x0000000000ffffff + ctr: 0x00000000ffffffff + header: abffffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000000100000000 + header: acffffff0100000000 + + kid: 0x0000000000ffffff + ctr: 0x000000ffffffffff + header: acffffffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0000010000000000 + header: adffffff010000000000 + + kid: 0x0000000000ffffff + ctr: 0x0000ffffffffffff + header: adffffffffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0001000000000000 + header: aeffffff01000000000000 + + kid: 0x0000000000ffffff + ctr: 0x00ffffffffffffff + header: aeffffffffffffffffffff + + kid: 0x0000000000ffffff + ctr: 0x0100000000000000 + header: afffffff0100000000000000 + + kid: 0x0000000000ffffff + ctr: 0xffffffffffffffff + header: afffffffffffffffffffffff + + kid: 0x0000000001000000 + ctr: 0x0000000000000000 + header: b001000000 + + kid: 0x0000000001000000 + ctr: 0x0000000000000001 + header: b101000000 + + kid: 0x0000000001000000 + ctr: 0x00000000000000ff + header: b801000000ff + + kid: 0x0000000001000000 + ctr: 0x0000000000000100 + header: b9010000000100 + + kid: 0x0000000001000000 + ctr: 0x000000000000ffff + header: b901000000ffff + + kid: 0x0000000001000000 + ctr: 0x0000000000010000 + header: ba01000000010000 + + kid: 0x0000000001000000 + ctr: 0x0000000000ffffff + header: ba01000000ffffff + + kid: 0x0000000001000000 + ctr: 0x0000000001000000 + header: bb0100000001000000 + + kid: 0x0000000001000000 + ctr: 0x00000000ffffffff + header: bb01000000ffffffff + + kid: 0x0000000001000000 + ctr: 0x0000000100000000 + header: bc010000000100000000 + + kid: 0x0000000001000000 + ctr: 0x000000ffffffffff + header: bc01000000ffffffffff + + kid: 0x0000000001000000 + ctr: 0x0000010000000000 + header: bd01000000010000000000 + + kid: 0x0000000001000000 + ctr: 0x0000ffffffffffff + header: bd01000000ffffffffffff + + kid: 0x0000000001000000 + ctr: 0x0001000000000000 + header: be0100000001000000000000 + + kid: 0x0000000001000000 + ctr: 0x00ffffffffffffff + header: be01000000ffffffffffffff + + kid: 0x0000000001000000 + ctr: 0x0100000000000000 + header: bf010000000100000000000000 + + kid: 0x0000000001000000 + ctr: 0xffffffffffffffff + header: bf01000000ffffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000000000000 + header: b0ffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000000000001 + header: b1ffffffff + + kid: 0x00000000ffffffff + ctr: 0x00000000000000ff + header: b8ffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000000000100 + header: b9ffffffff0100 + + kid: 0x00000000ffffffff + ctr: 0x000000000000ffff + header: b9ffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000000010000 + header: baffffffff010000 + + kid: 0x00000000ffffffff + ctr: 0x0000000000ffffff + header: baffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000001000000 + header: bbffffffff01000000 + + kid: 0x00000000ffffffff + ctr: 0x00000000ffffffff + header: bbffffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000000100000000 + header: bcffffffff0100000000 + + kid: 0x00000000ffffffff + ctr: 0x000000ffffffffff + header: bcffffffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0000010000000000 + header: bdffffffff010000000000 + + kid: 0x00000000ffffffff + ctr: 0x0000ffffffffffff + header: bdffffffffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0001000000000000 + header: beffffffff01000000000000 + + kid: 0x00000000ffffffff + ctr: 0x00ffffffffffffff + header: beffffffffffffffffffffff + + kid: 0x00000000ffffffff + ctr: 0x0100000000000000 + header: bfffffffff0100000000000000 + + kid: 0x00000000ffffffff + ctr: 0xffffffffffffffff + header: bfffffffffffffffffffffffff + + kid: 0x0000000100000000 + ctr: 0x0000000000000000 + header: c00100000000 + + kid: 0x0000000100000000 + ctr: 0x0000000000000001 + header: c10100000000 + + kid: 0x0000000100000000 + ctr: 0x00000000000000ff + header: c80100000000ff + + kid: 0x0000000100000000 + ctr: 0x0000000000000100 + header: c901000000000100 + + kid: 0x0000000100000000 + ctr: 0x000000000000ffff + header: c90100000000ffff + + kid: 0x0000000100000000 + ctr: 0x0000000000010000 + header: ca0100000000010000 + + kid: 0x0000000100000000 + ctr: 0x0000000000ffffff + header: ca0100000000ffffff + + kid: 0x0000000100000000 + ctr: 0x0000000001000000 + header: cb010000000001000000 + + kid: 0x0000000100000000 + ctr: 0x00000000ffffffff + header: cb0100000000ffffffff + + kid: 0x0000000100000000 + ctr: 0x0000000100000000 + header: cc01000000000100000000 + + kid: 0x0000000100000000 + ctr: 0x000000ffffffffff + header: cc0100000000ffffffffff + + kid: 0x0000000100000000 + ctr: 0x0000010000000000 + header: cd0100000000010000000000 + + kid: 0x0000000100000000 + ctr: 0x0000ffffffffffff + header: cd0100000000ffffffffffff + + kid: 0x0000000100000000 + ctr: 0x0001000000000000 + header: ce010000000001000000000000 + + kid: 0x0000000100000000 + ctr: 0x00ffffffffffffff + header: ce0100000000ffffffffffffff + + kid: 0x0000000100000000 + ctr: 0x0100000000000000 + header: cf01000000000100000000000000 + + kid: 0x0000000100000000 + ctr: 0xffffffffffffffff + header: cf0100000000ffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000000000000 + header: c0ffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000000000001 + header: c1ffffffffff + + kid: 0x000000ffffffffff + ctr: 0x00000000000000ff + header: c8ffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000000000100 + header: c9ffffffffff0100 + + kid: 0x000000ffffffffff + ctr: 0x000000000000ffff + header: c9ffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000000010000 + header: caffffffffff010000 + + kid: 0x000000ffffffffff + ctr: 0x0000000000ffffff + header: caffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000001000000 + header: cbffffffffff01000000 + + kid: 0x000000ffffffffff + ctr: 0x00000000ffffffff + header: cbffffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000000100000000 + header: ccffffffffff0100000000 + + kid: 0x000000ffffffffff + ctr: 0x000000ffffffffff + header: ccffffffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0000010000000000 + header: cdffffffffff010000000000 + + kid: 0x000000ffffffffff + ctr: 0x0000ffffffffffff + header: cdffffffffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0001000000000000 + header: ceffffffffff01000000000000 + + kid: 0x000000ffffffffff + ctr: 0x00ffffffffffffff + header: ceffffffffffffffffffffffff + + kid: 0x000000ffffffffff + ctr: 0x0100000000000000 + header: cfffffffffff0100000000000000 + + kid: 0x000000ffffffffff + ctr: 0xffffffffffffffff + header: cfffffffffffffffffffffffffff + + kid: 0x0000010000000000 + ctr: 0x0000000000000000 + header: d0010000000000 + + kid: 0x0000010000000000 + ctr: 0x0000000000000001 + header: d1010000000000 + + kid: 0x0000010000000000 + ctr: 0x00000000000000ff + header: d8010000000000ff + + kid: 0x0000010000000000 + ctr: 0x0000000000000100 + header: d90100000000000100 + + kid: 0x0000010000000000 + ctr: 0x000000000000ffff + header: d9010000000000ffff + + kid: 0x0000010000000000 + ctr: 0x0000000000010000 + header: da010000000000010000 + + kid: 0x0000010000000000 + ctr: 0x0000000000ffffff + header: da010000000000ffffff + + kid: 0x0000010000000000 + ctr: 0x0000000001000000 + header: db01000000000001000000 + + kid: 0x0000010000000000 + ctr: 0x00000000ffffffff + header: db010000000000ffffffff + + kid: 0x0000010000000000 + ctr: 0x0000000100000000 + header: dc0100000000000100000000 + + kid: 0x0000010000000000 + ctr: 0x000000ffffffffff + header: dc010000000000ffffffffff + + kid: 0x0000010000000000 + ctr: 0x0000010000000000 + header: dd010000000000010000000000 + + kid: 0x0000010000000000 + ctr: 0x0000ffffffffffff + header: dd010000000000ffffffffffff + + kid: 0x0000010000000000 + ctr: 0x0001000000000000 + header: de01000000000001000000000000 + + kid: 0x0000010000000000 + ctr: 0x00ffffffffffffff + header: de010000000000ffffffffffffff + + kid: 0x0000010000000000 + ctr: 0x0100000000000000 + header: df0100000000000100000000000000 + + kid: 0x0000010000000000 + ctr: 0xffffffffffffffff + header: df010000000000ffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000000000000 + header: d0ffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000000000001 + header: d1ffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x00000000000000ff + header: d8ffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000000000100 + header: d9ffffffffffff0100 + + kid: 0x0000ffffffffffff + ctr: 0x000000000000ffff + header: d9ffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000000010000 + header: daffffffffffff010000 + + kid: 0x0000ffffffffffff + ctr: 0x0000000000ffffff + header: daffffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000001000000 + header: dbffffffffffff01000000 + + kid: 0x0000ffffffffffff + ctr: 0x00000000ffffffff + header: dbffffffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000000100000000 + header: dcffffffffffff0100000000 + + kid: 0x0000ffffffffffff + ctr: 0x000000ffffffffff + header: dcffffffffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0000010000000000 + header: ddffffffffffff010000000000 + + kid: 0x0000ffffffffffff + ctr: 0x0000ffffffffffff + header: ddffffffffffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0001000000000000 + header: deffffffffffff01000000000000 + + kid: 0x0000ffffffffffff + ctr: 0x00ffffffffffffff + header: deffffffffffffffffffffffffff + + kid: 0x0000ffffffffffff + ctr: 0x0100000000000000 + header: dfffffffffffff0100000000000000 + + kid: 0x0000ffffffffffff + ctr: 0xffffffffffffffff + header: dfffffffffffffffffffffffffffff + + kid: 0x0001000000000000 + ctr: 0x0000000000000000 + header: e001000000000000 + + kid: 0x0001000000000000 + ctr: 0x0000000000000001 + header: e101000000000000 + + kid: 0x0001000000000000 + ctr: 0x00000000000000ff + header: e801000000000000ff + + kid: 0x0001000000000000 + ctr: 0x0000000000000100 + header: e9010000000000000100 + + kid: 0x0001000000000000 + ctr: 0x000000000000ffff + header: e901000000000000ffff + + kid: 0x0001000000000000 + ctr: 0x0000000000010000 + header: ea01000000000000010000 + + kid: 0x0001000000000000 + ctr: 0x0000000000ffffff + header: ea01000000000000ffffff + + kid: 0x0001000000000000 + ctr: 0x0000000001000000 + header: eb0100000000000001000000 + + kid: 0x0001000000000000 + ctr: 0x00000000ffffffff + header: eb01000000000000ffffffff + + kid: 0x0001000000000000 + ctr: 0x0000000100000000 + header: ec010000000000000100000000 + + kid: 0x0001000000000000 + ctr: 0x000000ffffffffff + header: ec01000000000000ffffffffff + + kid: 0x0001000000000000 + ctr: 0x0000010000000000 + header: ed01000000000000010000000000 + + kid: 0x0001000000000000 + ctr: 0x0000ffffffffffff + header: ed01000000000000ffffffffffff + + kid: 0x0001000000000000 + ctr: 0x0001000000000000 + header: ee0100000000000001000000000000 + + kid: 0x0001000000000000 + ctr: 0x00ffffffffffffff + header: ee01000000000000ffffffffffffff + + kid: 0x0001000000000000 + ctr: 0x0100000000000000 + header: ef010000000000000100000000000000 + + kid: 0x0001000000000000 + ctr: 0xffffffffffffffff + header: ef01000000000000ffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000000000000 + header: e0ffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000000000001 + header: e1ffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x00000000000000ff + header: e8ffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000000000100 + header: e9ffffffffffffff0100 + + kid: 0x00ffffffffffffff + ctr: 0x000000000000ffff + header: e9ffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000000010000 + header: eaffffffffffffff010000 + + kid: 0x00ffffffffffffff + ctr: 0x0000000000ffffff + header: eaffffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000001000000 + header: ebffffffffffffff01000000 + + kid: 0x00ffffffffffffff + ctr: 0x00000000ffffffff + header: ebffffffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000000100000000 + header: ecffffffffffffff0100000000 + + kid: 0x00ffffffffffffff + ctr: 0x000000ffffffffff + header: ecffffffffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0000010000000000 + header: edffffffffffffff010000000000 + + kid: 0x00ffffffffffffff + ctr: 0x0000ffffffffffff + header: edffffffffffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0001000000000000 + header: eeffffffffffffff01000000000000 + + kid: 0x00ffffffffffffff + ctr: 0x00ffffffffffffff + header: eeffffffffffffffffffffffffffff + + kid: 0x00ffffffffffffff + ctr: 0x0100000000000000 + header: efffffffffffffff0100000000000000 + + kid: 0x00ffffffffffffff + ctr: 0xffffffffffffffff + header: efffffffffffffffffffffffffffffff + + kid: 0x0100000000000000 + ctr: 0x0000000000000000 + header: f00100000000000000 + + kid: 0x0100000000000000 + ctr: 0x0000000000000001 + header: f10100000000000000 + + kid: 0x0100000000000000 + ctr: 0x00000000000000ff + header: f80100000000000000ff + + kid: 0x0100000000000000 + ctr: 0x0000000000000100 + header: f901000000000000000100 + + kid: 0x0100000000000000 + ctr: 0x000000000000ffff + header: f90100000000000000ffff + + kid: 0x0100000000000000 + ctr: 0x0000000000010000 + header: fa0100000000000000010000 + + kid: 0x0100000000000000 + ctr: 0x0000000000ffffff + header: fa0100000000000000ffffff + + kid: 0x0100000000000000 + ctr: 0x0000000001000000 + header: fb010000000000000001000000 + + kid: 0x0100000000000000 + ctr: 0x00000000ffffffff + header: fb0100000000000000ffffffff + + kid: 0x0100000000000000 + ctr: 0x0000000100000000 + header: fc01000000000000000100000000 + + kid: 0x0100000000000000 + ctr: 0x000000ffffffffff + header: fc0100000000000000ffffffffff + + kid: 0x0100000000000000 + ctr: 0x0000010000000000 + header: fd0100000000000000010000000000 + + kid: 0x0100000000000000 + ctr: 0x0000ffffffffffff + header: fd0100000000000000ffffffffffff + + kid: 0x0100000000000000 + ctr: 0x0001000000000000 + header: fe010000000000000001000000000000 + + kid: 0x0100000000000000 + ctr: 0x00ffffffffffffff + header: fe0100000000000000ffffffffffffff + + kid: 0x0100000000000000 + ctr: 0x0100000000000000 + header: ff010000000000000001000000000000 + 00 + + kid: 0x0100000000000000 + ctr: 0xffffffffffffffff + header: ff0100000000000000ffffffffffffff + ff + + kid: 0xffffffffffffffff + ctr: 0x0000000000000000 + header: f0ffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000000000000001 + header: f1ffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x00000000000000ff + header: f8ffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000000000000100 + header: f9ffffffffffffffff0100 + + kid: 0xffffffffffffffff + ctr: 0x000000000000ffff + header: f9ffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000000000010000 + header: faffffffffffffffff010000 + + kid: 0xffffffffffffffff + ctr: 0x0000000000ffffff + header: faffffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000000001000000 + header: fbffffffffffffffff01000000 + + kid: 0xffffffffffffffff + ctr: 0x00000000ffffffff + header: fbffffffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000000100000000 + header: fcffffffffffffffff0100000000 + + kid: 0xffffffffffffffff + ctr: 0x000000ffffffffff + header: fcffffffffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0000010000000000 + header: fdffffffffffffffff010000000000 + + kid: 0xffffffffffffffff + ctr: 0x0000ffffffffffff + header: fdffffffffffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0001000000000000 + header: feffffffffffffffff01000000000000 + + kid: 0xffffffffffffffff + ctr: 0x00ffffffffffffff + header: feffffffffffffffffffffffffffffff + + kid: 0xffffffffffffffff + ctr: 0x0100000000000000 + header: ffffffffffffffffff01000000000000 + 00 + + kid: 0xffffffffffffffff + ctr: 0xffffffffffffffff + header: ffffffffffffffffffffffffffffffff + ff + +C.2. AEAD Encryption/Decryption Using AES-CTR and HMAC + + For each case, we provide: + + * cipher_suite: The index of the cipher suite in use (see + Section 8.1) + + * key: The key input to encryption/decryption + + * enc_key: The encryption subkey produced by the derive_subkeys() + algorithm + + * auth_key: The encryption subkey produced by the derive_subkeys() + algorithm + + * nonce: The nonce input to encryption/decryption + + * aad: The aad input to encryption/decryption + + * pt: The plaintext + + * ct: The ciphertext + + An implementation should verify that the following are true, where + AEAD.Encrypt and AEAD.Decrypt are as defined in Section 4.5.1: + + * AEAD.Encrypt(key, nonce, aad, pt) == ct + + * AEAD.Decrypt(key, nonce, aad, ct) == pt + + The other values in the test vector are intermediate values provided + to facilitate debugging of test failures. + + cipher_suite: 0x0001 + key: 000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + enc_key: 000102030405060708090a0b0c0d0e0f + auth_key: 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + nonce: 101112131415161718191a1b + aad: 4945544620534672616d65205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 6339af04ada1d064688a442b8dc69d5b + 6bfa40f4bef0583e8081069cc60705 + + cipher_suite: 0x0002 + key: 000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + enc_key: 000102030405060708090a0b0c0d0e0f + auth_key: 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + nonce: 101112131415161718191a1b + aad: 4945544620534672616d65205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 6339af04ada1d064688a442b8dc69d5b + 6bfa40f4be6e93b7da076927bb + + cipher_suite: 0x0003 + key: 000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + enc_key: 000102030405060708090a0b0c0d0e0f + auth_key: 101112131415161718191a1b1c1d1e1f + 202122232425262728292a2b2c2d2e2f + nonce: 101112131415161718191a1b + aad: 4945544620534672616d65205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 6339af04ada1d064688a442b8dc69d5b + 6bfa40f4be09480509 + +C.3. SFrame Encryption/Decryption + + For each case, we provide: + + * cipher_suite: The index of the cipher suite in use (see + Section 8.1) + + * kid: A KID value + + * ctr: A CTR value + + * base_key: The base_key input to the derive_key_salt algorithm + + * sframe_key_label: The label used to derive sframe_key in the + derive_key_salt algorithm + + * sframe_salt_label: The label used to derive sframe_salt in the + derive_key_salt algorithm + + * sframe_secret: The sframe_secret variable in the derive_key_salt + algorithm + + * sframe_key: The sframe_key value produced by the derive_key_salt + algorithm + + * sframe_salt: The sframe_salt value produced by the derive_key_salt + algorithm + + * metadata: The metadata input to the SFrame encrypt algorithm + + * pt: The plaintext + + * ct: The SFrame ciphertext + + An implementation should verify that the following are true, where + encrypt and decrypt are as defined in Section 4.4, using an SFrame + context initialized with base_key assigned to kid: + + * encrypt(ctr, kid, metadata, plaintext) == ct + + * decrypt(metadata, ct) == pt + + The other values in the test vector are intermediate values provided + to facilitate debugging of test failures. + + cipher_suite: 0x0001 + kid: 0x0000000000000123 + ctr: 0x0000000000004567 + base_key: 000102030405060708090a0b0c0d0e0f + sframe_key_label: 534672616d6520312e30205365637265 + 74206b65792000000000000001230001 + sframe_salt_label: 534672616d6520312e30205365637265 + 742073616c7420000000000000012300 + 01 + sframe_secret: d926952ca8b7ec4a95941d1ada3a5203 + ceff8cceee34f574d23909eb314c40c0 + sframe_key: 3f7d9a7c83ae8e1c8a11ae695ab59314 + b367e359fadac7b9c46b2bc6f81f46e1 + 6b96f0811868d59402b7e870102720b3 + sframe_salt: 50b29329a04dc0f184ac3168 + metadata: 4945544620534672616d65205747 + nonce: 50b29329a04dc0f184ac740f + aad: 99012345674945544620534672616d65 + 205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 9901234567449408b6f490086165b9d6 + f62b24ae1a59a56486b4ae8ed036b889 + 12e24f11 + + cipher_suite: 0x0002 + kid: 0x0000000000000123 + ctr: 0x0000000000004567 + base_key: 000102030405060708090a0b0c0d0e0f + sframe_key_label: 534672616d6520312e30205365637265 + 74206b65792000000000000001230002 + sframe_salt_label: 534672616d6520312e30205365637265 + 742073616c7420000000000000012300 + 02 + sframe_secret: d926952ca8b7ec4a95941d1ada3a5203 + ceff8cceee34f574d23909eb314c40c0 + sframe_key: e2ec5c797540310483b16bf6e7a570d2 + a27d192fe869c7ccd8584a8d9dab9154 + 9fbe553f5113461ec6aa83bf3865553e + sframe_salt: e68ac8dd3d02fbcd368c5577 + metadata: 4945544620534672616d65205747 + nonce: e68ac8dd3d02fbcd368c1010 + aad: 99012345674945544620534672616d65 + 205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 99012345673f31438db4d09434e43afa + 0f8a2f00867a2be085046a9f5cb4f101 + d607 + + cipher_suite: 0x0003 + kid: 0x0000000000000123 + ctr: 0x0000000000004567 + base_key: 000102030405060708090a0b0c0d0e0f + sframe_key_label: 534672616d6520312e30205365637265 + 74206b65792000000000000001230003 + sframe_salt_label: 534672616d6520312e30205365637265 + 742073616c7420000000000000012300 + 03 + sframe_secret: d926952ca8b7ec4a95941d1ada3a5203 + ceff8cceee34f574d23909eb314c40c0 + sframe_key: 2c5703089cbb8c583475e4fc461d97d1 + 8809df79b6d550f78eb6d50ffa80d892 + 11d57909934f46f5405e38cd583c69fe + sframe_salt: 38c16e4f5159700c00c7f350 + metadata: 4945544620534672616d65205747 + nonce: 38c16e4f5159700c00c7b637 + aad: 99012345674945544620534672616d65 + 205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 990123456717fc8af28a5a695afcfc6c + 8df6358a17e26b2fcb3bae32e443 + + cipher_suite: 0x0004 + kid: 0x0000000000000123 + ctr: 0x0000000000004567 + base_key: 000102030405060708090a0b0c0d0e0f + sframe_key_label: 534672616d6520312e30205365637265 + 74206b65792000000000000001230004 + sframe_salt_label: 534672616d6520312e30205365637265 + 742073616c7420000000000000012300 + 04 + sframe_secret: d926952ca8b7ec4a95941d1ada3a5203 + ceff8cceee34f574d23909eb314c40c0 + sframe_key: d34f547f4ca4f9a7447006fe7fcbf768 + sframe_salt: 75234edefe07819026751816 + metadata: 4945544620534672616d65205747 + nonce: 75234edefe07819026755d71 + aad: 99012345674945544620534672616d65 + 205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 9901234567b7412c2513a1b66dbb4884 + 1bbaf17f598751176ad847681a69c6d0 + b091c07018ce4adb34eb + + cipher_suite: 0x0005 + kid: 0x0000000000000123 + ctr: 0x0000000000004567 + base_key: 000102030405060708090a0b0c0d0e0f + sframe_key_label: 534672616d6520312e30205365637265 + 74206b65792000000000000001230005 + sframe_salt_label: 534672616d6520312e30205365637265 + 742073616c7420000000000000012300 + 05 + sframe_secret: 0fc3ea6de6aac97a35f194cf9bed94d4 + b5230f1cb45a785c9fe5dce9c188938a + b6ba005bc4c0a19181599e9d1bcf7b74 + aca48b60bf5e254e546d809313e083a3 + sframe_key: d3e27b0d4a5ae9e55df01a70e6d4d28d + 969b246e2936f4b7a5d9b494da6b9633 + sframe_salt: 84991c167b8cd23c93708ec7 + metadata: 4945544620534672616d65205747 + nonce: 84991c167b8cd23c9370cba0 + aad: 99012345674945544620534672616d65 + 205747 + pt: 64726166742d696574662d736672616d + 652d656e63 + ct: 990123456794f509d36e9beacb0e261d + 99c7d1e972f1fed787d4049f17ca2135 + 3c1cc24d56ceabced279 + +Acknowledgements + + The authors wish to specially thank Dr. Alex Gouaillard as one of the + early contributors to the document. His passion and energy were key + to the design and development of SFrame. + +Contributors + + Frédéric Jacobs + Apple + Email: frederic.jacobs@apple.com + + + Marta Mularczyk + Amazon + Email: mulmarta@amazon.com + + + Suhas Nandakumar + Cisco + Email: snandaku@cisco.com + + + Tomas Rigaux + Cisco + Email: trigaux@cisco.com + + + Raphael Robert + Phoenix R&D + Email: ietf@raphaelrobert.com + + +Authors' Addresses + + Emad Omara + Apple + Email: eomara@apple.com + + + Justin Uberti + Fixie.ai + Email: justin@fixie.ai + + + Sergio Garcia Murillo + CoSMo Software + Email: sergio.garcia.murillo@cosmosoftware.io + + + Richard Barnes (editor) + Cisco + Email: rlb@ipv.sx + + + Youenn Fablet + Apple + Email: youenn@apple.com -- cgit v1.2.3