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 |
270 crate::traits::EntropySourceType::User => SecurityLevel::Deterministic,
271 };
272
273 let deterministic = matches!(
274 entropy_source.source_type(),
275 crate::traits::EntropySourceType::Deterministic |
276 crate::traits::EntropySourceType::User
277 );
278
279 Self {
280 entropy_source,
281 validator,
282 security_level,
283 deterministic,
284 reseed_counter: 0,
285 bytes_generated: 0,
286 reseed_interval: if deterministic {
287 None
288 } else {
289 Some(1024 * 1024)
290 },
291 }
292 }
293
294 pub fn with_config(config: &RngConfig) -> Result<Self> {
308 let entropy_source = if let Some(_source) = &config.entropy_source {
309 crate::entropy::EntropySourceFactory::create_best_available()?
312 } else {
313 crate::entropy::EntropySourceFactory::create_best_available()?
314 };
315
316 let validator = match config.security_level {
318 SecurityLevel::Hardware => EntropyValidator::with_settings(64, 8192, 0.4, false),
319 SecurityLevel::CryptographicallySecure => {
320 EntropyValidator::with_settings(64, 8192, 0.3, false)
321 }
322 SecurityLevel::Deterministic => EntropyValidator::with_settings(32, 1024, 0.1, false),
323 SecurityLevel::Software => EntropyValidator::with_settings(64, 8192, 0.3, false),
324 };
325 let deterministic =
326 entropy_source.source_type() == crate::traits::EntropySourceType::Deterministic;
327
328 Ok(Self {
329 entropy_source,
330 validator,
331 security_level: config.security_level,
332 deterministic,
333 reseed_counter: 0,
334 bytes_generated: 0,
335 reseed_interval: config.reseed_interval,
336 })
337 }
338
339 pub fn is_deterministic(&self) -> bool {
341 self.deterministic
342 }
343
344 pub fn security_level(&self) -> SecurityLevel {
346 self.security_level
347 }
348
349 pub fn entropy_source_name(&self) -> &'static str {
351 self.entropy_source.name()
352 }
353
354 pub fn entropy_source_type(&self) -> crate::traits::EntropySourceType {
356 self.entropy_source.source_type()
357 }
358
359 pub fn reseed_counter(&self) -> u32 {
361 self.reseed_counter
362 }
363
364 pub fn bytes_generated(&self) -> usize {
366 self.bytes_generated
367 }
368
369 pub fn is_secure(&self) -> bool {
371 self.security_level == SecurityLevel::CryptographicallySecure
372 }
373
374 pub fn entropy_quality(&self) -> f64 {
376 match self.security_level {
377 SecurityLevel::CryptographicallySecure => 1.0,
378 SecurityLevel::Deterministic => 0.0,
379 SecurityLevel::Hardware => 0.95,
380 SecurityLevel::Software => 0.8,
381 }
382 }
383
384 fn needs_reseed(&self) -> bool {
386 if let Some(interval) = self.reseed_interval {
387 self.bytes_generated >= interval
388 } else {
389 false
390 }
391 }
392
393 fn reseed_if_needed(&mut self) -> Result<()> {
395 if self.needs_reseed() {
396 self.reseed()?;
397 }
398 Ok(())
399 }
400}
401
402#[cfg(feature = "alloc")]
403impl SecureRng for LibQRng {
404 fn fill_bytes_secure(&mut self, dest: &mut [u8]) -> Result<()> {
405 self.reseed_if_needed()?;
407
408 self.entropy_source.get_entropy(dest)?;
410
411 if !self.deterministic && dest.len() >= 64 {
418 self.validator.validate_entropy(&dest[..64])?;
419 }
420
421 self.bytes_generated += dest.len();
423
424 Ok(())
425 }
426
427 fn next_u32_secure(&mut self) -> Result<u32> {
428 let mut bytes = [0u8; 4];
429 self.fill_bytes_secure(&mut bytes)?;
430 Ok(u32::from_le_bytes(bytes))
431 }
432
433 fn next_u64_secure(&mut self) -> Result<u64> {
434 let mut bytes = [0u8; 8];
435 self.fill_bytes_secure(&mut bytes)?;
436 Ok(u64::from_le_bytes(bytes))
437 }
438
439 fn initialize(&mut self, entropy: &[u8]) -> Result<()> {
440 if self.deterministic {
442 let seed: [u8; 32] = entropy.try_into().map_err(|_| {
443 crate::Error::invalid_configuration(
444 "deterministic seed",
445 "exactly 32 bytes",
446 "slice length is not 32",
447 )
448 })?;
449 let new_source =
450 crate::entropy::EntropySourceFactory::create_deterministic_entropy(seed);
451 self.entropy_source = new_source;
452 self.reseed_counter = 0;
453 self.bytes_generated = 0;
454 }
455 Ok(())
458 }
459
460 fn is_secure(&self) -> bool {
461 !self.deterministic
462 }
463
464 fn entropy_quality(&self) -> f64 {
465 self.entropy_source.quality()
466 }
467
468 fn security_level(&self) -> SecurityLevel {
469 self.security_level
470 }
471
472 fn reseed(&mut self) -> Result<()> {
473 if self.deterministic {
474 return Ok(()); }
476
477 self.reseed_counter = self.reseed_counter.wrapping_add(1);
480 self.bytes_generated = 0;
481
482 Ok(())
483 }
484
485 fn state_size(&self) -> usize {
486 64
488 }
489
490 fn reseed_interval(&self) -> Option<usize> {
491 self.reseed_interval
492 }
493}
494
495#[cfg(feature = "alloc")]
496impl TryRng for LibQRng {
497 type Error = core::convert::Infallible;
498
499 fn try_next_u32(&mut self) -> core::result::Result<u32, Self::Error> {
500 match self.next_u32_secure() {
501 Ok(value) => Ok(value),
502 Err(_) => rng_abort(),
503 }
504 }
505
506 fn try_next_u64(&mut self) -> core::result::Result<u64, Self::Error> {
507 match self.next_u64_secure() {
508 Ok(value) => Ok(value),
509 Err(_) => rng_abort(),
510 }
511 }
512
513 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), Self::Error> {
514 match self.fill_bytes_secure(dest) {
515 Ok(()) => Ok(()),
516 Err(_) => rng_abort(),
517 }
518 }
519}
520
521#[cfg(feature = "alloc")]
527#[inline(never)]
528#[allow(clippy::panic)]
529fn rng_abort() -> ! {
530 #[cfg(feature = "std")]
531 std::process::abort();
532 #[cfg(not(feature = "std"))]
533 panic!("CRITICAL SECURITY FAILURE: RNG entropy unavailable");
534}
535
536#[cfg(feature = "alloc")]
537impl TryCryptoRng for LibQRng {}
538
539#[cfg(feature = "alloc")]
540impl LibQRng {
541 pub fn fill<T>(&mut self, dest: &mut [T])
556 where
557 T: Copy + Default,
558 {
559 if dest.is_empty() {
560 return;
561 }
562
563 let size = core::mem::size_of::<T>();
565 if size == 0 {
566 return;
567 }
568 let total_bytes = core::mem::size_of_val(dest);
569
570 let mut bytes = vec![0u8; total_bytes];
572
573 if self.fill_bytes_secure(&mut bytes).is_err() {
576 rng_abort();
577 }
578
579 for (i, chunk) in bytes.chunks_exact(size).enumerate() {
581 if i < dest.len() {
582 unsafe {
585 let ptr = dest.as_mut_ptr().add(i).cast::<u8>();
586 core::ptr::copy_nonoverlapping(chunk.as_ptr(), ptr, size);
587 }
588 }
589 }
590 }
591}
592
593#[cfg(feature = "alloc")]
598impl fmt::Display for LibQRng {
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 write!(
601 f,
602 "LibQRng(security_level: {}, entropy_source: {}, deterministic: {}, reseed_counter: {})",
603 self.security_level,
604 self.entropy_source.name(),
605 self.deterministic,
606 self.reseed_counter
607 )
608 }
609}
610
611pub struct LibQRngProvider;
616
617impl LibQRngProvider {
618 pub fn new() -> Self {
620 Self
621 }
622}
623
624#[cfg(feature = "alloc")]
625impl RngProvider for LibQRngProvider {
626 fn create_rng(&self, config: &RngConfig) -> Result<Box<dyn SecureRng>> {
627 let rng = LibQRng::with_config(config)?;
628 Ok(Box::new(rng))
629 }
630
631 fn name(&self) -> &'static str {
632 "libQ RNG Provider"
633 }
634
635 fn capabilities(&self) -> ProviderCapabilities {
636 ProviderCapabilities {
637 secure: true,
638 deterministic: true,
639 hardware: true,
640 reseeding: true,
641 custom_entropy: true,
642 no_std: true,
643 wasm: true,
644 }
645 }
646
647 fn supports_config(&self, config: &RngConfig) -> bool {
648 let _ = config;
650 true
651 }
652
653 fn priority(&self) -> u32 {
654 100 }
656}
657
658impl Default for LibQRngProvider {
659 fn default() -> Self {
660 Self::new()
661 }
662}
663
664#[cfg(test)]
665mod tests {
666 #[cfg(all(not(feature = "std"), feature = "alloc"))]
667 use alloc::format;
668
669 #[cfg(feature = "alloc")]
670 use rand_core::Rng;
671
672 #[cfg(feature = "alloc")]
673 use super::*;
674
675 #[test]
676 #[cfg(feature = "alloc")]
677 fn test_libq_rng_deterministic_creation() {
678 let mut seed = [0u8; 32];
679 seed[..8].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
680 let rng = LibQRng::new_deterministic(seed);
681 assert!(rng.is_deterministic());
682 assert_eq!(rng.security_level(), SecurityLevel::Deterministic);
683 assert!(!rng.is_secure());
684 }
685
686 #[test]
687 #[cfg(feature = "alloc")]
688 fn test_libq_rng_deterministic_consistency() {
689 let seed = [42u8; 32];
690 let mut rng1 = LibQRng::new_deterministic(seed);
691 let mut rng2 = LibQRng::new_deterministic(seed);
692
693 let mut bytes1 = [0u8; 32];
694 let mut bytes2 = [0u8; 32];
695
696 rng1.fill_bytes(&mut bytes1);
697 rng2.fill_bytes(&mut bytes2);
698
699 assert_eq!(bytes1, bytes2);
700 }
701
702 #[test]
703 #[cfg(feature = "alloc")]
704 fn test_libq_rng_deterministic_golden_zero_seed() {
705 use crate::kt128_expander::Kt128Expander;
706
707 let expected = crate::kt128_expander::KT128_DET_GOLDEN_ZERO_SEED_64;
708 let mut rng = LibQRng::new_deterministic([0u8; 32]);
709 let mut out = [0u8; 64];
710 rng.fill_bytes(&mut out);
711 let mut direct = Kt128Expander::from_det_seed_32([0u8; 32]);
712 let mut expected_direct = [0u8; 64];
713 direct.fill_bytes(&mut expected_direct);
714 assert_eq!(out, expected);
715 assert_eq!(out, expected_direct);
716 }
717
718 #[test]
721 #[cfg(feature = "alloc")]
722 fn test_libq_rng_deterministic_seeds_differ_in_final_byte_yield_different_streams() {
723 let seed_a = [0u8; 32];
724 let mut seed_b = [0u8; 32];
725 seed_b[31] = 1;
726
727 let mut rng_a = LibQRng::new_deterministic(seed_a);
728 let mut rng_b = LibQRng::new_deterministic(seed_b);
729
730 let mut out_a = [0u8; 64];
731 let mut out_b = [0u8; 64];
732 rng_a.fill_bytes(&mut out_a);
733 rng_b.fill_bytes(&mut out_b);
734
735 assert_ne!(
736 out_a, out_b,
737 "KT128 streams from different 32-byte keys must diverge immediately"
738 );
739 }
740
741 #[test]
742 #[cfg(feature = "alloc")]
743 fn test_libq_rng_custom_creation() {
744 let entropy_data = vec![1, 2, 3, 4, 5, 6, 7, 8];
745 let entropy_source = crate::entropy::UserEntropySource::new(entropy_data);
746 let rng = LibQRng::new_custom(entropy_source);
747 assert!(rng.is_deterministic());
748 assert_eq!(rng.security_level(), SecurityLevel::Deterministic);
749 }
750
751 #[test]
752 #[cfg(feature = "alloc")]
753 fn test_libq_rng_config_creation() {
754 let config = RngConfig::default();
755 let rng = LibQRng::with_config(&config);
756 assert!(rng.is_ok());
757 }
758
759 #[test]
760 #[cfg(feature = "alloc")]
761 fn test_libq_rng_provider_creation() {
762 let provider = LibQRngProvider::new();
763 assert_eq!(provider.name(), "libQ RNG Provider");
764 assert_eq!(provider.priority(), 100);
765 }
766
767 #[test]
768 #[cfg(feature = "alloc")]
769 fn test_libq_rng_provider_capabilities() {
770 let provider = LibQRngProvider::new();
771 let caps = provider.capabilities();
772 assert!(caps.secure);
773 assert!(caps.deterministic);
774 assert!(caps.hardware);
775 assert!(caps.reseeding);
776 assert!(caps.custom_entropy);
777 assert!(caps.no_std);
778 assert!(caps.wasm);
779 }
780
781 #[test]
782 #[cfg(feature = "alloc")]
783 fn test_libq_rng_provider_create_rng() {
784 let provider = LibQRngProvider::new();
785 let config = RngConfig::default();
786 let rng = provider.create_rng(&config);
787 assert!(rng.is_ok());
788 }
789
790 #[test]
791 #[cfg(feature = "alloc")]
792 fn test_libq_rng_reseed_counter() {
793 let mut seed = [0u8; 32];
794 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
795 let rng = LibQRng::new_deterministic(seed);
796 assert_eq!(rng.reseed_counter(), 0);
797 assert_eq!(rng.bytes_generated(), 0);
798 }
799
800 #[test]
801 #[cfg(feature = "alloc")]
802 fn test_libq_rng_entropy_source_info() {
803 let mut seed = [0u8; 32];
804 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
805 let rng = LibQRng::new_deterministic(seed);
806 assert!(!rng.entropy_source_name().is_empty());
807 assert_eq!(
808 rng.entropy_source_type(),
809 crate::traits::EntropySourceType::Deterministic
810 );
811 }
812
813 #[test]
814 #[cfg(feature = "alloc")]
815 fn test_libq_rng_display() {
816 let mut seed = [0u8; 32];
817 seed[..4].copy_from_slice(&[1, 2, 3, 4]);
818 let rng = LibQRng::new_deterministic(seed);
819 let display = format!("{rng}");
820 assert!(display.contains("LibQRng"));
821 assert!(display.contains("Deterministic"));
822 }
823}