Skip to content

Commit aba0246

Browse files
authored
Merge pull request #9389 from holtrop/rust-wc-pbkdf2
Rust wrapper: add PBKDF2 and PKCS #12 PBKDF wrappers
2 parents b0a7f59 + 797194f commit aba0246

File tree

5 files changed

+267
-2
lines changed

5 files changed

+267
-2
lines changed

doc/dox_comments/header_files-ja/pwdbased.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen,
9696
byte pass[] = { }; // initialize with password
9797
byte salt[] = { }; // initialize with salt
9898
99-
ret = wc_PKCS512_PBKDF(key, pass, sizeof(pass), salt, sizeof(salt), 2048,
99+
ret = wc_PKCS12_PBKDF(key, pass, sizeof(pass), salt, sizeof(salt), 2048,
100100
sizeof(key), SHA512, 1);
101101
if ( ret != 0 ) {
102102
// error deriving key from password

doc/dox_comments/header_files/pwdbased.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen,
155155
byte pass[] = { }; // initialize with password
156156
byte salt[] = { }; // initialize with salt
157157
158-
ret = wc_PKCS512_PBKDF(key, pass, sizeof(pass), salt, sizeof(salt), 2048,
158+
ret = wc_PKCS12_PBKDF(key, pass, sizeof(pass), salt, sizeof(salt), 2048,
159159
sizeof(key), WC_SHA512, 1);
160160
if ( ret != 0 ) {
161161
// error deriving key from password

wrapper/rust/wolfssl-sys/headers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
#include "wolfssl/wolfcrypt/signature.h"
1919
#include "wolfssl/wolfcrypt/logging.h"
2020
#include "wolfssl/wolfcrypt/aes.h"
21+
#include "wolfssl/wolfcrypt/pwdbased.h"

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

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,231 @@ pub const SRTCP_LABEL_SALT: u8 = ws::WC_SRTCP_LABEL_SALT as u8;
3838
pub const SRTP_LABEL_HDR_ENCRYPTION: u8 = ws::WC_SRTP_LABEL_HDR_ENCRYPTION as u8;
3939
pub const SRTP_LABEL_HDR_SALT: u8 = ws::WC_SRTP_LABEL_HDR_SALT as u8;
4040

41+
/// Implement Password Based Key Derivation Function 2 (PBKDF2) converting an
42+
/// input password with a concatenated salt into a more secure key which is
43+
/// written to the `out` buffer.
44+
///
45+
/// # Parameters
46+
///
47+
/// * `password`: Password to use for key derivation.
48+
/// * `salt`: Salt value to use for key derivation.
49+
/// * `iterations`: Number of times to process the hash.
50+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
51+
/// * `out`: Output buffer in which to store the generated key.
52+
///
53+
/// # Returns
54+
///
55+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
56+
/// library error code value.
57+
///
58+
/// # Example
59+
///
60+
/// ```rust
61+
/// use wolfssl::wolfcrypt::kdf::pbkdf2;
62+
/// use wolfssl::wolfcrypt::hmac::HMAC;
63+
/// let password = b"passwordpassword";
64+
/// let salt = [0x78u8, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06];
65+
/// let iterations = 2048;
66+
/// let expected_key = [
67+
/// 0x43u8, 0x6d, 0xb5, 0xe8, 0xd0, 0xfb, 0x3f, 0x35, 0x42, 0x48, 0x39, 0xbc,
68+
/// 0x2d, 0xd4, 0xf9, 0x37, 0xd4, 0x95, 0x16, 0xa7, 0x2a, 0x9a, 0x21, 0xd1
69+
/// ];
70+
/// let mut keyout = [0u8; 24];
71+
/// pbkdf2(password, &salt, iterations, HMAC::TYPE_SHA256, &mut keyout).expect("Error with pbkdf2()");
72+
/// assert_eq!(keyout, expected_key);
73+
/// ```
74+
pub fn pbkdf2(password: &[u8], salt: &[u8], iterations: i32, typ: i32, out: &mut [u8]) -> Result<(), i32> {
75+
let password_size = password.len() as i32;
76+
let salt_size = salt.len() as i32;
77+
let out_size = out.len() as i32;
78+
let rc = unsafe {
79+
ws::wc_PBKDF2(out.as_mut_ptr(), password.as_ptr(), password_size,
80+
salt.as_ptr(), salt_size, iterations, out_size, typ)
81+
};
82+
if rc != 0 {
83+
return Err(rc);
84+
}
85+
Ok(())
86+
}
87+
88+
/// Implement Password Based Key Derivation Function 2 (PBKDF2) converting an
89+
/// input password with a concatenated salt into a more secure key which is
90+
/// written to the `out` buffer.
91+
/// This version allows optional heap hint and device ID parameters.
92+
///
93+
/// # Parameters
94+
///
95+
/// * `password`: Password to use for key derivation.
96+
/// * `salt`: Salt value to use for key derivation.
97+
/// * `iterations`: Number of times to process the hash.
98+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
99+
/// * `heap`: Optional heap hint.
100+
/// * `dev_id` Optional device ID to use with crypto callbacks or async hardware.
101+
/// * `out`: Output buffer in which to store the generated key.
102+
///
103+
/// # Returns
104+
///
105+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
106+
/// library error code value.
107+
///
108+
/// # Example
109+
///
110+
/// ```rust
111+
/// use wolfssl::wolfcrypt::kdf::pbkdf2_ex;
112+
/// use wolfssl::wolfcrypt::hmac::HMAC;
113+
/// let password = b"passwordpassword";
114+
/// let salt = [0x78u8, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06];
115+
/// let iterations = 2048;
116+
/// let expected_key = [
117+
/// 0x43u8, 0x6d, 0xb5, 0xe8, 0xd0, 0xfb, 0x3f, 0x35, 0x42, 0x48, 0x39, 0xbc,
118+
/// 0x2d, 0xd4, 0xf9, 0x37, 0xd4, 0x95, 0x16, 0xa7, 0x2a, 0x9a, 0x21, 0xd1
119+
/// ];
120+
/// let mut keyout = [0u8; 24];
121+
/// pbkdf2_ex(password, &salt, iterations, HMAC::TYPE_SHA256, None, None, &mut keyout).expect("Error with pbkdf2()");
122+
/// assert_eq!(keyout, expected_key);
123+
/// ```
124+
pub fn pbkdf2_ex(password: &[u8], salt: &[u8], iterations: i32, typ: i32, heap: Option<*mut std::os::raw::c_void>, dev_id: Option<i32>, out: &mut [u8]) -> Result<(), i32> {
125+
let password_size = password.len() as i32;
126+
let salt_size = salt.len() as i32;
127+
let out_size = out.len() as i32;
128+
let heap = match heap {
129+
Some(heap) => heap,
130+
None => core::ptr::null_mut(),
131+
};
132+
let dev_id = match dev_id {
133+
Some(dev_id) => dev_id,
134+
None => ws::INVALID_DEVID,
135+
};
136+
let rc = unsafe {
137+
ws::wc_PBKDF2_ex(out.as_mut_ptr(), password.as_ptr(), password_size,
138+
salt.as_ptr(), salt_size, iterations, out_size, typ, heap, dev_id)
139+
};
140+
if rc != 0 {
141+
return Err(rc);
142+
}
143+
Ok(())
144+
}
145+
146+
/// This function implements the Password Based Key Derivation Function
147+
/// (PBKDF) described in RFC 7292 Appendix B. This function converts an input
148+
/// password with a concatenated salt into a more secure key, which it stores
149+
/// in `out`. It allows the user to select any of the supported HMAC hash
150+
/// functions, including: WC_MD5, WC_SHA, WC_SHA256, WC_SHA384, WC_SHA512,
151+
/// WC_SHA3_224, WC_SHA3_256, WC_SHA3_384 or WC_SHA3_512.
152+
///
153+
/// # Parameters
154+
///
155+
/// * `password`: Password to use for key derivation.
156+
/// * `salt`: Salt value to use for key derivation.
157+
/// * `iterations`: Number of times to process the hash.
158+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
159+
/// * `id`: Byte identifier indicating the purpose of key generation. It is
160+
/// used to diversify the key output, and should be assigned as follows:
161+
/// ID=1: pseudorandom bits are to be used as key material for performing
162+
/// encryption or decryption. ID=2: pseudorandom bits are to be used an IV
163+
/// (Initial Value) for encryption or decryption. ID=3: pseudorandom bits
164+
/// are to be used as an integrity key for MACing.
165+
/// * `out`: Output buffer in which to store the generated key.
166+
///
167+
/// # Returns
168+
///
169+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
170+
/// library error code value.
171+
///
172+
/// # Example
173+
///
174+
/// ```rust
175+
/// use wolfssl::wolfcrypt::kdf::pkcs12_pbkdf;
176+
/// use wolfssl::wolfcrypt::hmac::HMAC;
177+
/// let password = [0x00u8, 0x73, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x67, 0x00, 0x00];
178+
/// let salt = [0x0au8, 0x58, 0xCF, 0x64, 0x53, 0x0d, 0x82, 0x3f];
179+
/// let expected_key = [
180+
/// 0x27u8, 0xE9, 0x0D, 0x7E, 0xD5, 0xA1, 0xC4, 0x11,
181+
/// 0xBA, 0x87, 0x8B, 0xC0, 0x90, 0xF5, 0xCE, 0xBE,
182+
/// 0x5E, 0x9D, 0x5F, 0xE3, 0xD6, 0x2B, 0x73, 0xAA
183+
/// ];
184+
/// let iterations = 1;
185+
/// let mut keyout = [0u8; 24];
186+
/// pkcs12_pbkdf(&password, &salt, iterations, HMAC::TYPE_SHA256, 1, &mut keyout).expect("Error with pkcs12_pbkdf()");
187+
/// assert_eq!(keyout, expected_key);
188+
/// ```
189+
pub fn pkcs12_pbkdf(password: &[u8], salt: &[u8], iterations: i32, typ: i32, id: i32, out: &mut [u8]) -> Result<(), i32> {
190+
let password_size = password.len() as i32;
191+
let salt_size = salt.len() as i32;
192+
let out_size = out.len() as i32;
193+
let rc = unsafe {
194+
ws::wc_PKCS12_PBKDF(out.as_mut_ptr(), password.as_ptr(), password_size,
195+
salt.as_ptr(), salt_size, iterations, out_size, typ, id)
196+
};
197+
if rc != 0 {
198+
return Err(rc);
199+
}
200+
Ok(())
201+
}
202+
203+
/// This function implements the Password Based Key Derivation Function
204+
/// (PBKDF) described in RFC 7292 Appendix B. This function converts an input
205+
/// password with a concatenated salt into a more secure key, which it stores
206+
/// in `out`. It allows the user to select any of the supported HMAC hash
207+
/// functions, including: WC_MD5, WC_SHA, WC_SHA256, WC_SHA384, WC_SHA512,
208+
/// WC_SHA3_224, WC_SHA3_256, WC_SHA3_384 or WC_SHA3_512.
209+
/// This version allows an optional heap hint parameter.
210+
///
211+
/// # Parameters
212+
///
213+
/// * `password`: Password to use for key derivation.
214+
/// * `salt`: Salt value to use for key derivation.
215+
/// * `iterations`: Number of times to process the hash.
216+
/// * `typ`: Hash type, one of `HMAC::TYPE_*`.
217+
/// * `id`: Byte identifier indicating the purpose of key generation. It is
218+
/// used to diversify the key output, and should be assigned as follows:
219+
/// ID=1: pseudorandom bits are to be used as key material for performing
220+
/// encryption or decryption. ID=2: pseudorandom bits are to be used an IV
221+
/// (Initial Value) for encryption or decryption. ID=3: pseudorandom bits
222+
/// are to be used as an integrity key for MACing.
223+
/// * `heap`: Optional heap hint.
224+
/// * `out`: Output buffer in which to store the generated key.
225+
///
226+
/// # Returns
227+
///
228+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
229+
/// library error code value.
230+
///
231+
/// # Example
232+
///
233+
/// ```rust
234+
/// use wolfssl::wolfcrypt::kdf::pkcs12_pbkdf_ex;
235+
/// use wolfssl::wolfcrypt::hmac::HMAC;
236+
/// let password = [0x00u8, 0x73, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x67, 0x00, 0x00];
237+
/// let salt = [0x0au8, 0x58, 0xCF, 0x64, 0x53, 0x0d, 0x82, 0x3f];
238+
/// let expected_key = [
239+
/// 0x27u8, 0xE9, 0x0D, 0x7E, 0xD5, 0xA1, 0xC4, 0x11,
240+
/// 0xBA, 0x87, 0x8B, 0xC0, 0x90, 0xF5, 0xCE, 0xBE,
241+
/// 0x5E, 0x9D, 0x5F, 0xE3, 0xD6, 0x2B, 0x73, 0xAA
242+
/// ];
243+
/// let iterations = 1;
244+
/// let mut keyout = [0u8; 24];
245+
/// pkcs12_pbkdf_ex(&password, &salt, iterations, HMAC::TYPE_SHA256, 1, None, &mut keyout).expect("Error with pkcs12_pbkdf_ex()");
246+
/// assert_eq!(keyout, expected_key);
247+
/// ```
248+
pub fn pkcs12_pbkdf_ex(password: &[u8], salt: &[u8], iterations: i32, typ: i32, id: i32, heap: Option<*mut std::os::raw::c_void>, out: &mut [u8]) -> Result<(), i32> {
249+
let password_size = password.len() as i32;
250+
let salt_size = salt.len() as i32;
251+
let out_size = out.len() as i32;
252+
let heap = match heap {
253+
Some(heap) => heap,
254+
None => core::ptr::null_mut(),
255+
};
256+
let rc = unsafe {
257+
ws::wc_PKCS12_PBKDF_ex(out.as_mut_ptr(), password.as_ptr(), password_size,
258+
salt.as_ptr(), salt_size, iterations, out_size, typ, id, heap)
259+
};
260+
if rc != 0 {
261+
return Err(rc);
262+
}
263+
Ok(())
264+
}
265+
41266
/// Perform RFC 5869 HKDF-Extract operation for TLS v1.3 key derivation.
42267
///
43268
/// # Parameters

wrapper/rust/wolfssl/tests/test_kdf.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,45 @@ use wolfssl::wolfcrypt::hmac::HMAC;
22
use wolfssl::wolfcrypt::kdf::*;
33
use wolfssl::wolfcrypt::sha::SHA256;
44

5+
#[test]
6+
fn test_pbkdf2() {
7+
let password = b"passwordpassword";
8+
let salt = [0x78u8, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06];
9+
let iterations = 2048;
10+
let expected_key = [
11+
0x43u8, 0x6d, 0xb5, 0xe8, 0xd0, 0xfb, 0x3f, 0x35, 0x42, 0x48, 0x39, 0xbc,
12+
0x2d, 0xd4, 0xf9, 0x37, 0xd4, 0x95, 0x16, 0xa7, 0x2a, 0x9a, 0x21, 0xd1
13+
];
14+
15+
let mut keyout = [0u8; 24];
16+
pbkdf2(password, &salt, iterations, HMAC::TYPE_SHA256, &mut keyout).expect("Error with pbkdf2()");
17+
assert_eq!(keyout, expected_key);
18+
19+
let mut keyout = [0u8; 24];
20+
pbkdf2_ex(password, &salt, iterations, HMAC::TYPE_SHA256, None, None, &mut keyout).expect("Error with pbkdf2()");
21+
assert_eq!(keyout, expected_key);
22+
}
23+
24+
#[test]
25+
fn test_pkcs12_pbkdf() {
26+
let password = [0x00u8, 0x73, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x67, 0x00, 0x00];
27+
let salt = [0x0au8, 0x58, 0xCF, 0x64, 0x53, 0x0d, 0x82, 0x3f];
28+
let expected_key = [
29+
0x27u8, 0xE9, 0x0D, 0x7E, 0xD5, 0xA1, 0xC4, 0x11,
30+
0xBA, 0x87, 0x8B, 0xC0, 0x90, 0xF5, 0xCE, 0xBE,
31+
0x5E, 0x9D, 0x5F, 0xE3, 0xD6, 0x2B, 0x73, 0xAA
32+
];
33+
let iterations = 1;
34+
35+
let mut keyout = [0u8; 24];
36+
pkcs12_pbkdf(&password, &salt, iterations, HMAC::TYPE_SHA256, 1, &mut keyout).expect("Error with pkcs12_pbkdf()");
37+
assert_eq!(keyout, expected_key);
38+
39+
let mut keyout = [0u8; 24];
40+
pkcs12_pbkdf_ex(&password, &salt, iterations, HMAC::TYPE_SHA256, 1, None, &mut keyout).expect("Error with pkcs12_pbkdf_ex()");
41+
assert_eq!(keyout, expected_key);
42+
}
43+
544
#[test]
645
fn test_tls13_hkdf_extract_expand() {
746
let hash_hello1 = [

0 commit comments

Comments
 (0)