Merge pull request #9357 from holtrop/rust-wc-srtp-kdf

Rust wrapper: add SRTP/SRTCP KDF functions to kdf module
This commit is contained in:
Daniel Pouzzner
2025-10-30 23:45:48 -05:00
committed by GitHub
3 changed files with 321 additions and 1 deletions

View File

@@ -195,7 +195,7 @@ int wc_SRTP_KDF_label(const byte* key, word32 keySz, const byte* salt,
\sa wc_SRTP_KDF_label
\sa wc_SRTP_KDF_kdr_to_idx
*/
int wc_SRTP_KDF_label(const byte* key, word32 keySz, const byte* salt,
int wc_SRTCP_KDF_label(const byte* key, word32 keySz, const byte* salt,
word32 saltSz, int kdrIdx, const byte* idx, byte label, byte* outKey,
word32 outKeySz);
/*!

View File

@@ -29,6 +29,15 @@ the raw C functions in a memory-safe and easy-to-use Rust API.
use crate::wolfcrypt::hmac::HMAC;
use wolfssl_sys as ws;
pub const SRTP_LABEL_ENCRYPTION: u8 = ws::WC_SRTP_LABEL_ENCRYPTION as u8;
pub const SRTP_LABEL_MSG_AUTH: u8 = ws::WC_SRTP_LABEL_MSG_AUTH as u8;
pub const SRTP_LABEL_SALT: u8 = ws::WC_SRTP_LABEL_SALT as u8;
pub const SRTCP_LABEL_ENCRYPTION: u8 = ws::WC_SRTCP_LABEL_ENCRYPTION as u8;
pub const SRTCP_LABEL_MSG_AUTH: u8 = ws::WC_SRTCP_LABEL_MSG_AUTH as u8;
pub const SRTCP_LABEL_SALT: u8 = ws::WC_SRTCP_LABEL_SALT as u8;
pub const SRTP_LABEL_HDR_ENCRYPTION: u8 = ws::WC_SRTP_LABEL_HDR_ENCRYPTION as u8;
pub const SRTP_LABEL_HDR_SALT: u8 = ws::WC_SRTP_LABEL_HDR_SALT as u8;
/// Perform RFC 5869 HKDF-Extract operation for TLS v1.3 key derivation.
///
/// # Parameters
@@ -189,3 +198,208 @@ pub fn ssh_kdf(typ: i32, key_id: u8, k: &[u8], h: &[u8], session_id: &[u8], key:
}
Ok(())
}
/// Perform SRTP KDF algorithm to derive keys.
///
/// # Parameters
///
/// * `key`: Key to use with encryption.
/// * `salt`: Random non-secret value.
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
/// * `idx`: Index value to XOR in.
/// * `key1`: Output buffer for first key (label of 0x00).
/// * `key2`: Output buffer for second key (label of 0x01).
/// * `key3`: Output buffer for third key (label of 0x02).
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl::wolfcrypt::kdf::*;
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
/// let mut key_e = [0u8; 16];
/// let mut key_a = [0u8; 20];
/// let mut key_s = [0u8; 14];
/// srtp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtp_kdf()");
/// ```
pub fn srtp_kdf(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
key1: &mut [u8], key2: &mut [u8], key3: &mut [u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let salt_size = salt.len() as u32;
let key1_size = key1.len() as u32;
let key2_size = key2.len() as u32;
let key3_size = key3.len() as u32;
let rc = unsafe {
ws::wc_SRTP_KDF(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
kdr_index, idx.as_ptr(), key1.as_mut_ptr(), key1_size,
key2.as_mut_ptr(), key2_size, key3.as_mut_ptr(), key3_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Perform SRTP KDF algorithm to derive a key with a given label.
///
/// # Parameters
///
/// * `key`: Key to use with encryption.
/// * `salt`: Random non-secret value.
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
/// * `idx`: Index value to XOR in.
/// * `label`: Label: typically one of `SRTP_LABEL_*`.
/// * `keyout`: Output buffer for generated key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl::wolfcrypt::kdf::*;
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
/// let mut key_a = [0u8; 20];
/// srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtp_kdf_label()");
/// ```
pub fn srtp_kdf_label(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
label: u8, keyout: &mut [u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let salt_size = salt.len() as u32;
let keyout_size = keyout.len() as u32;
let rc = unsafe {
ws::wc_SRTP_KDF_label(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
kdr_index, idx.as_ptr(), label, keyout.as_mut_ptr(), keyout_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Perform SRTCP KDF algorithm to derive keys.
///
/// # Parameters
///
/// * `key`: Key to use with encryption. Key length must be 16, 24, or 32.
/// * `salt`: Random non-secret value.
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
/// * `idx`: Index value to XOR in.
/// * `key1`: Output buffer for first key (label of 0x00).
/// * `key2`: Output buffer for second key (label of 0x01).
/// * `key3`: Output buffer for third key (label of 0x02).
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl::wolfcrypt::kdf::*;
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
/// let mut key_e = [0u8; 16];
/// let mut key_a = [0u8; 20];
/// let mut key_s = [0u8; 14];
/// srtcp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtcp_kdf()");
/// ```
pub fn srtcp_kdf(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
key1: &mut [u8], key2: &mut [u8], key3: &mut [u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let salt_size = salt.len() as u32;
let key1_size = key1.len() as u32;
let key2_size = key2.len() as u32;
let key3_size = key3.len() as u32;
let rc = unsafe {
ws::wc_SRTCP_KDF(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
kdr_index, idx.as_ptr(), key1.as_mut_ptr(), key1_size,
key2.as_mut_ptr(), key2_size, key3.as_mut_ptr(), key3_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Perform SRTCP KDF algorithm to derive a key with a given label.
///
/// # Parameters
///
/// * `key`: Key to use with encryption.
/// * `salt`: Random non-secret value.
/// * `kdr_index`: Key derivation rate: -1 for 0, otherwise KDR = 2^kdr_index.
/// * `idx`: Index value to XOR in.
/// * `label`: Label: typically one of `SRTCP_LABEL_*`.
/// * `keyout`: Output buffer for generated key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl::wolfcrypt::kdf::*;
/// let key = [0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
/// 0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90];
/// let salt = [0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
/// 0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6];
/// let index = [0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca];
/// let mut key_a = [0u8; 20];
/// srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtcp_kdf_label()");
/// ```
pub fn srtcp_kdf_label(key: &[u8], salt: &[u8], kdr_index: i32, idx: &[u8],
label: u8, keyout: &mut [u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let salt_size = salt.len() as u32;
let keyout_size = keyout.len() as u32;
let rc = unsafe {
ws::wc_SRTCP_KDF_label(key.as_ptr(), key_size, salt.as_ptr(), salt_size,
kdr_index, idx.as_ptr(), label, keyout.as_mut_ptr(), keyout_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Convert a Key Derivation Rate (KDR) value to an index for use in the
/// SRTP/SRTCP KDF API.
///
/// # Parameters
///
/// * `kdr`: Key derivation rate to convert.
///
/// # Returns
///
/// Key derivation rate index (kdr_index).
///
/// # Example
///
/// ```rust
/// use wolfssl::wolfcrypt::kdf::*;
/// let kdr_index = srtp_kdr_to_index(16);
/// ```
pub fn srtp_kdr_to_index(kdr: u32) -> i32 {
unsafe { ws::wc_SRTP_KDF_kdr_to_idx(kdr) }
}

View File

@@ -91,3 +91,109 @@ fn test_ssh_kdf() {
assert_eq!(out, ssh_kdf_set3_a);
}
#[test]
fn test_srtp_kdf() {
let key = [
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
];
let salt = [
0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6
];
let index = [
0x48u8, 0x71, 0x65, 0x64, 0x9c, 0xca
];
let expected_ke = [
0xdcu8, 0x38, 0x21, 0x92, 0xab, 0x65, 0x10, 0x8a,
0x86, 0xb2, 0x59, 0xb6, 0x1b, 0x3a, 0xf4, 0x6f
];
let expected_ka = [
0xb8u8, 0x39, 0x37, 0xfb, 0x32, 0x17, 0x92, 0xee,
0x87, 0xb7, 0x88, 0x19, 0x3b, 0xe5, 0xa4, 0xe3,
0xbd, 0x32, 0x6e, 0xe4
];
let expected_ks = [
0xf1u8, 0xc0, 0x35, 0xc0, 0x0b, 0x5a, 0x54, 0xa6,
0x16, 0x92, 0xc0, 0x16, 0x27, 0x6c
];
let mut key_e = [0u8; 16];
let mut key_a = [0u8; 20];
let mut key_s = [0u8; 14];
srtp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtp_kdf()");
assert_eq!(key_e, expected_ke);
assert_eq!(key_a, expected_ka);
assert_eq!(key_s, expected_ks);
let mut key_e = [0u8; 16];
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_ENCRYPTION, &mut key_e).expect("Error with srtp_kdf_label()");
assert_eq!(key_e, expected_ke);
let mut key_a = [0u8; 20];
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtp_kdf_label()");
assert_eq!(key_a, expected_ka);
let mut key_s = [0u8; 14];
srtp_kdf_label(&key, &salt, -1, &index, SRTP_LABEL_SALT, &mut key_s).expect("Error with srtp_kdf_label()");
assert_eq!(key_s, expected_ks);
}
#[test]
fn test_srtcp_kdf() {
let key = [
0xc4u8, 0x80, 0x9f, 0x6d, 0x36, 0x98, 0x88, 0x72,
0x8e, 0x26, 0xad, 0xb5, 0x32, 0x12, 0x98, 0x90
];
let salt = [
0x0eu8, 0x23, 0x00, 0x6c, 0x6c, 0x04, 0x4f, 0x56,
0x62, 0x40, 0x0e, 0x9d, 0x1b, 0xd6
];
let index = [
0x56u8, 0xf3, 0xf1, 0x97
];
let expected_ke = [
0xabu8, 0x5b, 0xe0, 0xb4, 0x56, 0x23, 0x5d, 0xcf,
0x77, 0xd5, 0x08, 0x69, 0x29, 0xba, 0xfb, 0x38
];
let expected_ka = [
0xc5u8, 0x2f, 0xde, 0x0b, 0x80, 0xb0, 0xf0, 0xba,
0xd8, 0xd1, 0x56, 0x45, 0xcb, 0x86, 0xe7, 0xc7,
0xc3, 0xd8, 0x77, 0x0e
];
let expected_ks = [
0xdeu8, 0xb5, 0xf8, 0x5f, 0x81, 0x33, 0x6a, 0x96,
0x5e, 0xd3, 0x2b, 0xb7, 0xed, 0xe8
];
let mut key_e = [0u8; 16];
let mut key_a = [0u8; 20];
let mut key_s = [0u8; 14];
srtcp_kdf(&key, &salt, -1, &index, &mut key_e, &mut key_a, &mut key_s).expect("Error with srtcp_kdf()");
assert_eq!(key_e, expected_ke);
assert_eq!(key_a, expected_ka);
assert_eq!(key_s, expected_ks);
let mut key_e = [0u8; 16];
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_ENCRYPTION, &mut key_e).expect("Error with srtcp_kdf_label()");
assert_eq!(key_e, expected_ke);
let mut key_a = [0u8; 20];
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_MSG_AUTH, &mut key_a).expect("Error with srtcp_kdf_label()");
assert_eq!(key_a, expected_ka);
let mut key_s = [0u8; 14];
srtcp_kdf_label(&key, &salt, -1, &index, SRTCP_LABEL_SALT, &mut key_s).expect("Error with srtcp_kdf_label()");
assert_eq!(key_s, expected_ks);
}
#[test]
fn test_srtp_kdr_to_idx() {
assert_eq!(srtp_kdr_to_index(0), -1);
assert_eq!(srtp_kdr_to_index(1), 0);
assert_eq!(srtp_kdr_to_index(2), 1);
assert_eq!(srtp_kdr_to_index(4), 2);
assert_eq!(srtp_kdr_to_index(8), 3);
assert_eq!(srtp_kdr_to_index(16), 4);
assert_eq!(srtp_kdr_to_index(65536), 16);
assert_eq!(srtp_kdr_to_index(1048576), 20);
}