Skip to content

Commit 33b08ed

Browse files
Merge pull request #9328 from holtrop/rust-wc-hmac
Rust wrapper: add wolfssl::wolfcrypt::hmac module
2 parents 985a090 + 2721231 commit 33b08ed

File tree

6 files changed

+542
-0
lines changed

6 files changed

+542
-0
lines changed

wrapper/rust/include.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ 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
23+
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hmac.rs
2224
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/random.rs
2325
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/rsa.rs
2426
EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/sha.rs
2527
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_aes.rs
2628
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_dh.rs
2729
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_ecc.rs
30+
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hkdf.rs
31+
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hmac.rs
2832
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_random.rs
2933
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_rsa.rs
3034
EXTRA_DIST += wrapper/rust/wolfssl/tests/test_sha.rs

wrapper/rust/wolfssl/src/wolfcrypt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
pub mod aes;
2222
pub mod dh;
2323
pub mod ecc;
24+
pub mod hkdf;
25+
pub mod hmac;
2426
pub mod random;
2527
pub mod rsa;
2628
pub mod sha;
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+
}

0 commit comments

Comments
 (0)