Skip to content

Commit 89f27ce

Browse files
authored
Merge pull request #9453 from holtrop/rust-wc-random-additions
Rust wrapper: add HAVE_HASHDRBG RNG functions
2 parents eac5c29 + 15b55ef commit 89f27ce

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

wrapper/rust/wolfssl/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ fn scan_cfg() -> Result<()> {
165165
check_cfg(&binding, "wc_SSH_KDF", "kdf_ssh");
166166
check_cfg(&binding, "wc_Tls13_HKDF_Extract_ex", "kdf_tls13");
167167

168+
/* random */
169+
check_cfg(&binding, "wc_RNG_DRBG_Reseed", "random_hashdrbg");
170+
168171
/* rsa */
169172
check_cfg(&binding, "wc_InitRsaKey", "rsa");
170173
check_cfg(&binding, "wc_RsaDirect", "rsa_direct");

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

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,132 @@ impl RNG {
159159
}
160160
}
161161

162+
/// Create and test functionality of DRBG.
163+
///
164+
/// # Parameters
165+
///
166+
/// * `nonce`: Optional nonce to use to initialize DRBG.
167+
/// * `seed_a`: Buffer containing seed data (required).
168+
/// * `seed_b`: Optional buffer containing more seed data. If present, the
169+
/// DRBG will be reseeded.
170+
/// * `output`: Output buffer.
171+
///
172+
/// # Returns
173+
///
174+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
175+
/// library error code value.
176+
///
177+
/// # Example
178+
///
179+
/// ```rust
180+
/// #![cfg(random_hashdrbg)]
181+
/// use wolfssl::wolfcrypt::random::RNG;
182+
/// let nonce = [99u8, 88, 77, 66];
183+
/// let seed_a = [42u8, 33, 55, 88];
184+
/// let seed_b = [45u8, 10, 20, 30];
185+
/// let mut output = [0u8; 128];
186+
/// RNG::health_test(Some(&nonce), &seed_a, Some(&seed_b), &mut output).expect("Error with health_test()");
187+
/// ```
188+
#[cfg(random_hashdrbg)]
189+
pub fn health_test(nonce: Option<&[u8]>, seed_a: &[u8], seed_b: Option<&[u8]>, output: &mut [u8]) -> Result<(), i32> {
190+
Self::health_test_ex(nonce, seed_a, seed_b, output, None, None)
191+
}
192+
193+
/// Create and test functionality of DRBG with optional heap and device ID.
194+
///
195+
/// # Parameters
196+
///
197+
/// * `nonce`: Optional nonce to use to initialize DRBG.
198+
/// * `seed_a`: Buffer containing seed data (required).
199+
/// * `seed_b`: Optional buffer containing more seed data. If present, the
200+
/// DRBG will be reseeded.
201+
/// * `output`: Output buffer.
202+
/// * `heap`: Optional heap hint.
203+
/// * `dev_id` Optional device ID to use with crypto callbacks or async hardware.
204+
///
205+
/// # Returns
206+
///
207+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
208+
/// library error code value.
209+
///
210+
/// # Example
211+
///
212+
/// ```rust
213+
/// #![cfg(random_hashdrbg)]
214+
/// use wolfssl::wolfcrypt::random::RNG;
215+
/// let nonce = [99u8, 88, 77, 66];
216+
/// let seed_a = [42u8, 33, 55, 88];
217+
/// let seed_b = [45u8, 10, 20, 30];
218+
/// let mut output = [0u8; 128];
219+
/// RNG::health_test_ex(Some(&nonce), &seed_a, Some(&seed_b), &mut output, None, None).expect("Error with health_test_ex()");
220+
/// ```
221+
#[cfg(random_hashdrbg)]
222+
pub fn health_test_ex(nonce: Option<&[u8]>, seed_a: &[u8], seed_b: Option<&[u8]>, output: &mut [u8], heap: Option<*mut std::os::raw::c_void>, dev_id: Option<i32>) -> Result<(), i32> {
223+
let mut nonce_ptr = core::ptr::null();
224+
let mut nonce_size = 0u32;
225+
if let Some(nonce) = nonce {
226+
nonce_ptr = nonce.as_ptr();
227+
nonce_size = nonce.len() as u32;
228+
}
229+
let seed_a_size = seed_a.len() as u32;
230+
let mut seed_b_ptr = core::ptr::null();
231+
let mut seed_b_size = 0u32;
232+
if let Some(seed_b) = seed_b {
233+
seed_b_ptr = seed_b.as_ptr();
234+
seed_b_size = seed_b.len() as u32;
235+
}
236+
let output_size = output.len() as u32;
237+
let heap = match heap {
238+
Some(heap) => heap,
239+
None => core::ptr::null_mut(),
240+
};
241+
let dev_id = match dev_id {
242+
Some(dev_id) => dev_id,
243+
None => sys::INVALID_DEVID,
244+
};
245+
let rc = unsafe {
246+
sys::wc_RNG_HealthTest_ex(if seed_b_size > 0 {1} else {0},
247+
nonce_ptr, nonce_size,
248+
seed_a.as_ptr(), seed_a_size,
249+
seed_b_ptr, seed_b_size,
250+
output.as_mut_ptr(), output_size,
251+
heap, dev_id)
252+
};
253+
if rc != 0 {
254+
return Err(rc);
255+
}
256+
Ok(())
257+
}
258+
259+
/// Test a seed.
260+
///
261+
/// # Parameters
262+
///
263+
/// * `seed`: Buffer containing seed data.
264+
///
265+
/// # Returns
266+
///
267+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
268+
/// library error code value.
269+
///
270+
/// # Example
271+
///
272+
/// ```rust
273+
/// #![cfg(random_hashdrbg)]
274+
/// use wolfssl::wolfcrypt::random::RNG;
275+
/// let seed = [42u8, 33, 55, 88];
276+
/// RNG::test_seed(&seed).expect("Error with test_seed()");
277+
/// ```
278+
#[cfg(random_hashdrbg)]
279+
pub fn test_seed(seed: &[u8]) -> Result<(), i32> {
280+
let seed_size = seed.len() as u32;
281+
let rc = unsafe { sys::wc_RNG_TestSeed(seed.as_ptr(), seed_size) };
282+
if rc != 0 {
283+
return Err(rc);
284+
}
285+
Ok(())
286+
}
287+
162288
/// Generate a single cryptographically secure random byte.
163289
///
164290
/// This method calls the `wc_RNG_GenerateByte` wolfSSL library function to
@@ -202,6 +328,38 @@ impl RNG {
202328
Err(rc)
203329
}
204330
}
331+
332+
/// Reseed random number generator.
333+
///
334+
/// # Parameters
335+
///
336+
/// * `seed`: Buffer with new seed data.
337+
///
338+
/// # Returns
339+
///
340+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
341+
/// library error code value.
342+
///
343+
/// # Example
344+
///
345+
/// ```rust
346+
/// #![cfg(random_hashdrbg)]
347+
/// use wolfssl::wolfcrypt::random::RNG;
348+
/// let mut rng = RNG::new().expect("Failed to create RNG");
349+
/// let seed = [1u8, 2, 3, 4];
350+
/// rng.reseed(&seed).expect("Error with reseed()");
351+
/// ```
352+
#[cfg(random_hashdrbg)]
353+
pub fn reseed(&mut self, seed: &[u8]) -> Result<(), i32> {
354+
let seed_size = seed.len() as u32;
355+
let rc = unsafe {
356+
sys::wc_RNG_DRBG_Reseed(&mut self.wc_rng, seed.as_ptr(), seed_size)
357+
};
358+
if rc != 0 {
359+
return Err(rc);
360+
}
361+
Ok(())
362+
}
205363
}
206364

