apple_cryptokit/key_derivation/hkdf_sha384.rs
1use super::KeyDerivationFunction;
2use crate::error::{CryptoKitError, Result};
3
4// HKDF-SHA384 Swift FFI declarations
5extern "C" {
6 #[link_name = "hkdf_sha384_derive"]
7 fn swift_hkdf_sha384_derive(
8 input_key: *const u8,
9 input_key_len: i32,
10 salt: *const u8,
11 salt_len: i32,
12 info: *const u8,
13 info_len: i32,
14 output_length: i32,
15 output: *mut u8,
16 ) -> i32;
17}
18
19/// HKDF-SHA384 key derivation implementation
20#[allow(non_camel_case_types)]
21pub struct HKDF_SHA384;
22
23impl HKDF_SHA384 {
24 /// Derive key from input key material using SHA384 hash algorithm
25 ///
26 /// # Parameters
27 /// * `input_key_material` - Input key material
28 /// * `salt` - Salt value (optional, recommended)
29 /// * `info` - Application-specific information (optional)
30 /// * `output_length` - Output key length
31 ///
32 /// # Returns
33 /// Derived key data
34 ///
35 /// # Errors
36 /// Returns `CryptoKitError::DerivationFailed` if key derivation fails
37 ///
38 /// # Example
39 /// ```rust,no_run
40 /// use apple_cryptokit::key_derivation::hkdf_sha384::HKDF_SHA384;
41 /// use apple_cryptokit::key_derivation::KeyDerivationFunction;
42 ///
43 /// let ikm = b"input key material";
44 /// let salt = b"optional salt";
45 /// let info = b"application context";
46 ///
47 /// let derived_key = HKDF_SHA384::derive(ikm, salt, info, 48).unwrap();
48 /// ```
49 pub fn derive_key(
50 input_key_material: &[u8],
51 salt: &[u8],
52 info: &[u8],
53 output_length: usize,
54 ) -> Result<Vec<u8>> {
55 Self::derive(input_key_material, salt, info, output_length)
56 }
57}
58
59impl KeyDerivationFunction for HKDF_SHA384 {
60 fn derive_to(
61 input_key_material: &[u8],
62 salt: &[u8],
63 info: &[u8],
64 output: &mut [u8],
65 ) -> Result<usize> {
66 if input_key_material.is_empty() {
67 return Err(CryptoKitError::InvalidInput(
68 "Input key material cannot be empty".to_string(),
69 ));
70 }
71
72 let output_length = output.len();
73 if output_length == 0 || output_length > 255 * 48 {
74 // SHA384 outputs 48 bytes, maximum 255 output blocks
75 return Err(CryptoKitError::InvalidLength);
76 }
77
78 unsafe {
79 let result = swift_hkdf_sha384_derive(
80 input_key_material.as_ptr(),
81 input_key_material.len() as i32,
82 salt.as_ptr(),
83 salt.len() as i32,
84 info.as_ptr(),
85 info.len() as i32,
86 output_length as i32,
87 output.as_mut_ptr(),
88 );
89
90 if result == 0 {
91 Ok(output_length)
92 } else {
93 Err(CryptoKitError::DerivationFailed)
94 }
95 }
96 }
97}
98
99/// Convenience function: HKDF-SHA384 key derivation
100///
101/// # Parameters
102/// * `input_key_material` - Input key material
103/// * `salt` - Salt value (optional, recommended)
104/// * `info` - Application-specific information (optional)
105/// * `output_length` - Output key length
106pub fn hkdf_sha384_derive(
107 input_key_material: &[u8],
108 salt: &[u8],
109 info: &[u8],
110 output_length: usize,
111) -> Result<Vec<u8>> {
112 HKDF_SHA384::derive(input_key_material, salt, info, output_length)
113}