@@ -16,7 +16,8 @@ use crate::error::map_error;
16
16
use crate :: {
17
17
arc_castable, box_castable, ffi_panic_boundary, free_arc, free_box, rustls_result,
18
18
set_arc_mut_ptr, set_boxed_mut_ptr, to_boxed_mut_ptr, try_clone_arc, try_mut_from_ptr,
19
- try_mut_from_ptr_ptr, try_ref_from_ptr, try_ref_from_ptr_ptr, try_slice, try_take,
19
+ try_mut_from_ptr_ptr, try_ref_from_ptr, try_ref_from_ptr_ptr, try_slice, try_slice_mut,
20
+ try_take,
20
21
} ;
21
22
22
23
box_castable ! {
@@ -338,6 +339,29 @@ pub extern "C" fn rustls_crypto_provider_load_key(
338
339
}
339
340
}
340
341
342
+ /// Write `len` bytes of cryptographically secure random data to `buff` using the crypto provider.
343
+ ///
344
+ /// `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership
345
+ /// of the buffer.
346
+ ///
347
+ /// Returns `RUSTLS_RESULT_OK` on success, or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure.
348
+ #[ no_mangle]
349
+ pub extern "C" fn rustls_crypto_provider_random (
350
+ provider : * const rustls_crypto_provider ,
351
+ buff : * mut u8 ,
352
+ len : size_t ,
353
+ ) -> rustls_result {
354
+ ffi_panic_boundary ! {
355
+ match try_clone_arc!( provider)
356
+ . secure_random
357
+ . fill( try_slice_mut!( buff, len) )
358
+ {
359
+ Ok ( _) => rustls_result:: Ok ,
360
+ Err ( _) => rustls_result:: GetRandomFailed ,
361
+ }
362
+ }
363
+ }
364
+
341
365
/// Frees the `rustls_crypto_provider`.
342
366
///
343
367
/// Calling with `NULL` is fine.
@@ -388,6 +412,30 @@ pub extern "C" fn rustls_default_crypto_provider_ciphersuites_get(
388
412
}
389
413
}
390
414
415
+ /// Write `len` bytes of cryptographically secure random data to `buff` using the process-wide
416
+ /// default crypto provider.
417
+ ///
418
+ /// `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership
419
+ /// of the buffer.
420
+ ///
421
+ /// Returns `RUSTLS_RESULT_OK` on success, and one of `RUSTLS_RESULT_NO_DEFAULT_CRYPTO_PROVIDER`
422
+ /// or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure.
423
+ #[ no_mangle]
424
+ pub extern "C" fn rustls_default_crypto_provider_random (
425
+ buff : * mut u8 ,
426
+ len : size_t ,
427
+ ) -> rustls_result {
428
+ ffi_panic_boundary ! {
429
+ match get_default_or_install_from_crate_features( ) {
430
+ Some ( provider) => match provider. secure_random. fill( try_slice_mut!( buff, len) ) {
431
+ Ok ( _) => rustls_result:: Ok ,
432
+ Err ( _) => rustls_result:: GetRandomFailed ,
433
+ } ,
434
+ None => rustls_result:: NoDefaultCryptoProvider ,
435
+ }
436
+ }
437
+ }
438
+
391
439
box_castable ! {
392
440
/// A signing key that can be used to construct a certified key.
393
441
// NOTE: we box cast an arc over the dyn trait per the pattern described
@@ -445,3 +493,49 @@ fn provider_from_crate_features() -> Option<CryptoProvider> {
445
493
#[ allow( unreachable_code) ]
446
494
None
447
495
}
496
+
497
+ #[ cfg( all( test, not( miri) ) ) ]
498
+ mod tests {
499
+ use std:: ptr;
500
+
501
+ use super :: * ;
502
+ use rustls_result;
503
+
504
+ /// Simple smoketest of CSRNG fill with specific provider.
505
+ #[ test]
506
+ fn random_data ( ) {
507
+ let provider = rustls_crypto_provider_default ( ) ;
508
+ assert ! ( !provider. is_null( ) ) ;
509
+
510
+ // NULL buffer should return an error.
511
+ let result = rustls_crypto_provider_random ( provider, ptr:: null_mut ( ) , 1337 ) ;
512
+ assert_eq ! ( result, rustls_result:: NullParameter ) ;
513
+
514
+ let mut buff = vec ! [ 0 ; 32 ] ;
515
+
516
+ // NULL provider should return an error and not touch buff.
517
+ let result = rustls_crypto_provider_random ( ptr:: null ( ) , buff. as_mut_ptr ( ) , buff. len ( ) ) ;
518
+ assert_eq ! ( buff, vec![ 0 ; 32 ] ) ;
519
+ assert_eq ! ( result, rustls_result:: NullParameter ) ;
520
+
521
+ // Proper parameters should return OK and overwrite the buffer.
522
+ let result = rustls_crypto_provider_random ( provider, buff. as_mut_ptr ( ) , buff. len ( ) ) ;
523
+ assert_eq ! ( result, rustls_result:: Ok ) ;
524
+ assert_ne ! ( buff, vec![ 0 ; 32 ] ) ;
525
+ }
526
+
527
+ /// Simple smoketest of CSRNG fill with default provider.
528
+ #[ test]
529
+ fn default_random_data ( ) {
530
+ // NULL buffer should return an error.
531
+ let result = rustls_default_crypto_provider_random ( ptr:: null_mut ( ) , 1337 ) ;
532
+ assert_eq ! ( result, rustls_result:: NullParameter ) ;
533
+
534
+ let mut buff = vec ! [ 0 ; 32 ] ;
535
+
536
+ // Proper parameters should return OK and overwrite the buffer.
537
+ let result = rustls_default_crypto_provider_random ( buff. as_mut_ptr ( ) , buff. len ( ) ) ;
538
+ assert_eq ! ( result, rustls_result:: Ok ) ;
539
+ assert_ne ! ( buff, vec![ 0 ; 32 ] ) ;
540
+ }
541
+ }
0 commit comments