1 use super::*; 2 use crate::key_derivation::*; 3 4 use bytes::{Buf, Bytes, BytesMut}; 5 use lazy_static::lazy_static; 6 7 pub struct RTCPTestCase { 8 ssrc: u32, 9 index: usize, 10 encrypted: Bytes, 11 decrypted: Bytes, 12 } 13 14 lazy_static! { 15 static ref RTCP_TEST_MASTER_KEY: Bytes = Bytes::from_static(&[ 16 0xfd, 0xa6, 0x25, 0x95, 0xd7, 0xf6, 0x92, 0x6f, 0x7d, 0x9c, 0x02, 0x4c, 0xc9, 0x20, 0x9f, 17 0x34 18 ]); 19 20 static ref RTCP_TEST_MASTER_SALT: Bytes = Bytes::from_static(&[ 21 0xa9, 0x65, 0x19, 0x85, 0x54, 0x0b, 0x47, 0xbe, 0x2f, 0x27, 0xa8, 0xb8, 0x81, 0x23 22 ]); 23 24 static ref RTCP_TEST_CASES: Vec<RTCPTestCase> = vec![ 25 RTCPTestCase { 26 ssrc: 0x66ef91ff, 27 index: 0, 28 encrypted: Bytes::from_static(&[ 29 0x80, 0xc8, 0x00, 0x06, 0x66, 0xef, 0x91, 0xff, 0xcd, 0x34, 0xc5, 0x78, 0xb2, 0x8b, 30 0xe1, 0x6b, 0xc5, 0x09, 0xd5, 0x77, 0xe4, 0xce, 0x5f, 0x20, 0x80, 0x21, 0xbd, 0x66, 31 0x74, 0x65, 0xe9, 0x5f, 0x49, 0xe5, 0xf5, 0xc0, 0x68, 0x4e, 0xe5, 0x6a, 0x78, 0x07, 32 0x75, 0x46, 0xed, 0x90, 0xf6, 0xdc, 0x9d, 0xef, 0x3b, 0xdf, 0xf2, 0x79, 0xa9, 0xd8, 33 0x80, 0x00, 0x00, 0x01, 0x60, 0xc0, 0xae, 0xb5, 0x6f, 0x40, 0x88, 0x0e, 0x28, 0xba 34 ]), 35 decrypted: Bytes::from_static(&[ 36 0x80, 0xc8, 0x00, 0x06, 0x66, 0xef, 0x91, 0xff, 0xdf, 0x48, 0x80, 0xdd, 0x61, 0xa6, 37 0x2e, 0xd3, 0xd8, 0xbc, 0xde, 0xbe, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x16, 0x04, 38 0x81, 0xca, 0x00, 0x06, 0x66, 0xef, 0x91, 0xff, 0x01, 0x10, 0x52, 0x6e, 0x54, 0x35, 39 0x43, 0x6d, 0x4a, 0x68, 0x7a, 0x79, 0x65, 0x74, 0x41, 0x78, 0x77, 0x2b, 0x00, 0x00 40 ]), 41 }, 42 RTCPTestCase{ 43 ssrc: 0x11111111, 44 index: 0, 45 encrypted: Bytes::from_static(&[ 46 0x80, 0xc8, 0x00, 0x06, 0x11, 0x11, 0x11, 0x11, 0x17, 0x8c, 0x15, 0xf1, 0x4b, 0x11, 47 0xda, 0xf5, 0x74, 0x53, 0x86, 0x2b, 0xc9, 0x07, 0x29, 0x40, 0xbf, 0x22, 0xf6, 0x46, 48 0x11, 0xa4, 0xc1, 0x3a, 0xff, 0x5a, 0xbd, 0xd0, 0xf8, 0x8b, 0x38, 0xe4, 0x95, 0x38, 49 0x5d, 0xcf, 0x1b, 0xf5, 0x27, 0x77, 0xfb, 0xdb, 0x3f, 0x10, 0x68, 0x99, 0xd8, 0xad, 50 0x80, 0x00, 0x00, 0x01, 0x34, 0x3c, 0x2e, 0x83, 0x17, 0x13, 0x93, 0x69, 0xcf, 0xc0 51 ]), 52 decrypted: Bytes::from_static(&[ 53 0x80, 0xc8, 0x00, 0x06, 0x11, 0x11, 0x11, 0x11, 0xdf, 0x48, 0x80, 0xdd, 0x61, 0xa6, 54 0x2e, 0xd3, 0xd8, 0xbc, 0xde, 0xbe, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x16, 0x04, 55 0x81, 0xca, 0x00, 0x06, 0x66, 0xef, 0x91, 0xff, 0x01, 0x10, 0x52, 0x6e, 0x54, 0x35, 56 0x43, 0x6d, 0x4a, 0x68, 0x7a, 0x79, 0x65, 0x74, 0x41, 0x78, 0x77, 0x2b, 0x00, 0x00 57 ]), 58 }, 59 RTCPTestCase{ 60 ssrc: 0x11111111, 61 index: 0x7ffffffe, // Upper boundary of index 62 encrypted: Bytes::from_static(&[ 63 0x80, 0xc8, 0x00, 0x06, 0x11, 0x11, 0x11, 0x11, 0x17, 0x8c, 0x15, 0xf1, 0x4b, 0x11, 64 0xda, 0xf5, 0x74, 0x53, 0x86, 0x2b, 0xc9, 0x07, 0x29, 0x40, 0xbf, 0x22, 0xf6, 0x46, 65 0x11, 0xa4, 0xc1, 0x3a, 0xff, 0x5a, 0xbd, 0xd0, 0xf8, 0x8b, 0x38, 0xe4, 0x95, 0x38, 66 0x5d, 0xcf, 0x1b, 0xf5, 0x27, 0x77, 0xfb, 0xdb, 0x3f, 0x10, 0x68, 0x99, 0xd8, 0xad, 67 0xff, 0xff, 0xff, 0xff, 0x5a, 0x99, 0xce, 0xed, 0x9f, 0x2e, 0x4d, 0x9d, 0xfa, 0x97 68 ]), 69 decrypted: Bytes::from_static(&[ 70 0x80, 0xc8, 0x0, 0x6, 0x11, 0x11, 0x11, 0x11, 0x4, 0x99, 0x47, 0x53, 0xc4, 0x1e, 71 0xb9, 0xde, 0x52, 0xa3, 0x1d, 0x77, 0x2f, 0xff, 0xcc, 0x75, 0xbb, 0x6a, 0x29, 0xb8, 72 0x1, 0xb7, 0x2e, 0x4b, 0x4e, 0xcb, 0xa4, 0x81, 0x2d, 0x46, 0x4, 0x5e, 0x86, 0x90, 73 0x17, 0x4f, 0x4d, 0x78, 0x2f, 0x58, 0xb8, 0x67, 0x91, 0x89, 0xe3, 0x61, 0x1, 0x7d 74 ]), 75 }, 76 RTCPTestCase{ 77 ssrc: 0x11111111, 78 index: 0x7fffffff, // Will be wrapped to 0 79 encrypted: Bytes::from_static(&[ 80 0x80, 0xc8, 0x00, 0x06, 0x11, 0x11, 0x11, 0x11, 0x17, 0x8c, 0x15, 0xf1, 0x4b, 0x11, 81 0xda, 0xf5, 0x74, 0x53, 0x86, 0x2b, 0xc9, 0x07, 0x29, 0x40, 0xbf, 0x22, 0xf6, 0x46, 82 0x11, 0xa4, 0xc1, 0x3a, 0xff, 0x5a, 0xbd, 0xd0, 0xf8, 0x8b, 0x38, 0xe4, 0x95, 0x38, 83 0x5d, 0xcf, 0x1b, 0xf5, 0x27, 0x77, 0xfb, 0xdb, 0x3f, 0x10, 0x68, 0x99, 0xd8, 0xad, 84 0x80, 0x00, 0x00, 0x00, 0x7d, 0x51, 0xf8, 0x0e, 0x56, 0x40, 0x72, 0x7b, 0x9e, 0x02 85 ]), 86 decrypted: Bytes::from_static(&[ 87 0x80, 0xc8, 0x0, 0x6, 0x11, 0x11, 0x11, 0x11, 0xda, 0xb5, 0xe0, 0x56, 0x9a, 0x4a, 88 0x74, 0xed, 0x8a, 0x54, 0xc, 0xcf, 0xd5, 0x9, 0xb1, 0x40, 0x1, 0x42, 0xc3, 0x9a, 89 0x76, 0x0, 0xa9, 0xd4, 0xf7, 0x29, 0x9e, 0x51, 0xfb, 0x3c, 0xc1, 0x74, 0x72, 0xf9, 90 0x52, 0xb1, 0x92, 0x31, 0xca, 0x22, 0xab, 0x3e, 0xc5, 0x5f, 0x83, 0x34, 0xf0, 0x28 91 ]), 92 }, 93 ]; 94 } 95 96 #[test] 97 fn test_rtcp_lifecycle() -> Result<()> { 98 let mut encrypt_context = Context::new( 99 &RTCP_TEST_MASTER_KEY, 100 &RTCP_TEST_MASTER_SALT, 101 ProtectionProfile::Aes128CmHmacSha1_80, 102 None, 103 None, 104 )?; 105 let mut decrypt_context = Context::new( 106 &RTCP_TEST_MASTER_KEY, 107 &RTCP_TEST_MASTER_SALT, 108 ProtectionProfile::Aes128CmHmacSha1_80, 109 None, 110 None, 111 )?; 112 113 for test_case in &*RTCP_TEST_CASES { 114 let decrypt_result = decrypt_context.decrypt_rtcp(&test_case.encrypted)?; 115 assert_eq!( 116 decrypt_result, test_case.decrypted, 117 "RTCP failed to decrypt" 118 ); 119 120 encrypt_context.set_index(test_case.ssrc, test_case.index); 121 let encrypt_result = encrypt_context.encrypt_rtcp(&test_case.decrypted)?; 122 assert_eq!( 123 encrypt_result, test_case.encrypted, 124 "RTCP failed to encrypt" 125 ); 126 } 127 128 Ok(()) 129 } 130 131 #[test] 132 fn test_rtcp_invalid_auth_tag() -> Result<()> { 133 let auth_tag_len = ProtectionProfile::Aes128CmHmacSha1_80.auth_tag_len(); 134 135 let mut decrypt_context = Context::new( 136 &RTCP_TEST_MASTER_KEY, 137 &RTCP_TEST_MASTER_SALT, 138 ProtectionProfile::Aes128CmHmacSha1_80, 139 None, 140 None, 141 )?; 142 143 let decrypt_result = decrypt_context.decrypt_rtcp(&RTCP_TEST_CASES[0].encrypted)?; 144 assert_eq!( 145 decrypt_result, RTCP_TEST_CASES[0].decrypted, 146 "RTCP failed to decrypt" 147 ); 148 149 // Zero out auth tag 150 let mut rtcp_packet = BytesMut::new(); 151 rtcp_packet.extend_from_slice(&RTCP_TEST_CASES[0].encrypted); 152 let rtcp_packet_len = rtcp_packet.len(); 153 rtcp_packet[rtcp_packet_len - auth_tag_len..].copy_from_slice(&vec![0; auth_tag_len]); 154 let rtcp_packet = rtcp_packet.freeze(); 155 let decrypt_result = decrypt_context.decrypt_rtcp(&rtcp_packet); 156 assert!( 157 decrypt_result.is_err(), 158 "Was able to decrypt RTCP packet with invalid Auth Tag" 159 ); 160 161 Ok(()) 162 } 163 164 #[test] 165 fn test_rtcp_replay_detector_separation() -> Result<()> { 166 let mut decrypt_context = Context::new( 167 &RTCP_TEST_MASTER_KEY, 168 &RTCP_TEST_MASTER_SALT, 169 ProtectionProfile::Aes128CmHmacSha1_80, 170 None, 171 Some(srtcp_replay_protection(10)), 172 )?; 173 174 let rtcp_packet1 = RTCP_TEST_CASES[0].encrypted.clone(); 175 let decrypt_result1 = decrypt_context.decrypt_rtcp(&rtcp_packet1)?; 176 assert_eq!( 177 decrypt_result1, RTCP_TEST_CASES[0].decrypted, 178 "RTCP failed to decrypt" 179 ); 180 181 let rtcp_packet2 = RTCP_TEST_CASES[1].encrypted.clone(); 182 let decrypt_result2 = decrypt_context.decrypt_rtcp(&rtcp_packet2)?; 183 assert_eq!( 184 decrypt_result2, RTCP_TEST_CASES[1].decrypted, 185 "RTCP failed to decrypt" 186 ); 187 188 let result = decrypt_context.decrypt_rtcp(&rtcp_packet1); 189 assert!( 190 result.is_err(), 191 "Was able to decrypt duplicated RTCP packet" 192 ); 193 194 let result = decrypt_context.decrypt_rtcp(&rtcp_packet2); 195 assert!( 196 result.is_err(), 197 "Was able to decrypt duplicated RTCP packet" 198 ); 199 200 Ok(()) 201 } 202 203 fn get_rtcp_index(encrypted: &Bytes, auth_tag_len: usize) -> u32 { 204 let tail_offset = encrypted.len() - (auth_tag_len + SRTCP_INDEX_SIZE); 205 let reader = &mut encrypted.slice(tail_offset..tail_offset + SRTCP_INDEX_SIZE); 206 //^(1 << 31) 207 reader.get_u32() & 0x7FFFFFFF 208 } 209 210 #[test] 211 fn test_encrypt_rtcp_separation() -> Result<()> { 212 let mut encrypt_context = Context::new( 213 &RTCP_TEST_MASTER_KEY, 214 &RTCP_TEST_MASTER_SALT, 215 ProtectionProfile::Aes128CmHmacSha1_80, 216 None, 217 None, 218 )?; 219 220 let auth_tag_len = ProtectionProfile::Aes128CmHmacSha1_80.auth_tag_len(); 221 222 let mut decrypt_context = Context::new( 223 &RTCP_TEST_MASTER_KEY, 224 &RTCP_TEST_MASTER_SALT, 225 ProtectionProfile::Aes128CmHmacSha1_80, 226 None, 227 Some(srtcp_replay_protection(10)), 228 )?; 229 230 let inputs = vec![ 231 RTCP_TEST_CASES[0].decrypted.clone(), 232 RTCP_TEST_CASES[1].decrypted.clone(), 233 RTCP_TEST_CASES[0].decrypted.clone(), 234 RTCP_TEST_CASES[1].decrypted.clone(), 235 ]; 236 let mut encrypted_rctps = vec![]; 237 238 for input in &inputs { 239 let encrypted = encrypt_context.encrypt_rtcp(input)?; 240 encrypted_rctps.push(encrypted); 241 } 242 243 for (i, expected_index) in [1, 1, 2, 2].iter().enumerate() { 244 assert_eq!( 245 *expected_index, 246 get_rtcp_index(&encrypted_rctps[i], auth_tag_len), 247 "RTCP index does not match" 248 ); 249 } 250 251 for (i, output) in encrypted_rctps.iter().enumerate() { 252 let decrypted = decrypt_context.decrypt_rtcp(output)?; 253 assert_eq!(inputs[i], decrypted); 254 } 255 256 Ok(()) 257 } 258