rng.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 generators 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::impls::next_u32_via_fill;
  13. use rand_core::impls::next_u64_via_fill;
  14. use rand_core::CryptoRng;
  15. use rand_core::Error;
  16. use rand_core::RngCore;
  17. use external::c_tor_crypto_rand;
  18. use external::c_tor_crypto_seed_rng;
  19. use external::c_tor_crypto_strongest_rand;
  20. use tor_log::LogDomain;
  21. use tor_log::LogSeverity;
  22. /// Largest strong entropy request permitted.
  23. //
  24. // C_RUST_COUPLED: `MAX_STRONGEST_RAND_SIZE` /src/common/crypto_rand.c
  25. const MAX_STRONGEST_RAND_SIZE: usize = 256;
  26. /// A wrapper around OpenSSL's RNG.
  27. pub struct TorRng {
  28. // This private, zero-length field forces the struct to be treated the
  29. // same as its opaque C couterpart.
  30. _unused: [u8; 0],
  31. }
  32. /// Mark `TorRng` as being suitable for cryptographic purposes.
  33. impl CryptoRng for TorRng {}
  34. impl TorRng {
  35. // C_RUST_COUPLED: `crypto_seed_rng()` /src/common/crypto_rand.c
  36. #[allow(dead_code)]
  37. pub fn new() -> Self {
  38. if !c_tor_crypto_seed_rng() {
  39. tor_log_msg!(
  40. LogSeverity::Warn,
  41. LogDomain::General,
  42. "TorRng::from_seed()",
  43. "The RNG could not be seeded!"
  44. );
  45. }
  46. // XXX also log success at info level —isis
  47. TorRng { _unused: [0u8; 0] }
  48. }
  49. }
  50. impl RngCore for TorRng {
  51. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  52. fn next_u32(&mut self) -> u32 {
  53. next_u32_via_fill(self)
  54. }
  55. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  56. fn next_u64(&mut self) -> u64 {
  57. next_u64_via_fill(self)
  58. }
  59. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  60. fn fill_bytes(&mut self, dest: &mut [u8]) {
  61. c_tor_crypto_rand(dest);
  62. }
  63. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  64. fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
  65. Ok(self.fill_bytes(dest))
  66. }
  67. }
  68. /// A CSPRNG which hashes together randomness from OpenSSL's RNG and entropy
  69. /// obtained from the operating system.
  70. pub struct TorStrongestRng {
  71. // This private, zero-length field forces the struct to be treated the
  72. // same as its opaque C couterpart.
  73. _unused: [u8; 0],
  74. }
  75. /// Mark `TorRng` as being suitable for cryptographic purposes.
  76. impl CryptoRng for TorStrongestRng {}
  77. impl TorStrongestRng {
  78. // C_RUST_COUPLED: `crypto_seed_rng()` /src/common/crypto_rand.c
  79. #[allow(dead_code)]
  80. pub fn new() -> Self {
  81. if !c_tor_crypto_seed_rng() {
  82. tor_log_msg!(
  83. LogSeverity::Warn,
  84. LogDomain::General,
  85. "TorStrongestRng::from_seed()",
  86. "The RNG could not be seeded!"
  87. );
  88. }
  89. // XXX also log success at info level —isis
  90. TorStrongestRng { _unused: [0u8; 0] }
  91. }
  92. }
  93. impl RngCore for TorStrongestRng {
  94. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  95. fn next_u32(&mut self) -> u32 {
  96. next_u32_via_fill(self)
  97. }
  98. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  99. fn next_u64(&mut self) -> u64 {
  100. next_u64_via_fill(self)
  101. }
  102. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  103. fn fill_bytes(&mut self, dest: &mut [u8]) {
  104. debug_assert!(dest.len() <= MAX_STRONGEST_RAND_SIZE);
  105. c_tor_crypto_strongest_rand(dest);
  106. }
  107. // C_RUST_COUPLED: `crypto_strongest_rand()` /src/common/crypto_rand.c
  108. fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
  109. Ok(self.fill_bytes(dest))
  110. }
  111. }
  112. }
  113. // For testing, we expose a pure-Rust implementation.
  114. #[cfg(test)]
  115. mod internal {
  116. // It doesn't matter if we pretend ChaCha is a CSPRNG in tests.
  117. pub use rand_crate::ChaChaRng as TorRng;
  118. pub use rand_crate::ChaChaRng as TorStrongestRng;
  119. }
  120. // Finally, expose the public functionality of whichever appropriate internal
  121. // module.
  122. pub use self::internal::*;