fix(audit): address C2, C3, M4, M5 from 2026-05-25 audit

C2: Add EncryptingTransport wrapper — all media I/O now goes through
ChaChaSession encrypt/decrypt before hitting the QUIC datagram path.
cli.rs run_live/run_silence/run_file_mode accept Arc<dyn MediaTransport>
and receive a wrapped transport after the handshake.

C3: Wire VideoScorer::observe() into both plain and trunked forwarding
loops in room.rs. Packets from participants with Abusive verdict are
dropped before forwarding. last_bwe_kbps tracked from quality reports.

M4: Widen FEC repair symbol index from u8 to u16 throughout
(FecEncoder::generate_repair, FecDecoder::add_symbol, all call sites in
call.rs, bench.rs, pipeline.rs, wzp-android). Eliminates theoretical
wrapping when num_source + repair_count > 255.

M5: Track last_encrypt_timestamp in ChaChaSession. debug_assert in
encrypt() that timestamp is non-decreasing across calls (including post-
rekey). complete_rekey() explicitly preserves last_encrypt_timestamp to
prevent accidental timestamp reset regressions.

583 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-05-25 06:20:05 +04:00
parent 15af58a95d
commit 52a6f5e048
13 changed files with 299 additions and 29 deletions

View File

@@ -73,7 +73,7 @@ impl FecDecoder for RaptorQFecDecoder {
fn add_symbol(
&mut self,
block_id: u8,
symbol_index: u8,
symbol_index: u16,
_is_repair: bool,
data: &[u8],
) -> Result<(), FecError> {
@@ -195,7 +195,7 @@ mod tests {
// Feed all source symbols (using the length-prefixed padded data).
for (i, pkt) in source_pkts.iter().enumerate() {
decoder.add_symbol(0, i as u8, false, pkt.data()).unwrap();
decoder.add_symbol(0, i as u16, false, pkt.data()).unwrap();
}
let result = decoder.try_decode(0).unwrap();
@@ -293,10 +293,10 @@ mod tests {
// Interleave symbols from block 0 and block 1
for i in 0..FRAMES_PER_BLOCK {
decoder
.add_symbol(0, i as u8, false, pkts_a[i].data())
.add_symbol(0, i as u16, false, pkts_a[i].data())
.unwrap();
decoder
.add_symbol(1, i as u8, false, pkts_b[i].data())
.add_symbol(1, i as u16, false, pkts_b[i].data())
.unwrap();
}

View File

@@ -108,7 +108,7 @@ impl FecEncoder for RaptorQFecEncoder {
Ok(())
}
fn generate_repair(&mut self, ratio: f32) -> Result<Vec<(u8, Vec<u8>)>, FecError> {
fn generate_repair(&mut self, ratio: f32) -> Result<Vec<(u16, Vec<u8>)>, FecError> {
if self.source_symbols.is_empty() {
return Ok(vec![]);
}
@@ -133,11 +133,11 @@ impl FecEncoder for RaptorQFecEncoder {
// Generate repair packets starting from offset 0 (ESIs begin at num_source).
let repair_packets: Vec<EncodingPacket> = encoder.repair_packets(0, num_repair);
let result: Vec<(u8, Vec<u8>)> = repair_packets
let result: Vec<(u16, Vec<u8>)> = repair_packets
.into_iter()
.enumerate()
.map(|(i, pkt): (usize, EncodingPacket)| {
let idx = (num_source as u8).wrapping_add(i as u8);
let idx = (num_source as u16).wrapping_add(i as u16);
(idx, pkt.data().to_vec())
})
.collect();