1use 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")]
232pub struct Kt128Rng {
233 pub buffer: [u8; 32], pub position: usize,
237 counter: u64,
238}
239
240#[cfg(feature = "hash")]
241impl Kt128Rng {
242 pub fn new() -> crate::Result<Self> {
248 #[cfg(feature = "getrandom")]
249 {
250 let mut seed = [0u8; 32];
252 getrandom::fill(&mut seed).map_err(|_| Error::EntropySourceUnavailable {
253 source: "system",
254 context: Some("getrandom failed"),
255 })?;
256 Ok(Self::from_seed(&seed))
257 }
258 #[cfg(not(feature = "getrandom"))]
259 {
260 Err(Error::FeatureNotAvailable {
262 feature: "secure entropy",
263 required_features: &["getrandom"],
264 })
265 }
266 }
267
268 #[must_use]
270 pub fn from_seed(seed: &[u8]) -> Self {
271 use lib_q_hash::digest::{
272 ExtendableOutput,
273 Update,
274 XofReader,
275 };
276
277 let mut k12 = lib_q_hash::Kt128::new(b"HPKE-RNG");
278 k12.update(seed);
279 let mut reader = k12.finalize_xof();
280
281 let mut buffer = [0u8; 32];
283 reader.read(&mut buffer);
284
285 Self {
286 buffer,
287 position: 0,
288 counter: 0,
289 }
290 }
291
292 pub fn refill(&mut self) {
294 use lib_q_hash::digest::{
295 ExtendableOutput,
296 Update,
297 XofReader,
298 };
299
300 let mut k12 = lib_q_hash::Kt128::new(b"HPKE-RNG");
302 k12.update(&self.buffer);
303 k12.update(&self.counter.to_le_bytes());
304 let mut reader = k12.finalize_xof();
305 reader.read(&mut self.buffer);
306 self.counter = self.counter.wrapping_add(1);
307 self.position = 0;
308 }
309}
310
311#[cfg(feature = "hash")]
312impl TryRng for Kt128Rng {
313 type Error = core::convert::Infallible;
314
315 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
316 let mut bytes = [0u8; 4];
317 self.try_fill_bytes(&mut bytes)?;
318 Ok(u32::from_le_bytes(bytes))
319 }
320
321 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
322 let mut bytes = [0u8; 8];
323 self.try_fill_bytes(&mut bytes)?;
324 Ok(u64::from_le_bytes(bytes))
325 }
326
327 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
328 let mut remaining = dest.len();
329 let mut offset = 0;
330
331 while remaining > 0 {
332 if self.position >= self.buffer.len() {
333 self.refill();
334 }
335
336 let available = self.buffer.len() - self.position;
337 let to_copy = core::cmp::min(remaining, available);
338
339 dest[offset..offset + to_copy]
340 .copy_from_slice(&self.buffer[self.position..self.position + to_copy]);
341
342 self.position += to_copy;
343 offset += to_copy;
344 remaining -= to_copy;
345 }
346 Ok(())
347 }
348}
349
350#[cfg(feature = "hash")]
351impl TryCryptoRng for Kt128Rng {}
352
353pub struct FnDsaRng {
358 #[cfg(feature = "rand")]
359 rng: Option<rand::rngs::ThreadRng>,
360}
361
362impl Default for FnDsaRng {
363 fn default() -> Self {
364 Self::new()
365 }
366}
367
368impl FnDsaRng {
369 #[must_use]
371 pub fn new() -> Self {
372 #[cfg(feature = "rand")]
373 {
374 Self {
375 rng: Some(rand::rng()),
376 }
377 }
378 #[cfg(not(feature = "rand"))]
379 {
380 Self {}
381 }
382 }
383}
384
385impl TryRng for FnDsaRng {
386 type Error = core::convert::Infallible;
387
388 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
389 #[cfg(feature = "rand")]
390 {
391 if let Some(ref mut rng) = self.rng {
392 Ok(rng.next_u32())
393 } else {
394 let mut bytes = [0u8; 4];
395 self.try_fill_bytes(&mut bytes)?;
396 Ok(u32::from_le_bytes(bytes))
397 }
398 }
399 #[cfg(not(feature = "rand"))]
400 {
401 #[cfg(feature = "getrandom")]
402 {
403 let mut bytes = [0u8; 4];
404 getrandom::fill(&mut bytes).expect("Failed to get random bytes from getrandom");
405 Ok(u32::from_le_bytes(bytes))
406 }
407 #[cfg(not(feature = "getrandom"))]
408 {
409 panic!(
410 "FnDsaRng requires either 'rand' or 'getrandom' feature. \
411 Use deterministic RNG for testing without these features."
412 );
413 }
414 }
415 }
416
417 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
418 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
419 {
420 let mut bytes = [0u8; 8];
421 getrandom::fill(&mut bytes).expect("Failed to get random bytes from getrandom");
422 Ok(u64::from_le_bytes(bytes))
423 }
424
425 #[cfg(not(all(feature = "getrandom", not(feature = "rand"))))]
426 {
427 let upper = u64::from(self.try_next_u32()?);
428 let lower = u64::from(self.try_next_u32()?);
429 Ok((upper << 32) | lower)
430 }
431 }
432
433 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
434 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
438 {
439 getrandom::fill(dest).expect("Failed to get random bytes from getrandom");
440 Ok(())
441 }
442
443 #[cfg(not(all(feature = "getrandom", not(feature = "rand"))))]
444 {
445 for chunk in dest.chunks_mut(4) {
446 let bytes = self.try_next_u32()?.to_le_bytes();
447 let len = chunk.len().min(4);
448 chunk[..len].copy_from_slice(&bytes[..len]);
449 }
450 Ok(())
451 }
452 }
453}
454
455impl TryCryptoRng for FnDsaRng {}
456
457#[cfg(test)]
458mod tests {
459 use rand_core::Rng;
460
461 use super::*;
462
463 #[test]
464 fn test_classical_mceliece_rng_creation() {
465 let rng = ClassicalMcElieceRng::new();
466 assert!(!rng.deterministic);
467 assert_eq!(rng.state, 0);
468 assert_eq!(rng.counter, 0);
469 }
470
471 #[test]
472 fn test_classical_mceliece_deterministic_rng_creation() {
473 let rng = ClassicalMcElieceRng::new_deterministic(12345);
474 assert!(rng.deterministic);
475 assert_ne!(rng.state, 0);
477 assert_eq!(rng.counter, 0);
478 }
479
480 #[test]
481 fn test_classical_mceliece_deterministic_rng_consistency() {
482 let mut rng1 = ClassicalMcElieceRng::new_deterministic(42);
483 let mut rng2 = ClassicalMcElieceRng::new_deterministic(42);
484
485 let mut bytes1 = [0u8; 32];
486 let mut bytes2 = [0u8; 32];
487
488 rng1.fill_bytes(&mut bytes1);
489 rng2.fill_bytes(&mut bytes2);
490
491 assert_eq!(bytes1, bytes2);
492 }
493
494 #[test]
495 fn test_classical_mceliece_rng_interface() {
496 let mut rng = ClassicalMcElieceRng::new_deterministic(100);
497
498 let mut bytes = [0u8; 16];
500 rng.fill_bytes(&mut bytes);
501 assert_ne!(bytes, [0u8; 16]); let val1 = rng.next_u32();
505 let val2 = rng.next_u32();
506 assert_ne!(val1, val2); let val3 = rng.next_u64();
510 let val4 = rng.next_u64();
511 assert_ne!(val3, val4); }
513
514 #[test]
515 fn test_classical_mceliece_randombytes_init() {
516 let mut rng = ClassicalMcElieceRng::new_deterministic(0);
517 let entropy = [1u8; 48];
518
519 rng.randombytes_init(entropy);
520
521 assert_ne!(rng.state, 0);
523 assert_eq!(rng.reseed_counter, 1);
524 }
525
526 #[test]
527 fn test_fn_dsa_rng_creation() {
528 let _rng = FnDsaRng::new();
529 }
532
533 #[test]
534 #[cfg(any(feature = "rand", feature = "getrandom"))]
535 fn test_fn_dsa_rng_interface() {
536 let mut rng = FnDsaRng::new();
537
538 let mut bytes = [0u8; 16];
540 rng.fill_bytes(&mut bytes);
541 let val1 = rng.next_u32();
545 let val2 = rng.next_u32();
546 assert_ne!(val1, val2);
548
549 let val3 = rng.next_u64();
551 let val4 = rng.next_u64();
552 assert_ne!(val3, val4);
554 }
555
556 #[test]
559 #[cfg(all(feature = "getrandom", not(feature = "rand")))]
560 fn test_fn_dsa_rng_fill_bytes_getrandom_only_odd_length() {
561 let mut rng = FnDsaRng::new();
562 let mut buf = [0u8; 1281];
563 rng.fill_bytes(&mut buf);
564 }
565}