diff --git a/doc/dox_comments/header_files/kdf.h b/doc/dox_comments/header_files/kdf.h index fcd62cdc0..06e6b4fd6 100644 --- a/doc/dox_comments/header_files/kdf.h +++ b/doc/dox_comments/header_files/kdf.h @@ -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); /*! diff --git a/wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs b/wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs index a2e6c213d..6c6f04464 100644 --- a/wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs +++ b/wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs @@ -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) } +} diff --git a/wrapper/rust/wolfssl/tests/test_kdf.rs b/wrapper/rust/wolfssl/tests/test_kdf.rs index 785fb9201..b6ddd609b 100644 --- a/wrapper/rust/wolfssl/tests/test_kdf.rs +++ b/wrapper/rust/wolfssl/tests/test_kdf.rs @@ -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); +}