207365
impl Drop for RNG {

wrapper/rust/wolfssl/tests/test_random.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ fn test_rng_new_with_nonce_ex_and_drop() {
2828
let _rng = RNG::new_with_nonce_ex(&mut nonce, None, None).expect("Failed to create RNG");
2929
}
3030

31+
#[test]
32+
#[cfg(random_hashdrbg)]
33+
fn test_health_test() {
34+
let nonce = [99u8, 88, 77, 66];
35+
let seed_a = [42u8, 33, 55, 88];
36+
let seed_b = [45u8, 10, 20, 30];
37+
let mut output = [0u8; 128];
38+
RNG::health_test(Some(&nonce), &seed_a, Some(&seed_b), &mut output).expect("Error with health_test()");
39+
}
40+
41+
#[test]
42+
#[cfg(random_hashdrbg)]
43+
fn test_test_seed() {
44+
let seed = [42u8, 33, 55, 88];
45+
RNG::test_seed(&seed).expect("Error with test_seed()");
46+
}
47+
3148
// Test that generate_byte() returns random values.
3249
#[test]
3350
fn test_rng_generate_byte() {
@@ -70,3 +87,11 @@ fn test_rng_generate_block_u32() {
7087
assert_ne!(buffer[buffer.len() - 1], 0u32);
7188
assert_ne!(buffer[buffer.len() - 1], 0xFFFF_FFFFu32);
7289
}
90+
91+
#[test]
92+
#[cfg(random_hashdrbg)]
93+
fn test_rng_reseed() {
94+
let mut rng = RNG::new().expect("Failed to create RNG");
95+
let seed = [1u8, 2, 3, 4];
96+
rng.reseed(&seed).expect("Error with reseed()");
97+
}

0 commit comments

Comments
 (0)