Skip to content

Commit df4a212

Browse files
Rust wrapper: add wolfssl::wolfcrypt::hkdf module
1 parent b801396 commit df4a212

6 files changed

Lines changed: 226 additions & 193 deletions

File tree

wrapper/rust/include.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt.rs
1919
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/aes.rs
2020
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/dh.rs
2121
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/ecc.rs
22+
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hkdf.rs
2223
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hmac.rs
2324
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/random.rs
2425
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/rsa.rs
2526
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/sha.rs
2627
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_aes.rs
2728
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_dh.rs
2829
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_ecc.rs
30+
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hkdf.rs
2931
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hmac.rs
3032
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_random.rs
3133
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_rsa.rs

wrapper/rust/wolfssl/src/wolfcrypt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
pub mod aes;
2222
pub mod dh;
2323
pub mod ecc;
24+
pub mod hkdf;
2425
pub mod hmac;
2526
pub mod random;
2627
pub mod rsa;
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright (C) 2025 wolfSSL Inc.
3+
*
4+
* This file is part of wolfSSL.
5+
*
6+
* wolfSSL is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* wolfSSL is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
19+
*/
20+
21+
/*!
22+
This module provides a Rust wrapper for the wolfCrypt library's HMAC Key
23+
Derivation Function (HKDF) functionality.
24+
25+
It leverages the `wolfssl-sys` crate for low-level FFI bindings, encapsulating
26+
the raw C functions in a memory-safe and easy-to-use Rust API.
27+
*/
28+
29+
use crate::wolfcrypt::hmac::HMAC;
30+
use wolfssl_sys as ws;
31+
32+
/// Perform HKDF-Extract operation.
33+
///
34+
/// This utilizes HMAC to convert `key`, with an optional `salt`, into a
35+
/// derived key which is written to `out`.
36+
///
37+
/// # Parameters
38+
///
39+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
40+
/// * `salt`: Salt value (optional).
41+
/// * `key`: Initial Key Material (IKM).
42+
/// * `out`: Output buffer to store HKDF-Extract result. The size of this
43+
/// buffer must match `HMAC::get_hmac_size_by_type(typ)`.
44+
///
45+
/// # Returns
46+
///
47+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
48+
/// library error code value.
49+
///
50+
/// # Example
51+
///
52+
/// ```rust
53+
/// use wolfssl::wolfcrypt::hkdf::*;
54+
/// use wolfssl::wolfcrypt::hmac::HMAC;
55+
/// use wolfssl_sys as ws;
56+
/// let ikm = b"MyPassword0";
57+
/// let salt = b"12345678ABCDEFGH";
58+
/// let mut extract_out = [0u8; ws::WC_SHA256_DIGEST_SIZE as usize];
59+
/// hkdf_extract(HMAC::TYPE_SHA256, Some(salt), ikm, &mut extract_out).expect("Error with hkdf_extract()");
60+
/// ```
61+
pub fn hkdf_extract(typ: i32, salt: Option<&[u8]>, key: &[u8], out: &mut [u8]) -> Result<(), i32> {
62+
let mut salt_ptr = core::ptr::null();
63+
let mut salt_size = 0u32;
64+
if let Some(salt) = salt {
65+
salt_ptr = salt.as_ptr();
66+
salt_size = salt.len() as u32;
67+
}
68+
let key_size = key.len() as u32;
69+
if out.len() != HMAC::get_hmac_size_by_type(typ)? {
70+
return Err(ws::wolfCrypt_ErrorCodes_BUFFER_E);
71+
}
72+
let rc = unsafe {
73+
ws::wc_HKDF_Extract(typ, salt_ptr, salt_size,
74+
key.as_ptr(), key_size, out.as_mut_ptr())
75+
};
76+
if rc != 0 {
77+
return Err(rc);
78+
}
79+
Ok(())
80+
}
81+
82+
/// Perform HKDF-Expand operation.
83+
///
84+
/// This utilizes HMAC to convert `key`, with optional `info`, into a
85+
/// derived key which is written to `out`.
86+
///
87+
/// # Parameters
88+
///
89+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
90+
/// * `key`: Key to use for KDF (typically output of `hkdf_extract()`).
91+
/// * `info`: Optional buffer containing additional info.
92+
/// * `out`: Output buffer to store HKDF-Expand result. The buffer can be
93+
/// any size.
94+
///
95+
/// # Returns
96+
///
97+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
98+
/// library error code value.
99+
///
100+
/// # Example
101+
///
102+
/// ```rust
103+
/// use wolfssl::wolfcrypt::hkdf::*;
104+
/// use wolfssl::wolfcrypt::hmac::HMAC;
105+
/// use wolfssl_sys as ws;
106+
/// let ikm = b"MyPassword0";
107+
/// let salt = b"12345678ABCDEFGH";
108+
/// let mut extract_out = [0u8; ws::WC_SHA256_DIGEST_SIZE as usize];
109+
/// hkdf_extract(HMAC::TYPE_SHA256, Some(salt), ikm, &mut extract_out).expect("Error with hkdf_extract()");
110+
/// let info = b"0";
111+
/// let mut expand_out = [0u8; 16];
112+
/// hkdf_expand(HMAC::TYPE_SHA256, &extract_out, Some(info), &mut expand_out).expect("Error with hkdf_expand()");
113+
/// ```
114+
pub fn hkdf_expand(typ: i32, key: &[u8], info: Option<&[u8]>, out: &mut [u8]) -> Result<(), i32> {
115+
let key_size = key.len() as u32;
116+
let mut info_ptr = core::ptr::null();
117+
let mut info_size = 0u32;
118+
if let Some(info) = info {
119+
info_ptr = info.as_ptr();
120+
info_size = info.len() as u32;
121+
}
122+
let out_size = out.len() as u32;
123+
let rc = unsafe {
124+
ws::wc_HKDF_Expand(typ, key.as_ptr(), key_size,
125+
info_ptr, info_size, out.as_mut_ptr(), out_size)
126+
};
127+
if rc != 0 {
128+
return Err(rc);
129+
}
130+
Ok(())
131+
}
132+
133+
/// Perform HMAC Key Derivation Function (HKDF) operation.
134+
///
135+
/// This utilizes HMAC to convert `key`, with an optional `salt` and
136+
/// optional `info` into a derived key which is written to `out`.
137+
///
138+
/// This one-shot function is a combination of `hkdf_extract()` and `hkdf_expand()`.
139+
///
140+
/// # Parameters
141+
///
142+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
143+
/// * `key`: Initial Key Material (IKM).
144+
/// * `salt`: Salt value (optional).
145+
/// * `info`: Optional buffer containing additional info.
146+
/// * `out`: Output buffer to store HKDF result. The buffer can be any size.
147+
///
148+
/// # Returns
149+
///
150+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
151+
/// library error code value.
152+
///
153+
/// # Example
154+
///
155+
/// ```rust
156+
/// use wolfssl::wolfcrypt::hkdf::*;
157+
/// use wolfssl::wolfcrypt::hmac::HMAC;
158+
/// let ikm = b"MyPassword0";
159+
/// let salt = b"12345678ABCDEFGH";
160+
/// let info = b"0";
161+
/// let mut out = [0u8; 16];
162+
/// hkdf(HMAC::TYPE_SHA256, ikm, Some(salt), Some(info), &mut out).expect("Error with hkdf()");
163+
/// ```
164+
pub fn hkdf(typ: i32, key: &[u8], salt: Option<&[u8]>, info: Option<&[u8]>, out: &mut[u8]) -> Result<(), i32> {
165+
let key_size = key.len() as u32;
166+
let mut salt_ptr = core::ptr::null();
167+
let mut salt_size = 0u32;
168+
if let Some(salt) = salt {
169+
salt_ptr = salt.as_ptr();
170+
salt_size = salt.len() as u32;
171+
}
172+
let mut info_ptr = core::ptr::null();
173+
let mut info_size = 0u32;
174+
if let Some(info) = info {
175+
info_ptr = info.as_ptr();
176+
info_size = info.len() as u32;
177+
}
178+
let out_size = out.len() as u32;
179+
let rc = unsafe {
180+
ws::wc_HKDF(typ, key.as_ptr(), key_size, salt_ptr, salt_size,
181+
info_ptr, info_size, out.as_mut_ptr(), out_size)
182+
};
183+
if rc != 0 {
184+
return Err(rc);
185+
}
186+
Ok(())
187+
}

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

