diff --git a/examples/srtpsrv.rs b/examples/srtpsrv.rs index 0b153fd..1d3e083 100644 --- a/examples/srtpsrv.rs +++ b/examples/srtpsrv.rs @@ -39,7 +39,7 @@ fn main() { let master_key = hex_str_to_bytes(matches.value_of("MASTER_KEY").unwrap()); let master_salt = hex_str_to_bytes(matches.value_of("MASTER_SALT").unwrap()); - let context = Context::new_srtp(&master_key, &master_salt); + let context = Context::::new(&master_key, &master_salt); let future = track_err!(UdpSocket::bind(addr)) .and_then(move |socket| SrtpRecvLoop::new(socket, context)); diff --git a/src/rfc3711.rs b/src/rfc3711.rs index 375ce14..833d17a 100644 --- a/src/rfc3711.rs +++ b/src/rfc3711.rs @@ -3,12 +3,13 @@ use fixedbitset::FixedBitSet; use handy_async::sync_io::{ReadExt, WriteExt}; use num::BigUint; use std::borrow::Cow; +use std::collections::BTreeMap; use std::io::{Read, Write}; use io::{ReadFrom, WriteTo}; use rfc3550; use traits::{ReadPacket, RtcpPacket, RtpPacket, WritePacket}; -use types::U48; +use types::{Ssrc, U48}; use {ErrorKind, Result}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -33,18 +34,20 @@ impl Default for AuthenticationAlgorithm { } } -pub trait Protocol: Sized { +pub trait Protocol: Sized + Default { type PacketIndex: Sized + Ord + Into + Into + Copy; const ENC_KEY_LABEL: u8; const AUTH_KEY_LABEL: u8; const SALT_KEY_LABEL: u8; + fn read_ssrc(packet: &[u8]) -> Result; fn determine_incoming_packet_index( context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], ) -> Result; fn determine_outgoing_packet_index( - context: &Context, + context: &SsrcContext, packet: &[u8], ) -> Result; fn get_authenticated_bytes<'a>( @@ -52,12 +55,20 @@ pub trait Protocol: Sized { index: Self::PacketIndex, auth_portion: &'a [u8], ) -> Result>; - fn decrypt(context: &Context, packet: &[u8], index: Self::PacketIndex) - -> Result>; - fn encrypt(context: &Context, packet: &[u8], index: Self::PacketIndex) - -> Result>; - fn update_highest_recv_index(context: &mut Context, index: Self::PacketIndex); - fn update_highest_sent_index(context: &mut Context, index: Self::PacketIndex); + fn decrypt( + context: &Context, + ssrc_context: &SsrcContext, + packet: &[u8], + index: Self::PacketIndex, + ) -> Result>; + fn encrypt( + context: &Context, + ssrc_context: &SsrcContext, + packet: &[u8], + index: Self::PacketIndex, + ) -> Result>; + fn update_highest_recv_index(context: &mut SsrcContext, index: Self::PacketIndex); + fn update_highest_sent_index(context: &mut SsrcContext, index: Self::PacketIndex); } // TODO maybe use type marker to ensure one context is only ever used for either sending OR receiving @@ -73,12 +84,17 @@ pub struct Context { pub key_derivation_rate: u8, pub encryption: EncryptionAlgorithm, pub authentication: AuthenticationAlgorithm, + pub auth_tag_len: usize, + pub ssrc_context: BTreeMap>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SsrcContext { pub replay_window_head: u64, pub replay_window: FixedBitSet, pub session_encr_key: Vec, pub session_salt_key: Vec, pub session_auth_key: Vec, - pub auth_tag_len: usize, pub protocol_specific: P, } @@ -93,28 +109,20 @@ pub struct Srtcp { pub highest_sent_index: u32, // actually only 31-bits } -impl Context { - pub fn new_srtp(master_key: &[u8], master_salt: &[u8]) -> Self { - Context::new( - master_key, - master_salt, - Srtp { - rollover_counter: 0, - highest_seq_num: 0, - }, - ) +impl Default for Srtp { + fn default() -> Self { + Srtp { + rollover_counter: 0, + highest_seq_num: 0, + } } } -impl Context { - pub fn new_srtcp(master_key: &[u8], master_salt: &[u8]) -> Self { - Context::new( - master_key, - master_salt, - Srtcp { - highest_sent_index: 0, - }, - ) +impl Default for Srtcp { + fn default() -> Self { + Srtcp { + highest_sent_index: 0, + } } } @@ -129,23 +137,23 @@ impl Srtp { // sequence number and current rollover_counter, i.e. determining the most // likely (minimizing index offset) ROC for the given sequence number. // As per https://tools.ietf.org/html/rfc3711#section-3.3.1 - fn estimate_packet_index(context: &Context, seq_num: u16) -> U48 { + fn estimate_packet_index(context: &Self, seq_num: u16) -> U48 { let Srtp { highest_seq_num, rollover_counter, - } = context.protocol_specific; + } = context; let mid_seq_num = 1 << 15; - let probable_roc = if highest_seq_num < mid_seq_num { + let probable_roc = if *highest_seq_num < mid_seq_num { if highest_seq_num + mid_seq_num < seq_num { rollover_counter.wrapping_sub(1) } else { - rollover_counter + *rollover_counter } } else { if highest_seq_num - mid_seq_num > seq_num { rollover_counter.wrapping_add(1) } else { - rollover_counter + *rollover_counter } }; (U48::from(probable_roc) << 16) + U48::from(seq_num) @@ -158,20 +166,33 @@ impl Protocol for Srtp { const AUTH_KEY_LABEL: u8 = 1; const SALT_KEY_LABEL: u8 = 2; + fn read_ssrc(packet: &[u8]) -> Result { + let reader = &mut &packet[..]; + let header = track_try!(rfc3550::RtpFixedHeader::read_from(reader)); + Ok(header.ssrc) + } + fn determine_incoming_packet_index( - context: &Context, + _context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], ) -> Result { let seq_num = track_try!(Srtp::parse_seq_num(packet)); - Ok(Srtp::estimate_packet_index(context, seq_num)) + Ok(Srtp::estimate_packet_index( + &ssrc_context.protocol_specific, + seq_num, + )) } fn determine_outgoing_packet_index( - context: &Context, + context: &SsrcContext, packet: &[u8], ) -> Result { let seq_num = track_try!(Srtp::parse_seq_num(packet)); - Ok(Srtp::estimate_packet_index(context, seq_num)) + Ok(Srtp::estimate_packet_index( + &context.protocol_specific, + seq_num, + )) } fn get_authenticated_bytes<'a>( @@ -188,6 +209,7 @@ impl Protocol for Srtp { fn decrypt( context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], index: Self::PacketIndex, ) -> Result> { @@ -198,12 +220,13 @@ impl Protocol for Srtp { let mut decrypted: Vec = Vec::new(); track_try!(header.write_to(&mut decrypted)); - context.decrypt_portion(encrypted_portion, &mut decrypted, ssrc, index); + context.decrypt_portion(ssrc_context, encrypted_portion, &mut decrypted, ssrc, index); Ok(decrypted) } fn encrypt( context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], index: Self::PacketIndex, ) -> Result> { @@ -214,11 +237,11 @@ impl Protocol for Srtp { let mut encrypted: Vec = Vec::new(); track_try!(header.write_to(&mut encrypted)); - context.encrypt_portion(plaintext_portion, &mut encrypted, ssrc, index); + context.encrypt_portion(ssrc_context, plaintext_portion, &mut encrypted, ssrc, index); Ok(encrypted) } - fn update_highest_recv_index(context: &mut Context, index: Self::PacketIndex) { + fn update_highest_recv_index(context: &mut SsrcContext, index: Self::PacketIndex) { // https://tools.ietf.org/html/rfc3711#section-3.3.1 let state = &mut context.protocol_specific; let rollover_counter = (index >> 16) as u32; @@ -233,7 +256,7 @@ impl Protocol for Srtp { } } - fn update_highest_sent_index(context: &mut Context, index: Self::PacketIndex) { + fn update_highest_sent_index(context: &mut SsrcContext, index: Self::PacketIndex) { // Unless we assume that packets are properly ordered when sent, // we have to use the same algorithm to update the ROC as when receiving them. Self::update_highest_recv_index(context, index); @@ -246,8 +269,15 @@ impl Protocol for Srtcp { const AUTH_KEY_LABEL: u8 = 4; const SALT_KEY_LABEL: u8 = 5; + fn read_ssrc(packet: &[u8]) -> Result { + let reader = &mut &packet[..]; + track_try!(reader.read_u32be()); + track_err!(reader.read_u32be()) + } + fn determine_incoming_packet_index( context: &Context, + _ssrc_context: &SsrcContext, packet: &[u8], ) -> Result { let reader = &mut &packet[packet.len() - context.auth_tag_len - 4..]; @@ -256,7 +286,7 @@ impl Protocol for Srtcp { } fn determine_outgoing_packet_index( - context: &Context, + context: &SsrcContext, _packet: &[u8], ) -> Result { const MODULO: u32 = 1 << 31; @@ -274,6 +304,7 @@ impl Protocol for Srtcp { fn decrypt( context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], index: Self::PacketIndex, ) -> Result> { @@ -291,12 +322,13 @@ impl Protocol for Srtcp { let encrypted_portion = &reader[0..reader.len() - context.auth_tag_len - 4]; let mut decrypted = Vec::from(&packet[..8]); - context.decrypt_portion(encrypted_portion, &mut decrypted, ssrc, index); + context.decrypt_portion(ssrc_context, encrypted_portion, &mut decrypted, ssrc, index); Ok(decrypted) } fn encrypt( context: &Context, + ssrc_context: &SsrcContext, packet: &[u8], index: Self::PacketIndex, ) -> Result> { @@ -306,17 +338,17 @@ impl Protocol for Srtcp { let plaintext_portion = &reader[0..]; let mut encrypted = Vec::from(&packet[..8]); - context.decrypt_portion(plaintext_portion, &mut encrypted, ssrc, index); + context.decrypt_portion(ssrc_context, plaintext_portion, &mut encrypted, ssrc, index); let index_with_e_bit = index | 0x8000_0000; // "encrypted"-bit track_try!(encrypted.write_u32be(index_with_e_bit)); Ok(encrypted) } - fn update_highest_recv_index(_context: &mut Context, _index: Self::PacketIndex) { + fn update_highest_recv_index(_context: &mut SsrcContext, _index: Self::PacketIndex) { // full packet inex is part of SRTCP packets, no need to keep track of it } - fn update_highest_sent_index(context: &mut Context, index: Self::PacketIndex) { + fn update_highest_sent_index(context: &mut SsrcContext, index: Self::PacketIndex) { // we're giving out indices in strictly ascending order in determine_outgoing_packet_index context.protocol_specific.highest_sent_index = index; } @@ -326,23 +358,35 @@ impl Context

