Spracherkennung für: .yml vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
# Meta information
meta:
# Document name and ID
id: group-call
name: Group Call Protocol
# Virtual namespace, just containing the below docstring
index: &index
_doc: |-
# Group Call Protocol (Supplementary)
This is a supplementary section to the corresponding protobuf section with
messages that use structbuf instead of protobuf. All defined messages here
follow the same logic.
# Real-Time media end-to-end encryption
e2e: &e2e
frame:
_doc: |-
And end-to-end encrypted audio/video frame.
Steps to extract the unencrypted header from frame data (encrypted or
unencrypted):
1. Let `data` be the given encrypted or unencrypted frame data.
2. Let `offset` be `0`.
3. If the codec for this frame is Opus, there is no unencrypted header.
Leave `offset` at `0`.
4. If the codec for this frame is VP8:
1. If the LSB of the first byte is `1`, set `offset` to `10` and abort
these sub-steps.
2. Set `offset` to 3.
5. Return a tuple of:
- unencrypted-header: A view of all bytes until `offset`
(i.e. `data[0..offset]`).
- payload: A view of all bytes from `offset` (i.e. `data[offset..]`).
When creating a media frame:
1. Let `data` be the given frame data.
2. If `data` is greater than `65536 - 16 - 6` bytes, log a warning and
abort these steps.
3. Let `unencrypted-header` and `payload` be the result of the above
described header extraction steps by applying it on `data.
4. Let `frame-mfsn` be a copy of the current MFSN. Then, immediately
increase MFSN by 1.
IMPORTANT: The MFSN **must** be guarded by a mutex if multithreading
is involved. It is critical to prevent nonce reuse!
5. Let `nonce` be the byte concatenation of the following items in this
order:
- `u32-le(frame-mfsn)`
- 8 zero bytes
6. Let `pcmk` be the current PCMK with the associated context.
7. Let `ad` be the byte concatenation of the following items in this
order:
- `u8(pcmk.epoch)`
- `u8(pcmk.ratchet-counter)`
- `u32-le(frame-mfsn)`
- `unencrypted-header`
8. Encrypt the media frame and let `encrypted-payload` be the result:
AES-256-GCM(
key=pcmk.pcmfk,
nonce=nonce,
auth-tag-length=16 (bytes),
auth-tag-position=append,
data=payload,
additional-data=ad,
)
9. Encode the `frame` struct:
- `data`: The byte concatenation of `unencrypted-header`,
`encrypted-payload` (including the AES GCM authentication tag).
- `footer.key-epoch`: `pcmk.epoch`
- `footer.key-ratchet-counter`: `pcmk-ratchet-counter`
- `footer.mfsn`: `frame-mfsn`
10. Increase MFSN by `1`.
11. Send the encoded `frame` struct.
When receiving a media frame:
1. Let `frame` be the received struct.
2. If `frame.data` is greater than `65536` bytes, log a warning and abort
these steps.
3. Let `unencrypted-header` and `payload` be the result of the above
described header extraction steps by applying it on `frame.data`.
4. Let `pcmk` be the current PCMK with the associated context for the
participant that sent this frame.
5. If `frame.epoch` is greater than `pcmk.epoch` or wrapped back to `0`,
seek through all successors until a media key with the same `epoch`
could be determined.
1. If no key could be determined, discard the media frame and abort
these steps.
2. Replace `pcmk` with the succeeding media key that matched `epoch`.
Note: An implementation **must** ensure that only succeeding keys
are being used. Rolling back to a preceeding media key is
forbidden.
6. If `frame.ratchet-counter` is less than `pcmk.ratchet-counter`, discard
the media frame and abort these steps.
7. If `frame.ratchet-counter` is greater than `pcmk.ratchet-counter`,
apply the necessary amount of ratchet rounds to `pcmk` so the counters
are equal.
8. Let `nonce` be the byte concatenation of the following items in this
order:
- `u32-le(frame.footer.mfsn)`
- 8 zero bytes
9. Let `ad` be the byte concatenation of the following items in this
order:
- `u8(pcmk.epoch)`
- `u8(pcmk.ratchet-counter)`
- `u32-le(frame.footer.mfsn)`
- `unencrypted-header`
10. Decrypt the media frame and let `decrypted-payload` be the result:
AES-256-GCM(
key=pcmk.pcmfk,
nonce=nonce,
auth-tag-length=16 (bytes),
auth-tag-position=append,
data=payload,
additional-data=ad,
)
11. If decryption failed, discard the media frame and abort these steps.
12. Let `data` be the byte concatenation of `unencrypted-header` and
`decrypted-payload`.
13. Forward `data` to the media pipeline.
Note: There is limited replay mitigation. The SFU is able to replay old
frames that were recorded in this media key epoch and ratchet iteration.
fields:
- _doc: |-
This contains the following data (in this order):
- Unencrypted frame header (if any, 0 to 10 bytes)
- Encrypted audio/video frame
- AES GCM authentication tag (16 bytes)
- The `footer` struct
name: data
type: b*
footer:
_doc: |-
Footer of an end-to-end encrypted audio/video frame.
fields:
- _doc: |-
Media key epoch. This is the same value as in
`group-call.MediaKey.epoch`.
name: key-epoch
type: u8
- _doc: |-
Media key ratchet counter. This is the same value as in
`MediaKey.ratchet_counter`.
name: key-ratchet-counter
type: u8
- _doc: |-
Sequence number of the media frame (MFSN).
Note: Like the epoch and the ratchet counter, the MFSN is shared
across different media types.
name: mfsn
type: u32-le
# Parsed struct namespaces (mapped into separate files)
namespaces:
index: *index
e2e: *e2e
[Dauer der Verarbeitung: 0.14 Sekunden, vorverarbeitet 2026-04-27]