Lines changed: 0 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -264,163 +264,3 @@ impl Drop for HMAC {
264264
unsafe { ws::wc_HmacFree(&mut self.wc_hmac); }
265265
}
266266
}
267-
268-
/// HMAC Key Derivation Function (HKDF) functionality.
269-
pub struct HKDF {
270-
}
271-
272-
impl HKDF {
273-
/// Perform HKDF-Extract operation.
274-
///
275-
/// This utilizes HMAC to convert `key`, with an optional `salt`, into a
276-
/// derived key which is written to `out`.
277-
///
278-
/// # Parameters
279-
///
280-
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
281-
/// * `salt`: Salt value (optional).
282-
/// * `key`: Initial Key Material (IKM).
283-
/// * `out`: Output buffer to store HKDF-Extract result. The size of this
284-
/// buffer must match `HMAC::get_hmac_size_by_type(typ)`.
285-
///
286-
/// # Returns
287-
///
288-
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
289-
/// library error code value.
290-
///
291-
/// # Example
292-
///
293-
/// ```rust
294-
/// use wolfssl::wolfcrypt::hmac::{HMAC,HKDF};
295-
/// use wolfssl_sys as ws;
296-
/// let ikm = b"MyPassword0";
297-
/// let salt = b"12345678ABCDEFGH";
298-
/// let mut extract_out = [0u8; ws::WC_SHA256_DIGEST_SIZE as usize];
299-
/// HKDF::extract(HMAC::TYPE_SHA256, Some(salt), ikm, &mut extract_out).expect("Error with extract()");
300-
/// ```
301-
pub fn extract(typ: i32, salt: Option<&[u8]>, key: &[u8], out: &mut [u8]) -> Result<(), i32> {
302-
let mut salt_ptr = core::ptr::null();
303-
let mut salt_size = 0u32;
304-
if let Some(salt) = salt {
305-
salt_ptr = salt.as_ptr();
306-
salt_size = salt.len() as u32;
307-
}
308-
let key_size = key.len() as u32;
309-
if out.len() != HMAC::get_hmac_size_by_type(typ)? {
310-
return Err(ws::wolfCrypt_ErrorCodes_BUFFER_E);
311-
}
312-
let rc = unsafe {
313-
ws::wc_HKDF_Extract(typ, salt_ptr, salt_size,
314-
key.as_ptr(), key_size, out.as_mut_ptr())
315-
};
316-
if rc != 0 {
317-
return Err(rc);
318-
}
319-
Ok(())
320-
}
321-
322-
/// Perform HKDF-Expand operation.
323-
///
324-
/// This utilizes HMAC to convert `key`, with optional `info`, into a
325-
/// derived key which is written to `out`.
326-
///
327-
/// # Parameters
328-
///
329-
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
330-
/// * `key`: Key to use for KDF (typically output of `HKDF::extract()`).
331-
/// * `info`: Optional buffer containing additional info.
332-
/// * `out`: Output buffer to store HKDF-Expand result. The buffer can be
333-
/// any size.
334-
///
335-
/// # Returns
336-
///
337-
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
338-
/// library error code value.
339-
///
340-
/// # Example
341-
///
342-
/// ```rust
343-
/// use wolfssl::wolfcrypt::hmac::{HMAC,HKDF};
344-
/// use wolfssl_sys as ws;
345-
/// let ikm = b"MyPassword0";
346-
/// let salt = b"12345678ABCDEFGH";
347-
/// let mut extract_out = [0u8; ws::WC_SHA256_DIGEST_SIZE as usize];
348-
/// HKDF::extract(HMAC::TYPE_SHA256, Some(salt), ikm, &mut extract_out).expect("Error with extract()");
349-
/// let info = b"0";
350-
/// let mut expand_out = [0u8; 16];
351-
/// HKDF::expand(HMAC::TYPE_SHA256, &extract_out, Some(info), &mut expand_out).expect("Error with expand()");
352-
/// ```
353-
pub fn expand(typ: i32, key: &[u8], info: Option<&[u8]>, out: &mut [u8]) -> Result<(), i32> {
354-
let key_size = key.len() as u32;
355-
let mut info_ptr = core::ptr::null();
356-
let mut info_size = 0u32;
357-
if let Some(info) = info {
358-
info_ptr = info.as_ptr();
359-
info_size = info.len() as u32;
360-
}
361-
let out_size = out.len() as u32;
362-
let rc = unsafe {
363-
ws::wc_HKDF_Expand(typ, key.as_ptr(), key_size,
364-
info_ptr, info_size, out.as_mut_ptr(), out_size)
365-
};
366-
if rc != 0 {
367-
return Err(rc);
368-
}
369-
Ok(())
370-
}
371-
372-
/// Perform HMAC Key Derivation Function (HKDF) operation.
373-
///
374-
/// This utilizes HMAC to convert `key`, with an optional `salt` and
375-
/// optional `info` into a derived key which is written to `out`.
376-
///
377-
/// This one-shot function is a combination of `extract()` and `expand()`.
378-
///
379-
/// # Parameters
380-
///
381-
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
382-
/// * `key`: Initial Key Material (IKM).
383-
/// * `salt`: Salt value (optional).
384-
/// * `info`: Optional buffer containing additional info.
385-
/// * `out`: Output buffer to store HKDF result. The buffer can be any size.
386-
///
387-
/// # Returns
388-
///
389-
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
390-
/// library error code value.
391-
///
392-
/// # Example
393-
///
394-
/// ```rust
395-
/// use wolfssl::wolfcrypt::hmac::{HMAC,HKDF};
396-
/// let ikm = b"MyPassword0";
397-
/// let salt = b"12345678ABCDEFGH";
398-
/// let info = b"0";
399-
/// let mut out = [0u8; 16];
400-
/// HKDF::hkdf(HMAC::TYPE_SHA256, ikm, Some(salt), Some(info), &mut out).expect("Error with hkdf()");
401-
/// ```
402-
pub fn hkdf(typ: i32, key: &[u8], salt: Option<&[u8]>, info: Option<&[u8]>, out: &mut[u8]) -> Result<(), i32> {
403-
let key_size = key.len() as u32;
404-
let mut salt_ptr = core::ptr::null();
405-
let mut salt_size = 0u32;
406-
if let Some(salt) = salt {
407-
salt_ptr = salt.as_ptr();
408-
salt_size = salt.len() as u32;
409-
}
410-
let mut info_ptr = core::ptr::null();
411-
let mut info_size = 0u32;
412-
if let Some(info) = info {
413-
info_ptr = info.as_ptr();
414-
info_size = info.len() as u32;
415-
}
416-
let out_size = out.len() as u32;
417-
let rc = unsafe {
418-
ws::wc_HKDF(typ, key.as_ptr(), key_size, salt_ptr, salt_size,
419-
info_ptr, info_size, out.as_mut_ptr(), out_size)
420-
};
421-
if rc != 0 {
422-
return Err(rc);
423-
}
424-
Ok(())
425-
}
426-
}

0 commit comments

Comments
 (0)