diff --git a/cipher-in-kdf/draft-ietf-sframe-enc.html b/cipher-in-kdf/draft-ietf-sframe-enc.html deleted file mode 100644 index f8a2a4a..0000000 --- a/cipher-in-kdf/draft-ietf-sframe-enc.html +++ /dev/null @@ -1,5938 +0,0 @@ - - -
- - - -Internet-Draft | -SFrame | -September 2023 | -
Omara, et al. | -Expires 16 March 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 16 March 2024.¶
-- Copyright (c) 2023 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 encryptions and authentication are required:¶
-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 end-to-end encryption mechanism 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.¶
-Initialization Vector¶
-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:¶
-This document defines an encryption mechanism that provides effective end-to-end -encryption, is simple to implement, has no dependencies on RTP, and minimizes -encryption bandwidth overhead. Because SFrame can encrypt a full frame, rather -than individual packets, bandwidth overhead can be reduced by adding encryption -overhead only once per media frame, instead of once per packet.¶
-SFrame is a general encryption framing, intended to be used as an E2E encryption -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 -in 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 IVs.¶
-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.¶
-The SFrame header specifies two values from which encryption parameters are -derived:¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. A typical approach to achieving this gaurantee 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 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 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 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)¶
-Each SFrame encryption or decryption operation is premised on a single secret
-base_key
, which is labeled with an integer KID value signaled in the SFrame
-header.¶
The sender and receivers need to agree on which key should be used for a given -KID. The process for provisioning keys and their KID values is beyond the scope -of this specification, but its security properties will bound the assurances -that SFrame provides. For example, if SFrame is used to provide E2E security -against intermediary media nodes, then SFrame keys 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) - info = "SFrame 1.0 Secret key " + KID + cipher_suite - sframe_key = HKDF-Expand(sframe_secret, info, AEAD.Nk) - 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 client 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.¶
--def decrypt(metadata, sframe_ciphertext): - KID, CTR, 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.¶
-Each SFrame session uses a single cipher suite that specifies the following -primitives:¶
-This document defines the following cipher suites, with the constants defined in -Section 4.4:¶
-Name | -Nh | -Nk | -Nn | -Nt | -
---|---|---|---|---|
- AES_128_CTR_HMAC_SHA256_80
- |
- 32 | -48 | -12 | -10 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- 32 | -48 | -12 | -8 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- 32 | -48 | -12 | -4 | -
- AES_128_GCM_SHA256_128
- |
- 32 | -16 | -12 | -16 | -
- AES_256_GCM_SHA512_128
- |
- 64 | -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 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) - iv = nonce + 0x00000000 # append four zero bytes - ct = AES-CTR.Encrypt(enc_key, iv, 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") - - iv = nonce + 0x00000000 # append four zero bytes - return AES-CTR.Decrypt(enc_key, iv, 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:¶
-base_key
mappings to participating clients¶
-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 mid-call, 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.¶
-The Messaging Layer Security (MLS) protocol provides group authenticated key -exchange [I-D.ietf-mls-architecture] [I-D.ietf-mls-protocol]. In -principle, it could be used to instantiate the sender key scheme above, but it -can also be used more efficiently directly.¶
-MLS creates a linear sequence of keys, each of which is shared among the members -of a group at a given point in time. When a member joins or leaves the group, a -new key is produced that is known only to the augmented or reduced group. Each -step in the lifetime of the group is know as an "epoch", and each member of the -group is assigned an "index" that is constant for the time they are in the -group.¶
-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 about -how to do this stream selection but in general, in order to do so, 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 interacts 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 it, the sender MUST encode each spatial layer of a -given picture in a different frame. That is, an RTP frame may contain more than -one SFrame encrypted frame with an incrementing frame counter.¶
-Forward and Post-Compromise Security requires that the e2ee keys are updated -anytime a participant joins/leave 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 encrypted 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.¶
-Receiver will re-request an key frame then, 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 when the new e2ee key is in use, the time -required for the new participant to display the video is minimized.¶
-Some codes support partial decoding, where it can decrypt individual packets -without waiting for the full frame to arrive, with SFrame this won't be possible -because the decoder will not access the packets until the entire frame has -arrived and was decrypted.¶
-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 cipher suites defined in this draft use short authentication tags for -encryption, however it can easily support other ciphers with full authentication -tag if the short ones are proved insecure.¶
-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:¶
-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:¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
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 | -
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.¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. 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. Note that 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 applications KID assignment strategy MUST be structured to
-assure the non-reuse properties discussed above.¶
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 SHOULD NOT use SFrame-authenticated
-metadata until after the SFrame decrypt function has authenticated it.¶
Note: The metadata
input is a feature at risk, and needs more confirmation that it
-is useful and/or needed.¶
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:¶
-Figure 8 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:¶
-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]:¶
-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 9. 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 10.¶
-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:¶
--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: ff01000000000000000100000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0xffffffffffffffff -header: ff0100000000000000ffffffffffffffff -¶ -
-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: ffffffffffffffffff0100000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0xffffffffffffffff -header: ffffffffffffffffffffffffffffffffff -¶ -
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: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -enc_key: 000102030405060708090a0b0c0d0e0f -auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4bef0583e8081069cc60705 -¶ -
-cipher_suite: 0x0002 -key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -enc_key: 000102030405060708090a0b0c0d0e0f -auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4be6e93b7da076927bb -¶ -
-cipher_suite: 0x0003 -key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -enc_key: 000102030405060708090a0b0c0d0e0f -auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4be09480509 -¶ -
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: 534672616d6520312e3020536563726574206b65792000000000000001230001 -sframe_salt_label: 534672616d6520312e30205365637265742073616c742000000000000001230001 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 3f7d9a7c83ae8e1c8a11ae695ab59314b367e359fadac7b9c46b2bc6f81f46e16b96f0811868d59402b7e870102720b3 -sframe_salt: 50b29329a04dc0f184ac3168 -metadata: 4945544620534672616d65205747 -nonce: 50b29329a04dc0f184ac740f -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 9901234567449408b6f490086165b9d6f62b24ae1a59a56486b4ae8ed036b88912e24f11 -¶ -
-cipher_suite: 0x0002 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b65792000000000000001230002 -sframe_salt_label: 534672616d6520312e30205365637265742073616c742000000000000001230002 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: e2ec5c797540310483b16bf6e7a570d2a27d192fe869c7ccd8584a8d9dab91549fbe553f5113461ec6aa83bf3865553e -sframe_salt: e68ac8dd3d02fbcd368c5577 -metadata: 4945544620534672616d65205747 -nonce: e68ac8dd3d02fbcd368c1010 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 99012345673f31438db4d09434e43afa0f8a2f00867a2be085046a9f5cb4f101d607 -¶ -
-cipher_suite: 0x0003 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b65792000000000000001230003 -sframe_salt_label: 534672616d6520312e30205365637265742073616c742000000000000001230003 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 2c5703089cbb8c583475e4fc461d97d18809df79b6d550f78eb6d50ffa80d89211d57909934f46f5405e38cd583c69fe -sframe_salt: 38c16e4f5159700c00c7f350 -metadata: 4945544620534672616d65205747 -nonce: 38c16e4f5159700c00c7b637 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 990123456717fc8af28a5a695afcfc6c8df6358a17e26b2fcb3bae32e443 -¶ -
-cipher_suite: 0x0004 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b65792000000000000001230004 -sframe_salt_label: 534672616d6520312e30205365637265742073616c742000000000000001230004 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: d34f547f4ca4f9a7447006fe7fcbf768 -sframe_salt: 75234edefe07819026751816 -metadata: 4945544620534672616d65205747 -nonce: 75234edefe07819026755d71 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 9901234567b7412c2513a1b66dbb48841bbaf17f598751176ad847681a69c6d0b091c07018ce4adb34eb -¶ -
-cipher_suite: 0x0005 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b65792000000000000001230005 -sframe_salt_label: 534672616d6520312e30205365637265742073616c742000000000000001230005 -sframe_secret: 0fc3ea6de6aac97a35f194cf9bed94d4b5230f1cb45a785c9fe5dce9c188938ab6ba005bc4c0a19181599e9d1bcf7b74aca48b60bf5e254e546d809313e083a3 -sframe_key: d3e27b0d4a5ae9e55df01a70e6d4d28d969b246e2936f4b7a5d9b494da6b9633 -sframe_salt: 84991c167b8cd23c93708ec7 -metadata: 4945544620534672616d65205747 -nonce: 84991c167b8cd23c9370cba0 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 990123456794f509d36e9beacb0e261d99c7d1e972f1fed787d4049f17ca21353c1cc24d56ceabced279 -¶ -
SFrame | -plain text | -same as main | -
Internet-Draft | -SFrame | -September 2023 | -
Omara, et al. | -Expires 4 March 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 4 March 2024.¶
-- Copyright (c) 2023 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 encryptions and authentication are required:¶
-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 end-to-end encryption mechanism 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.¶
-Initialization Vector¶
-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:¶
-This document defines an encryption mechanism that provides effective end-to-end -encryption, is simple to implement, has no dependencies on RTP, and minimizes -encryption bandwidth overhead. Because SFrame can encrypt a full frame, rather -than individual packets, bandwidth overhead can be reduced by adding encryption -overhead only once per media frame, instead of once per packet.¶
-SFrame is a general encryption framing, intended to be used as an E2E encryption -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 -in 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 IVs.¶
-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.¶
-The SFrame header specifies two values from which encryption parameters are -derived:¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. A typical approach to achieving this gaurantee is -outlined in Section 9.1.¶
-Both the counter and the key id are encoded as integers in network (big-endian) -byte order, in a variable length format to decrease the overhead. The length of -each field is up to 8 bytes and is represented in 3 bits in the SFrame header: -000 represents a length of 1, 001 a length of 2, etc.¶
-The first byte in the SFrame header has a fixed format and contains the header -metadata:¶
- -This field MUST be set to zero on sending, and MUST be ignored by receivers.¶
-This field indicates the length of the CTR field in bytes, minus one (the -range of possible values is thus 1-8).¶
-Indicates if the key field contains the key id or the key length.¶
-This field contains the key id (KID) if the X flag is set to 0, or the key -length (KLEN) if set to 1.¶
-If X flag is 0, then the KID is in the range of 0-7 and the counter (CTR) is -found in the next LEN bytes:¶
- -If X flag is 1 then KLEN is the length of the key (KID) in bytes, minus one -(the range of possible lengths is thus 1-8). The KID is encoded in -the KLEN bytes following the metadata byte, and the counter (CTR) is encoded -in the next LEN bytes:¶
-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 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)¶
-Each SFrame encryption or decryption operation is premised on a single secret
-base_key
, which is labeled with an integer KID value signaled in the SFrame
-header.¶
The sender and receivers need to agree on which key should be used for a given -KID. The process for provisioning keys and their KID values is beyond the scope -of this specification, but its security properties will bound the assurances -that SFrame provides. For example, if SFrame is used to provide E2E security -against intermediary media nodes, then SFrame keys 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 = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret key " + KID, AEAD.Nk) - sframe_salt = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret salt " + KID, AEAD.Nn) - return sframe_key, sframe_salt -¶ -
In the derivation of sframe_secret
, the +
operator represents concatenation
-of byte strings and the KID value is encoded as an 8-byte big-endian integer
-(not the compressed form used in the SFrame header).¶
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 client 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.¶
--def decrypt(metadata, sframe_ciphertext): - KID, CTR, 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.¶
-Each SFrame session uses a single cipher suite that specifies the following -primitives:¶
-This document defines the following cipher suites, with the constants defined in -Section 4.4:¶
-Name | -Nh | -Nk | -Nn | -Nt | -
---|---|---|---|---|
- AES_128_CTR_HMAC_SHA256_80
- |
- 32 | -16 | -12 | -10 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- 32 | -16 | -12 | -8 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- 32 | -16 | -12 | -4 | -
- AES_128_GCM_SHA256_128
- |
- 32 | -16 | -12 | -16 | -
- AES_256_GCM_SHA512_128
- |
- 64 | -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 using HKDF. The subkeys are derived as
-follows, where Nk
represents the key size for the AES block cipher in use,
-Nh
represents the output size of the hash function, and Nt
represents the
-size of a tag for the cipher in bytes (as in Table 2):¶
-def derive_subkeys(sframe_key): - tag_len = encode_big_endian(Nt, 8) - aead_label = "SFrame 1.0 AES CTR AEAD " + tag_len - aead_secret = HKDF-Extract(aead_label, sframe_key) - enc_key = HKDF-Expand(aead_secret, "enc", Nk) - auth_key = HKDF-Expand(aead_secret, "auth", Nh) - 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 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) - iv = nonce + 0x00000000 # append four zero bytes - ct = AES-CTR.Encrypt(enc_key, iv, 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") - - iv = nonce + 0x00000000 # append four zero bytes - return AES-CTR.Decrypt(enc_key, iv, 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:¶
-base_key
mappings to participating clients¶
-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 encryption key. 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 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:¶
--sender_base_key[i+1] = HKDF-Expand( - HKDF-Extract("", sender_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 mid-call, 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.¶
-The Messaging Layer Security (MLS) protocol provides group authenticated key -exchange [I-D.ietf-mls-architecture] [I-D.ietf-mls-protocol]. In -principle, it could be used to instantiate the sender key scheme above, but it -can also be used more efficiently directly.¶
-MLS creates a linear sequence of keys, each of which is shared among the members -of a group at a given point in time. When a member joins or leaves the group, a -new key is produced that is known only to the augmented or reduced group. Each -step in the lifetime of the group is know as an "epoch", and each member of the -group is assigned an "index" that is constant for the time they are in the -group.¶
-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 KIDs and sender_base_key
values on demand,
-as it needs to encrypt/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 about -how to do this stream selection but in general, in order to do so, 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 interacts 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 it, the sender MUST encode each spatial layer of a -given picture in a different frame. That is, an RTP frame may contain more than -one SFrame encrypted frame with an incrementing frame counter.¶
-Forward and Post-Compromise Security requires that the e2ee keys are updated -anytime a participant joins/leave 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 encrypted 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.¶
-Receiver will re-request an key frame then, 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 when the new e2ee key is in use, the time -required for the new participant to display the video is minimized.¶
-Some codes support partial decoding, where it can decrypt individual packets -without waiting for the full frame to arrive, with SFrame this won't be possible -because the decoder will not access the packets until the entire frame has -arrived and was decrypted.¶
-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 cipher suites defined in this draft use short authentication tags for -encryption, however it can easily support other ciphers with full authentication -tag if the short ones are proved insecure.¶
-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:¶
-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:¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
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 | -
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.¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. 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. Note that 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 applications KID assignment strategy MUST be structured to
-assure the non-reuse properties discussed above.¶
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 SHOULD NOT use SFrame-authenticated
-metadata until after the SFrame decrypt function has authenticated it.¶
Note: The metadata
input is a feature at risk, and needs more confirmation that it
-is useful and/or needed.¶
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:¶
-Figure 8 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:¶
-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 | -Explanataion | -
---|---|---|
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]:¶
-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 9. 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 10.¶
-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:¶
--kid: 0x0000000000000000 -ctr: 0x0000000000000000 -header: 0000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000000001 -header: 0001 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00000000000000ff -header: 00ff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000000100 -header: 100100 -¶ -
-kid: 0x0000000000000000 -ctr: 0x000000000000ffff -header: 10ffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000010000 -header: 20010000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000ffffff -header: 20ffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000001000000 -header: 3001000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00000000ffffffff -header: 30ffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000100000000 -header: 400100000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x000000ffffffffff -header: 40ffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000010000000000 -header: 50010000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000ffffffffffff -header: 50ffffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0001000000000000 -header: 6001000000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00ffffffffffffff -header: 60ffffffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0100000000000000 -header: 700100000000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0xffffffffffffffff -header: 70ffffffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000000 -header: 0100 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000001 -header: 0101 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00000000000000ff -header: 01ff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000100 -header: 110100 -¶ -
-kid: 0x0000000000000001 -ctr: 0x000000000000ffff -header: 11ffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000010000 -header: 21010000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000ffffff -header: 21ffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000001000000 -header: 3101000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00000000ffffffff -header: 31ffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000100000000 -header: 410100000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x000000ffffffffff -header: 41ffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000010000000000 -header: 51010000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000ffffffffffff -header: 51ffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0001000000000000 -header: 6101000000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00ffffffffffffff -header: 61ffffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0100000000000000 -header: 710100000000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0xffffffffffffffff -header: 71ffffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000000 -header: 08ff00 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000001 -header: 08ff01 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00000000000000ff -header: 08ffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000100 -header: 18ff0100 -¶ -
-kid: 0x00000000000000ff -ctr: 0x000000000000ffff -header: 18ffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000010000 -header: 28ff010000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000ffffff -header: 28ffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000001000000 -header: 38ff01000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00000000ffffffff -header: 38ffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000100000000 -header: 48ff0100000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x000000ffffffffff -header: 48ffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000010000000000 -header: 58ff010000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000ffffffffffff -header: 58ffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0001000000000000 -header: 68ff01000000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00ffffffffffffff -header: 68ffffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0100000000000000 -header: 78ff0100000000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0xffffffffffffffff -header: 78ffffffffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000000 -header: 09010000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000001 -header: 09010001 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00000000000000ff -header: 090100ff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000100 -header: 1901000100 -¶ -
-kid: 0x0000000000000100 -ctr: 0x000000000000ffff -header: 190100ffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000010000 -header: 290100010000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000ffffff -header: 290100ffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000001000000 -header: 39010001000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00000000ffffffff -header: 390100ffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000100000000 -header: 4901000100000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x000000ffffffffff -header: 490100ffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000010000000000 -header: 590100010000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000ffffffffffff -header: 590100ffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0001000000000000 -header: 69010001000000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00ffffffffffffff -header: 690100ffffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0100000000000000 -header: 7901000100000000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0xffffffffffffffff -header: 790100ffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000000 -header: 09ffff00 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000001 -header: 09ffff01 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00000000000000ff -header: 09ffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000100 -header: 19ffff0100 -¶ -
-kid: 0x000000000000ffff -ctr: 0x000000000000ffff -header: 19ffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000010000 -header: 29ffff010000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000ffffff -header: 29ffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000001000000 -header: 39ffff01000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00000000ffffffff -header: 39ffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000100000000 -header: 49ffff0100000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x000000ffffffffff -header: 49ffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000010000000000 -header: 59ffff010000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000ffffffffffff -header: 59ffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0001000000000000 -header: 69ffff01000000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00ffffffffffffff -header: 69ffffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0100000000000000 -header: 79ffff0100000000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0xffffffffffffffff -header: 79ffffffffffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000000 -header: 0a01000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000001 -header: 0a01000001 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00000000000000ff -header: 0a010000ff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000100 -header: 1a0100000100 -¶ -
-kid: 0x0000000000010000 -ctr: 0x000000000000ffff -header: 1a010000ffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000010000 -header: 2a010000010000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000ffffff -header: 2a010000ffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000001000000 -header: 3a01000001000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00000000ffffffff -header: 3a010000ffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000100000000 -header: 4a0100000100000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x000000ffffffffff -header: 4a010000ffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000010000000000 -header: 5a010000010000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000ffffffffffff -header: 5a010000ffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0001000000000000 -header: 6a01000001000000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00ffffffffffffff -header: 6a010000ffffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0100000000000000 -header: 7a0100000100000000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0xffffffffffffffff -header: 7a010000ffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000000 -header: 0affffff00 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000001 -header: 0affffff01 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00000000000000ff -header: 0affffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000100 -header: 1affffff0100 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x000000000000ffff -header: 1affffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000010000 -header: 2affffff010000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000ffffff -header: 2affffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000001000000 -header: 3affffff01000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00000000ffffffff -header: 3affffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000100000000 -header: 4affffff0100000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x000000ffffffffff -header: 4affffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000010000000000 -header: 5affffff010000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000ffffffffffff -header: 5affffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0001000000000000 -header: 6affffff01000000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00ffffffffffffff -header: 6affffffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0100000000000000 -header: 7affffff0100000000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0xffffffffffffffff -header: 7affffffffffffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000000 -header: 0b0100000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000001 -header: 0b0100000001 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00000000000000ff -header: 0b01000000ff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000100 -header: 1b010000000100 -¶ -
-kid: 0x0000000001000000 -ctr: 0x000000000000ffff -header: 1b01000000ffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000010000 -header: 2b01000000010000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000ffffff -header: 2b01000000ffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000001000000 -header: 3b0100000001000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00000000ffffffff -header: 3b01000000ffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000100000000 -header: 4b010000000100000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x000000ffffffffff -header: 4b01000000ffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000010000000000 -header: 5b01000000010000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000ffffffffffff -header: 5b01000000ffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0001000000000000 -header: 6b0100000001000000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00ffffffffffffff -header: 6b01000000ffffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0100000000000000 -header: 7b010000000100000000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0xffffffffffffffff -header: 7b01000000ffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000000 -header: 0bffffffff00 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000001 -header: 0bffffffff01 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00000000000000ff -header: 0bffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000100 -header: 1bffffffff0100 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x000000000000ffff -header: 1bffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000010000 -header: 2bffffffff010000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000ffffff -header: 2bffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000001000000 -header: 3bffffffff01000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00000000ffffffff -header: 3bffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000100000000 -header: 4bffffffff0100000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x000000ffffffffff -header: 4bffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000010000000000 -header: 5bffffffff010000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000ffffffffffff -header: 5bffffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0001000000000000 -header: 6bffffffff01000000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00ffffffffffffff -header: 6bffffffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0100000000000000 -header: 7bffffffff0100000000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0xffffffffffffffff -header: 7bffffffffffffffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000000 -header: 0c010000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000001 -header: 0c010000000001 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00000000000000ff -header: 0c0100000000ff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000100 -header: 1c01000000000100 -¶ -
-kid: 0x0000000100000000 -ctr: 0x000000000000ffff -header: 1c0100000000ffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000010000 -header: 2c0100000000010000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000ffffff -header: 2c0100000000ffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000001000000 -header: 3c010000000001000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00000000ffffffff -header: 3c0100000000ffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000100000000 -header: 4c01000000000100000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x000000ffffffffff -header: 4c0100000000ffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000010000000000 -header: 5c0100000000010000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000ffffffffffff -header: 5c0100000000ffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0001000000000000 -header: 6c010000000001000000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00ffffffffffffff -header: 6c0100000000ffffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0100000000000000 -header: 7c01000000000100000000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0xffffffffffffffff -header: 7c0100000000ffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000000 -header: 0cffffffffff00 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000001 -header: 0cffffffffff01 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00000000000000ff -header: 0cffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000100 -header: 1cffffffffff0100 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x000000000000ffff -header: 1cffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000010000 -header: 2cffffffffff010000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000ffffff -header: 2cffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000001000000 -header: 3cffffffffff01000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00000000ffffffff -header: 3cffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000100000000 -header: 4cffffffffff0100000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x000000ffffffffff -header: 4cffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000010000000000 -header: 5cffffffffff010000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000ffffffffffff -header: 5cffffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0001000000000000 -header: 6cffffffffff01000000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00ffffffffffffff -header: 6cffffffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0100000000000000 -header: 7cffffffffff0100000000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0xffffffffffffffff -header: 7cffffffffffffffffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000000 -header: 0d01000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000001 -header: 0d01000000000001 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00000000000000ff -header: 0d010000000000ff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000100 -header: 1d0100000000000100 -¶ -
-kid: 0x0000010000000000 -ctr: 0x000000000000ffff -header: 1d010000000000ffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000010000 -header: 2d010000000000010000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000ffffff -header: 2d010000000000ffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000001000000 -header: 3d01000000000001000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00000000ffffffff -header: 3d010000000000ffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000100000000 -header: 4d0100000000000100000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x000000ffffffffff -header: 4d010000000000ffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000010000000000 -header: 5d010000000000010000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000ffffffffffff -header: 5d010000000000ffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0001000000000000 -header: 6d01000000000001000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00ffffffffffffff -header: 6d010000000000ffffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0100000000000000 -header: 7d0100000000000100000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0xffffffffffffffff -header: 7d010000000000ffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000000 -header: 0dffffffffffff00 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000001 -header: 0dffffffffffff01 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00000000000000ff -header: 0dffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000100 -header: 1dffffffffffff0100 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x000000000000ffff -header: 1dffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000010000 -header: 2dffffffffffff010000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000ffffff -header: 2dffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000001000000 -header: 3dffffffffffff01000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00000000ffffffff -header: 3dffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000100000000 -header: 4dffffffffffff0100000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x000000ffffffffff -header: 4dffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000010000000000 -header: 5dffffffffffff010000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000ffffffffffff -header: 5dffffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0001000000000000 -header: 6dffffffffffff01000000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00ffffffffffffff -header: 6dffffffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0100000000000000 -header: 7dffffffffffff0100000000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0xffffffffffffffff -header: 7dffffffffffffffffffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000000 -header: 0e0100000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000001 -header: 0e0100000000000001 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00000000000000ff -header: 0e01000000000000ff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000100 -header: 1e010000000000000100 -¶ -
-kid: 0x0001000000000000 -ctr: 0x000000000000ffff -header: 1e01000000000000ffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000010000 -header: 2e01000000000000010000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000ffffff -header: 2e01000000000000ffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000001000000 -header: 3e0100000000000001000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00000000ffffffff -header: 3e01000000000000ffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000100000000 -header: 4e010000000000000100000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x000000ffffffffff -header: 4e01000000000000ffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000010000000000 -header: 5e01000000000000010000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000ffffffffffff -header: 5e01000000000000ffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0001000000000000 -header: 6e0100000000000001000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00ffffffffffffff -header: 6e01000000000000ffffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0100000000000000 -header: 7e010000000000000100000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0xffffffffffffffff -header: 7e01000000000000ffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000000 -header: 0effffffffffffff00 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000001 -header: 0effffffffffffff01 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00000000000000ff -header: 0effffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000100 -header: 1effffffffffffff0100 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x000000000000ffff -header: 1effffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000010000 -header: 2effffffffffffff010000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000ffffff -header: 2effffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000001000000 -header: 3effffffffffffff01000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00000000ffffffff -header: 3effffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000100000000 -header: 4effffffffffffff0100000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x000000ffffffffff -header: 4effffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000010000000000 -header: 5effffffffffffff010000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000ffffffffffff -header: 5effffffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0001000000000000 -header: 6effffffffffffff01000000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00ffffffffffffff -header: 6effffffffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0100000000000000 -header: 7effffffffffffff0100000000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0xffffffffffffffff -header: 7effffffffffffffffffffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000000 -header: 0f010000000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000001 -header: 0f010000000000000001 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00000000000000ff -header: 0f0100000000000000ff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000100 -header: 1f01000000000000000100 -¶ -
-kid: 0x0100000000000000 -ctr: 0x000000000000ffff -header: 1f0100000000000000ffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000010000 -header: 2f0100000000000000010000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000ffffff -header: 2f0100000000000000ffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000001000000 -header: 3f010000000000000001000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00000000ffffffff -header: 3f0100000000000000ffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000100000000 -header: 4f01000000000000000100000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x000000ffffffffff -header: 4f0100000000000000ffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000010000000000 -header: 5f0100000000000000010000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000ffffffffffff -header: 5f0100000000000000ffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0001000000000000 -header: 6f010000000000000001000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00ffffffffffffff -header: 6f0100000000000000ffffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0100000000000000 -header: 7f01000000000000000100000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0xffffffffffffffff -header: 7f0100000000000000ffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000000 -header: 0fffffffffffffffff00 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000001 -header: 0fffffffffffffffff01 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00000000000000ff -header: 0fffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000100 -header: 1fffffffffffffffff0100 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x000000000000ffff -header: 1fffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000010000 -header: 2fffffffffffffffff010000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000ffffff -header: 2fffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000001000000 -header: 3fffffffffffffffff01000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00000000ffffffff -header: 3fffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000100000000 -header: 4fffffffffffffffff0100000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x000000ffffffffff -header: 4fffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000010000000000 -header: 5fffffffffffffffff010000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000ffffffffffff -header: 5fffffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0001000000000000 -header: 6fffffffffffffffff01000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00ffffffffffffff -header: 6fffffffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0100000000000000 -header: 7fffffffffffffffff0100000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0xffffffffffffffff -header: 7fffffffffffffffffffffffffffffffff -¶ -
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¶
-aead_label
: The aead_label
variable in the derive_subkeys()
algorithm¶
-aead_secret
: The aead_secret
variable in the derive_subkeys()
algorithm¶
-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 -aead_label: 534672616d6520312e302041455320435452204145414420000000000000000a -aead_secret: fda0fef7af62639ae1c6440f430395f54623f9a49db659201312ed6d9999a580 -enc_key: d6a61ca11fe8397b24954cda8b9543cf -auth_key: 0a43277c91120b7c7b6584bede06fcdfe0d07f9d1c9f15fcf0cad50aaecdd585 -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1075c7114e10c12f20a709450ef8a891e9f070d4fae7b01f558599c929fdfd -¶ -
-cipher_suite: 0x0002 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000008 -aead_secret: a0d71a69b2033a5a246eefbed19d95aee712a7639a752e5ad3a2b44c9f331caa -enc_key: 0ef75d1dd74b81e4d2252e6daa7226da -auth_key: 5584d32db18ede79fe8071a334ff31eb2ca0249a7845a61965d2ec620a50c59e -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: f8551395579efc8dfdda575ed1a048f8b6cbf0e85653f0a514dea191e4 -¶ -
-cipher_suite: 0x0003 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000004 -aead_secret: ff69640f46d50930ce38bcf5aa5f6417a5bff98a991c79da06a0be460211dd36 -enc_key: 96a673a94981bd85e71fcf05c79f2a01 -auth_key: bbf3b39da1eb8ed31fc5e0b26896a070f1a43e5ad3009b4c9d6c32e77ac68fce -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: d6455bdbe7b5e8cdda861a8e90835637c0f7990349ce9052e6 -¶ -
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: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 190123456740043f25262c0ca52e9374b070f24b02764715c2e303388c9495324037d043 -¶ -
-cipher_suite: 0x0002 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1901234567729eef4910d734abfd392cdff0f67d2a8d06041eef5f895e4cecc03a6d -¶ -
-cipher_suite: 0x0003 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 190123456717fd0a325fdcd5f0d68089ee5bd17df6296b69b6b0e70c8d73 -¶ -
-cipher_suite: 0x0004 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1901234567b8bf87709717f709a35b4e91b2109e5c1ca4f76179415f8bb15d70a9be7eb89c7adb76d300 -¶ -
-cipher_suite: 0x0005 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: 0fc3ea6de6aac97a35f194cf9bed94d4b5230f1cb45a785c9fe5dce9c188938ab6ba005bc4c0a19181599e9d1bcf7b74aca48b60bf5e254e546d809313e083a3 -sframe_key: e9e405efb7cd325030760935bf49fd5669d7c19eb84ca74b419a1487cf835107 -sframe_salt: 11007b537a1cf728a4c544c1 -metadata: 4945544620534672616d65205747 -nonce: 11007b537a1cf728a4c501a6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 19012345671e11c62748536fd55fdbc9560daea4825bfecbb05489cd41cb7a1556e001989a4485e8a02f -¶ -
SFrame | -plain text | -same as main | -
SFrame | -plain text | -same as main | -
Internet-Draft | -SFrame | -September 2023 | -
Omara, et al. | -Expires 4 March 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 4 March 2024.¶
-- Copyright (c) 2023 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 encryptions and authentication are required:¶
-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 end-to-end encryption mechanism 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.¶
-Initialization Vector¶
-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:¶
-This document defines an encryption mechanism that provides effective end-to-end -encryption, is simple to implement, has no dependencies on RTP, and minimizes -encryption bandwidth overhead. Because SFrame can encrypt a full frame, rather -than individual packets, bandwidth overhead can be reduced by adding encryption -overhead only once per media frame, instead of once per packet.¶
-SFrame is a general encryption framing, intended to be used as an E2E encryption -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 -in 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 IVs.¶
-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.¶
-The SFrame header specifies two values from which encryption parameters are -derived:¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. A typical approach to achieving this gaurantee is -outlined in Section 9.1.¶
-Both the counter and the key id are encoded as integers in network (big-endian) -byte order, in a variable length format to decrease the overhead. The length of -each field is up to 8 bytes and is represented in 3 bits in the SFrame header: -000 represents a length of 1, 001 a length of 2, etc.¶
-The first byte in the SFrame header has a fixed format and contains the header -metadata:¶
- -This field MUST be set to zero on sending, and MUST be ignored by receivers.¶
-This field indicates the length of the CTR field in bytes, minus one (the -range of possible values is thus 1-8).¶
-Indicates if the key field contains the key id or the key length.¶
-This field contains the key id (KID) if the X flag is set to 0, or the key -length (KLEN) if set to 1.¶
-If X flag is 0, then the KID is in the range of 0-7 and the counter (CTR) is -found in the next LEN bytes:¶
- -If X flag is 1 then KLEN is the length of the key (KID) in bytes, minus one -(the range of possible lengths is thus 1-8). The KID is encoded in -the KLEN bytes following the metadata byte, and the counter (CTR) is encoded -in the next LEN bytes:¶
-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 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)¶
-Each SFrame encryption or decryption operation is premised on a single secret
-base_key
, which is labeled with an integer KID value signaled in the SFrame
-header.¶
The sender and receivers need to agree on which key should be used for a given -KID. The process for provisioning keys and their KID values is beyond the scope -of this specification, but its security properties will bound the assurances -that SFrame provides. For example, if SFrame is used to provide E2E security -against intermediary media nodes, then SFrame keys 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 = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret key " + KID, AEAD.Nk) - sframe_salt = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret salt " + KID, AEAD.Nn) - return sframe_key, sframe_salt -¶ -
In the derivation of sframe_secret
, the +
operator represents concatenation
-of byte strings and the KID value is encoded as an 8-byte big-endian integer
-(not the compressed form used in the SFrame header).¶
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 client 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.¶
--def decrypt(metadata, sframe_ciphertext): - KID, CTR, 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.¶
-Each SFrame session uses a single cipher suite that specifies the following -primitives:¶
-This document defines the following cipher suites, with the constants defined in -Section 4.4:¶
-Name | -Nh | -Nk | -Nn | -Nt | -
---|---|---|---|---|
- AES_128_CTR_HMAC_SHA256_80
- |
- 32 | -16 | -12 | -10 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- 32 | -16 | -12 | -8 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- 32 | -16 | -12 | -4 | -
- AES_128_GCM_SHA256_128
- |
- 32 | -16 | -12 | -16 | -
- AES_256_GCM_SHA512_128
- |
- 64 | -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 using HKDF. The subkeys are derived as
-follows, where Nk
represents the key size for the AES block cipher in use,
-Nh
represents the output size of the hash function, and Nt
represents the
-size of a tag for the cipher in bytes (as in Table 2):¶
-def derive_subkeys(sframe_key): - tag_len = encode_big_endian(Nt, 8) - aead_label = "SFrame 1.0 AES CTR AEAD " + tag_len - aead_secret = HKDF-Extract(aead_label, sframe_key) - enc_key = HKDF-Expand(aead_secret, "enc", Nk) - auth_key = HKDF-Expand(aead_secret, "auth", Nh) - 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 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) - ct = AES-CTR.Encrypt(enc_key, nonce, 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") - - return AES-CTR.Decrypt(enc_key, nonce, 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:¶
-base_key
mappings to participating clients¶
-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 encryption key. 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 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:¶
--sender_base_key[i+1] = HKDF-Expand( - HKDF-Extract("", sender_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 mid-call, 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.¶
-The Messaging Layer Security (MLS) protocol provides group authenticated key -exchange [I-D.ietf-mls-architecture] [I-D.ietf-mls-protocol]. In -principle, it could be used to instantiate the sender key scheme above, but it -can also be used more efficiently directly.¶
-MLS creates a linear sequence of keys, each of which is shared among the members -of a group at a given point in time. When a member joins or leaves the group, a -new key is produced that is known only to the augmented or reduced group. Each -step in the lifetime of the group is know as an "epoch", and each member of the -group is assigned an "index" that is constant for the time they are in the -group.¶
-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 KIDs and sender_base_key
values on demand,
-as it needs to encrypt/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 about -how to do this stream selection but in general, in order to do so, 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 interacts 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 it, the sender MUST encode each spatial layer of a -given picture in a different frame. That is, an RTP frame may contain more than -one SFrame encrypted frame with an incrementing frame counter.¶
-Forward and Post-Compromise Security requires that the e2ee keys are updated -anytime a participant joins/leave 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 encrypted 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.¶
-Receiver will re-request an key frame then, 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 when the new e2ee key is in use, the time -required for the new participant to display the video is minimized.¶
-Some codes support partial decoding, where it can decrypt individual packets -without waiting for the full frame to arrive, with SFrame this won't be possible -because the decoder will not access the packets until the entire frame has -arrived and was decrypted.¶
-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 cipher suites defined in this draft use short authentication tags for -encryption, however it can easily support other ciphers with full authentication -tag if the short ones are proved insecure.¶
-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:¶
-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:¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
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 | -
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.¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. 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. Note that 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 applications KID assignment strategy MUST be structured to
-assure the non-reuse properties discussed above.¶
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 SHOULD NOT use SFrame-authenticated
-metadata until after the SFrame decrypt function has authenticated it.¶
Note: The metadata
input is a feature at risk, and needs more confirmation that it
-is useful and/or needed.¶
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:¶
-Figure 8 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:¶
-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 | -Explanataion | -
---|---|---|
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]:¶
-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 9. 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 10.¶
-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:¶
--kid: 0x0000000000000000 -ctr: 0x0000000000000000 -header: 0000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000000001 -header: 0001 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00000000000000ff -header: 00ff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000000100 -header: 100100 -¶ -
-kid: 0x0000000000000000 -ctr: 0x000000000000ffff -header: 10ffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000010000 -header: 20010000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000000ffffff -header: 20ffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000001000000 -header: 3001000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00000000ffffffff -header: 30ffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000000100000000 -header: 400100000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x000000ffffffffff -header: 40ffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000010000000000 -header: 50010000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x0000ffffffffffff -header: 50ffffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0001000000000000 -header: 6001000000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0x00ffffffffffffff -header: 60ffffffffffffff -¶ -
-kid: 0x0000000000000000 -ctr: 0x0100000000000000 -header: 700100000000000000 -¶ -
-kid: 0x0000000000000000 -ctr: 0xffffffffffffffff -header: 70ffffffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000000 -header: 0100 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000001 -header: 0101 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00000000000000ff -header: 01ff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000000100 -header: 110100 -¶ -
-kid: 0x0000000000000001 -ctr: 0x000000000000ffff -header: 11ffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000010000 -header: 21010000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000000ffffff -header: 21ffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000001000000 -header: 3101000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00000000ffffffff -header: 31ffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000000100000000 -header: 410100000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x000000ffffffffff -header: 41ffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000010000000000 -header: 51010000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x0000ffffffffffff -header: 51ffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0001000000000000 -header: 6101000000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0x00ffffffffffffff -header: 61ffffffffffffff -¶ -
-kid: 0x0000000000000001 -ctr: 0x0100000000000000 -header: 710100000000000000 -¶ -
-kid: 0x0000000000000001 -ctr: 0xffffffffffffffff -header: 71ffffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000000 -header: 08ff00 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000001 -header: 08ff01 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00000000000000ff -header: 08ffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000000100 -header: 18ff0100 -¶ -
-kid: 0x00000000000000ff -ctr: 0x000000000000ffff -header: 18ffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000010000 -header: 28ff010000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000000ffffff -header: 28ffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000001000000 -header: 38ff01000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00000000ffffffff -header: 38ffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000000100000000 -header: 48ff0100000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x000000ffffffffff -header: 48ffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000010000000000 -header: 58ff010000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x0000ffffffffffff -header: 58ffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0001000000000000 -header: 68ff01000000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0x00ffffffffffffff -header: 68ffffffffffffffff -¶ -
-kid: 0x00000000000000ff -ctr: 0x0100000000000000 -header: 78ff0100000000000000 -¶ -
-kid: 0x00000000000000ff -ctr: 0xffffffffffffffff -header: 78ffffffffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000000 -header: 09010000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000001 -header: 09010001 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00000000000000ff -header: 090100ff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000000100 -header: 1901000100 -¶ -
-kid: 0x0000000000000100 -ctr: 0x000000000000ffff -header: 190100ffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000010000 -header: 290100010000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000000ffffff -header: 290100ffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000001000000 -header: 39010001000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00000000ffffffff -header: 390100ffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000000100000000 -header: 4901000100000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x000000ffffffffff -header: 490100ffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000010000000000 -header: 590100010000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x0000ffffffffffff -header: 590100ffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0001000000000000 -header: 69010001000000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0x00ffffffffffffff -header: 690100ffffffffffffff -¶ -
-kid: 0x0000000000000100 -ctr: 0x0100000000000000 -header: 7901000100000000000000 -¶ -
-kid: 0x0000000000000100 -ctr: 0xffffffffffffffff -header: 790100ffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000000 -header: 09ffff00 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000001 -header: 09ffff01 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00000000000000ff -header: 09ffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000000100 -header: 19ffff0100 -¶ -
-kid: 0x000000000000ffff -ctr: 0x000000000000ffff -header: 19ffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000010000 -header: 29ffff010000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000000ffffff -header: 29ffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000001000000 -header: 39ffff01000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00000000ffffffff -header: 39ffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000000100000000 -header: 49ffff0100000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x000000ffffffffff -header: 49ffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000010000000000 -header: 59ffff010000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x0000ffffffffffff -header: 59ffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0001000000000000 -header: 69ffff01000000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0x00ffffffffffffff -header: 69ffffffffffffffffff -¶ -
-kid: 0x000000000000ffff -ctr: 0x0100000000000000 -header: 79ffff0100000000000000 -¶ -
-kid: 0x000000000000ffff -ctr: 0xffffffffffffffff -header: 79ffffffffffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000000 -header: 0a01000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000001 -header: 0a01000001 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00000000000000ff -header: 0a010000ff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000000100 -header: 1a0100000100 -¶ -
-kid: 0x0000000000010000 -ctr: 0x000000000000ffff -header: 1a010000ffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000010000 -header: 2a010000010000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000000ffffff -header: 2a010000ffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000001000000 -header: 3a01000001000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00000000ffffffff -header: 3a010000ffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000000100000000 -header: 4a0100000100000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x000000ffffffffff -header: 4a010000ffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000010000000000 -header: 5a010000010000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x0000ffffffffffff -header: 5a010000ffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0001000000000000 -header: 6a01000001000000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0x00ffffffffffffff -header: 6a010000ffffffffffffff -¶ -
-kid: 0x0000000000010000 -ctr: 0x0100000000000000 -header: 7a0100000100000000000000 -¶ -
-kid: 0x0000000000010000 -ctr: 0xffffffffffffffff -header: 7a010000ffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000000 -header: 0affffff00 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000001 -header: 0affffff01 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00000000000000ff -header: 0affffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000000100 -header: 1affffff0100 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x000000000000ffff -header: 1affffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000010000 -header: 2affffff010000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000000ffffff -header: 2affffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000001000000 -header: 3affffff01000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00000000ffffffff -header: 3affffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000000100000000 -header: 4affffff0100000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x000000ffffffffff -header: 4affffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000010000000000 -header: 5affffff010000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0000ffffffffffff -header: 5affffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0001000000000000 -header: 6affffff01000000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0x00ffffffffffffff -header: 6affffffffffffffffffff -¶ -
-kid: 0x0000000000ffffff -ctr: 0x0100000000000000 -header: 7affffff0100000000000000 -¶ -
-kid: 0x0000000000ffffff -ctr: 0xffffffffffffffff -header: 7affffffffffffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000000 -header: 0b0100000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000001 -header: 0b0100000001 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00000000000000ff -header: 0b01000000ff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000000100 -header: 1b010000000100 -¶ -
-kid: 0x0000000001000000 -ctr: 0x000000000000ffff -header: 1b01000000ffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000010000 -header: 2b01000000010000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000000ffffff -header: 2b01000000ffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000001000000 -header: 3b0100000001000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00000000ffffffff -header: 3b01000000ffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000000100000000 -header: 4b010000000100000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x000000ffffffffff -header: 4b01000000ffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000010000000000 -header: 5b01000000010000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x0000ffffffffffff -header: 5b01000000ffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0001000000000000 -header: 6b0100000001000000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0x00ffffffffffffff -header: 6b01000000ffffffffffffff -¶ -
-kid: 0x0000000001000000 -ctr: 0x0100000000000000 -header: 7b010000000100000000000000 -¶ -
-kid: 0x0000000001000000 -ctr: 0xffffffffffffffff -header: 7b01000000ffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000000 -header: 0bffffffff00 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000001 -header: 0bffffffff01 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00000000000000ff -header: 0bffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000000100 -header: 1bffffffff0100 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x000000000000ffff -header: 1bffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000010000 -header: 2bffffffff010000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000000ffffff -header: 2bffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000001000000 -header: 3bffffffff01000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00000000ffffffff -header: 3bffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000000100000000 -header: 4bffffffff0100000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x000000ffffffffff -header: 4bffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000010000000000 -header: 5bffffffff010000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0000ffffffffffff -header: 5bffffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0001000000000000 -header: 6bffffffff01000000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0x00ffffffffffffff -header: 6bffffffffffffffffffffff -¶ -
-kid: 0x00000000ffffffff -ctr: 0x0100000000000000 -header: 7bffffffff0100000000000000 -¶ -
-kid: 0x00000000ffffffff -ctr: 0xffffffffffffffff -header: 7bffffffffffffffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000000 -header: 0c010000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000001 -header: 0c010000000001 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00000000000000ff -header: 0c0100000000ff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000000100 -header: 1c01000000000100 -¶ -
-kid: 0x0000000100000000 -ctr: 0x000000000000ffff -header: 1c0100000000ffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000010000 -header: 2c0100000000010000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000000ffffff -header: 2c0100000000ffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000001000000 -header: 3c010000000001000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00000000ffffffff -header: 3c0100000000ffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000000100000000 -header: 4c01000000000100000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x000000ffffffffff -header: 4c0100000000ffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000010000000000 -header: 5c0100000000010000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x0000ffffffffffff -header: 5c0100000000ffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0001000000000000 -header: 6c010000000001000000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0x00ffffffffffffff -header: 6c0100000000ffffffffffffff -¶ -
-kid: 0x0000000100000000 -ctr: 0x0100000000000000 -header: 7c01000000000100000000000000 -¶ -
-kid: 0x0000000100000000 -ctr: 0xffffffffffffffff -header: 7c0100000000ffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000000 -header: 0cffffffffff00 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000001 -header: 0cffffffffff01 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00000000000000ff -header: 0cffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000000100 -header: 1cffffffffff0100 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x000000000000ffff -header: 1cffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000010000 -header: 2cffffffffff010000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000000ffffff -header: 2cffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000001000000 -header: 3cffffffffff01000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00000000ffffffff -header: 3cffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000000100000000 -header: 4cffffffffff0100000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x000000ffffffffff -header: 4cffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000010000000000 -header: 5cffffffffff010000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0000ffffffffffff -header: 5cffffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0001000000000000 -header: 6cffffffffff01000000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0x00ffffffffffffff -header: 6cffffffffffffffffffffffff -¶ -
-kid: 0x000000ffffffffff -ctr: 0x0100000000000000 -header: 7cffffffffff0100000000000000 -¶ -
-kid: 0x000000ffffffffff -ctr: 0xffffffffffffffff -header: 7cffffffffffffffffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000000 -header: 0d01000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000001 -header: 0d01000000000001 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00000000000000ff -header: 0d010000000000ff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000000100 -header: 1d0100000000000100 -¶ -
-kid: 0x0000010000000000 -ctr: 0x000000000000ffff -header: 1d010000000000ffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000010000 -header: 2d010000000000010000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000000ffffff -header: 2d010000000000ffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000001000000 -header: 3d01000000000001000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00000000ffffffff -header: 3d010000000000ffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000000100000000 -header: 4d0100000000000100000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x000000ffffffffff -header: 4d010000000000ffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000010000000000 -header: 5d010000000000010000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x0000ffffffffffff -header: 5d010000000000ffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0001000000000000 -header: 6d01000000000001000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0x00ffffffffffffff -header: 6d010000000000ffffffffffffff -¶ -
-kid: 0x0000010000000000 -ctr: 0x0100000000000000 -header: 7d0100000000000100000000000000 -¶ -
-kid: 0x0000010000000000 -ctr: 0xffffffffffffffff -header: 7d010000000000ffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000000 -header: 0dffffffffffff00 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000001 -header: 0dffffffffffff01 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00000000000000ff -header: 0dffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000000100 -header: 1dffffffffffff0100 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x000000000000ffff -header: 1dffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000010000 -header: 2dffffffffffff010000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000000ffffff -header: 2dffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000001000000 -header: 3dffffffffffff01000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00000000ffffffff -header: 3dffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000000100000000 -header: 4dffffffffffff0100000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x000000ffffffffff -header: 4dffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000010000000000 -header: 5dffffffffffff010000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0000ffffffffffff -header: 5dffffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0001000000000000 -header: 6dffffffffffff01000000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x00ffffffffffffff -header: 6dffffffffffffffffffffffffff -¶ -
-kid: 0x0000ffffffffffff -ctr: 0x0100000000000000 -header: 7dffffffffffff0100000000000000 -¶ -
-kid: 0x0000ffffffffffff -ctr: 0xffffffffffffffff -header: 7dffffffffffffffffffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000000 -header: 0e0100000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000001 -header: 0e0100000000000001 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00000000000000ff -header: 0e01000000000000ff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000000100 -header: 1e010000000000000100 -¶ -
-kid: 0x0001000000000000 -ctr: 0x000000000000ffff -header: 1e01000000000000ffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000010000 -header: 2e01000000000000010000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000000ffffff -header: 2e01000000000000ffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000001000000 -header: 3e0100000000000001000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00000000ffffffff -header: 3e01000000000000ffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000000100000000 -header: 4e010000000000000100000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x000000ffffffffff -header: 4e01000000000000ffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000010000000000 -header: 5e01000000000000010000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x0000ffffffffffff -header: 5e01000000000000ffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0001000000000000 -header: 6e0100000000000001000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0x00ffffffffffffff -header: 6e01000000000000ffffffffffffff -¶ -
-kid: 0x0001000000000000 -ctr: 0x0100000000000000 -header: 7e010000000000000100000000000000 -¶ -
-kid: 0x0001000000000000 -ctr: 0xffffffffffffffff -header: 7e01000000000000ffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000000 -header: 0effffffffffffff00 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000001 -header: 0effffffffffffff01 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00000000000000ff -header: 0effffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000000100 -header: 1effffffffffffff0100 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x000000000000ffff -header: 1effffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000010000 -header: 2effffffffffffff010000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000000ffffff -header: 2effffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000001000000 -header: 3effffffffffffff01000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00000000ffffffff -header: 3effffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000000100000000 -header: 4effffffffffffff0100000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x000000ffffffffff -header: 4effffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000010000000000 -header: 5effffffffffffff010000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0000ffffffffffff -header: 5effffffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0001000000000000 -header: 6effffffffffffff01000000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x00ffffffffffffff -header: 6effffffffffffffffffffffffffff -¶ -
-kid: 0x00ffffffffffffff -ctr: 0x0100000000000000 -header: 7effffffffffffff0100000000000000 -¶ -
-kid: 0x00ffffffffffffff -ctr: 0xffffffffffffffff -header: 7effffffffffffffffffffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000000 -header: 0f010000000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000001 -header: 0f010000000000000001 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00000000000000ff -header: 0f0100000000000000ff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000000100 -header: 1f01000000000000000100 -¶ -
-kid: 0x0100000000000000 -ctr: 0x000000000000ffff -header: 1f0100000000000000ffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000010000 -header: 2f0100000000000000010000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000000ffffff -header: 2f0100000000000000ffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000001000000 -header: 3f010000000000000001000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00000000ffffffff -header: 3f0100000000000000ffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000000100000000 -header: 4f01000000000000000100000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x000000ffffffffff -header: 4f0100000000000000ffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000010000000000 -header: 5f0100000000000000010000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x0000ffffffffffff -header: 5f0100000000000000ffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0001000000000000 -header: 6f010000000000000001000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0x00ffffffffffffff -header: 6f0100000000000000ffffffffffffff -¶ -
-kid: 0x0100000000000000 -ctr: 0x0100000000000000 -header: 7f01000000000000000100000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0xffffffffffffffff -header: 7f0100000000000000ffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000000 -header: 0fffffffffffffffff00 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000001 -header: 0fffffffffffffffff01 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00000000000000ff -header: 0fffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000000100 -header: 1fffffffffffffffff0100 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x000000000000ffff -header: 1fffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000010000 -header: 2fffffffffffffffff010000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000000ffffff -header: 2fffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000001000000 -header: 3fffffffffffffffff01000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00000000ffffffff -header: 3fffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000000100000000 -header: 4fffffffffffffffff0100000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x000000ffffffffff -header: 4fffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000010000000000 -header: 5fffffffffffffffff010000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0000ffffffffffff -header: 5fffffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0001000000000000 -header: 6fffffffffffffffff01000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0x00ffffffffffffff -header: 6fffffffffffffffffffffffffffffff -¶ -
-kid: 0xffffffffffffffff -ctr: 0x0100000000000000 -header: 7fffffffffffffffff0100000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0xffffffffffffffff -header: 7fffffffffffffffffffffffffffffffff -¶ -
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¶
-aead_label
: The aead_label
variable in the derive_subkeys()
algorithm¶
-aead_secret
: The aead_secret
variable in the derive_subkeys()
algorithm¶
-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 -aead_label: 534672616d6520312e302041455320435452204145414420000000000000000a -aead_secret: fda0fef7af62639ae1c6440f430395f54623f9a49db659201312ed6d9999a580 -enc_key: d6a61ca11fe8397b24954cda8b9543cf -auth_key: 0a43277c91120b7c7b6584bede06fcdfe0d07f9d1c9f15fcf0cad50aaecdd585 -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1075c7114e10c12f20a709450ef8a891e9f070d4fae7b01f558599c929fdfd -¶ -
-cipher_suite: 0x0002 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000008 -aead_secret: a0d71a69b2033a5a246eefbed19d95aee712a7639a752e5ad3a2b44c9f331caa -enc_key: 0ef75d1dd74b81e4d2252e6daa7226da -auth_key: 5584d32db18ede79fe8071a334ff31eb2ca0249a7845a61965d2ec620a50c59e -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: f8551395579efc8dfdda575ed1a048f8b6cbf0e85653f0a514dea191e4 -¶ -
-cipher_suite: 0x0003 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000004 -aead_secret: ff69640f46d50930ce38bcf5aa5f6417a5bff98a991c79da06a0be460211dd36 -enc_key: 96a673a94981bd85e71fcf05c79f2a01 -auth_key: bbf3b39da1eb8ed31fc5e0b26896a070f1a43e5ad3009b4c9d6c32e77ac68fce -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: d6455bdbe7b5e8cdda861a8e90835637c0f7990349ce9052e6 -¶ -
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: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 190123456740043f25262c0ca52e9374b070f24b02764715c2e303388c9495324037d043 -¶ -
-cipher_suite: 0x0002 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1901234567729eef4910d734abfd392cdff0f67d2a8d06041eef5f895e4cecc03a6d -¶ -
-cipher_suite: 0x0003 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 190123456717fd0a325fdcd5f0d68089ee5bd17df6296b69b6b0e70c8d73 -¶ -
-cipher_suite: 0x0004 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1901234567b8bf87709717f709a35b4e91b2109e5c1ca4f76179415f8bb15d70a9be7eb89c7adb76d300 -¶ -
-cipher_suite: 0x0005 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: 0fc3ea6de6aac97a35f194cf9bed94d4b5230f1cb45a785c9fe5dce9c188938ab6ba005bc4c0a19181599e9d1bcf7b74aca48b60bf5e254e546d809313e083a3 -sframe_key: e9e405efb7cd325030760935bf49fd5669d7c19eb84ca74b419a1487cf835107 -sframe_salt: 11007b537a1cf728a4c544c1 -metadata: 4945544620534672616d65205747 -nonce: 11007b537a1cf728a4c501a6 -aad: 19012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 19012345671e11c62748536fd55fdbc9560daea4825bfecbb05489cd41cb7a1556e001989a4485e8a02f -¶ -
SFrame | -plain text | -same as main | -
Internet-Draft | -SFrame | -September 2023 | -
Omara, et al. | -Expires 16 March 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 16 March 2024.¶
-- Copyright (c) 2023 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 encryptions and authentication are required:¶
-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 end-to-end encryption mechanism 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.¶
-Initialization Vector¶
-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:¶
-This document defines an encryption mechanism that provides effective end-to-end -encryption, is simple to implement, has no dependencies on RTP, and minimizes -encryption bandwidth overhead. Because SFrame can encrypt a full frame, rather -than individual packets, bandwidth overhead can be reduced by adding encryption -overhead only once per media frame, instead of once per packet.¶
-SFrame is a general encryption framing, intended to be used as an E2E encryption -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 -in 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 IVs.¶
-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.¶
-The SFrame header specifies two values from which encryption parameters are -derived:¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. A typical approach to achieving this gaurantee 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 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 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 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)¶
-Each SFrame encryption or decryption operation is premised on a single secret
-base_key
, which is labeled with an integer KID value signaled in the SFrame
-header.¶
The sender and receivers need to agree on which key should be used for a given -KID. The process for provisioning keys and their KID values is beyond the scope -of this specification, but its security properties will bound the assurances -that SFrame provides. For example, if SFrame is used to provide E2E security -against intermediary media nodes, then SFrame keys 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 = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret key " + KID, AEAD.Nk) - sframe_salt = HKDF-Expand(sframe_secret, "SFrame 1.0 Secret salt " + KID, AEAD.Nn) - return sframe_key, sframe_salt -¶ -
In the derivation of sframe_secret
, the +
operator represents concatenation
-of byte strings and the KID value is encoded as an 8-byte big-endian integer
-(not the compressed form used in the SFrame header).¶
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 client 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.¶
--def decrypt(metadata, sframe_ciphertext): - KID, CTR, 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.¶
-Each SFrame session uses a single cipher suite that specifies the following -primitives:¶
-This document defines the following cipher suites, with the constants defined in -Section 4.4:¶
-Name | -Nh | -Nk | -Nn | -Nt | -
---|---|---|---|---|
- AES_128_CTR_HMAC_SHA256_80
- |
- 32 | -16 | -12 | -10 | -
- AES_128_CTR_HMAC_SHA256_64
- |
- 32 | -16 | -12 | -8 | -
- AES_128_CTR_HMAC_SHA256_32
- |
- 32 | -16 | -12 | -4 | -
- AES_128_GCM_SHA256_128
- |
- 32 | -16 | -12 | -16 | -
- AES_256_GCM_SHA512_128
- |
- 64 | -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 using HKDF. The subkeys are derived as
-follows, where Nk
represents the key size for the AES block cipher in use,
-Nh
represents the output size of the hash function, and Nt
represents the
-size of a tag for the cipher in bytes (as in Table 2):¶
-def derive_subkeys(sframe_key): - tag_len = encode_big_endian(Nt, 8) - aead_label = "SFrame 1.0 AES CTR AEAD " + tag_len - aead_secret = HKDF-Extract(aead_label, sframe_key) - enc_key = HKDF-Expand(aead_secret, "enc", Nk) - auth_key = HKDF-Expand(aead_secret, "auth", Nh) - 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 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) - iv = nonce + 0x00000000 # append four zero bytes - ct = AES-CTR.Encrypt(enc_key, iv, 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") - - iv = nonce + 0x00000000 # append four zero bytes - return AES-CTR.Decrypt(enc_key, iv, 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:¶
-base_key
mappings to participating clients¶
-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 mid-call, 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.¶
-The Messaging Layer Security (MLS) protocol provides group authenticated key -exchange [I-D.ietf-mls-architecture] [I-D.ietf-mls-protocol]. In -principle, it could be used to instantiate the sender key scheme above, but it -can also be used more efficiently directly.¶
-MLS creates a linear sequence of keys, each of which is shared among the members -of a group at a given point in time. When a member joins or leaves the group, a -new key is produced that is known only to the augmented or reduced group. Each -step in the lifetime of the group is know as an "epoch", and each member of the -group is assigned an "index" that is constant for the time they are in the -group.¶
-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 about -how to do this stream selection but in general, in order to do so, 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 interacts 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 it, the sender MUST encode each spatial layer of a -given picture in a different frame. That is, an RTP frame may contain more than -one SFrame encrypted frame with an incrementing frame counter.¶
-Forward and Post-Compromise Security requires that the e2ee keys are updated -anytime a participant joins/leave 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 encrypted 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.¶
-Receiver will re-request an key frame then, 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 when the new e2ee key is in use, the time -required for the new participant to display the video is minimized.¶
-Some codes support partial decoding, where it can decrypt individual packets -without waiting for the full frame to arrive, with SFrame this won't be possible -because the decoder will not access the packets until the entire frame has -arrived and was decrypted.¶
-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 cipher suites defined in this draft use short authentication tags for -encryption, however it can easily support other ciphers with full authentication -tag if the short ones are proved insecure.¶
-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:¶
-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:¶
-Initial contents:¶
-Value | -Name | -Reference | -
---|---|---|
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.¶
-Applications MUST ensure that each (KID, CTR) combination is used for exactly -one encryption operation. 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. Note that 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 applications KID assignment strategy MUST be structured to
-assure the non-reuse properties discussed above.¶
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 SHOULD NOT use SFrame-authenticated
-metadata until after the SFrame decrypt function has authenticated it.¶
Note: The metadata
input is a feature at risk, and needs more confirmation that it
-is useful and/or needed.¶
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:¶
-Figure 8 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:¶
-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]:¶
-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 9. 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 10.¶
-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:¶
--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: ff01000000000000000100000000000000 -¶ -
-kid: 0x0100000000000000 -ctr: 0xffffffffffffffff -header: ff0100000000000000ffffffffffffffff -¶ -
-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: ffffffffffffffffff0100000000000000 -¶ -
-kid: 0xffffffffffffffff -ctr: 0xffffffffffffffff -header: ffffffffffffffffffffffffffffffffff -¶ -
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¶
-aead_label
: The aead_label
variable in the derive_subkeys()
algorithm¶
-aead_secret
: The aead_secret
variable in the derive_subkeys()
algorithm¶
-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 -aead_label: 534672616d6520312e302041455320435452204145414420000000000000000a -aead_secret: fda0fef7af62639ae1c6440f430395f54623f9a49db659201312ed6d9999a580 -enc_key: d6a61ca11fe8397b24954cda8b9543cf -auth_key: 0a43277c91120b7c7b6584bede06fcdfe0d07f9d1c9f15fcf0cad50aaecdd585 -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 1075c7114e10c12f20a709450ef8a891e9f070d4fae7b01f558599c929fdfd -¶ -
-cipher_suite: 0x0002 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000008 -aead_secret: a0d71a69b2033a5a246eefbed19d95aee712a7639a752e5ad3a2b44c9f331caa -enc_key: 0ef75d1dd74b81e4d2252e6daa7226da -auth_key: 5584d32db18ede79fe8071a334ff31eb2ca0249a7845a61965d2ec620a50c59e -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: f8551395579efc8dfdda575ed1a048f8b6cbf0e85653f0a514dea191e4 -¶ -
-cipher_suite: 0x0003 -key: 000102030405060708090a0b0c0d0e0f -aead_label: 534672616d6520312e3020414553204354522041454144200000000000000004 -aead_secret: ff69640f46d50930ce38bcf5aa5f6417a5bff98a991c79da06a0be460211dd36 -enc_key: 96a673a94981bd85e71fcf05c79f2a01 -auth_key: bbf3b39da1eb8ed31fc5e0b26896a070f1a43e5ad3009b4c9d6c32e77ac68fce -nonce: 101112131415161718191a1b -aad: 4945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: d6455bdbe7b5e8cdda861a8e90835637c0f7990349ce9052e6 -¶ -
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: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 990123456740043f25262c0ca52e9374b070f24b02764715c2e3a11aa151434fb21c5cd5 -¶ -
-cipher_suite: 0x0002 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 9901234567729eef4910d734abfd392cdff0f67d2a8d06041eeff314c4eed66e6ac9 -¶ -
-cipher_suite: 0x0003 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 990123456717fd0a325fdcd5f0d68089ee5bd17df6296b69b6b093bb7543 -¶ -
-cipher_suite: 0x0004 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: d926952ca8b7ec4a95941d1ada3a5203ceff8cceee34f574d23909eb314c40c0 -sframe_key: 73bb177a9fe6c02597132fe430ca2d99 -sframe_salt: 55582aa5aaced36a74544d91 -metadata: 4945544620534672616d65205747 -nonce: 55582aa5aaced36a745408f6 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 9901234567b8bf87709717f709a35b4e91b2109e5c1ca4f76179d886194a784e1a37619d4693a758d570 -¶ -
-cipher_suite: 0x0005 -kid: 0x0000000000000123 -ctr: 0x0000000000004567 -base_key: 000102030405060708090a0b0c0d0e0f -sframe_key_label: 534672616d6520312e3020536563726574206b6579200000000000000123 -sframe_salt_label: 534672616d6520312e30205365637265742073616c74200000000000000123 -sframe_secret: 0fc3ea6de6aac97a35f194cf9bed94d4b5230f1cb45a785c9fe5dce9c188938ab6ba005bc4c0a19181599e9d1bcf7b74aca48b60bf5e254e546d809313e083a3 -sframe_key: e9e405efb7cd325030760935bf49fd5669d7c19eb84ca74b419a1487cf835107 -sframe_salt: 11007b537a1cf728a4c544c1 -metadata: 4945544620534672616d65205747 -nonce: 11007b537a1cf728a4c501a6 -aad: 99012345674945544620534672616d65205747 -pt: 64726166742d696574662d736672616d652d656e63 -ct: 99012345671e11c62748536fd55fdbc9560daea4825bfecbb05414d67aaa9f5f23d33367d33712010ebe -¶ -
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 | -
SFrame | -plain text | -diff with main | -
SFrame | -plain text | -diff with main | -
SFrame | -plain text | -diff with main | -
SFrame | -plain text | -diff with main | +SFrame | +plain text | +diff with main |