rng.rs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (c) 2018, The Tor Project, Inc.
  2. // Copyright (c) 2018, isis agora lovecruft
  3. // See LICENSE for licensing information
  4. //! Wrappers for Tor's random number generator to provide implementations of
  5. //! `rand_core` traits.
  6. // This is the real implementation, in use in production, which calls into our C
  7. // wrappers in /src/common/crypto_rand.c, which call into OpenSSL, system
  8. // libraries, and make syscalls.
  9. #[cfg(not(test))]
  10. mod internal {
  11. use std::u64;
  12. use rand_core::CryptoRng;
  13. use rand_core::Error;
  14. use rand_core::RngCore;
  15. use rand_core::impls::next_u32_via_fill;
  16. use rand_core::impls::next_u64_via_fill;
  17. use external::c_tor_crypto_strongest_rand;
  18. use external::c_tor_crypto_seed_rng;
  19. use tor_log::LogDomain;
  20. use tor_log::LogSeverity;
  21. /// Largest strong entropy request permitted.
  22. //
  23. // C_RUST_COUPLED: `MAX_STRONGEST_RAND_SIZE` /src/common/crypto_rand.c
  24. const MAX_STRONGEST_RAND_SIZE: usize = 256;
  25. /// A wrapper around OpenSSL's RNG.
  26. pub struct TorRng {
  27. // This private, zero-length field forces the struct to be treated the
  28. // same as its opaque C couterpart.
  29. _unused: [u8; 0],
  30. }
  31. /// Mark `TorRng` as being suitable for cryptographic purposes.
  32. impl CryptoRng for TorRng {}
  33. impl TorRng {
  34. // C_RUST_COUPLED: `crypto_seed_rng()` /src/common/crypto_rand.c
  35. #[allow(dead_code)]
  36. fn new() -> Self {
  37. if !c_tor_crypto_seed_rng() {
  38. tor_log_msg!(LogSeverity::Warn, LogDomain::General,
  39. "TorRng::from_seed()",
  40. "The RNG could not be seeded!");
  41. }
  42. // XXX also log success at info level —isis
  43. TorRng{ _unused: [0u8; 0] }
  44. }
  45. }
  46. impl RngCore for TorRng {
  47. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  48. fn next_u32(&mut self) -> u32 {
  49. next_u32_via_fill(self)
  50. }
  51. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  52. fn next_u64(&mut self) -> u64 {
  53. next_u64_via_fill(self)
  54. }
  55. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  56. fn fill_bytes(&mut self, dest: &mut [u8]) {
  57. debug_assert!(dest.len() <= MAX_STRONGEST_RAND_SIZE);
  58. c_tor_crypto_strongest_rand(dest);
  59. }
  60. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  61. fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
  62. Ok(self.fill_bytes(dest))
  63. }
  64. }
  65. }
  66. // For testing, we expose the pure-Rust implementation of a
  67. // cryptographically-insecure PRNG which mirrors the implementation of
  68. // `tor_weak_rng_t` in C.
  69. #[cfg(test)]
  70. mod internal {
  71. use prng::TorInsecurePrng;
  72. pub type TorRng = TorInsecurePrng;
  73. }
  74. // Finally, expose the public functionality of whichever appropriate internal
  75. // module.
  76. pub use self::internal::*;