lib_q_random/
specialized.rs1use core::fmt;
7
8#[cfg_attr(not(feature = "rand"), allow(unused_imports))]
9use rand_core::{
10 Rng,
11 TryCryptoRng,
12 TryRng,
13};
14
15#[cfg(feature = "hash")]
16use crate::Error;
17
18#[derive(Clone, Debug, PartialEq)]
23pub struct ClassicalMcElieceRng {
24 state: u64,
26 counter: u64,
28 deterministic: bool,
30 reseed_counter: u32,
32}
33
34impl ClassicalMcElieceRng {
35 #[must_use]
41 pub fn new() -> Self {
42 Self {
43 state: 0,
44 counter: 0,
45 deterministic: false,
46 reseed_counter: 0,
47 }
48 }
49
50 #[must_use]
55 pub fn new_deterministic(seed: u64) -> Self {
56 Self {
57 state: seed
58 .wrapping_mul(6_364_136_223_846_793_005_u64)
59 .wrapping_add(1_442_695_040_888_963_407_u64),
60 counter: 0,
61 deterministic: true,
62 reseed_counter: 0,
63 }
64 }
65
66 #[must_use]
71 pub fn new_deterministic_from_bytes(seed_bytes: &[u8]) -> Self {
72 let mut hash = 0u64;
73 for (i, &byte) in seed_bytes.iter().enumerate() {
74 hash = hash.wrapping_add(u64::from(byte) << (i % 8));
75 }
76 Self::new_deterministic(hash)
77 }
78
79 pub fn randombytes_init(&mut self, entropy_input: [u8; 48]) {
85 if self.deterministic {
86 let mut hash = 0u64;
88 for (i, &byte) in entropy_input.iter().enumerate() {
89 hash = hash.wrapping_add(u64::from(byte) << (i % 8));
90 }
91 self.state = self.state.wrapping_add(hash);
92 self.counter = 0;
93 self.reseed_counter = 1;
94 }
95 }
98
99 fn generate_bytes(&mut self, dest: &mut [u8]) {
101 if self.deterministic {
102 self.generate_deterministic_bytes(dest);
103 } else {
104 self.generate_secure_bytes(dest);
105 }
106 }
107
108 fn generate_deterministic_bytes(&mut self, dest: &mut [u8]) {
113 for chunk in dest.chunks_mut(8) {
114 for _ in 0..3 {
119 self.state = self
120 .state
121 .wrapping_mul(6_364_136_223_846_793_005_u64)
122 .wrapping_add(1_442_695_040_888_963_407_u64);
123 }
124
125 self.counter = self.counter.wrapping_add(1);
126
127 let mut value = self.state ^
130 self.counter ^
131 (u64::from(self.reseed_counter) << 32) ^
132 (u64::from(self.reseed_counter) << 16);
133
134 value = value.wrapping_mul(0x9E37_79B9_7F4A_7C15_u64); value ^= value >> 33;
138 value = value.wrapping_mul(0x9E37_79B9_7F4A_7C15_u64);
139 value ^= value >> 29;
140 value = value.wrapping_mul(0xC4CE_B9FE_1A85_EC53_u64);
141 value ^= value >> 32;
142
143 let bytes = value.to_le_bytes();
144
145 let len = chunk.len().min(8);
146 chunk[..len].copy_from_slice(&bytes[..len]);
147 }
148
149 self.reseed_counter = self.reseed_counter.wrapping_add(1);
150 }
151
152 fn generate_secure_bytes(&mut self, dest: &mut [u8]) {
158 #[cfg(feature = "getrandom")]
159 {
160 assert!(
162 getrandom::fill(dest).is_ok(),
163 "lib_q_random::ClassicalMcElieceRng: getrandom::fill failed; \
164 refusing non-OS RNG output (enable `custom-entropy` or fix the environment)"
165 );
166 }
167
168 #[cfg(not(feature = "getrandom"))]
169 {
170 let _ = dest;
171 panic!(
175 "lib_q_random: ClassicalMcElieceRng requires the `getrandom` crate feature for secure output; \
176 enable `getrandom`/`secure`/`classical-mceliece`, or use `new_deterministic` for tests"
177 );
178 }
179
180 self.reseed_counter = self.reseed_counter.wrapping_add(1);
181 }
182}
183
184impl Default for ClassicalMcElieceRng {
185 fn default() -> Self {
186 Self::new()
187 }
188}
189
190impl Eq for ClassicalMcElieceRng {}
191
192impl fmt::Display for ClassicalMcElieceRng {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 writeln!(f, "ClassicalMcElieceRng {{")?;
195 writeln!(f, " state = {}", self.state)?;
196 writeln!(f, " counter = {}", self.counter)?;
197 writeln!(f, " deterministic = {}", self.deterministic)?;
198 writeln!(f, " reseed_counter = {}", self.reseed_counter)?;
199 writeln!(f, "}}")
200 }
201}
202
203impl TryRng for ClassicalMcElieceRng {
204 type Error = core::convert::Infallible;
205
206 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
207 let mut bytes = [0u8; 4];
208 self.try_fill_bytes(&mut bytes)?;
209 Ok(u32::from_le_bytes(bytes))
210 }
211
212 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
213 let mut bytes = [0u8; 8];
214 self.try_fill_bytes(&mut bytes)?;
215 Ok(u64::from_le_bytes(bytes))
216 }
217
218 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
219 self.generate_bytes(dest);
220 Ok(())
221 }
222}
223
224impl TryCryptoRng for ClassicalMcElieceRng {}
225
226#[cfg(feature = "hash")]
232#[derive(Clone, Debug)]
233pub struct Kt128Rng {
234 expander: crate::kt128_expander::Kt128Expander,
235}
236
237#[cfg(feature = "hash")]
238impl Kt128Rng {
239 pub fn new() -> crate::Result<Self> {
245 #[cfg(feature = "getrandom")]
246 {
247 let mut seed = [0u8; 32];
249 getrandom::fill(&mut seed).map_err(|_| Error::EntropySourceUnavailable {
250 source: "system",
251 context: Some("getrandom failed"),
252 })?;
253 Ok(Self::from_seed(&seed))
254 }
255 #[cfg(not(feature = "getrandom"))]
256 {
257 Err(Error::FeatureNotAvailable {
259 feature: "secure entropy",
260 required_features: &["getrandom"],
261 })
262 }
263 }
264
265 #[must_use]
267 pub fn from_seed(seed: &[u8]) -> Self {
268 Self {
269 expander: crate::kt128_expander::Kt128Expander::from_seed(
270 crate::kt128_expander::DOMAIN_HPKE_RNG,
271 seed,
272 ),
273 }
274 }
275
276 pub fn refill(&mut self) {
278 self.expander.refill();
279 }
280}
281
282#[cfg(feature = "hash")]
283impl TryRng for Kt128Rng {
284 type Error = core::convert::Infallible;
285
286 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
287 let mut bytes = [0u8; 4];
288 self.try_fill_bytes(&mut bytes)?;
289 Ok(u32::from_le_bytes(bytes))
290 }
291
292 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
293 let mut bytes = [0u8; 8];
294 self.try_fill_bytes(&mut bytes)?;
295 Ok(u64::from_le_bytes(bytes))
296 }
297
298 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
299 self.expander.fill_bytes(dest);
300 Ok(())
301 }
302}
303
304#[cfg(feature = "hash")]
305#[cfg(test)]
306mod kt128_rng_tests {
307 use super::*;
308 use crate::kt128_expander::Kt128Expander;
309
310 #[test]
312 fn test_kt128_rng_matches_hpke_domain_expander() {
313 let seed = [9u8; 32];
314 let mut rng = Kt128Rng::from_seed(&seed);
315 let mut exp = Kt128Expander::from_seed(crate::kt128_expander::DOMAIN_HPKE_RNG, &seed);
316 let mut a = [0u8; 128];
317 let mut b = [0u8; 128];
318 rng.fill_bytes(&mut a);
319 exp.fill_bytes(&mut b);
320 assert_eq!(a, b);
321 }
322}
323
324#[cfg(feature = "hash")]
325impl TryCryptoRng for Kt128Rng {}
326
327pub struct FnDsaRng {
332 #[cfg(feature = "rand")]
333 rng: Option<rand::rngs::ThreadRng>,
334}
335
336impl Default for FnDsaRng {
337 fn default() -> Self {
338 Self::new()
339 }
340}
341
342impl FnDsaRng {
343 #[must_use]
345 pub fn new() -> Self {
346 #[cfg(feature = "rand")]
347 {
348 Self {
349 rng: Some(rand::rng()),
350 }
351 }
352 #[cfg(not(feature = "rand"))]
353 {
354 Self {}
355 }
356 }
357}
358
359impl TryRng for FnDsaRng {
360 type Error = core::convert::Infallible;
361
362 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
363 #[cfg(feature = "rand")]
364 {
365 if let Some(ref mut rng) = self.rng {
366 Ok(rng.next_u32())
367 } else {
368 let mut bytes = [0u8; 4];
369 self.try_fill_bytes(&mut bytes)?;
370 Ok(u32::from_le_bytes(bytes))
371 }
372 }
373 #[cfg(not(feature = "rand"))]
374 {
375 #[cfg(feature = "getrandom")]
376 {
377 let mut bytes = [0u8; 4];
378 getrandom::fill(&mut bytes).expect("Failed to get random bytes from getrandom");
379 Ok(u32::from_le_bytes(bytes))
380 }
381 #[cfg(not(feature = "getrandom"))]
382 {
383 panic!(
384 "FnDsaRng requires either 'rand' or 'getrandom' feature. \
385 Use deterministic RNG for testing without these features."
386 );
387 }
388 }
389 }
390
391 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
392 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
393 {
394 let mut bytes = [0u8; 8];
395 getrandom::fill(&mut bytes).expect("Failed to get random bytes from getrandom");
396 Ok(u64::from_le_bytes(bytes))
397 }
398
399 #[cfg(not(all(feature = "getrandom", not(feature = "rand"))))]
400 {
401 let upper = u64::from(self.try_next_u32()?);
402 let lower = u64::from(self.try_next_u32()?);
403 Ok((upper << 32) | lower)
404 }
405 }
406
407 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
408 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
412 {
413 getrandom::fill(dest).expect("Failed to get random bytes from getrandom");
414 Ok(())
415 }
416
417 #[cfg(not(all(feature = "getrandom", not(feature = "rand"))))]
418 {
419 for chunk in dest.chunks_mut(4) {
420 let bytes = self.try_next_u32()?.to_le_bytes();
421 let len = chunk.len().min(4);
422 chunk[..len].copy_from_slice(&bytes[..len]);
423 }
424 Ok(())
425 }
426 }
427}
428
429impl TryCryptoRng for FnDsaRng {}
430
431#[cfg(test)]
432mod tests {
433 use rand_core::Rng;
434
435 use super::*;
436
437 #[test]
438 fn test_classical_mceliece_rng_creation() {
439 let rng = ClassicalMcElieceRng::new();
440 assert!(!rng.deterministic);
441 assert_eq!(rng.state, 0);
442 assert_eq!(rng.counter, 0);
443 }
444
445 #[test]
446 fn test_classical_mceliece_deterministic_rng_creation() {
447 let rng = ClassicalMcElieceRng::new_deterministic(12345);
448 assert!(rng.deterministic);
449 assert_ne!(rng.state, 0);
451 assert_eq!(rng.counter, 0);
452 }
453
454 #[test]
455 fn test_classical_mceliece_deterministic_rng_consistency() {
456 let mut rng1 = ClassicalMcElieceRng::new_deterministic(42);
457 let mut rng2 = ClassicalMcElieceRng::new_deterministic(42);
458
459 let mut bytes1 = [0u8; 32];
460 let mut bytes2 = [0u8; 32];
461
462 rng1.fill_bytes(&mut bytes1);
463 rng2.fill_bytes(&mut bytes2);
464
465 assert_eq!(bytes1, bytes2);
466 }
467
468 #[test]
469 fn test_classical_mceliece_rng_interface() {
470 let mut rng = ClassicalMcElieceRng::new_deterministic(100);
471
472 let mut bytes = [0u8; 16];
474 rng.fill_bytes(&mut bytes);
475 assert_ne!(bytes, [0u8; 16]); let val1 = rng.next_u32();
479 let val2 = rng.next_u32();
480 assert_ne!(val1, val2); let val3 = rng.next_u64();
484 let val4 = rng.next_u64();
485 assert_ne!(val3, val4); }
487
488 #[test]
489 fn test_classical_mceliece_randombytes_init() {
490 let mut rng = ClassicalMcElieceRng::new_deterministic(0);
491 let entropy = [1u8; 48];
492
493 rng.randombytes_init(entropy);
494
495 assert_ne!(rng.state, 0);
497 assert_eq!(rng.reseed_counter, 1);
498 }
499
500 #[test]
501 fn test_fn_dsa_rng_creation() {
502 let _rng = FnDsaRng::new();
503 }
506
507 #[test]
508 #[cfg(any(feature = "rand", feature = "getrandom"))]
509 fn test_fn_dsa_rng_interface() {
510 let mut rng = FnDsaRng::new();
511
512 let mut bytes = [0u8; 16];
514 rng.fill_bytes(&mut bytes);
515 let val1 = rng.next_u32();
519 let val2 = rng.next_u32();
520 assert_ne!(val1, val2);
522
523 let val3 = rng.next_u64();
525 let val4 = rng.next_u64();
526 assert_ne!(val3, val4);
528 }
529
530 #[test]
533 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
534 fn test_fn_dsa_rng_fill_bytes_getrandom_only_odd_length() {
535 let mut rng = FnDsaRng::new();
536 let mut buf = [0u8; 1281];
537 rng.fill_bytes(&mut buf);
538 }
539}