Support multiple SSRCs on the same SRT(C)P session
parent
5a770f79c3
commit
ad85e55b66
|
@ -39,7 +39,7 @@ fn main() {
|
||||||
|
|
||||||
let master_key = hex_str_to_bytes(matches.value_of("MASTER_KEY").unwrap());
|
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 master_salt = hex_str_to_bytes(matches.value_of("MASTER_SALT").unwrap());
|
||||||
let context = Context::new_srtp(&master_key, &master_salt);
|
let context = Context::<Srtp>::new(&master_key, &master_salt);
|
||||||
let future = track_err!(UdpSocket::bind(addr))
|
let future = track_err!(UdpSocket::bind(addr))
|
||||||
.and_then(move |socket| SrtpRecvLoop::new(socket, context));
|
.and_then(move |socket| SrtpRecvLoop::new(socket, context));
|
||||||
|
|
||||||
|
|
362
src/rfc3711.rs
362
src/rfc3711.rs
|
@ -3,12 +3,13 @@ use fixedbitset::FixedBitSet;
|
||||||
use handy_async::sync_io::{ReadExt, WriteExt};
|
use handy_async::sync_io::{ReadExt, WriteExt};
|
||||||
use num::BigUint;
|
use num::BigUint;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use io::{ReadFrom, WriteTo};
|
use io::{ReadFrom, WriteTo};
|
||||||
use rfc3550;
|
use rfc3550;
|
||||||
use traits::{ReadPacket, RtcpPacket, RtpPacket, WritePacket};
|
use traits::{ReadPacket, RtcpPacket, RtpPacket, WritePacket};
|
||||||
use types::U48;
|
use types::{Ssrc, U48};
|
||||||
use {ErrorKind, Result};
|
use {ErrorKind, Result};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[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<u64> + Into<BigUint> + Copy;
|
type PacketIndex: Sized + Ord + Into<u64> + Into<BigUint> + Copy;
|
||||||
const ENC_KEY_LABEL: u8;
|
const ENC_KEY_LABEL: u8;
|
||||||
const AUTH_KEY_LABEL: u8;
|
const AUTH_KEY_LABEL: u8;
|
||||||
const SALT_KEY_LABEL: u8;
|
const SALT_KEY_LABEL: u8;
|
||||||
|
|
||||||
|
fn read_ssrc(packet: &[u8]) -> Result<Ssrc>;
|
||||||
fn determine_incoming_packet_index(
|
fn determine_incoming_packet_index(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex>;
|
) -> Result<Self::PacketIndex>;
|
||||||
fn determine_outgoing_packet_index(
|
fn determine_outgoing_packet_index(
|
||||||
context: &Context<Self>,
|
context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex>;
|
) -> Result<Self::PacketIndex>;
|
||||||
fn get_authenticated_bytes<'a>(
|
fn get_authenticated_bytes<'a>(
|
||||||
|
@ -52,12 +55,20 @@ pub trait Protocol: Sized {
|
||||||
index: Self::PacketIndex,
|
index: Self::PacketIndex,
|
||||||
auth_portion: &'a [u8],
|
auth_portion: &'a [u8],
|
||||||
) -> Result<Cow<'a, [u8]>>;
|
) -> Result<Cow<'a, [u8]>>;
|
||||||
fn decrypt(context: &Context<Self>, packet: &[u8], index: Self::PacketIndex)
|
fn decrypt(
|
||||||
-> Result<Vec<u8>>;
|
context: &Context<Self>,
|
||||||
fn encrypt(context: &Context<Self>, packet: &[u8], index: Self::PacketIndex)
|
ssrc_context: &SsrcContext<Self>,
|
||||||
-> Result<Vec<u8>>;
|
packet: &[u8],
|
||||||
fn update_highest_recv_index(context: &mut Context<Self>, index: Self::PacketIndex);
|
index: Self::PacketIndex,
|
||||||
fn update_highest_sent_index(context: &mut Context<Self>, index: Self::PacketIndex);
|
) -> Result<Vec<u8>>;
|
||||||
|
fn encrypt(
|
||||||
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
|
packet: &[u8],
|
||||||
|
index: Self::PacketIndex,
|
||||||
|
) -> Result<Vec<u8>>;
|
||||||
|
fn update_highest_recv_index(context: &mut SsrcContext<Self>, index: Self::PacketIndex);
|
||||||
|
fn update_highest_sent_index(context: &mut SsrcContext<Self>, index: Self::PacketIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO maybe use type marker to ensure one context is only ever used for either sending OR receiving
|
// 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<P: Protocol> {
|
||||||
pub key_derivation_rate: u8,
|
pub key_derivation_rate: u8,
|
||||||
pub encryption: EncryptionAlgorithm,
|
pub encryption: EncryptionAlgorithm,
|
||||||
pub authentication: AuthenticationAlgorithm,
|
pub authentication: AuthenticationAlgorithm,
|
||||||
|
pub auth_tag_len: usize,
|
||||||
|
pub ssrc_context: BTreeMap<u32, SsrcContext<P>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct SsrcContext<P: Protocol> {
|
||||||
pub replay_window_head: u64,
|
pub replay_window_head: u64,
|
||||||
pub replay_window: FixedBitSet,
|
pub replay_window: FixedBitSet,
|
||||||
pub session_encr_key: Vec<u8>,
|
pub session_encr_key: Vec<u8>,
|
||||||
pub session_salt_key: Vec<u8>,
|
pub session_salt_key: Vec<u8>,
|
||||||
pub session_auth_key: Vec<u8>,
|
pub session_auth_key: Vec<u8>,
|
||||||
pub auth_tag_len: usize,
|
|
||||||
pub protocol_specific: P,
|
pub protocol_specific: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,28 +109,20 @@ pub struct Srtcp {
|
||||||
pub highest_sent_index: u32, // actually only 31-bits
|
pub highest_sent_index: u32, // actually only 31-bits
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context<Srtp> {
|
impl Default for Srtp {
|
||||||
pub fn new_srtp(master_key: &[u8], master_salt: &[u8]) -> Self {
|
fn default() -> Self {
|
||||||
Context::new(
|
|
||||||
master_key,
|
|
||||||
master_salt,
|
|
||||||
Srtp {
|
Srtp {
|
||||||
rollover_counter: 0,
|
rollover_counter: 0,
|
||||||
highest_seq_num: 0,
|
highest_seq_num: 0,
|
||||||
},
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context<Srtcp> {
|
impl Default for Srtcp {
|
||||||
pub fn new_srtcp(master_key: &[u8], master_salt: &[u8]) -> Self {
|
fn default() -> Self {
|
||||||
Context::new(
|
|
||||||
master_key,
|
|
||||||
master_salt,
|
|
||||||
Srtcp {
|
Srtcp {
|
||||||
highest_sent_index: 0,
|
highest_sent_index: 0,
|
||||||
},
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,23 +137,23 @@ impl Srtp {
|
||||||
// sequence number and current rollover_counter, i.e. determining the most
|
// sequence number and current rollover_counter, i.e. determining the most
|
||||||
// likely (minimizing index offset) ROC for the given sequence number.
|
// likely (minimizing index offset) ROC for the given sequence number.
|
||||||
// As per https://tools.ietf.org/html/rfc3711#section-3.3.1
|
// As per https://tools.ietf.org/html/rfc3711#section-3.3.1
|
||||||
fn estimate_packet_index(context: &Context<Self>, seq_num: u16) -> U48 {
|
fn estimate_packet_index(context: &Self, seq_num: u16) -> U48 {
|
||||||
let Srtp {
|
let Srtp {
|
||||||
highest_seq_num,
|
highest_seq_num,
|
||||||
rollover_counter,
|
rollover_counter,
|
||||||
} = context.protocol_specific;
|
} = context;
|
||||||
let mid_seq_num = 1 << 15;
|
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 {
|
if highest_seq_num + mid_seq_num < seq_num {
|
||||||
rollover_counter.wrapping_sub(1)
|
rollover_counter.wrapping_sub(1)
|
||||||
} else {
|
} else {
|
||||||
rollover_counter
|
*rollover_counter
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if highest_seq_num - mid_seq_num > seq_num {
|
if highest_seq_num - mid_seq_num > seq_num {
|
||||||
rollover_counter.wrapping_add(1)
|
rollover_counter.wrapping_add(1)
|
||||||
} else {
|
} else {
|
||||||
rollover_counter
|
*rollover_counter
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(U48::from(probable_roc) << 16) + U48::from(seq_num)
|
(U48::from(probable_roc) << 16) + U48::from(seq_num)
|
||||||
|
@ -158,20 +166,33 @@ impl Protocol for Srtp {
|
||||||
const AUTH_KEY_LABEL: u8 = 1;
|
const AUTH_KEY_LABEL: u8 = 1;
|
||||||
const SALT_KEY_LABEL: u8 = 2;
|
const SALT_KEY_LABEL: u8 = 2;
|
||||||
|
|
||||||
|
fn read_ssrc(packet: &[u8]) -> Result<Ssrc> {
|
||||||
|
let reader = &mut &packet[..];
|
||||||
|
let header = track_try!(rfc3550::RtpFixedHeader::read_from(reader));
|
||||||
|
Ok(header.ssrc)
|
||||||
|
}
|
||||||
|
|
||||||
fn determine_incoming_packet_index(
|
fn determine_incoming_packet_index(
|
||||||
context: &Context<Self>,
|
_context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex> {
|
) -> Result<Self::PacketIndex> {
|
||||||
let seq_num = track_try!(Srtp::parse_seq_num(packet));
|
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(
|
fn determine_outgoing_packet_index(
|
||||||
context: &Context<Self>,
|
context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex> {
|
) -> Result<Self::PacketIndex> {
|
||||||
let seq_num = track_try!(Srtp::parse_seq_num(packet));
|
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>(
|
fn get_authenticated_bytes<'a>(
|
||||||
|
@ -188,6 +209,7 @@ impl Protocol for Srtp {
|
||||||
|
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
index: Self::PacketIndex,
|
index: Self::PacketIndex,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
|
@ -198,12 +220,13 @@ impl Protocol for Srtp {
|
||||||
|
|
||||||
let mut decrypted: Vec<u8> = Vec::new();
|
let mut decrypted: Vec<u8> = Vec::new();
|
||||||
track_try!(header.write_to(&mut decrypted));
|
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)
|
Ok(decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encrypt(
|
fn encrypt(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
index: Self::PacketIndex,
|
index: Self::PacketIndex,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
|
@ -214,11 +237,11 @@ impl Protocol for Srtp {
|
||||||
|
|
||||||
let mut encrypted: Vec<u8> = Vec::new();
|
let mut encrypted: Vec<u8> = Vec::new();
|
||||||
track_try!(header.write_to(&mut encrypted));
|
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)
|
Ok(encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_highest_recv_index(context: &mut Context<Self>, index: Self::PacketIndex) {
|
fn update_highest_recv_index(context: &mut SsrcContext<Self>, index: Self::PacketIndex) {
|
||||||
// https://tools.ietf.org/html/rfc3711#section-3.3.1
|
// https://tools.ietf.org/html/rfc3711#section-3.3.1
|
||||||
let state = &mut context.protocol_specific;
|
let state = &mut context.protocol_specific;
|
||||||
let rollover_counter = (index >> 16) as u32;
|
let rollover_counter = (index >> 16) as u32;
|
||||||
|
@ -233,7 +256,7 @@ impl Protocol for Srtp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_highest_sent_index(context: &mut Context<Self>, index: Self::PacketIndex) {
|
fn update_highest_sent_index(context: &mut SsrcContext<Self>, index: Self::PacketIndex) {
|
||||||
// Unless we assume that packets are properly ordered when sent,
|
// 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.
|
// we have to use the same algorithm to update the ROC as when receiving them.
|
||||||
Self::update_highest_recv_index(context, index);
|
Self::update_highest_recv_index(context, index);
|
||||||
|
@ -246,8 +269,15 @@ impl Protocol for Srtcp {
|
||||||
const AUTH_KEY_LABEL: u8 = 4;
|
const AUTH_KEY_LABEL: u8 = 4;
|
||||||
const SALT_KEY_LABEL: u8 = 5;
|
const SALT_KEY_LABEL: u8 = 5;
|
||||||
|
|
||||||
|
fn read_ssrc(packet: &[u8]) -> Result<Ssrc> {
|
||||||
|
let reader = &mut &packet[..];
|
||||||
|
track_try!(reader.read_u32be());
|
||||||
|
track_err!(reader.read_u32be())
|
||||||
|
}
|
||||||
|
|
||||||
fn determine_incoming_packet_index(
|
fn determine_incoming_packet_index(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
_ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex> {
|
) -> Result<Self::PacketIndex> {
|
||||||
let reader = &mut &packet[packet.len() - context.auth_tag_len - 4..];
|
let reader = &mut &packet[packet.len() - context.auth_tag_len - 4..];
|
||||||
|
@ -256,7 +286,7 @@ impl Protocol for Srtcp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_outgoing_packet_index(
|
fn determine_outgoing_packet_index(
|
||||||
context: &Context<Self>,
|
context: &SsrcContext<Self>,
|
||||||
_packet: &[u8],
|
_packet: &[u8],
|
||||||
) -> Result<Self::PacketIndex> {
|
) -> Result<Self::PacketIndex> {
|
||||||
const MODULO: u32 = 1 << 31;
|
const MODULO: u32 = 1 << 31;
|
||||||
|
@ -274,6 +304,7 @@ impl Protocol for Srtcp {
|
||||||
|
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
index: Self::PacketIndex,
|
index: Self::PacketIndex,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
|
@ -291,12 +322,13 @@ impl Protocol for Srtcp {
|
||||||
let encrypted_portion = &reader[0..reader.len() - context.auth_tag_len - 4];
|
let encrypted_portion = &reader[0..reader.len() - context.auth_tag_len - 4];
|
||||||
|
|
||||||
let mut decrypted = Vec::from(&packet[..8]);
|
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)
|
Ok(decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encrypt(
|
fn encrypt(
|
||||||
context: &Context<Self>,
|
context: &Context<Self>,
|
||||||
|
ssrc_context: &SsrcContext<Self>,
|
||||||
packet: &[u8],
|
packet: &[u8],
|
||||||
index: Self::PacketIndex,
|
index: Self::PacketIndex,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
|
@ -306,17 +338,17 @@ impl Protocol for Srtcp {
|
||||||
let plaintext_portion = &reader[0..];
|
let plaintext_portion = &reader[0..];
|
||||||
|
|
||||||
let mut encrypted = Vec::from(&packet[..8]);
|
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
|
let index_with_e_bit = index | 0x8000_0000; // "encrypted"-bit
|
||||||
track_try!(encrypted.write_u32be(index_with_e_bit));
|
track_try!(encrypted.write_u32be(index_with_e_bit));
|
||||||
Ok(encrypted)
|
Ok(encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_highest_recv_index(_context: &mut Context<Self>, _index: Self::PacketIndex) {
|
fn update_highest_recv_index(_context: &mut SsrcContext<Self>, _index: Self::PacketIndex) {
|
||||||
// full packet inex is part of SRTCP packets, no need to keep track of it
|
// full packet inex is part of SRTCP packets, no need to keep track of it
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_highest_sent_index(context: &mut Context<Self>, index: Self::PacketIndex) {
|
fn update_highest_sent_index(context: &mut SsrcContext<Self>, index: Self::PacketIndex) {
|
||||||
// we're giving out indices in strictly ascending order in determine_outgoing_packet_index
|
// we're giving out indices in strictly ascending order in determine_outgoing_packet_index
|
||||||
context.protocol_specific.highest_sent_index = index;
|
context.protocol_specific.highest_sent_index = index;
|
||||||
}
|
}
|
||||||
|
@ -326,23 +358,35 @@ impl<P: Protocol> Context<P>
|
||||||
where
|
where
|
||||||
u64: From<P::PacketIndex>,
|
u64: From<P::PacketIndex>,
|
||||||
{
|
{
|
||||||
pub fn new(master_key: &[u8], master_salt: &[u8], protocol_specific: P) -> Self {
|
pub fn new(master_key: &[u8], master_salt: &[u8]) -> Self {
|
||||||
Context {
|
Context {
|
||||||
master_key: Vec::from(master_key),
|
master_key: Vec::from(master_key),
|
||||||
master_salt: Vec::from(master_salt),
|
master_salt: Vec::from(master_salt),
|
||||||
key_derivation_rate: 0,
|
key_derivation_rate: 0,
|
||||||
encryption: EncryptionAlgorithm::default(),
|
encryption: EncryptionAlgorithm::default(),
|
||||||
authentication: AuthenticationAlgorithm::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_head: 0,
|
||||||
replay_window: FixedBitSet::with_capacity(128),
|
replay_window: FixedBitSet::with_capacity(128),
|
||||||
session_encr_key: vec![0; 128 / 8],
|
session_encr_key: vec![0; 128 / 8],
|
||||||
session_salt_key: vec![0; 112 / 8],
|
session_salt_key: vec![0; 112 / 8],
|
||||||
session_auth_key: vec![0; 160 / 8],
|
session_auth_key: vec![0; 160 / 8],
|
||||||
auth_tag_len: 80 / 8,
|
protocol_specific: P::default(),
|
||||||
protocol_specific,
|
};
|
||||||
|
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 {
|
let index = if self.key_derivation_rate == 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
@ -362,57 +406,72 @@ where
|
||||||
BigUint::from_bytes_be(&[P::SALT_KEY_LABEL, 0, 0, 0, 0, 0, 0]) + index.clone();
|
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);
|
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,
|
&self.master_key,
|
||||||
enc_key_id ^ master_salt.clone(),
|
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,
|
&self.master_key,
|
||||||
auth_key_id ^ master_salt.clone(),
|
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,
|
&self.master_key,
|
||||||
salt_key_id ^ master_salt.clone(),
|
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<P>,
|
||||||
|
packet: &[u8],
|
||||||
|
index: P::PacketIndex,
|
||||||
|
) -> Result<()> {
|
||||||
let auth_portion = &packet[..packet.len() - self.auth_tag_len];
|
let auth_portion = &packet[..packet.len() - self.auth_tag_len];
|
||||||
let auth_tag = &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 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);
|
expected_tag.truncate(self.auth_tag_len);
|
||||||
track_assert_eq!(auth_tag, &expected_tag[..], ErrorKind::Invalid);
|
track_assert_eq!(auth_tag, &expected_tag[..], ErrorKind::Invalid);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_auth_tag(&self, packet: &[u8], index: P::PacketIndex) -> Result<Vec<u8>> {
|
pub fn generate_auth_tag(
|
||||||
|
&self,
|
||||||
|
context: &SsrcContext<P>,
|
||||||
|
packet: &[u8],
|
||||||
|
index: P::PacketIndex,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
let auth_bytes = track_try!(P::get_authenticated_bytes(self, index, packet));
|
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);
|
tag.truncate(self.auth_tag_len);
|
||||||
Ok(tag)
|
Ok(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_portion(
|
pub fn decrypt_portion(
|
||||||
&self,
|
&self,
|
||||||
|
context: &SsrcContext<P>,
|
||||||
encrypted: &[u8],
|
encrypted: &[u8],
|
||||||
decrypted: &mut Vec<u8>,
|
decrypted: &mut Vec<u8>,
|
||||||
ssrc: u32,
|
ssrc: u32,
|
||||||
index: P::PacketIndex,
|
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 ^ (BigUint::from(ssrc) << 64);
|
||||||
let iv = iv ^ (index.into() << 16);
|
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 =
|
let mut ctr = crypto::aes::ctr(
|
||||||
crypto::aes::ctr(crypto::aes::KeySize::KeySize128, &self.session_encr_key, iv);
|
crypto::aes::KeySize::KeySize128,
|
||||||
let block_size = self.session_encr_key.len();
|
&context.session_encr_key,
|
||||||
|
iv,
|
||||||
|
);
|
||||||
|
let block_size = context.session_encr_key.len();
|
||||||
|
|
||||||
for block in encrypted.chunks(block_size) {
|
for block in encrypted.chunks(block_size) {
|
||||||
let old_len = decrypted.len();
|
let old_len = decrypted.len();
|
||||||
|
@ -420,25 +479,34 @@ where
|
||||||
ctr.process(block, &mut decrypted[old_len..]);
|
ctr.process(block, &mut decrypted[old_len..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn decrypt(&mut self, packet: &[u8], index: P::PacketIndex) -> Result<Vec<u8>> {
|
pub fn decrypt(
|
||||||
P::decrypt(self, packet, index)
|
&self,
|
||||||
|
context: &SsrcContext<P>,
|
||||||
|
packet: &[u8],
|
||||||
|
index: P::PacketIndex,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
P::decrypt(self, context, packet, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt_portion(
|
pub fn encrypt_portion(
|
||||||
&self,
|
&self,
|
||||||
|
context: &SsrcContext<P>,
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
encrypted: &mut Vec<u8>,
|
encrypted: &mut Vec<u8>,
|
||||||
ssrc: u32,
|
ssrc: u32,
|
||||||
index: P::PacketIndex,
|
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 ^ (BigUint::from(ssrc) << 64);
|
||||||
let iv = iv ^ (index.into() << 16);
|
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 =
|
let mut ctr = crypto::aes::ctr(
|
||||||
crypto::aes::ctr(crypto::aes::KeySize::KeySize128, &self.session_encr_key, iv);
|
crypto::aes::KeySize::KeySize128,
|
||||||
let block_size = self.session_encr_key.len();
|
&context.session_encr_key,
|
||||||
|
iv,
|
||||||
|
);
|
||||||
|
let block_size = context.session_encr_key.len();
|
||||||
|
|
||||||
for block in plaintext.chunks(block_size) {
|
for block in plaintext.chunks(block_size) {
|
||||||
let old_len = encrypted.len();
|
let old_len = encrypted.len();
|
||||||
|
@ -446,61 +514,83 @@ where
|
||||||
ctr.process(block, &mut encrypted[old_len..]);
|
ctr.process(block, &mut encrypted[old_len..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn encrypt(&mut self, packet: &[u8], index: P::PacketIndex) -> Result<Vec<u8>> {
|
pub fn encrypt(
|
||||||
P::encrypt(self, packet, index)
|
&self,
|
||||||
|
context: &SsrcContext<P>,
|
||||||
|
packet: &[u8],
|
||||||
|
index: P::PacketIndex,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
P::encrypt(self, context, packet, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc3711#section-3.3
|
// https://tools.ietf.org/html/rfc3711#section-3.3
|
||||||
// https://tools.ietf.org/html/rfc3711#section-3.4
|
// https://tools.ietf.org/html/rfc3711#section-3.4
|
||||||
pub fn process_incoming(&mut self, packet: &[u8]) -> Result<Vec<u8>> {
|
pub fn process_incoming(&mut self, packet: &[u8]) -> Result<Vec<u8>> {
|
||||||
// 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
|
// 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
|
// Step 3: Determine master key and salt
|
||||||
// TODO: support re-keying
|
// TODO: support re-keying
|
||||||
// TODO: support MKI
|
// TODO: support MKI
|
||||||
|
|
||||||
// Step 4: Determine session keys and salt
|
// Step 4: Determine session keys and salt
|
||||||
self.update_session_keys(index);
|
self.update_session_keys(ssrc, index);
|
||||||
|
|
||||||
|
let idx = u64::from(index);
|
||||||
|
let (result, window_size) = {
|
||||||
|
let ssrc_context = self.ssrc_context.get(&ssrc).unwrap();
|
||||||
|
|
||||||
// Step 5: Replay protection and authentication
|
// Step 5: Replay protection and authentication
|
||||||
let idx = u64::from(index);
|
let window_size = ssrc_context.replay_window.len() as u64;
|
||||||
let window_size = self.replay_window.len() as u64;
|
if idx <= ssrc_context.replay_window_head {
|
||||||
if idx <= self.replay_window_head {
|
|
||||||
track_assert!(
|
track_assert!(
|
||||||
idx + window_size > self.replay_window_head,
|
idx + window_size > ssrc_context.replay_window_head,
|
||||||
ErrorKind::Invalid
|
ErrorKind::Invalid
|
||||||
);
|
);
|
||||||
track_assert!(
|
track_assert!(
|
||||||
!self.replay_window[(idx % window_size) as usize],
|
!ssrc_context.replay_window[(idx % window_size) as usize],
|
||||||
ErrorKind::Invalid
|
ErrorKind::Invalid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
track_try!(self.authenticate(packet, index));
|
track_try!(self.authenticate(ssrc_context, packet, index));
|
||||||
|
|
||||||
// Step 6: Decryption
|
// Step 6: Decryption
|
||||||
let result = track_try!(self.decrypt(packet, index));
|
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
|
// Step 7: Update ROC, highest sequence number and replay protection
|
||||||
if idx > self.replay_window_head {
|
if idx > ssrc_context.replay_window_head {
|
||||||
if idx - self.replay_window_head >= window_size {
|
if idx - ssrc_context.replay_window_head >= window_size {
|
||||||
self.replay_window.clear()
|
ssrc_context.replay_window.clear()
|
||||||
} else {
|
} else {
|
||||||
let start = ((self.replay_window_head + 1) % window_size) as usize;
|
let start = ((ssrc_context.replay_window_head + 1) % window_size) as usize;
|
||||||
let end = (idx % window_size) as usize;
|
let end = (idx % window_size) as usize;
|
||||||
if start > end {
|
if start > end {
|
||||||
self.replay_window.set_range(start.., false);
|
ssrc_context.replay_window.set_range(start.., false);
|
||||||
self.replay_window.set_range(..end, false);
|
ssrc_context.replay_window.set_range(..end, false);
|
||||||
} else {
|
} else {
|
||||||
self.replay_window.set_range(start..end, false);
|
ssrc_context.replay_window.set_range(start..end, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.replay_window_head = idx;
|
ssrc_context.replay_window_head = idx;
|
||||||
}
|
}
|
||||||
self.replay_window.insert((idx % window_size) as usize);
|
ssrc_context
|
||||||
P::update_highest_recv_index(self, index);
|
.replay_window
|
||||||
|
.insert((idx % window_size) as usize);
|
||||||
|
P::update_highest_recv_index(ssrc_context, index);
|
||||||
|
};
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
@ -508,30 +598,40 @@ where
|
||||||
// https://tools.ietf.org/html/rfc3711#section-3.3
|
// https://tools.ietf.org/html/rfc3711#section-3.3
|
||||||
// https://tools.ietf.org/html/rfc3711#section-3.4
|
// https://tools.ietf.org/html/rfc3711#section-3.4
|
||||||
pub fn process_outgoing(&mut self, packet: &[u8]) -> Result<Vec<u8>> {
|
pub fn process_outgoing(&mut self, packet: &[u8]) -> Result<Vec<u8>> {
|
||||||
// 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
|
// 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
|
// Step 3: Determine master key and salt
|
||||||
// TODO: support re-keying
|
// TODO: support re-keying
|
||||||
// TODO: support MKI
|
// TODO: support MKI
|
||||||
|
|
||||||
// Step 4: Determine session keys and salt
|
// Step 4: Determine session keys and salt
|
||||||
self.update_session_keys(index);
|
self.update_session_keys(ssrc, index);
|
||||||
|
|
||||||
// Step 5: Encryption
|
// 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
|
// Step 6: Append MKI if MKI indicator is set
|
||||||
// TODO: support MKI
|
// TODO: support MKI
|
||||||
|
|
||||||
// Step 7: Signing
|
// 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);
|
result.extend(auth_tag);
|
||||||
|
|
||||||
// Step 7: Update ROC and highest sequence number
|
// 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)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
@ -706,20 +806,20 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtp_packet_index_estimation_works() {
|
fn rtp_packet_index_estimation_works() {
|
||||||
let mut context = Context::new_srtp(&[], &[]);
|
let mut context = Srtp::default();
|
||||||
let roc = 0u32;
|
let roc = 0u32;
|
||||||
let roc_n1 = roc.wrapping_sub(1);
|
let roc_n1 = roc.wrapping_sub(1);
|
||||||
let roc_p1 = roc.wrapping_add(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 i = |roc, seq_num| ((roc as u64) << 16) + seq_num as u64;
|
||||||
let estimate = |ctx: &Context<Srtp>, 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, 1), i(roc, 1)); // lower but same roc
|
||||||
assert_eq!(estimate(&context, 10001), i(roc, 10001)); // higher 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
|
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, 60001), i(roc, 60001)); // higher but same roc
|
||||||
assert_eq!(estimate(&context, 30001), i(roc, 30001)); // lower 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
|
assert_eq!(estimate(&context, 10001), i(roc_p1, 10001)); // roc+1
|
||||||
|
@ -731,6 +831,7 @@ mod test {
|
||||||
const TEST_MASTER_SALT: &[u8] = &[
|
const TEST_MASTER_SALT: &[u8] = &[
|
||||||
127, 31, 227, 93, 120, 247, 126, 117, 231, 159, 123, 235, 95, 122,
|
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] = &[
|
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,
|
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,
|
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,
|
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,
|
146, 94, 74, 156, 171, 245, 239, 220, 205, 145, 206,
|
||||||
];
|
];
|
||||||
|
const TEST_SRTCP_SSRC: Ssrc = 3270675037;
|
||||||
const TEST_SRTCP_PACKET: &[u8] = &[
|
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,
|
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,
|
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,
|
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_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] = &[
|
const TEST_2_SRTP_PACKET_BEFORE_ROLLOVER: &[u8] = &[
|
||||||
0x80, 0x61, 0xff, 0xff, 0x87, 0xf5, 0xee, 0x93, 0x0a, 0xc3, 0xc2, 0xbd, 0x93, 0x04, 0x0b,
|
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,
|
0x4d, 0xe9, 0x55, 0x69, 0xb7, 0xac, 0x88, 0xc5, 0xd6, 0xc2, 0x75, 0xb8, 0x15, 0x86, 0xc3,
|
||||||
|
@ -776,7 +879,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtp_decryption_works() {
|
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 mut rtp_reader = SrtpPacketReader::new(context, rfc3550::RtpPacketReader);
|
||||||
let packet = rtp_reader.read_packet(&mut TEST_SRTP_PACKET).unwrap();
|
let packet = rtp_reader.read_packet(&mut TEST_SRTP_PACKET).unwrap();
|
||||||
|
|
||||||
|
@ -794,8 +898,14 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtp_decryption_with_rollover_works() {
|
fn rtp_decryption_with_rollover_works() {
|
||||||
let mut context = Context::new_srtp(&TEST_2_MASTER_KEY, &TEST_2_MASTER_SALT);
|
let mut context = Context::<Srtp>::new(&TEST_2_MASTER_KEY, &TEST_2_MASTER_SALT);
|
||||||
context.protocol_specific.highest_seq_num = 65534;
|
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);
|
let mut rtp_reader = SrtpPacketReader::new(context, rfc3550::RtpPacketReader);
|
||||||
rtp_reader
|
rtp_reader
|
||||||
.read_packet(&mut TEST_2_SRTP_PACKET_BEFORE_ROLLOVER)
|
.read_packet(&mut TEST_2_SRTP_PACKET_BEFORE_ROLLOVER)
|
||||||
|
@ -821,7 +931,8 @@ mod test {
|
||||||
236, 161, 194, 6, 232, 194, 230,
|
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 mut rtcp_reader = SrtcpPacketReader::new(context, rfc4585::RtcpPacketReader);
|
||||||
let packet = track_try_unwrap!(rtcp_reader.read_packet(&mut &packet[..]));
|
let packet = track_try_unwrap!(rtcp_reader.read_packet(&mut &packet[..]));
|
||||||
println!("# {:?}", packet);
|
println!("# {:?}", packet);
|
||||||
|
@ -829,8 +940,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtp_decryption_encryption_are_inverse() {
|
fn rtp_decryption_encryption_are_inverse() {
|
||||||
let mut dec_context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut dec_context = Context::<Srtp>::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
||||||
let mut enc_context = Context::new_srtp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut enc_context = Context::<Srtp>::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 decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTP_PACKET));
|
||||||
let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
||||||
assert_eq!(&encrypted[..], TEST_SRTP_PACKET);
|
assert_eq!(&encrypted[..], TEST_SRTP_PACKET);
|
||||||
|
@ -838,8 +951,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtcp_decryption_encryption_are_inverse() {
|
fn rtcp_decryption_encryption_are_inverse() {
|
||||||
let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut dec_context = Context::<Srtcp>::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
||||||
let mut enc_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut enc_context = Context::<Srtcp>::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 decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTCP_PACKET));
|
||||||
let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
let encrypted = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
||||||
assert_eq!(&encrypted[..], TEST_SRTCP_PACKET);
|
assert_eq!(&encrypted[..], TEST_SRTCP_PACKET);
|
||||||
|
@ -847,8 +962,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rtcp_encryption_does_not_use_two_time_pad() {
|
fn rtcp_encryption_does_not_use_two_time_pad() {
|
||||||
let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut dec_context = Context::<Srtcp>::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
||||||
let mut enc_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut enc_context = Context::<Srtcp>::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 decrypted = track_try_unwrap!(dec_context.process_incoming(TEST_SRTCP_PACKET));
|
||||||
let encrypted_1 = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
let encrypted_1 = track_try_unwrap!(enc_context.process_outgoing(&decrypted));
|
||||||
let encrypted_2 = 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]
|
#[test]
|
||||||
fn rtp_does_not_allow_packet_replay() {
|
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::<Srtp>::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_ok());
|
||||||
assert!(dec_context.process_incoming(TEST_SRTP_PACKET).is_err());
|
assert!(dec_context.process_incoming(TEST_SRTP_PACKET).is_err());
|
||||||
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]
|
#[test]
|
||||||
fn rtcp_does_not_allow_packet_replay() {
|
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::<Srtcp>::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_ok());
|
||||||
assert!(dec_context.process_incoming(TEST_SRTCP_PACKET).is_err());
|
assert!(dec_context.process_incoming(TEST_SRTCP_PACKET).is_err());
|
||||||
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]
|
#[test]
|
||||||
fn rtcp_does_not_allow_delayed_packet_replay() {
|
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::<Srtcp>::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 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::<Srtcp>::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
||||||
|
enc_context.add_ssrc(TEST_SRTCP_SSRC);
|
||||||
const N: usize = 10;
|
const N: usize = 10;
|
||||||
let encs: Vec<_> = (0..N)
|
let encs: Vec<_> = (0..N)
|
||||||
.map(|_| enc_context.process_outgoing(&decrypted).unwrap())
|
.map(|_| enc_context.process_outgoing(&decrypted).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut dec_context = Context::new_srtcp(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
let mut dec_context = Context::<Srtcp>::new(&TEST_MASTER_KEY, &TEST_MASTER_SALT);
|
||||||
dec_context.replay_window = FixedBitSet::with_capacity(4);
|
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[0]).is_ok());
|
||||||
assert!(dec_context.process_incoming(&encs[1]).is_ok());
|
assert!(dec_context.process_incoming(&encs[1]).is_ok());
|
||||||
|
|
Loading…
Reference in New Issue