Rust wrapper: add rand_core trait support

This commit is contained in:
Josh Holtrop
2026-03-09 15:11:40 -04:00
parent 7efc962d04
commit 07acf8d33d
5 changed files with 97 additions and 5 deletions
+7
View File
@@ -156,6 +156,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
[[package]]
name = "regex"
version = "1.11.2"
@@ -290,5 +296,6 @@ name = "wolfssl-wolfcrypt"
version = "1.2.0"
dependencies = [
"bindgen",
"rand_core",
"regex",
]
@@ -12,6 +12,10 @@ readme = "README.md"
[features]
std = []
rand_core = ["dep:rand_core"]
[dependencies]
rand_core = { version = "0.10", optional = true, default-features = false }
[build-dependencies]
bindgen = "0.72.1"
+8 -5
View File
@@ -1,16 +1,19 @@
FEATURES := rand_core
CARGO_FEATURE_FLAGS := --features $(FEATURES)
.PHONY: all
all:
cargo build
cargo clippy
cargo doc
cargo build $(CARGO_FEATURE_FLAGS)
cargo clippy $(CARGO_FEATURE_FLAGS)
cargo doc $(CARGO_FEATURE_FLAGS)
.PHONY: test
test:
cargo test -- --test-threads=1
cargo test $(CARGO_FEATURE_FLAGS) -- --test-threads=1
.PHONY: testfips
testfips:
cargo test --lib --bins --tests -- --test-threads=1
cargo test $(CARGO_FEATURE_FLAGS) --lib --bins --tests -- --test-threads=1
.PHONY: clean
clean:
@@ -380,6 +380,34 @@ impl RNG {
}
}
/// Implement `rand_core::TryRng` for `RNG`, allowing it to be used anywhere
/// a standard Rust RNG is expected.
///
/// `Error` is set to `Infallible` so that the blanket impls for `Rng` and
/// `CryptoRng` apply automatically. wolfSSL RNG failures cause a panic, which
/// is consistent with the infallible contract.
#[cfg(feature = "rand_core")]
impl rand_core::TryRng for RNG {
type Error = core::convert::Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
rand_core::utils::next_word_via_fill(self)
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
rand_core::utils::next_word_via_fill(self)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
self.generate_block(dest).expect("RNG failure");
Ok(())
}
}
/// Mark `RNG` as a cryptographically secure random number generator.
#[cfg(feature = "rand_core")]
impl rand_core::TryCryptoRng for RNG {}
impl Drop for RNG {
/// Safely free the underlying wolfSSL RNG context.
///
@@ -97,3 +97,53 @@ fn test_rng_reseed() {
let seed = [1u8, 2, 3, 4];
rng.reseed(&seed).expect("Error with reseed()");
}
#[test]
#[cfg(feature = "rand_core")]
fn test_rng_rand_core_fill_bytes() {
use rand_core::Rng;
let mut rng = RNG::new().expect("Failed to create RNG");
let mut buf = [0u8; 32];
rng.fill_bytes(&mut buf);
assert_ne!(buf, [0u8; 32]);
}
#[test]
#[cfg(feature = "rand_core")]
fn test_rng_rand_core_try_fill_bytes() {
use rand_core::TryRng;
let mut rng = RNG::new().expect("Failed to create RNG");
let mut buf = [0u8; 32];
rng.try_fill_bytes(&mut buf).expect("Failed to try_fill_bytes");
assert_ne!(buf, [0u8; 32]);
}
#[test]
#[cfg(feature = "rand_core")]
fn test_rng_rand_core_next_u32() {
use rand_core::Rng;
let mut rng = RNG::new().expect("Failed to create RNG");
// Generate several values and verify they aren't all zero
let v: u64 = (0..4).map(|_| rng.next_u32() as u64).sum();
assert_ne!(v, 0);
}
#[test]
#[cfg(feature = "rand_core")]
fn test_rng_rand_core_next_u64() {
use rand_core::Rng;
let mut rng = RNG::new().expect("Failed to create RNG");
// Generate two values and verify they aren't all ones
let v1 = rng.next_u64();
let v2 = rng.next_u64();
assert_ne!(v1 & v2, u64::MAX);
}
#[test]
#[cfg(feature = "rand_core")]
fn test_rng_is_crypto_rng() {
use rand_core::CryptoRng;
fn requires_crypto_rng<R: CryptoRng>(_: &R) {}
let rng = RNG::new().expect("Failed to create RNG");
requires_crypto_rng(&rng);
}