srt_protocol/protocol/encryption/
stream.rs1use std::fmt::Debug;
2
3use aes::cipher::StreamCipher;
4use cipher::KeyIvInit;
5
6type Aes128Ctr = ctr::Ctr64BE<aes::Aes128>;
7type Aes192Ctr = ctr::Ctr64BE<aes::Aes192>;
8type Aes256Ctr = ctr::Ctr64BE<aes::Aes256>;
9
10use crate::{
11 packet::*,
12 settings::{KeySettings, KeySize},
13};
14
15use super::key::*;
16
17#[derive(Debug, Eq, PartialEq)]
18pub enum KeyMaterialError {
19 NoKeys,
20 InvalidSaltLength,
21 InvalidKeyFlags(KeyFlags, KeySize, usize),
22 InvalidInitializationVector(WrapInitializationVector),
23 InvalidRefreshResponse(KeyingMaterialMessage),
24}
25
26#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct StreamEncryptionKeys {
28 salt: Salt,
29 even_key: Option<EncryptionKey>,
30 odd_key: Option<EncryptionKey>,
31}
32
33impl StreamEncryptionKeys {
34 pub fn new(salt: Salt) -> Self {
35 Self {
36 salt,
37 even_key: None,
38 odd_key: None,
39 }
40 }
41
42 pub fn new_random(key_size: KeySize) -> Self {
43 Self {
44 salt: Salt::new_random(),
45 even_key: Some(EncryptionKey::new_random(key_size)),
46 odd_key: Some(EncryptionKey::new_random(key_size)),
47 }
48 }
49
50 pub fn commission_next_key(
51 &mut self,
52 active_sek: DataEncryption,
53 key_settings: &KeySettings,
54 ) -> Option<KeyingMaterialMessage> {
55 use DataEncryption::*;
56 let new_random_key = EncryptionKey::new_random;
57 match active_sek {
58 Even => self.odd_key = Some(new_random_key(key_settings.key_size)),
59 Odd => self.even_key = Some(new_random_key(key_settings.key_size)),
60 None => return Option::None,
61 }
62 self.wrap_with(key_settings)
63 }
64
65 pub fn first_active_sek(&self) -> DataEncryption {
66 if self.even_key.is_some() {
67 DataEncryption::Even
68 } else if self.odd_key.is_some() {
69 DataEncryption::Odd
70 } else {
71 DataEncryption::None
72 }
73 }
74
75 pub fn unwrap_from(
76 key_settings: &KeySettings,
77 key_material: &KeyingMaterialMessage,
78 ) -> Result<Self, KeyMaterialError> {
79 use KeyMaterialError::*;
80 let salt = Salt::try_from(key_material.salt.as_slice()).map_err(|_| InvalidSaltLength)?;
82 let kek = KeyEncryptionKey::new(key_settings, &salt);
83
84 if key_material.key_flags.bits().count_ones() as usize * key_settings.key_size.as_usize()
85 + 8
86 != key_material.wrapped_keys.len()
87 {
88 return Err(KeyMaterialError::InvalidKeyFlags(
89 key_material.key_flags,
90 key_settings.key_size,
91 key_material.wrapped_keys.len(),
92 ));
93 }
94
95 let wrapped_keys = key_material.wrapped_keys.as_slice();
96 let keys = kek
97 .decrypt_wrapped_keys(wrapped_keys)
98 .map_err(InvalidInitializationVector)?;
99
100 let key_flags = key_material.key_flags;
101 let key_size = kek.len();
102 let even_key = if key_flags.contains(KeyFlags::EVEN) {
103 Some(EncryptionKey::try_from(&keys[0..key_size]).unwrap())
104 } else {
105 None
106 };
107 let odd_key = if key_flags.contains(KeyFlags::ODD) {
108 Some(EncryptionKey::try_from(&keys[keys.len() - key_size..]).unwrap())
109 } else {
110 None
111 };
112
113 Ok(StreamEncryptionKeys {
114 salt,
115 even_key,
116 odd_key,
117 })
118 }
119
120 pub fn wrap_with(&self, key_settings: &KeySettings) -> Option<KeyingMaterialMessage> {
121 let kek = KeyEncryptionKey::new(key_settings, &self.salt);
122
123 let mut keys = Vec::new();
124 if let Some(k) = &self.even_key {
125 keys.extend(k.as_bytes());
126 }
127 if let Some(k) = &self.odd_key {
128 keys.extend(k.as_bytes());
129 }
130
131 let wrapped_keys = kek.encrypt_wrapped_keys(keys.as_slice());
132
133 Some(KeyingMaterialMessage {
134 pt: PacketType::KeyingMaterial,
135 key_flags: match (&self.even_key, &self.odd_key) {
136 (Some(_), Some(_)) => KeyFlags::EVEN | KeyFlags::ODD,
137 (Some(_), None) => KeyFlags::EVEN,
138 (None, Some(_)) => KeyFlags::ODD,
139 (None, None) => return None,
140 },
141 keki: 0, cipher: CipherType::Ctr,
143 auth: Auth::None,
144 salt: self.salt.as_slice().to_vec(),
145 wrapped_keys,
146 })
147 }
148
149 pub fn decrypt(
150 &self,
151 sek_selection: DataEncryption,
152 seq_number: SeqNumber,
153 data: &mut [u8],
154 ) -> Option<usize> {
155 let sek = self.get_key(sek_selection)?;
156 let iv = self.salt.generate_strean_iv_for(seq_number);
157
158 let nonce = iv.as_bytes();
159 use EncryptionKey::*;
160 match sek {
161 Bytes16(key) => Aes128Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
162 Bytes24(key) => Aes192Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
163 Bytes32(key) => Aes256Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
164 };
165
166 Some(data.len())
167 }
168
169 pub fn encrypt(
170 &self,
171 sek_selection: DataEncryption,
172 seq_number: SeqNumber,
173 data: &mut [u8],
174 ) -> Option<usize> {
175 let sek = self.get_key(sek_selection)?;
176 let iv = self.salt.generate_strean_iv_for(seq_number);
177
178 let nonce = iv.as_bytes();
179 use EncryptionKey::*;
180 match sek {
181 Bytes16(key) => Aes128Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
182 Bytes24(key) => Aes192Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
183 Bytes32(key) => Aes256Ctr::new(key.into(), nonce[..].into()).apply_keystream(data),
184 };
185
186 Some(data.len())
187 }
188
189 fn get_key(&self, active: DataEncryption) -> Option<&EncryptionKey> {
190 use crate::packet::DataEncryption::*;
191 match active {
192 Even => self.even_key.as_ref(),
193 Odd => self.odd_key.as_ref(),
194 None => Option::None,
195 }
196 }
197}
198
199#[cfg(test)]
200mod test {
201 use super::*;
202 use assert_matches::assert_matches;
203
204 fn key_settings() -> KeySettings {
205 KeySettings {
206 key_size: KeySize::AES128,
207 passphrase: "password123".into(),
208 }
209 }
210
211 #[test]
212 fn wrap_keys() {
213 let salt = b"\x00\x00\x00\x00\x00\x00\x00\x00\x85\x2c\x3c\xcd\x02\x65\x1a\x22";
214 let stream_encryption = StreamEncryptionKeys {
215 salt: Salt::try_from(salt).unwrap(),
216 odd_key: None,
217 even_key: EncryptionKey::try_from(b"\r\xab\xc8n/2\xb4\xa7\xb9\xbb\xa2\xf31*\xe4\"")
218 .ok(),
219 };
220
221 let kek = KeyEncryptionKey::new(&key_settings(), &stream_encryption.salt);
222 assert_eq!(
223 kek.as_bytes(),
224 b"\xe9\xa0\xa4\x30\x2f\x59\xd0\x63\xc8\x83\x32\xbe\x35\x88\x82\x08"
225 );
226
227 let expected_wrapped_keys =
228 b"31ea\x11\xe8\xb0P\xfe\x99\x9f\xd5h\xc2b\xfb\x1a3\xcc\xc8\x9cNw\xca";
229 let expected_keying_material = KeyingMaterialMessage {
230 pt: PacketType::KeyingMaterial,
231 key_flags: KeyFlags::EVEN,
232 keki: 0,
233 cipher: CipherType::Ctr,
234 auth: Auth::None,
235 salt: salt.to_vec(),
236 wrapped_keys: expected_wrapped_keys.to_vec(),
237 };
238
239 let keying_material = stream_encryption.wrap_with(&key_settings());
240 assert_eq!(
241 &keying_material.as_ref().unwrap().wrapped_keys[..],
242 &expected_wrapped_keys[..]
243 );
244
245 assert_eq!(keying_material.unwrap(), expected_keying_material);
246 }
247
248 #[test]
249 fn bad_password() {
250 let key_settings = &KeySettings {
251 key_size: KeySize::AES128,
252 passphrase: "badpassword".into(),
253 };
254 let key_material = KeyingMaterialMessage {
255 pt: PacketType::KeyingMaterial,
256 key_flags: KeyFlags::ODD,
257 keki: 0,
258 cipher: CipherType::Ctr,
259 auth: Auth::None,
260 salt: b"\x00\x00\x00\x00\x00\x00\x00\x00\x85\x2c\x3c\xcd\x02\x65\x1a\x22"[..].into(),
261 wrapped_keys: b"31ea\x11\xe8\xb0P\xfe\x99\x9f\xd5h\xc2b\xfb\x1a3\xcc\xc8\x9cNw\xca"[..]
262 .into(),
263 };
264
265 let res = StreamEncryptionKeys::unwrap_from(key_settings, &key_material);
266
267 assert_matches!(res, Err(_));
268 }
269
270 #[test]
271 fn wrap_key2() {
272 let salt = b"\x00\x00\x00\x00\x00\x00\x00\x00n\xd5+\x196\nq8";
273 let stream_encryption = StreamEncryptionKeys {
274 salt: Salt::try_from(salt).unwrap(),
275 odd_key: EncryptionKey::try_from(b"\r\xab\xc8n/2\xb4\xa7\xb9\xbb\xa2\xf31*\xe4\"").ok(),
276 even_key: None,
277 };
278
279 let kek = KeyEncryptionKey::new(&key_settings(), &stream_encryption.salt);
280 assert_eq!(
281 kek.as_bytes(),
282 b"\xde#\x1b\xfd9\x93z\xfb\xc3w\xa7\x80\xee\x80'\xa3"
283 );
284
285 let keying_material = KeyingMaterialMessage {
286 pt: PacketType::KeyingMaterial,
287 key_flags: KeyFlags::ODD,
288 keki: 0,
289 cipher: CipherType::Ctr,
290 auth: Auth::None,
291 salt: salt.to_vec(),
292 wrapped_keys: b"U\x06\xe9\xfd\xdfd\xf1'nr\xf4\xe9f\x81#(\xb7\xb5D\x19{\x9b\xcdx"
293 .to_vec(),
294 };
295
296 let stream_encryption =
297 StreamEncryptionKeys::unwrap_from(&key_settings(), &keying_material).unwrap();
298
299 assert_eq!(
300 stream_encryption.wrap_with(&key_settings()),
301 Some(keying_material)
302 );
303 }
304}