1#![allow(clippy::must_use_candidate)]
4
5#[cfg(feature = "alloc")]
11use alloc::{
12 boxed::Box,
13 vec,
14};
15#[cfg(feature = "alloc")]
16use core::fmt;
17
18#[cfg(feature = "alloc")]
19use rand_core::{
20 TryCryptoRng,
21 TryRng,
22};
23
24#[cfg(feature = "alloc")]
25use crate::Result;
26#[cfg(feature = "alloc")]
27use crate::traits::{
28 EntropySource,
29 ProviderCapabilities,
30 RngConfig,
31 RngProvider,
32 SecureRng,
33 SecurityLevel,
34};
35#[cfg(feature = "alloc")]
36use crate::validation::EntropyValidator;
37
38#[cfg(feature = "alloc")]
44pub struct LibQRng {
45 entropy_source: Box<dyn EntropySource>,
47 validator: EntropyValidator,
49 security_level: SecurityLevel,
51 deterministic: bool,
53 reseed_counter: u32,
55 bytes_generated: usize,
57 reseed_interval: Option<usize>,
59}
60
61#[cfg(feature = "alloc")]
62impl LibQRng {
63 pub fn new_secure() -> Result<Self> {
83 let entropy_source = crate::entropy::EntropySourceFactory::create_best_available()?;
84 let validator = EntropyValidator::with_settings(
86 64, 8192, 0.3, false, );
91
92 Ok(Self {
93 entropy_source,
94 validator,
95 security_level: SecurityLevel::CryptographicallySecure,
96 deterministic: false,
97 reseed_counter: 0,
98 bytes_generated: 0,
99 reseed_interval: Some(1024 * 1024), })
101 }
102
103 pub fn new_deterministic(seed: [u8; 32]) -> Self {
125 let entropy_source =
126 crate::entropy::EntropySourceFactory::create_deterministic_entropy(seed);
127 let validator = EntropyValidator::with_settings(
129 32, 1024, 0.1, false, );
134
135 Self {
136 entropy_source,
137 validator,
138 security_level: SecurityLevel::Deterministic,
139 deterministic: true,
140 reseed_counter: 0,
141 bytes_generated: 0,
142 reseed_interval: None, }
144 }
145
146 pub fn new_deterministic_from_u64(seed: u64) -> Self {
148 let entropy_source =
149 crate::entropy::EntropySourceFactory::create_deterministic_entropy_from_u64(seed);
150 let validator = EntropyValidator::with_settings(32, 1024, 0.1, false);
151
152 Self {
153 entropy_source,
154 validator,
155 security_level: SecurityLevel::Deterministic,
156 deterministic: true,
157 reseed_counter: 0,
158 bytes_generated: 0,
159 reseed_interval: None,
160 }
161 }
162
163 #[cfg(feature = "deterministic-saturnin")]
171 pub fn new_deterministic_saturnin(seed: [u8; 32]) -> Result<Self> {
172 let entropy_source = alloc::boxed::Box::new(
173 crate::saturnin_det::SaturninDeterministicEntropySource::new(seed)?,
174 );
175 let validator = EntropyValidator::with_settings(32, 1024, 0.1, false);
176 Ok(Self {
177 entropy_source,
178 validator,
179 security_level: SecurityLevel::Deterministic,
180 deterministic: true,
181 reseed_counter: 0,
182 bytes_generated: 0,
183 reseed_interval: None,
184 })
185 }
186
187 #[cfg(feature = "nist-drbg")]
208 pub fn new_nist_drbg(entropy_input: [u8; 48]) -> Self {
209 let entropy_source =
210 crate::entropy::EntropySourceFactory::create_nist_drbg_entropy(entropy_input);
211 let validator = EntropyValidator::with_settings(
213 256, 4096, 0.9, true, );
218
219 Self {
220 entropy_source,
221 validator,
222 security_level: SecurityLevel::CryptographicallySecure,
223 deterministic: true, reseed_counter: 0,
225 bytes_generated: 0,
226 reseed_interval: Some(1_000_000), }
228 }
229
230 pub fn new_custom<T: EntropySource + 'static>(entropy_source: T) -> Self {
251 let entropy_source = Box::new(entropy_source);
252 let validator = match entropy_source.source_type() {
254 crate::traits::EntropySourceType::Hardware => {
255 EntropyValidator::with_settings(64, 8192, 0.4, false)
256 }
257 crate::traits::EntropySourceType::OperatingSystem => {
258 EntropyValidator::with_settings(64, 8192, 0.3, false)
259 }
260 _ => EntropyValidator::with_settings(64, 8192, 0.3, false),
261 };
262
263 let security_level = match entropy_source.source_type() {
265 crate::traits::EntropySourceType::Hardware => SecurityLevel::Hardware,
266 crate::traits::EntropySourceType::OperatingSystem => {
267 SecurityLevel::CryptographicallySecure
268 }
269 crate::traits::EntropySourceType::Deterministic => SecurityLevel::Deterministic,
270 crate::traits::EntropySourceType::User => SecurityLevel::CryptographicallySecure,
271 };
272
273 let deterministic =
274 entropy_source.source_type() == crate::traits::EntropySourceType::Deterministic;
275
276 Self {
277 entropy_source,
278 validator,
279 security_level,
280 deterministic,
281 reseed_counter: 0,
282 bytes_generated: 0,
283 reseed_interval: if deterministic {
284 None
285 } else {
286 Some(1024 * 1024)
287 },
288 }
289 }
290
291 pub fn with_config(config: &RngConfig) -> Result<Self> {
305 let entropy_source = if let Some(_source) = &config.entropy_source {
306 crate::entropy::EntropySourceFactory::create_best_available()?
309 } else {
310 crate::entropy::EntropySourceFactory::create_best_available()?
311 };
312
313 let validator = match config.security_level {
315 SecurityLevel::Hardware => EntropyValidator::with_settings(64, 8192, 0.4, false),
316 SecurityLevel::CryptographicallySecure => {
317 EntropyValidator::with_settings(64, 8192, 0.3, false)
318 }
319 SecurityLevel::Deterministic => EntropyValidator::with_settings(32, 1024, 0.1, false),
320 SecurityLevel::Software => EntropyValidator::with_settings(64, 8192, 0.3, false),
321 };
322 let deterministic =
323 entropy_source.source_type() == crate::traits::EntropySourceType::Deterministic;
324
325 Ok(Self {
326 entropy_source,
327 validator,
328 security_level: config.security_level,
329 deterministic,
330 reseed_counter: 0,
331 bytes_generated: 0,
332 reseed_interval: config.reseed_interval,
333 })
334 }
335
336 pub fn is_deterministic(&self) -> bool {
338 self.deterministic
339 }
340
341 pub fn security_level(&self) -> SecurityLevel {
343 self.security_level
344 }
345
346 pub fn entropy_source_name(&self) -> &'static str {
348 self.entropy_source.name()
349 }
350
351 pub fn entropy_source_type(&self) -> crate::traits::EntropySourceType {
353 self.entropy_source.source_type()
354 }
355
356 pub fn reseed_counter(&self) -> u32 {
358 self.reseed_counter
359 }
360
361 pub fn bytes_generated(&self) -> usize {
363 self.bytes_generated
364 }
365
366 pub fn is_secure(&self) -> bool {
368 self.security_level == SecurityLevel::CryptographicallySecure
369 }
370
371 pub fn entropy_quality(&self) -> f64 {
373 match self.security_level {
374 SecurityLevel::CryptographicallySecure => 1.0,
375 SecurityLevel::Deterministic => 0.0,
376 SecurityLevel::Hardware => 0.95,
377 SecurityLevel::Software => 0.8,
378 }
379 }
380
381 fn needs_reseed(&self) -> bool {
383 if let Some(interval) = self.reseed_interval {
384 self.bytes_generated >= interval
385 } else {
386 false
387 }
388 }
389
390 fn reseed_if_needed(&mut self) -> Result<()> {
392 if self.needs_reseed() {
393 self.reseed()?;
394 }
395 Ok(())
396 }
397}
398
399#[cfg(feature = "alloc")]
400impl SecureRng for LibQRng {
401 fn fill_bytes_secure(&mut self, dest: &mut [u8]) -> Result<()> {
402 self.reseed_if_needed()?;
404
405 self.entropy_source.get_entropy(dest)?;
407
408 if !self.deterministic {
410 if dest.len() >= 8 {
412 let _ = self.validator.validate_entropy(dest);
413 }
414 }
415
416 self.bytes_generated += dest.len();
418
419 Ok(())
420 }
421
422 fn next_u32_secure(&mut self) -> Result<u32> {
423 let mut bytes = [0u8; 4];
424 self.fill_bytes_secure(&mut bytes)?;
425 Ok(u32::from_le_bytes(bytes))
426 }
427
428 fn next_u64_secure(&mut self) -> Result<u64> {
429 let mut bytes = [0u8; 8];
430 self.fill_bytes_secure(&mut bytes)?;
431 Ok(u64::from_le_bytes(bytes))
432 }
433
434 fn initialize(&mut self, entropy: &[u8]) -> Result<()> {
435 if self.deterministic {
437 let seed: [u8; 32] = entropy.try_into().map_err(|_| {
438 crate::Error::invalid_configuration(
439 "deterministic seed",
440 "exactly 32 bytes",
441 "slice length is not 32",
442 )
443 })?;
444 let new_source =
445 crate::entropy::EntropySourceFactory::create_deterministic_entropy(seed);
446 self.entropy_source = new_source;
447 self.reseed_counter = 0;
448 self.bytes_generated = 0;
449 }
450 Ok(())
453 }
454
455 fn is_secure(&self) -> bool {
456 !self.deterministic
457 }
458
459 fn entropy_quality(&self) -> f64 {
460 self.entropy_source.quality()
461 }
462
463 fn security_level(&self) -> SecurityLevel {
464 self.security_level
465 }
466
467 fn reseed(&mut self) -> Result<()> {
468 if self.deterministic {
469 return Ok(()); }
471
472 self.reseed_counter = self.reseed_counter.wrapping_add(1);
475 self.bytes_generated = 0;
476
477 Ok(())
478 }
479
480 fn state_size(&self) -> usize {
481 64
483 }
484
485 fn reseed_interval(&self) -> Option<usize> {
486 self.reseed_interval
487 }
488}
489
490#[cfg(feature = "alloc")]
491impl TryRng for LibQRng {
492 type Error = core::convert::Infallible;
493
494 fn try_next_u32(&mut self) -> core::result::Result<u32, Self::Error> {
495 match self.next_u32_secure() {
496 Ok(value) => Ok(value),
497 Err(_) => rng_abort(),
498 }
499 }
500
501 fn try_next_u64(&mut self) -> core::result::Result<u64, Self::Error> {
502 match self.next_u64_secure() {
503 Ok(value) => Ok(value),
504 Err(_) => rng_abort(),
505 }
506 }
507
508 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), Self::Error> {
509 match self.fill_bytes_secure(dest) {
510 Ok(()) => Ok(()),
511 Err(_) => rng_abort(),
512 }
513 }
514}
515
516#[cfg(feature = "alloc")]
522#[inline(never)]
523#[allow(clippy::panic)]
524fn rng_abort() -> ! {
525 #[cfg(feature = "std")]
526 std::process::abort();
527 #[cfg(not(feature = "std"))]
528 panic!("CRITICAL SECURITY FAILURE: RNG entropy unavailable");
529}
530
531#[cfg(feature = "alloc")]
532impl TryCryptoRng for LibQRng {}
533
534#[cfg(feature = "alloc")]
535impl LibQRng {
536 pub fn fill<T>(&mut self, dest: &mut [T])
551 where
552 T: Copy + Default,
553 {
554 if dest.is_empty() {
555 return;
556 }
557
558 let size = core::mem::size_of::<T>();
560 let total_bytes = core::mem::size_of_val(dest);
561
562 let mut bytes = vec![0u8; total_bytes];
564
565 let _ = self.fill_bytes_secure(&mut bytes);
567
568 for (i, chunk) in bytes.chunks_exact(size).enumerate() {
570 if i < dest.len() {
571 unsafe {
574 let ptr = dest.as_mut_ptr().add(i).cast::<u8>();
575 core::ptr::copy_nonoverlapping(chunk.as_ptr(), ptr, size);
576 }
577 }
578 }
579 }
580}
581
582#[cfg(feature = "alloc")]
587impl fmt::Display for LibQRng {
588 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589 write!(
590 f,
591 "LibQRng(security_level: {}, entropy_source: {}, deterministic: {}, reseed_counter: {})",
592 self.security_level,
593 self.entropy_source.name(),
594 self.deterministic,
595 self.reseed_counter
596 )
597 }
598}
599
600pub struct LibQRngProvider;
605
606impl LibQRngProvider {
607 pub fn new() -> Self {
609 Self
610 }
611}
612
613#[cfg(feature = "alloc")]
614impl RngProvider for LibQRngProvider {
615 fn create_rng(&self, config: &RngConfig) -> Result<Box<dyn SecureRng>> {
616 let rng = LibQRng::with_config(config)?;
617 Ok(Box::new(rng))
618 }
619
620 fn name(&self) -> &'static str {
621 "libQ RNG Provider"
622 }
623
624 fn capabilities(&self) -> ProviderCapabilities {
625 ProviderCapabilities {
626 secure: true,
627 deterministic: true,
628 hardware: true,
629 reseeding: true,
630 custom_entropy: true,
631 no_std: true,
632 wasm: true,
633 }
634 }
635
636 fn supports_config(&self, config: &RngConfig) -> bool {
637 let _ = config;
639 true
640 }
641
642 fn priority(&self) -> u32 {
643 100 }
645}
646
647impl Default for LibQRngProvider {
648 fn default() -> Self {
649 Self::new()
650 }
651}
652
653#[cfg(test)]
654mod tests {
655 #[cfg(all(not(feature = "std"), feature = "alloc"))]
656 use alloc::format;
657
658 #[cfg(feature = "alloc")]
659 use rand_core::Rng;
660
661 #[cfg(feature = "alloc")]
662 use super::*;
663
664 #[test]
665 #[cfg(feature = "alloc")]
666 fn test_libq_rng_deterministic_creation() {
667 let mut seed = [0u8; 32];
668 seed[..8].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
669 let rng = LibQRng::new_deterministic(seed);
670 assert!(rng.is_deterministic());
671 assert_eq!(rng.security_level(), SecurityLevel::Deterministic);
672 assert!(!rng.is_secure());
673 }
674
675 #[test]
676 #[cfg(feature = "alloc")]
677 fn test_libq_rng_deterministic_consistency() {
678 let seed = [42u8; 32];
679 let mut rng1 = LibQRng::new_deterministic(seed);
680 let mut rng2 = LibQRng::new_deterministic(seed);
681
682 let mut bytes1 = [0u8; 32];
683 let mut bytes2 = [0u8; 32];
684
685 rng1.fill_bytes(&mut bytes1);
686 rng2.fill_bytes(&mut bytes2);
687
688 assert_eq!(bytes1, bytes2);
689 }
690
691 #[test]
692 #[cfg(feature = "alloc")]
693 fn test_libq_rng_deterministic_golden_zero_seed() {
694 use crate::kt128_expander::Kt128Expander;
695
696 let expected = crate::kt128_expander::KT128_DET_GOLDEN_ZERO_SEED_64;
697 let mut rng = LibQRng::new_deterministic([0u8; 32]);
698 let mut out = [0u8; 64];
699 rng.fill_bytes(&mut out);
700 let mut direct = Kt128Expander::from_det_seed_32([0u8; 32]);
701 let mut expected_direct = [0u8; 64];
702 direct.fill_bytes(&mut expected_direct);
703 assert_eq!(out, expected);
704 assert_eq!(out, expected_direct);
705 }
706
707 #[test]
710 #[cfg(feature = "alloc")]
711 fn test_libq_rng_deterministic_seeds_differ_in_final_byte_yield_different_streams() {
712 let seed_a = [0u8; 32];
713 let mut seed_b = [0u8; 32];
714 seed_b[31] = 1;
715
716 let mut rng_a = LibQRng::new_deterministic(seed_a);
717 let mut rng_b = LibQRng::new_deterministic(seed_b);
718
719 let mut out_a = [0u8; 64];
720 let mut out_b = [0u8; 64];
721 rng_a.fill_bytes(&mut out_a);
722 rng_b.fill_bytes(&mut out_b);
723
724 assert_ne!(
725 out_a, out_b,
726 "KT128 streams from different 32-byte keys must diverge immediately"
727 );
728 }
729
730 #[test]
731 #[cfg(feature = "alloc")]
732 fn test_libq_rng_custom_creation() {
733 let entropy_data = vec![1, 2, 3, 4, 5, 6, 7, 8];
734 let entropy_source = crate::entropy::UserEntropySource::new(entropy_data);
735 let rng = LibQRng::new_custom(entropy_source);
736 assert!(!rng.is_deterministic());
737 assert_eq!(rng.security_level(), SecurityLevel::CryptographicallySecure);
738 }
739
740 #[test]
741 #[cfg(feature = "alloc")]
742 fn test_libq_rng_config_creation() {
743 let config = RngConfig::default();
744 let rng = LibQRng::with_config(&config);
745 assert!(rng.is_ok());
746 }
747
748 #[test]
749 #[cfg(feature = "alloc")]
750 fn test_libq_rng_provider_creation() {
751 let provider = LibQRngProvider::new();
752 assert_eq!(provider.name(), "libQ RNG Provider");
753 assert_eq!(provider.priority(), 100);
754 }
755
756 #[test]
757 #[cfg(feature = "alloc")]
758 fn test_libq_rng_provider_capabilities() {
759 let provider = LibQRngProvider::new();
760 let caps = provider.capabilities();
761 assert!(caps.secure);
762 assert!(caps.deterministic);
763 assert!(caps.hardware);
764 assert!(caps.reseeding);
765 assert!(caps.custom_entropy);
766 assert!(caps.no_std);
767 assert!(caps.wasm);
768 }
769
770 #[test]
771 #[cfg(feature = "alloc")]
772 fn test_libq_rng_provider_create_rng() {
773 let provider = LibQRngProvider::new();
774 let config = RngConfig::default();
775 let rng = provider.create_rng(&config);
776 assert!(rng.is_ok());
777 }
778
779 #[test]
780 #[cfg(feature = "alloc")]
781 fn test_libq_rng_reseed_counter() {
782 let mut seed = [0u8; 32];
783 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
784 let rng = LibQRng::new_deterministic(seed);
785 assert_eq!(rng.reseed_counter(), 0);
786 assert_eq!(rng.bytes_generated(), 0);
787 }
788
789 #[test]
790 #[cfg(feature = "alloc")]
791 fn test_libq_rng_entropy_source_info() {
792 let mut seed = [0u8; 32];
793 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
794 let rng = LibQRng::new_deterministic(seed);
795 assert!(!rng.entropy_source_name().is_empty());
796 assert_eq!(
797 rng.entropy_source_type(),
798 crate::traits::EntropySourceType::Deterministic
799 );
800 }
801
802 #[test]
803 #[cfg(feature = "alloc")]
804 fn test_libq_rng_display() {
805 let mut seed = [0u8; 32];
806 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
807 let rng = LibQRng::new_deterministic(seed);
808 let display = format!("{rng}");
809 assert!(display.contains("LibQRng"));
810 assert!(display.contains("Deterministic"));
811 }
812}