Completely Encrypting RTP Header Extensions and Contributing Sources
updates
- rfc-3711 — The Secure Real-time Transport Protocol (SRTP)
Extracted elements (25)
Encrypting the CSRC count field was considered but rejected because it would prevent parsing by existing RTP tools and increase complexity, with only a slight improvement in confidentiality — a pragmatic trade-off in favor of backward compatibility.
RFC 6904's per-extension encryption negotiation was deliberately avoided because it created complexity, only protected extension values (not IDs/lengths/CSRCs), bloated header extension space past the 14-extension one-byte limit, and had a significant implementation bug undetected for five years. Cryptex instead encrypts all header extensions and CSRCs as a single all-or-nothing mechanism.
The first two bytes of the RTP packet and the SSRC/sequence number fields are intentionally left unencrypted to preserve backward compatibility with systems that expect a standard RTPv2 structure for demultiplexing, and because SRTP key scheduling depends on sequence number and SSRC.
Cryptex reuses all framework procedures, transforms, and considerations from RFC 3711 (SRTP) except for the Encrypted Portion of the SRTP packet; the decryption procedure is identical to RFC 3711 except for the expanded Encrypted Portion.
Once both peers have verified Cryptex support via SDP exchange, senders can unilaterally decide whether to use Cryptex on a per-packet basis, enabling gradual or selective use without re-negotiation.
Peers MAY negotiate both Cryptex and RFC 6904 header extension encryption simultaneously via SDP offer/answer; either mechanism may be used on a per-packet basis, but a single packet cannot use both at the same time.
Generating subsequent SDP offers and answers MUST use the same procedures for including the 'a=cryptex' attribute as those used on the initial offer and answer.
If both Cryptex and RFC 6904 header extension encryption are supported and a packet is encrypted with Cryptex, it MUST NOT also use RFC 6904 header extension encryption, and vice versa.
If the RTP packet contains CSRCs but no header extensions, an empty extension block with the 0xC0DE tag and a 16-bit length field set to zero MUST be appended and the X bit MUST be set to 1, to signal to the receiver that the CSRCs are encrypted.
On receiving, the 'defined by profile' field MUST be checked; if it does not match a Cryptex value and Cryptex is mandatory, the implementation MUST stop processing the RTP packet and report an error.
On sending, the 16-bit RTP header extension tag MUST be set to 0xC0DE for one-byte headers or 0xC2DE for two-byte headers to indicate that Cryptex encryption has been applied.
The Cryptex mechanism MUST NOT be used with header extensions other than the RFC 8285 variety (one-byte and two-byte header extensions).
When a peer has advertised support for both Cryptex and RFC 6904, it is RECOMMENDED that the sender use Cryptex rather than RFC 6904 so that all header extensions and CSRCs are encrypted, unless there is a compelling reason (e.g., middlebox processing) to use RFC 6904.
When BUNDLE is in use (RFC 9143) and 'a=cryptex' is present for a media line, it MUST be present for all RTP-based 'm=' sections in the same bundle group, ensuring encrypted MID header extensions can be processed for stream association.
When using two-byte header extensions with Cryptex, the extension identifier with value 256 MUST NOT be negotiated, as its value would normally occupy the 'appbits' of the 'defined by profile' field, which are unavailable with the Cryptex values.
Cryptex is signaled via the new SDP property attribute 'a=cryptex', which takes no value and may appear at the session or media level. Its presence indicates the endpoint is capable of receiving Cryptex-encrypted RTP packets.
Implementations may create an intermediate representation for AEAD ciphers by swapping the extension header and CSRC identifiers to make the AAD and plaintext contiguous in memory; this intermediate form is only for internal use and MUST NOT be sent on the wire.
Two new 'defined by profile' field values are defined: 0xC0DE for encrypted one-byte header extensions (replacing 0xBEDE) and 0xC2DE for encrypted two-byte header extensions (replacing 0x100). These allow a receiver to identify Cryptex-encrypted packets.
This document adds the 'a=cryptex' SDP attribute to the 'attribute-name' subregistry of the 'Session Description Protocol (SDP) Parameters' registry. The attribute takes no value, is usable at both session and media levels, and has TRANSPORT mux category.
All security considerations from RFC 3711 Section 9 apply, except Section 9.4 (RTP header confidentiality), which Cryptex specifically addresses. The risks of weak or NULL authentication described in RFC 3711 Section 9.5 apply equally to Cryptex-encrypted header extensions.
Header extension identifiers can act as fingerprints revealing endpoint identity or application type. CSRC values in RTP packets can reveal who was speaking during a conference call, making their encryption (which Cryptex provides) important for privacy.
The fields left unencrypted by Cryptex — including RTP version, padding/extension bits, CSRC count, marker bit, payload type, sequence number, timestamp, SSRC, and header extension count — are considered to have low sensitivity. If any of these need encryption, SRTP is the wrong protocol and a fully encapsulating protocol like DTLS is preferred.
For AEAD ciphers (e.g., AES-GCM), the Additional Authenticated Data (AAD) consists of the 12-byte fixed RTP header and the 4-byte extension header ('defined by profile' + length), even though these are non-contiguous in the packet when CSRCs are present.
The Cryptex plaintext input is: CSRC identifiers (if used) || header extension data (excluding first 4 bytes) || RTP payload || RTP padding || RTP pad count. The first 4*CC bytes of ciphertext replace the CSRC fields; the remainder becomes the RTP payload.
The Encrypted Portion of a Cryptex SRTP packet includes all CSRC identifiers, the RTP header extension data (excluding the first 4-byte extension header), and the RTP payload. The first 4 bytes of the extension block (the 'defined by profile' field and length) are authenticated but NOT encrypted, as required by RFC 8285.