Skip to content

Commit bac055d

Browse files
authored
Merge pull request #9357 from holtrop/rust-wc-srtp-kdf
Rust wrapper: add SRTP/SRTCP KDF functions to kdf module
2 parents a2b3af0 + bc72ac3 commit bac055d

File tree

3 files changed

+321
-1
lines changed

3 files changed

+321
-1
lines changed

doc/dox_comments/header_files/kdf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ int wc_SRTP_KDF_label(const byte* key, word32 keySz, const byte* salt,
195195
\sa wc_SRTP_KDF_label
196196
\sa wc_SRTP_KDF_kdr_to_idx
197197
*/
198-
int wc_SRTP_KDF_label(const byte* key, word32 keySz, const byte* salt,
198+
int wc_SRTCP_KDF_label(const byte* key, word32 keySz, const byte* salt,
199199
word32 saltSz, int kdrIdx, const byte* idx, byte label, byte* outKey,
200200
word32 outKeySz);
201201
/*!

wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ the raw C functions in a memory-safe and easy-to-use Rust API.
2929
use crate::wolfcrypt::hmac::HMAC;
3030
use wolfssl_sys as ws;
3131

32+
pub const SRTP_LABEL_ENCRYPTION: u8 = ws::WC_SRTP_LABEL_ENCRYPTION as u8;
33+
pub const SRTP_LABEL_MSG_AUTH: u8 = ws::WC_SRTP_LABEL_MSG_AUTH as u8;
34+
pub const SRTP_LABEL_SALT: u8 = ws::WC_SRTP_LABEL_SALT as u8;
35+
pub const SRTCP_LABEL_ENCRYPTION: u8 = ws::WC_SRTCP_LABEL_ENCRYPTION as u8;
36+
pub const SRTCP_LABEL_MSG_AUTH: u8 = ws::WC_SRTCP_LABEL_MSG_AUTH as u8;
37+
pub const SRTCP_LABEL_SALT: u8 = ws::WC_SRTCP_LABEL_SALT as u8;
38+
pub const SRTP_LABEL_HDR_ENCRYPTION: u8 = ws::WC_SRTP_LABEL_HDR_ENCRYPTION as u8;
39+
pub const SRTP_LABEL_HDR_SALT: u8 = ws::WC_SRTP_LABEL_HDR_SALT as u8;
40+
3241
/// Perform RFC 5869 HKDF-Extract operation for TLS v1.3 key derivation.
3342
///
3443
/// # Parameters
@@ -189,3 +198,208 @@ pub fn ssh_kdf(typ: i32, key_id: u8, k: &[u8], h: &[u8], session_id: &[u8], key:
189198
}
190199
Ok(())
191200
}
201+
202+
/// Perform SRTP KDF algorithm to derive keys.
203+
///
204+
/// # Parameters
205+
///
206+
/// * `key`: Key to use with encryption.
207+
/// * `salt`: Random non-secret value.
208+
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
209+
/// * `idx`: Index value to XOR in.
210+
/// * `key1`: Output buffer for first key (label of 0x00).
211+
/// * `key2`: Output buffer for second key (label of 0x01).
212+
/// * `key3`: Output buffer for third key (label of 0x02).
213+
///
214+
/// # Returns
215+
///
216+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
217+
/// library error code value.
218+
///
219+
/// # Example
220+
///
221+
/// ```rust
222+
/// use wolfssl::wolfcrypt::kdf::*;
223+
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
224+
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
225+
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
226+
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
227+
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
228+
/// let mut key_e = [0u8; 16];
229+
/// let mut key_a = [0u8; 20];
230+
/// let mut key_s = [0u8; 14];
231+
/// srtp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtp_kdf()");
232+
/// ```
233+
pub fn srtp_kdf(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
234+
key1: &mut [u8], key2: &mut [u8], key3: &mut [u8]) -> Result<(), i32> {
235+
let key_size = key.len() as u32;
236+
let salt_size = salt.len() as u32;
237+
let key1_size = key1.len() as u32;
238+
let key2_size = key2.len() as u32;
239+
let key3_size = key3.len() as u32;
240+
let rc = unsafe {
241+
ws::wc_SRTP_KDF(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
242+
kdr_index, idx.as_ptr(), key1.as_mut_ptr(), key1_size,
243+
key2.as_mut_ptr(), key2_size, key3.as_mut_ptr(), key3_size)
244+
};
245+
if rc != 0 {
246+
return Err(rc);
247+
}
248+
Ok(())
249+
}
250+
251+
/// Perform SRTP KDF algorithm to derive a key with a given label.
252+
///
253+
/// # Parameters
254+
///
255+
/// * `key`: Key to use with encryption.
256+
/// * `salt`: Random non-secret value.
257+
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
258+
/// * `idx`: Index value to XOR in.
259+
/// * `label`: Label: typically one of `SRTP_LABEL_*`.
260+
/// * `keyout`: Output buffer for generated key.
261+
///
262+
/// # Returns
263+
///
264+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
265+
/// library error code value.
266+
///
267+
/// # Example
268+
///
269+
/// ```rust
270+
/// use wolfssl::wolfcrypt::kdf::*;
271+
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
272+
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
273+
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
274+
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
275+
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
276+
/// let mut key_a = [0u8; 20];
277+
/// srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtp_kdf_label()");
278+
/// ```
279+
pub fn srtp_kdf_label(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
280+
label: u8, keyout: &mut [u8]) -> Result<(), i32> {
281+
let key_size = key.len() as u32;
282+
let salt_size = salt.len() as u32;
283+
let keyout_size = keyout.len() as u32;
284+
let rc = unsafe {
285+
ws::wc_SRTP_KDF_label(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
286+
kdr_index, idx.as_ptr(), label, keyout.as_mut_ptr(), keyout_size)
287+
};
288+
if rc != 0 {
289+
return Err(rc);
290+
}
291+
Ok(())
292+
}
293+
294+
/// Perform SRTCP KDF algorithm to derive keys.
295+
///
296+
/// # Parameters
297+
///
298+
/// * `key`: Key to use with encryption. Key length must be 16, 24, or 32.
299+
/// * `salt`: Random non-secret value.
300+
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
301+
/// * `idx`: Index value to XOR in.
302+
/// * `key1`: Output buffer for first key (label of 0x00).
303+
/// * `key2`: Output buffer for second key (label of 0x01).
304+
/// * `key3`: Output buffer for third key (label of 0x02).
305+
///
306+
/// # Returns
307+
///
308+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
309+
/// library error code value.
310+
///
311+
/// # Example
312+
///
313+
/// ```rust
314+
/// use wolfssl::wolfcrypt::kdf::*;
315+
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
316+
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
317+
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
318+
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
319+
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
320+
/// let mut key_e = [0u8; 16];
321+
/// let mut key_a = [0u8; 20];
322+
/// let mut key_s = [0u8; 14];
323+
/// srtcp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtcp_kdf()");
324+
/// ```
325+
pub fn srtcp_kdf(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
326+
key1: &mut [u8], key2: &mut [u8], key3: &mut [u8]) -> Result<(), i32> {
327+
let key_size = key.len() as u32;
328+
let salt_size = salt.len() as u32;
329+
let key1_size = key1.len() as u32;
330+
let key2_size = key2.len() as u32;
331+
let key3_size = key3.len() as u32;
332+
let rc = unsafe {
333+
ws::wc_SRTCP_KDF(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
334+
kdr_index, idx.as_ptr(), key1.as_mut_ptr(), key1_size,
335+
key2.as_mut_ptr(), key2_size, key3.as_mut_ptr(), key3_size)
336+
};
337+
if rc != 0 {
338+
return Err(rc);
339+
}
340+
Ok(())
341+
}
342+
343+
/// Perform SRTCP KDF algorithm to derive a key with a given label.
344+
///
345+
/// # Parameters
346+
///
347+
/// * `key`: Key to use with encryption.
348+
/// * `salt`: Random non-secret value.
349+
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
350+
/// * `idx`: Index value to XOR in.
351+
/// * `label`: Label: typically one of `SRTCP_LABEL_*`.
352+
/// * `keyout`: Output buffer for generated key.
353+
///
354+
/// # Returns
355+
///
356+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
357+
/// library error code value.
358+
///
359+
/// # Example
360+
///
361+
/// ```rust
362+
/// use wolfssl::wolfcrypt::kdf::*;
363+
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
364+
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
365+
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
366+
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
367+
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
368+
/// let mut key_a = [0u8; 20];
369+
/// srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtcp_kdf_label()");
370+
/// ```
371+
pub fn srtcp_kdf_label(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
372+
label: u8, keyout: &mut [u8]) -> Result<(), i32> {
373+
let key_size = key.len() as u32;
374+
let salt_size = salt.len() as u32;
375+
let keyout_size = keyout.len() as u32;
376+
let rc = unsafe {
377+
ws::wc_SRTCP_KDF_label(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
378+
kdr_index, idx.as_ptr(), label, keyout.as_mut_ptr(), keyout_size)
379+
};
380+
if rc != 0 {
381+
return Err(rc);
382+
}
383+
Ok(())
384+
}
385+
386+
/// Convert a Key Derivation Rate (KDR) value to an index for use in the
387+
/// SRTP/SRTCP KDF API.
388+
///
389+
/// # Parameters
390+
///
391+
/// * `kdr`: Key derivation rate to convert.
392+
///
393+
/// # Returns
394+
///
395+
/// Key derivation rate index (kdr_index).
396+
///
397+
/// # Example
398+
///
399+
/// ```rust
400+
/// use wolfssl::wolfcrypt::kdf::*;
401+
/// let kdr_index = srtp_kdr_to_index(16);
402+
/// ```
403+
pub fn srtp_kdr_to_index(kdr: u32) -> i32 {
404+
unsafe { ws::wc_SRTP_KDF_kdr_to_idx(kdr) }
405+
}

wrapper/rust/wolfssl/tests/test_kdf.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,109 @@ fn test_ssh_kdf() {
9191

9292
assert_eq!(out, ssh_kdf_set3_a);
9393
}
94+
95+
#[test]
96+
fn test_srtp_kdf() {
97+
let key = [
98+
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
99+
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
100+
];
101+
let salt = [
102+
0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
103+
0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6
104+
];
105+
let index = [
106+
0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca
107+
];
108+
let expected_ke = [
109+
0xdcu8, 0x38, 0x21, 0x92, 0xab, 0x65, 0x10, 0x8a,
110+
0x86, 0xb2, 0x59, 0xb6, 0x1b, 0x3a, 0xf4, 0x6f
111+
];
112+
let expected_ka = [
113+
0xb8u8, 0x39, 0x37, 0xfb, 0x32, 0x17, 0x92, 0xee,
114+
0x87, 0xb7, 0x88, 0x19, 0x3b, 0xe5, 0xa4, 0xe3,
115+
0xbd, 0x32, 0x6e, 0xe4
116+
];
117+
let expected_ks = [
118+
0xf1u8, 0xc0, 0x35, 0xc0, 0x0b, 0x5a, 0x54, 0xa6,
119+
0x16, 0x92, 0xc0, 0x16, 0x27, 0x6c
120+
];
121+
let mut key_e = [0u8; 16];
122+
let mut key_a = [0u8; 20];
123+
let mut key_s = [0u8; 14];
124+
srtp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtp_kdf()");
125+
assert_eq!(key_e, expected_ke);
126+
assert_eq!(key_a, expected_ka);
127+
assert_eq!(key_s, expected_ks);
128+
129+
let mut key_e = [0u8; 16];
130+
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_ENCRYPTION, &mut key_e).expect("Error with srtp_kdf_label()");
131+
assert_eq!(key_e, expected_ke);
132+
133+
let mut key_a = [0u8; 20];
134+
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtp_kdf_label()");
135+
assert_eq!(key_a, expected_ka);
136+
137+
let mut key_s = [0u8; 14];
138+
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_SALT, &mut key_s).expect("Error with srtp_kdf_label()");
139+
assert_eq!(key_s, expected_ks);
140+
}
141+
142+
#[test]
143+
fn test_srtcp_kdf() {
144+
let key = [
145+
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
146+
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
147+
];
148+
let salt = [
149+
0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
150+
0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6
151+
];
152+
let index = [
153+
0x56u8, 0xf3, 0xf1, 0x97
154+
];
155+
let expected_ke = [
156+
0xabu8, 0x5b, 0xe0, 0xb4, 0x56, 0x23, 0x5d, 0xcf,
157+
0x77, 0xd5, 0x08, 0x69, 0x29, 0xba, 0xfb, 0x38
158+
];
159+
let expected_ka = [
160+
0xc5u8, 0x2f, 0xde, 0x0b, 0x80, 0xb0, 0xf0, 0xba,
161+
0xd8, 0xd1, 0x56, 0x45, 0xcb, 0x86, 0xe7, 0xc7,
162+
0xc3, 0xd8, 0x77, 0x0e
163+
];
164+
let expected_ks = [
165+
0xdeu8, 0xb5, 0xf8, 0x5f, 0x81, 0x33, 0x6a, 0x96,
166+
0x5e, 0xd3, 0x2b, 0xb7, 0xed, 0xe8
167+
];
168+
let mut key_e = [0u8; 16];
169+
let mut key_a = [0u8; 20];
170+
let mut key_s = [0u8; 14];
171+
srtcp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtcp_kdf()");
172+
assert_eq!(key_e, expected_ke);
173+
assert_eq!(key_a, expected_ka);
174+
assert_eq!(key_s, expected_ks);
175+
176+
let mut key_e = [0u8; 16];
177+
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_ENCRYPTION, &mut key_e).expect("Error with srtcp_kdf_label()");
178+
assert_eq!(key_e, expected_ke);
179+
180+
let mut key_a = [0u8; 20];
181+
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtcp_kdf_label()");
182+
assert_eq!(key_a, expected_ka);
183+
184+
let mut key_s = [0u8; 14];
185+
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_SALT, &mut key_s).expect("Error with srtcp_kdf_label()");
186+
assert_eq!(key_s, expected_ks);
187+
}
188+
189+
#[test]
190+
fn test_srtp_kdr_to_idx() {
191+
assert_eq!(srtp_kdr_to_index(0), -1);
192+
assert_eq!(srtp_kdr_to_index(1), 0);
193+
assert_eq!(srtp_kdr_to_index(2), 1);
194+
assert_eq!(srtp_kdr_to_index(4), 2);
195+
assert_eq!(srtp_kdr_to_index(8), 3);
196+
assert_eq!(srtp_kdr_to_index(16), 4);
197+
assert_eq!(srtp_kdr_to_index(65536), 16);
198+
assert_eq!(srtp_kdr_to_index(1048576), 20);
199+
}

0 commit comments

Comments
 (0)