diff --git a/artart-iana/draft-ietf-sframe-enc.html b/artart-iana/draft-ietf-sframe-enc.html deleted file mode 100644 index f133ff3..0000000 --- a/artart-iana/draft-ietf-sframe-enc.html +++ /dev/null @@ -1,6285 +0,0 @@ - - -
- - - -Internet-Draft | -SFrame | -February 2024 | -
Omara, et al. | -Expires 17 August 2024 | -[Page] | -
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.¶
-The proposed 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.¶
-This note is to be removed before publishing as an RFC.¶
-- The latest revision of this draft can be found at https://sframe-wg.github.io/sframe/draft-ietf-sframe-enc.html. - Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ietf-sframe-enc/.¶
-- Discussion of this document takes place on the - Secure Media Frames Working Group mailing list (mailto:sframe@ietf.org), - which is archived at https://mailarchive.ietf.org/arch/browse/sframe/. - Subscribe at https://www.ietf.org/mailman/listinfo/sframe/.¶
-Source for this draft and an issue tracker can be found at - https://github.com/sframe-wg/sframe.¶
-- This Internet-Draft is submitted in full conformance with the - provisions of BCP 78 and BCP 79.¶
-- Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF). Note that other groups may also distribute working - documents as Internet-Drafts. The list of current Internet-Drafts is - at https://datatracker.ietf.org/drafts/current/.¶
-- Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress."¶
-- This Internet-Draft will expire on 17 August 2024.¶
-- 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.¶
-Modern multi-party 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, -allowing for the media to be "end-to-end" encrypted 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:¶
-Hop-by-hop (HBH) encryption of media, metadata, and feedback messages -between the the endpoints and SFU¶
-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.¶
-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.¶
-Message Authentication Code¶
-End to End Encryption¶
-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 a sequence of media payloads, in both cases -regardless of whether those media payloads are transported over RTP or some -other protocol.¶
-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:¶
-Provide a secure E2EE mechanism for audio and video in conference calls -that can be used with arbitrary SFU servers.¶
-Decouple media encryption from key management to allow SFrame to be used -with an arbitrary key management system.¶
-Minimize packet expansion to allow successful conferencing in as many -network conditions as possible.¶
-Independence from the underlying transport, including use in non-RTP -transports, e.g., WebTransport [I-D.ietf-webtrans-overview].¶
-When used with RTP and its associated error resilience mechanisms, i.e., RTX -and FEC, require no special handling for RTX and FEC packets.¶
-Minimize the changes needed in SFU servers.¶
-Minimize the changes needed in endpoints.¶
-Work with the most popular audio and video codecs used in conferencing -scenarios.¶
-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, including details of how applications utilize SFrame for media protection, -as well as the actual mechanics of E2EE for protecting media.¶
-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][I-D.ietf-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: Either using SFrame to encrypt 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 C.¶
-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.¶
-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.¶
-An SFrame ciphertext comprises an SFrame header followed by the output of an -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.¶
-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.¶
-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 achieving this guarantee is -outlined in Section 9.1.¶
-The SFrame Header has the overall structure shown in Figure 2. The -first byte is a "config byte", with the following fields:¶
-Indicates if the K field contains the key id or the Key ID length.¶
-This field contains the Key ID (KID) if the X flag is set to 0, or the key id -length, minus one, if set to 1.¶
-Indicates if the C field contains the counter or the counter length.¶
-This field contains the counter (CTR) if the Y flag is set to 0, or the counter -length, minus one, if set to 1.¶
-The Key ID and Counter 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 configuration byte, with the Key ID first and Counter 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 3, depending on which of the X and Y flags are set.¶
-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 AES-CTR
-algorithm¶
Hash.Nh
- The size in bytes of the output of the hash function¶
Each SFrame encryption or decryption operation is premised on a single secret
-base_key
, which is labeled with an integer KID value signaled in the SFrame
-header.¶
The sender and receivers need to agree on which key should be used for a given -KID. Moreover, senders and receivers need to agree on whether keys will be used -for encryption or decryption only. The process for provisioning keys and their KID -values is beyond the scope of this specification, but its security properties will -bound the assurances that SFrame provides. For example, if SFrame is used to -provide E2E security against intermediary media nodes, then SFrame keys 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 counter value CTR to be used when encrypting (initially 0).¶
When encrypting a plaintext, the application specifies which KID is to be used,
-and the counter is incremented after successful encryption. When decrypting,
-the base_key
for decryption is selected from the available keys using the KID
-value in the SFrame Header.¶
A given key MUST NOT be used for encryption by multiple senders. Such reuse -would result in multiple encrypted frames being generated with the same (key, -nonce) pair, which harms the protections provided by many AEAD algorithms. -Implementations SHOULD mark each key as usable for encryption or decryption, -never both.¶
-Note that the set of available keys might change over the lifetime of a -real-time session. In such cases, the client will need to manage key usage to -avoid media loss due to a key being used to encrypt before all receivers are -able to use it to decrypt. For example, an application may make decryption-only -keys available immediately, but delay the use of keys for encryption until (a) -all receivers have acknowledged receipt of the new key or (b) a timeout expires.¶
-SFrame encrytion and decryption use a key and salt derived from the base_key
-associated to a KID. Given a base_key
value, the key and salt are derived
-using HKDF [RFC5869] as follows:¶
-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, info, AEAD.Nk) - - sframe_salt_label = "SFrame 1.0 Secret salt " + KID + cipher_suite - sframe_salt = HKDF-Expand(sframe_secret, info, 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.¶
-SFrame encryption uses the AEAD encryption algorithm for the cipher suite in use.
-The key for the encryption is the sframe_key
and the nonce is formed by XORing
-the sframe_salt
with the current counter, encoded 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] - - ctr = encode_big_endian(CTR, AEAD.Nn) - nonce = xor(sframe_salt, CTR) - - 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).¶
- -Before decrypting, a receiver needs to assemble a full SFrame ciphertext. When -an SFrame ciphertext may be 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 an 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, then 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.¶
- -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 | -
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 hundred-twenty-eight-bit tag, "_80" indicates -a eighty-bit tag, "_64" indicates a sixty-four-bit tag and "_32" indicates a -thirty-two-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 eighty-bit tags for video frames -and another cipher suite with thirty-two-bit tags for audio frames.¶
-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 Table 2).
-The encryption subkey comprises the first Nka
bytes and the authentication
-subkey comprises the remaining Nh
bytes.¶
-def derive_subkeys(sframe_key): - enc_key = sframe_key[..Nka] - 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) -¶ -
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.¶
-If the participants in a call have a pre-existing E2E-secure channel, they can
-use it to distribute SFrame keys. Each client participating in a call generates
-a fresh 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 SSRC). SFrame KID
-values are then used to distinguish between versions of the sender's base_key
.¶
Key IDs 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
-re-ordering window, since no more than 2R
ratchet steps can be
-active at a given time. The key generation is sent in the remaining 64 - R
-bits of the key ID.¶
-KID = (key_generation << R) + (ratchet_step % (1 << R)) -¶ -
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 up to the application 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 assures 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.¶
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 re-ordering window, since no more than 2E
-epochs can be active at a given time. Receivers MUST be prepared for the epoch
-counter to roll over, removing an old epoch when a new epoch with the same E
-lower bits is introduced.¶
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)) -¶ -
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.¶
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 to each frame and modify the RTP information of the incoming -packets when they are transmitted to the received participants.¶
-This section describes how this normal SFU modes of operation interact with the -E2EE provided by SFrame.¶
-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 in the same transport-level stream (e.g., an RTP stream defined -by either SSRC or MID) may carry media from different streams of different -participants. As different keys are used by each participant for encoding their -media, the receiver will be able to verify which is the sender of the media -coming within the RTP stream at any given point in time, preventing the SFU -trying to impersonate any of the participants with another participant's media.¶
-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.¶
-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 counter for each.¶
-In both temporal and spatial scalability, the SFU may choose to drop layers in -order to match a certain bitrate or 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.¶
-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 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 decodeable, so there is never a need to process two frames -together which might be on two sides of a key rotation.¶
-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, -this won't be possible because the decoder cannot access data until an entire -frame has arrived and has been decrypted.¶
-SFrame provides integrity protection to the SFrame Header (the key ID and -counter values), but 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 C.5), the hop-by-hop security -mechanisms provide confidentiality protection of the SFrame header between hops.¶
-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.¶
-Key exchange mechanism is out of scope of this document, however every client -SHOULD change their keys when new clients joins or leaves the call for forward -secrecy and post compromise security.¶
-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]).¶
-This document requests the creation of the following new IANA registries:¶
-SFrame Cipher Suites (Section 8.1)¶
-This registries should be under a heading of "SFrame", -and assignments are made via the Specification Required policy [RFC8126].¶
-RFC EDITOR: Please replace XXXX throughout with the RFC number assigned to -this document¶
-This 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.¶
-Template:¶
-Value: The numeric value of the cipher suite¶
-Name: The name of the cipher suite¶
-Reference: The document where this wire format is defined¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
0x0000 | -Reserved | -RFC XXXX | -
0x0001 | -
- AES_128_CTR_HMAC_SHA256_80
- |
- RFC XXXX | -
0x0002 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- RFC XXXX | -
0x0003 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- RFC XXXX | -
0x0004 | -
- AES_128_GCM_SHA256_128
- |
- RFC XXXX | -
0x0005 | -
- AES_256_GCM_SHA512_128
- |
- RFC XXXX | -
0xF000 - 0xFFFF | -Reserved for private use | -RFC XXXX | -
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 integration 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 up to the application -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 then not described in the media. -Applications might find it useful to extend the protocols used for negotiating -other media parameters (e.g., SDP [RFC4566]) to also negotiate parameters for -SFrame.¶
-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.¶
It is up to the application to provision 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.¶
It is also up to the application to define a rotation schedule for keys. For -example, one application might have an ephemeral group for every call and keep -rotating keys when end points 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.¶
-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.¶
-The metadata
input to SFrame operations is pure application-specified data. As
-such, it is up to the application 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.¶
-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.¶
-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 ciphersuite and -no KID mappings.¶
-Adding 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 counter value.¶
-Adding 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 9 shows an example of the types of structures and methods that could -be used to create an SFrame API in Rust.¶
-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:¶
-How many senders are involved in a conference (length of KID)¶
-How long the conference has been going on (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 secton, we compute overhead estimates for a collection -of common scenarios.¶
-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 on those seen in practice.¶
-Field | -Bytes | -Explanation | -
---|---|---|
Fixed header | -1 | -Fixed | -
Key ID (KID) | -2 | ->255 senders; or MLS epoch (E=4) and >16 senders | -
Counter (CTR) | -3 | -More than 24 hours of media in common cases | -
Cipher overhead | -16 | -Full GCM tag (longest defined here) | -
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.¶
-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.¶
-The below table considers three scenarios, based on recommended configurations -of the Opus codec [RFC6716]:¶
-Narrow-band speech: 120ms packets, 8Kbps¶
-Full-band speech: 20ms packets, 32Kbps¶
-Full-band stereo music: 10ms packets, 128Kbps¶
-Scenario | -fps | -Base Kbps | -Overhead Kbps | -Overhead % | -
---|---|---|---|---|
NB speech, 120ms packets | -8.3 | -8 | -1.4 | -17.9% | -
FB speech, 20ms packets | -50 | -32 | -8.6 | -26.9% | -
FB stereo, 10ms packets | -100 | -128 | -17.2 | -13.4% | -
Video frames can be larger than an MTU and thus are commonly split across -multiple frames. Table 5 and Table 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 are chosen to 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% | -
Scenario | -fps | -pps | -Base Kbps | -Overhead Kbps | -Overhead % | -
---|---|---|---|---|---|
426 x 240 | -7.5 | -7.5 | -45 | -1.3 | -2.9% | -
640 x 360 | -15 | -30 | -200 | -5.2 | -2.6% | -
640 x 360 | -30 | -60 | -400 | -10.3 | -2.6% | -
1280 x 720 | -30 | -180 | -1500 | -30.9 | -2.1% | -
1920 x 1080 | -60 | -780 | -7200 | -134.1 | -1.9% | -
In the per-frame case, the SFrame percentage overhead approaches zero as the -quality of the video goes up, 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%).¶
-Real conferences usually involve several audio and video streams. The overhead -of SFrame in such a conference is the aggregate of the overhead over 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 -sending high-quality. (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% | -
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 10. 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 11.¶
-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 [RFC4566], 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 / 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 [I-D.codec-agnostic-rtp-payload-format].¶
-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.¶
-For each case, we provide:¶
- -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 -¶ -
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:¶
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 -¶ -
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
:¶
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 -¶ -
SFrame | -plain text | -same as main | -
Internet-Draft | -SFrame | -February 2024 | -
Omara, et al. | -Expires 1 September 2024 | -[Page] | -
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.¶
-The proposed 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.¶
-This note is to be removed before publishing as an RFC.¶
-- The latest revision of this draft can be found at https://sframe-wg.github.io/sframe/draft-ietf-sframe-enc.html. - Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ietf-sframe-enc/.¶
-- Discussion of this document takes place on the - Secure Media Frames Working Group mailing list (mailto:sframe@ietf.org), - which is archived at https://mailarchive.ietf.org/arch/browse/sframe/. - Subscribe at https://www.ietf.org/mailman/listinfo/sframe/.¶
-Source for this draft and an issue tracker can be found at - https://github.com/sframe-wg/sframe.¶
-- This Internet-Draft is submitted in full conformance with the - provisions of BCP 78 and BCP 79.¶
-- Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF). Note that other groups may also distribute working - documents as Internet-Drafts. The list of current Internet-Drafts is - at https://datatracker.ietf.org/drafts/current/.¶
-- Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress."¶
-- This Internet-Draft will expire on 1 September 2024.¶
-- 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.¶
-Modern multi-party 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, -allowing for the media to be "end-to-end" encrypted 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:¶
-Hop-by-hop (HBH) encryption of media, metadata, and feedback messages -between the the endpoints and SFU¶
-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.¶
-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.¶
-Message Authentication Code¶
-End to End Encryption¶
-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 a sequence of media payloads, in both cases -regardless of whether those media payloads are transported over RTP or some -other protocol.¶
-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:¶
-Provide a secure E2EE mechanism for audio and video in conference calls -that can be used with arbitrary SFU servers.¶
-Decouple media encryption from key management to allow SFrame to be used -with an arbitrary key management system.¶
-Minimize packet expansion to allow successful conferencing in as many -network conditions as possible.¶
-Independence from the underlying transport, including use in non-RTP -transports, e.g., WebTransport [I-D.ietf-webtrans-overview].¶
-When used with RTP and its associated error resilience mechanisms, i.e., RTX -and FEC, require no special handling for RTX and FEC packets.¶
-Minimize the changes needed in SFU servers.¶
-Minimize the changes needed in endpoints.¶
-Work with the most popular audio and video codecs used in conferencing -scenarios.¶
-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, including details of how applications utilize SFrame for media protection, -as well as the actual mechanics of E2EE for protecting media.¶
-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][I-D.ietf-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: Either using SFrame to encrypt 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 C.¶
-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.¶
-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.¶
-An SFrame ciphertext comprises an SFrame header followed by the output of an -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.¶
-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.¶
-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 achieving this guarantee is -outlined in Section 9.1.¶
-The SFrame Header has the overall structure shown in Figure 2. The -first byte is a "config byte", with the following fields:¶
-Indicates if the K field contains the key id or the Key ID length.¶
-If the X flag is set to 0, this field contains the Key ID. If the X flag is -set to 1, then it contains the length of the Key ID, minus one.¶
-Indicates if the C field contains the counter or the counter length.¶
-This field contains the counter (CTR) if the Y flag is set to 0, or the counter -length, minus one, if set to 1.¶
-The Key ID and Counter 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 configuration byte, with the Key ID first and Counter 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 3, depending on which of the X and Y flags are set.¶
-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 AES-CTR
-algorithm¶
Hash.Nh
- The size in bytes of the output of the hash function¶
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 counter value CTR to be used when encrypting (initially 0).¶
When encrypting a plaintext, the application specifies which KID is to be used,
-and the counter is incremented after successful encryption. When decrypting,
-the base_key
for decryption is selected from the available keys using the KID
-value in the SFrame Header.¶
A given 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.¶
-SFrame encryption and decryption use a key and salt derived from the base_key
-associated to a KID. Given a base_key
value, the key and salt are derived
-using HKDF [RFC5869] as follows:¶
-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, info, AEAD.Nk) - - sframe_salt_label = "SFrame 1.0 Secret salt " + KID + cipher_suite - sframe_salt = HKDF-Expand(sframe_secret, info, 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.¶
-SFrame encryption uses the AEAD encryption algorithm for the cipher suite in use.
-The key for the encryption is the sframe_key
and the nonce is formed by XORing
-the sframe_salt
with the current counter, encoded 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).¶
- -Before decrypting, a receiver needs to assemble a full SFrame ciphertext. When -an SFrame ciphertext may be 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 an 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, then 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.¶
- -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 | -
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 hundred-twenty-eight-bit tag, "_80" indicates -a eighty-bit tag, "_64" indicates a sixty-four-bit tag and "_32" indicates a -thirty-two-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 eighty-bit tags for video frames -and another cipher suite with thirty-two-bit tags for audio frames.¶
-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 Table 2).
-The encryption subkey comprises the first Nka
bytes and the authentication
-subkey comprises the remaining Nh
bytes.¶
-def derive_subkeys(sframe_key): - enc_key = sframe_key[..Nka] - 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) -¶ -
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.¶
-If the participants in a call have a pre-existing E2E-secure channel, they can
-use it to distribute SFrame keys. Each client participating in a call generates
-a fresh 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 SSRC). SFrame KID
-values are then used to distinguish between versions of the sender's base_key
.¶
Key IDs 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
-re-ordering window, since no more than 2R
ratchet steps can be
-active at a given time. The key generation is sent in the remaining 64 - R
-bits of the key ID.¶
-KID = (key_generation << R) + (ratchet_step % (1 << R)) -¶ -
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 up to the application 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 assures 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.¶
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 re-ordering window, since no more than 2E
-epochs can be active at a given time. Receivers MUST be prepared for the epoch
-counter to roll over, removing an old epoch when a new epoch with the same E
-lower bits is introduced.¶
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)) -¶ -
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.¶
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 to each frame and modify the RTP information of the incoming -packets when they are transmitted to the received participants.¶
-This section describes how this normal SFU modes of operation interact with the -E2EE provided by SFrame.¶
-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 in the same transport-level stream (e.g., an RTP stream defined -by either SSRC or MID) may carry media from different streams of different -participants. As different keys are used by each participant for encoding their -media, the receiver will be able to verify which is the sender of the media -coming within the RTP stream at any given point in time, preventing the SFU -trying to impersonate any of the participants with another participant's media.¶
-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.¶
-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 counter for each.¶
-In both temporal and spatial scalability, the SFU may choose to drop layers in -order to match a certain bitrate or 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.¶
-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 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 decodeable, so there is never a need to process two frames -together which might be on two sides of a key rotation.¶
-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, -this won't be possible because the decoder cannot access data until an entire -frame has arrived and has been decrypted.¶
-SFrame provides integrity protection to the SFrame Header (the key ID and -counter values), but 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 C.5), the hop-by-hop security -mechanisms provide confidentiality protection of the SFrame header between hops.¶
-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.¶
-Key exchange mechanism is out of scope of this document, however every client -SHOULD change their keys when new clients joins or leaves the call for forward -secrecy and post compromise security.¶
-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]).¶
-This document requests the creation of the following new IANA registry:¶
-SFrame Cipher Suites (Section 8.1)¶
-This registry should be under a heading of "SFrame", and assignments are made -via the Specification Required policy [RFC8126].¶
-RFC EDITOR: Please replace XXXX throughout with the RFC number assigned to -this document¶
-This 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.¶
-Template:¶
-Value: The numeric value of the cipher suite¶
-Name: The name of the cipher suite¶
-Reference: The document where this cipher suite is defined¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
0x0000 | -Reserved | -RFC XXXX | -
0x0001 | -
- AES_128_CTR_HMAC_SHA256_80
- |
- RFC XXXX | -
0x0002 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- RFC XXXX | -
0x0003 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- RFC XXXX | -
0x0004 | -
- AES_128_GCM_SHA256_128
- |
- RFC XXXX | -
0x0005 | -
- AES_256_GCM_SHA512_128
- |
- RFC XXXX | -
0xF000 - 0xFFFF | -Reserved for private use | -RFC XXXX | -
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 integration 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 up to the application -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 then not described in the media. -Applications might find it useful to extend the protocols used for negotiating -other media parameters (e.g., SDP [RFC4566]) to also negotiate parameters for -SFrame.¶
-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.¶
It is up to the application to provision 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.¶
It is also up to the application to define a rotation schedule for keys. For -example, one application might have an ephemeral group for every call and keep -rotating keys when end points 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.¶
-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.¶
-The metadata
input to SFrame operations is pure application-specified data. As
-such, it is up to the application 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.¶
-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.¶
-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 ciphersuite and -no KID mappings.¶
-Adding 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 counter value.¶
-Adding 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 9 shows an example of the types of structures and methods that could -be used to create an SFrame API in Rust.¶
-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:¶
-How many senders are involved in a conference (length of KID)¶
-How long the conference has been going on (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 secton, we compute overhead estimates for a collection -of common scenarios.¶
-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 on those seen in practice.¶
-Field | -Bytes | -Explanation | -
---|---|---|
Fixed header | -1 | -Fixed | -
Key ID (KID) | -2 | ->255 senders; or MLS epoch (E=4) and >16 senders | -
Counter (CTR) | -3 | -More than 24 hours of media in common cases | -
Cipher overhead | -16 | -Full GCM tag (longest defined here) | -
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.¶
-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.¶
-The below table considers three scenarios, based on recommended configurations -of the Opus codec [RFC6716]:¶
-Narrow-band speech: 120ms packets, 8Kbps¶
-Full-band speech: 20ms packets, 32Kbps¶
-Full-band stereo music: 10ms packets, 128Kbps¶
-Scenario | -fps | -Base Kbps | -Overhead Kbps | -Overhead % | -
---|---|---|---|---|
NB speech, 120ms packets | -8.3 | -8 | -1.4 | -17.9% | -
FB speech, 20ms packets | -50 | -32 | -8.6 | -26.9% | -
FB stereo, 10ms packets | -100 | -128 | -17.2 | -13.4% | -
Video frames can be larger than an MTU and thus are commonly split across -multiple frames. Table 5 and Table 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 are chosen to 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% | -
Scenario | -fps | -pps | -Base Kbps | -Overhead Kbps | -Overhead % | -
---|---|---|---|---|---|
426 x 240 | -7.5 | -7.5 | -45 | -1.3 | -2.9% | -
640 x 360 | -15 | -30 | -200 | -5.2 | -2.6% | -
640 x 360 | -30 | -60 | -400 | -10.3 | -2.6% | -
1280 x 720 | -30 | -180 | -1500 | -30.9 | -2.1% | -
1920 x 1080 | -60 | -780 | -7200 | -134.1 | -1.9% | -
In the per-frame case, the SFrame percentage overhead approaches zero as the -quality of the video goes up, 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%).¶
-Real conferences usually involve several audio and video streams. The overhead -of SFrame in such a conference is the aggregate of the overhead over 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 -sending high-quality. (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% | -
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 10. 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 11.¶
-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 [RFC4566], 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 / 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 [I-D.codec-agnostic-rtp-payload-format].¶
-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.¶
-For each case, we provide:¶
- -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 -¶ -
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:¶
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 -¶ -
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
:¶
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 -¶ -
SFrame | -plain text | -same as main | -
SFrame | -plain text | -same as main | -
SFrame | -plain text | -diff with main | -
SFrame | -plain text | -same as main | -
SFrame | -plain text | -diff with main | +SFrame | +plain text | +diff with main |