where u64: From, { - pub fn new(master_key: &[u8], master_salt: &[u8], protocol_specific: P) -> Self { + pub fn new(master_key: &[u8], master_salt: &[u8]) -> Self { Context { master_key: Vec::from(master_key), master_salt: Vec::from(master_salt), key_derivation_rate: 0, encryption: EncryptionAlgorithm::default(), authentication: AuthenticationAlgorithm::default(), + auth_tag_len: 80 / 8, + ssrc_context: BTreeMap::new(), + } + } + + pub fn add_ssrc(&mut self, ssrc: Ssrc) { + let ssrc_context = SsrcContext { replay_window_head: 0, replay_window: FixedBitSet::with_capacity(128), session_encr_key: vec![0; 128 / 8], session_salt_key: vec![0; 112 / 8], session_auth_key: vec![0; 160 / 8], - auth_tag_len: 80 / 8, - protocol_specific, - } + protocol_specific: P::default(), + }; + assert!( + self.ssrc_context.insert(ssrc, ssrc_context).is_none(), + "SSRC {} had already been added", + ssrc + ); } - pub fn update_session_keys(&mut self, index: P::PacketIndex) { + + pub fn update_session_keys(&mut self, ssrc: Ssrc, index: P::PacketIndex) { let index = if self.key_derivation_rate == 0 { 0 } else { @@ -362,57 +406,72 @@ where BigUint::from_bytes_be(&[P::SALT_KEY_LABEL, 0, 0, 0, 0, 0, 0]) + index.clone(); let master_salt = BigUint::from_bytes_be(&self.master_salt); - self.session_encr_key = prf_n( + let context = self.ssrc_context.get_mut(&ssrc).unwrap(); + context.session_encr_key = prf_n( &self.master_key, enc_key_id ^ master_salt.clone(), - self.session_encr_key.len(), + context.session_encr_key.len(), ); - self.session_auth_key = prf_n( + context.session_auth_key = prf_n( &self.master_key, auth_key_id ^ master_salt.clone(), - self.session_auth_key.len(), + context.session_auth_key.len(), ); - self.session_salt_key = prf_n( + context.session_salt_key = prf_n( &self.master_key, salt_key_id ^ master_salt.clone(), - self.session_salt_key.len(), + context.session_salt_key.len(), ); } - pub fn authenticate(&self, packet: &[u8], index: P::PacketIndex) -> Result<()> { + pub fn authenticate( + &self, + context: &SsrcContext

, + packet: &[u8], + index: P::PacketIndex, + ) -> Result<()> { let auth_portion = &packet[..packet.len() - self.auth_tag_len]; let auth_tag = &packet[packet.len() - self.auth_tag_len..]; let auth_bytes = track_try!(P::get_authenticated_bytes(self, index, auth_portion)); - let mut expected_tag = hmac_hash_sha1(&self.session_auth_key, &auth_bytes); + let mut expected_tag = hmac_hash_sha1(&context.session_auth_key, &auth_bytes); expected_tag.truncate(self.auth_tag_len); track_assert_eq!(auth_tag, &expected_tag[..], ErrorKind::Invalid); Ok(()) } - pub fn generate_auth_tag(&self, packet: &[u8], index: P::PacketIndex) -> Result> { + pub fn generate_auth_tag( + &self, + context: &SsrcContext

, + packet: &[u8], + index: P::PacketIndex, + ) -> Result> { let auth_bytes = track_try!(P::get_authenticated_bytes(self, index, packet)); - let mut tag = hmac_hash_sha1(&self.session_auth_key, &auth_bytes); + let mut tag = hmac_hash_sha1(&context.session_auth_key, &auth_bytes); tag.truncate(self.auth_tag_len); Ok(tag) } pub fn decrypt_portion( &self, + context: &SsrcContext

, encrypted: &[u8], decrypted: &mut Vec, ssrc: u32, index: P::PacketIndex, ) { - let iv = BigUint::from_bytes_be(&self.session_salt_key) << 16; + let iv = BigUint::from_bytes_be(&context.session_salt_key) << 16; let iv = iv ^ (BigUint::from(ssrc) << 64); let iv = iv ^ (index.into() << 16); - let iv = &iv.to_bytes_be()[0..self.session_encr_key.len()]; + let iv = &iv.to_bytes_be()[0..context.session_encr_key.len()]; - let mut ctr = - crypto::aes::ctr(crypto::aes::KeySize::KeySize128, &self.session_encr_key, iv); - let block_size = self.session_encr_key.len(); + let mut ctr = crypto::aes::ctr( + crypto::aes::KeySize::KeySize128, + &context.session_encr_key, + iv, + ); + let block_size = context.session_encr_key.len(); for block in encrypted.chunks(block_size) { let old_len = decrypted.len(); @@ -420,25 +479,34 @@ where ctr.process(block, &mut decrypted[old_len..]); } } - pub fn decrypt(&mut self, packet: &[u8], index: P::PacketIndex) -> Result> { - P::decrypt(self, packet, index) + pub fn decrypt( + &self, + context: &SsrcContext

, + packet: &[u8], + index: P::PacketIndex, + ) -> Result> { + P::decrypt(self, context, packet, index) } pub fn encrypt_portion( &self, + context: &SsrcContext

, plaintext: &[u8], encrypted: &mut Vec, ssrc: u32, index: P::PacketIndex, ) { - let iv = BigUint::from_bytes_be(&self.session_salt_key) << 16; + let iv = BigUint::from_bytes_be(&context.session_salt_key) << 16; let iv = iv ^ (BigUint::from(ssrc) << 64); let iv = iv ^ (index.into() << 16); - let iv = &iv.to_bytes_be()[0..self.session_encr_key.len()]; + let iv = &iv.to_bytes_be()[0..context.session_encr_key.len()]; - let mut ctr = - crypto::aes::ctr(crypto::aes::KeySize::KeySize128, &self.session_encr_key, iv); - let block_size = self.session_encr_key.len(); + let mut ctr = crypto::aes::ctr( + crypto::aes::KeySize::KeySize128, + &context.session_encr_key, + iv, + ); + let block_size = context.session_encr_key.len(); for block in plaintext.chunks(block_size) { let old_len = encrypted.len(); @@ -446,61 +514,83 @@ where ctr.process(block, &mut encrypted[old_len..]); } } - pub fn encrypt(&mut self, packet: &[u8], index: P::PacketIndex) -> Result> { - P::encrypt(self, packet, index) + pub fn encrypt( + &self, + context: &SsrcContext

, + packet: &[u8], + index: P::PacketIndex, + ) -> Result> { + P::encrypt(self, context, packet, index) } // https://tools.ietf.org/html/rfc3711#section-3.3 // https://tools.ietf.org/html/rfc3711#section-3.4 pub fn process_incoming(&mut self, packet: &[u8]) -> Result> { - // Step 1: determining the correct context (has already happened at this point) + // Step 1: determining the correct context + let ssrc = track_try!(P::read_ssrc(packet)); + track_assert!(self.ssrc_context.contains_key(&ssrc), ErrorKind::Invalid, "Unknown SSRC {}", ssrc); // Step 2: Determine index of the packet - let index = track_try!(P::determine_incoming_packet_index(self, packet)); + let index = track_try!(P::determine_incoming_packet_index( + self, + self.ssrc_context.get(&ssrc).unwrap(), + packet + )); // Step 3: Determine master key and salt // TODO: support re-keying // TODO: support MKI // Step 4: Determine session keys and salt - self.update_session_keys(index); + self.update_session_keys(ssrc, index); - // Step 5: Replay protection and authentication let idx = u64::from(index); - let window_size = self.replay_window.len() as u64; - if idx <= self.replay_window_head { - track_assert!( - idx + window_size > self.replay_window_head, - ErrorKind::Invalid - ); - track_assert!( - !self.replay_window[(idx % window_size) as usize], - ErrorKind::Invalid - ); - } - track_try!(self.authenticate(packet, index)); + let (result, window_size) = { + let ssrc_context = self.ssrc_context.get(&ssrc).unwrap(); - // Step 6: Decryption - let result = track_try!(self.decrypt(packet, index)); - - // Step 7: Update ROC, highest sequence number and replay protection - if idx > self.replay_window_head { - if idx - self.replay_window_head >= window_size { - self.replay_window.clear() - } else { - let start = ((self.replay_window_head + 1) % window_size) as usize; - let end = (idx % window_size) as usize; - if start > end { - self.replay_window.set_range(start.., false); - self.replay_window.set_range(..end, false); - } else { - self.replay_window.set_range(start..end, false); - } + // Step 5: Replay protection and authentication + let window_size = ssrc_context.replay_window.len() as u64; + if idx <= ssrc_context.replay_window_head { + track_assert!( + idx + window_size > ssrc_context.replay_window_head, + ErrorKind::Invalid + ); + track_assert!( + !ssrc_context.replay_window[(idx % window_size) as usize], + ErrorKind::Invalid + ); } - self.replay_window_head = idx; - } - self.replay_window.insert((idx % window_size) as usize); - P::update_highest_recv_index(self, index); + track_try!(self.authenticate(ssrc_context, packet, index)); + + // Step 6: Decryption + let result = track_try!(self.decrypt(ssrc_context, packet, index)); + + (result, window_size) + }; + { + let ssrc_context = self.ssrc_context.get_mut(&ssrc).unwrap(); + + // Step 7: Update ROC, highest sequence number and replay protection + if idx > ssrc_context.replay_window_head { + if idx - ssrc_context.replay_window_head >= window_size { + ssrc_context.replay_window.clear() + } else { + let start = ((ssrc_context.replay_window_head + 1) % window_size) as usize; + let end = (idx % window_size) as usize; + if start > end { + ssrc_context.replay_window.set_range(start.., false); + ssrc_context.replay_window.set_range(..end, false); + } else { + ssrc_context.replay_window.set_range(start..end, false); + } + } + ssrc_context.replay_window_head = idx; + } + ssrc_context + .replay_window + .insert((idx % window_size) as usize); + P::update_highest_recv_index(ssrc_context, index); + }; Ok(result) } @@ -508,30 +598,40 @@ where // https://tools.ietf.org/html/rfc3711#section-3.3 // https://tools.ietf.org/html/rfc3711#section-3.4 pub fn process_outgoing(&mut self, packet: &[u8]) -> Result> { - // Step 1: determining the correct context (has already happened at this point) + // Step 1: determining the correct context + let ssrc = track_try!(P::read_ssrc(packet)); + track_assert!(self.ssrc_context.contains_key(&ssrc), ErrorKind::Invalid, "Unknown SSRC {}", ssrc); // Step 2: Determine index of the packet - let index = track_try!(P::determine_outgoing_packet_index(self, packet)); + let index = track_try!(P::determine_outgoing_packet_index( + self.ssrc_context.get(&ssrc).unwrap(), + packet + )); // Step 3: Determine master key and salt // TODO: support re-keying // TODO: support MKI // Step 4: Determine session keys and salt - self.update_session_keys(index); + self.update_session_keys(ssrc, index); // Step 5: Encryption - let mut result = track_try!(self.encrypt(packet, index)); + let mut result = + track_try!(self.encrypt(self.ssrc_context.get(&ssrc).unwrap(), packet, index)); // Step 6: Append MKI if MKI indicator is set // TODO: support MKI // Step 7: Signing - let auth_tag = track_try!(self.generate_auth_tag(&result[..], index)); + let auth_tag = track_try!(self.generate_auth_tag( + self.ssrc_context.get(&ssrc).unwrap(), + &result[..], + index + )); result.extend(auth_tag); // Step 7: Update ROC and highest sequence number - P::update_highest_sent_index(self, index); + P::update_highest_sent_index(self.ssrc_context.get_mut(&ssrc).unwrap(), index); Ok(result) } @@ -706,20 +806,20 @@ mod test { #[test] fn rtp_packet_index_estimation_works() { - let mut context = Context::new_srtp(&[], &[]); + let mut context = Srtp::default(); let roc = 0u32; let roc_n1 = roc.wrapping_sub(1); let roc_p1 = roc.wrapping_add(1); - context.protocol_specific.rollover_counter = roc; + context.rollover_counter = roc; let i = |roc, seq_num| ((roc as u64) << 16) + seq_num as u64; - let estimate = |ctx: &Context, seq_num| Srtp::estimate_packet_index(ctx, seq_num); + let estimate = |ctx: &Srtp, seq_num| Srtp::estimate_packet_index(ctx, seq_num); - context.protocol_specific.highest_seq_num = 1000; // low highest_seq_num + context.highest_seq_num = 1000; // low highest_seq_num assert_eq!(estimate(&context, 1), i(roc, 1)); // lower but same roc assert_eq!(estimate(&context, 10001), i(roc, 10001)); // higher but same roc assert_eq!(estimate(&context, 60001), i(roc_n1, 60001)); // roc-1 - context.protocol_specific.highest_seq_num = 60000; // high highest_seq_num + context.highest_seq_num = 60000; // high highest_seq_num assert_eq!(estimate(&context, 60001), i(roc, 60001)); // higher but same roc assert_eq!(estimate(&context, 30001), i(roc, 30001)); // lower but same roc assert_eq!(estimate(&context, 10001), i(roc_p1, 10001)); // roc+1 @@ -731,6 +831,7 @@ mod test { const TEST_MASTER_SALT: &[u8] = &[ 127, 31, 227, 93, 120, 247, 126, 117, 231, 159, 123, 235, 95, 122, ]; + const TEST_SRTP_SSRC: Ssrc = 446919554; const TEST_SRTP_PACKET: &[u8] = &[ 128, 0, 3, 92, 222, 161, 6, 76, 26, 163, 115, 130, 222, 0, 143, 87, 0, 227, 123, 91, 200, 238, 141, 220, 9, 191, 52, 111, 100, 62, 220, 158, 211, 79, 184, 199, 79, 182, 9, 248, 170, @@ -743,6 +844,7 @@ mod test { 7, 52, 191, 129, 239, 86, 78, 172, 229, 178, 112, 22, 125, 191, 164, 17, 193, 24, 152, 197, 146, 94, 74, 156, 171, 245, 239, 220, 205, 145, 206, ]; + const TEST_SRTCP_SSRC: Ssrc = 3270675037; const TEST_SRTCP_PACKET: &[u8] = &[ 128, 201, 0, 1, 194, 242, 138, 93, 177, 31, 99, 88, 187, 209, 173, 181, 135, 18, 79, 59, 119, 153, 115, 34, 75, 94, 96, 29, 32, 14, 118, 86, 145, 159, 203, 174, 225, 34, 196, 229, @@ -755,6 +857,7 @@ mod test { 124, 185, 61, 185, 219, 148, 249, 33, 222, 227, 189, 112, 23, 80, 114, 233, ]; const TEST_2_MASTER_SALT: &[u8] = &[93, 4, 23, 245, 147, 199, 112, 49, 24, 105, 140, 1, 77, 98]; + const TEST_2_SRTP_SSRC: Ssrc = 180601533; const TEST_2_SRTP_PACKET_BEFORE_ROLLOVER: &[u8] = &[ 0x80, 0x61, 0xff, 0xff, 0x87, 0xf5, 0xee, 0x93, 0x0a, 0xc3, 0xc2, 0xbd, 0x93, 0x04, 0x0b, 0x4d, 0xe9, 0x55, 0x69, 0xb7, 0xac, 0x88, 0xc5, 0xd6, 0xc2, 0x75, 0xb8, 0x15, 0x86, 0xc3, @@ -776,7 +879,8 @@ mod test { #[test] fn rtp_decryption_works() { - let context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut context = Context::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + context.add_ssrc(TEST_SRTP_SSRC); let mut rtp_reader = SrtpPacketReader::new(context, rfc3550::RtpPacketReader); let packet = rtp_reader.read_packet(&mut TEST_SRTP_PACKET).unwrap(); @@ -794,8 +898,14 @@ mod test { #[test] fn rtp_decryption_with_rollover_works() { - let mut context = Context::new_srtp(&TEST_2_MASTER_KEY, &TEST_2_MASTER_SALT); - context.protocol_specific.highest_seq_num = 65534; + let mut context = Context::::new(&TEST_2_MASTER_KEY, &TEST_2_MASTER_SALT); + context.add_ssrc(TEST_2_SRTP_SSRC); + context + .ssrc_context + .get_mut(&TEST_2_SRTP_SSRC) + .unwrap() + .protocol_specific + .highest_seq_num = 65534; let mut rtp_reader = SrtpPacketReader::new(context, rfc3550::RtpPacketReader); rtp_reader .read_packet(&mut TEST_2_SRTP_PACKET_BEFORE_ROLLOVER) @@ -821,7 +931,8 @@ mod test { 236, 161, 194, 6, 232, 194, 230, ]; - let context = Context::new_srtcp(&master_key, &master_salt); + let mut context = Context::new(&master_key, &master_salt); + context.add_ssrc(TEST_SRTCP_SSRC); let mut rtcp_reader = SrtcpPacketReader::new(context, rfc4585::RtcpPacketReader); let packet = track_try_unwrap!(rtcp_reader.read_packet(&mut &packet[..])); println!("# {:?}", packet); @@ -829,8 +940,10 @@ mod test { #[test] fn rtp_decryption_encryption_are_inverse() { - let mut dec_context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); - let mut enc_context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut enc_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTP_SSRC); + enc_context.add_ssrc(TEST_SRTP_SSRC); let decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTP_PACKET)); let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted)); assert_eq!(&encrypted[..], TEST_SRTP_PACKET); @@ -838,8 +951,10 @@ mod test { #[test] fn rtcp_decryption_encryption_are_inverse() { - let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); - let mut enc_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut enc_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTCP_SSRC); + enc_context.add_ssrc(TEST_SRTCP_SSRC); let decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTCP_PACKET)); let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted)); assert_eq!(&encrypted[..], TEST_SRTCP_PACKET); @@ -847,8 +962,10 @@ mod test { #[test] fn rtcp_encryption_does_not_use_two_time_pad() { - let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); - let mut enc_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut enc_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTCP_SSRC); + enc_context.add_ssrc(TEST_SRTCP_SSRC); let decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTCP_PACKET)); let encrypted_1 = track_try_unwrap!(enc_context.process_outgoing(&decrypted)); let encrypted_2 = track_try_unwrap!(enc_context.process_outgoing(&decrypted)); @@ -860,7 +977,8 @@ mod test { #[test] fn rtp_does_not_allow_packet_replay() { - let mut dec_context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTP_SSRC); assert!(dec_context.process_incoming(TEST_SRTP_PACKET).is_ok()); assert!(dec_context.process_incoming(TEST_SRTP_PACKET).is_err()); assert!(dec_context.process_incoming(TEST_SRTP_PACKET).is_err()); @@ -868,7 +986,8 @@ mod test { #[test] fn rtcp_does_not_allow_packet_replay() { - let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTCP_SSRC); assert!(dec_context.process_incoming(TEST_SRTCP_PACKET).is_ok()); assert!(dec_context.process_incoming(TEST_SRTCP_PACKET).is_err()); assert!(dec_context.process_incoming(TEST_SRTCP_PACKET).is_err()); @@ -876,17 +995,24 @@ mod test { #[test] fn rtcp_does_not_allow_delayed_packet_replay() { - let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTCP_SSRC); let decrypted = dec_context.process_incoming(TEST_SRTCP_PACKET).unwrap(); - let mut enc_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + let mut enc_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + enc_context.add_ssrc(TEST_SRTCP_SSRC); const N: usize = 10; let encs: Vec<_> = (0..N) .map(|_| enc_context.process_outgoing(&decrypted).unwrap()) .collect(); - let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT); - dec_context.replay_window = FixedBitSet::with_capacity(4); + let mut dec_context = Context::::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT); + dec_context.add_ssrc(TEST_SRTCP_SSRC); + dec_context + .ssrc_context + .get_mut(&TEST_SRTCP_SSRC) + .unwrap() + .replay_window = FixedBitSet::with_capacity(4); assert!(dec_context.process_incoming(&encs[0]).is_ok()); assert!(dec_context.process_incoming(&encs[1]).is_ok());