use super::KeyDerivationFunction;
use crate::error::{CryptoKitError, Result};
extern "C" {
#[link_name = "hkdf_sha512_derive"]
fn swift_hkdf_sha512_derive(
input_key: *const u8,
input_key_len: i32,
salt: *const u8,
salt_len: i32,
info: *const u8,
info_len: i32,
output_length: i32,
output: *mut u8,
) -> i32;
}
#[allow(non_camel_case_types)]
pub struct HKDF_SHA512;
impl HKDF_SHA512 {
pub fn derive_key(
input_key_material: &[u8],
salt: &[u8],
info: &[u8],
output_length: usize,
) -> Result<Vec<u8>> {
Self::derive(input_key_material, salt, info, output_length)
}
}
impl KeyDerivationFunction for HKDF_SHA512 {
fn derive_to(
input_key_material: &[u8],
salt: &[u8],
info: &[u8],
output: &mut [u8],
) -> Result<()> {
if input_key_material.is_empty() {
return Err(CryptoKitError::InvalidInput(
"Input key material cannot be empty".to_string(),
));
}
let output_length = output.len();
if output_length == 0 || output_length > 255 * 64 {
return Err(CryptoKitError::InvalidLength);
}
unsafe {
let result = swift_hkdf_sha512_derive(
input_key_material.as_ptr(),
input_key_material.len() as i32,
salt.as_ptr(),
salt.len() as i32,
info.as_ptr(),
info.len() as i32,
output_length as i32,
output.as_mut_ptr(),
);
if result == 0 {
Ok(())
} else {
Err(CryptoKitError::DerivationFailed)
}
}
}
}
pub fn hkdf_sha512_derive(
input_key_material: &[u8],
salt: &[u8],
info: &[u8],
output_length: usize,
) -> Result<Vec<u8>> {
HKDF_SHA512::derive(input_key_material, salt, info, output_length)
}