crypto_rand.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright (c) 2018-2019, The Tor Project, Inc.
  2. // Copyright (c) 2018, isis agora lovecruft
  3. // See LICENSE for licensing information
  4. //! Bindings to external (P)RNG interfaces and utilities in
  5. //! src/common/crypto_rand.[ch].
  6. //!
  7. //! We wrap our C implementations in src/common/crypto_rand.[ch] here in order
  8. //! to provide wrappers with native Rust types, and then provide more Rusty
  9. //! types and and trait implementations in src/rust/crypto/rand/.
  10. use std::time::Duration;
  11. use libc::c_double;
  12. use libc::c_int;
  13. use libc::size_t;
  14. use libc::time_t;
  15. use libc::uint8_t;
  16. extern "C" {
  17. fn crypto_seed_rng() -> c_int;
  18. fn crypto_rand(out: *mut uint8_t, out_len: size_t);
  19. fn crypto_strongest_rand(out: *mut uint8_t, out_len: size_t);
  20. fn crypto_rand_time_range(min: time_t, max: time_t) -> time_t;
  21. fn crypto_rand_double() -> c_double;
  22. }
  23. /// Seed OpenSSL's random number generator with bytes from the operating
  24. /// system.
  25. ///
  26. /// # Returns
  27. ///
  28. /// `true` on success; `false` on failure.
  29. pub fn c_tor_crypto_seed_rng() -> bool {
  30. let ret: c_int;
  31. unsafe {
  32. ret = crypto_seed_rng();
  33. }
  34. match ret {
  35. 0 => return true,
  36. _ => return false,
  37. }
  38. }
  39. /// Fill the bytes of `dest` with random data.
  40. pub fn c_tor_crypto_rand(dest: &mut [u8]) {
  41. unsafe {
  42. crypto_rand(dest.as_mut_ptr(), dest.len() as size_t);
  43. }
  44. }
  45. /// Fill the bytes of `dest` with "strong" random data by hashing
  46. /// together randomness obtained from OpenSSL's RNG and the operating
  47. /// system.
  48. pub fn c_tor_crypto_strongest_rand(dest: &mut [u8]) {
  49. // We'll let the C side panic if the len is larger than
  50. // MAX_STRONGEST_RAND_SIZE, rather than potentially panicking here. A
  51. // paranoid caller should assert on the length of dest *before* calling this
  52. // function.
  53. unsafe {
  54. crypto_strongest_rand(dest.as_mut_ptr(), dest.len() as size_t);
  55. }
  56. }
  57. /// Get a random time, in seconds since the Unix Epoch.
  58. ///
  59. /// # Returns
  60. ///
  61. /// A `std::time::Duration` of seconds since the Unix Epoch.
  62. pub fn c_tor_crypto_rand_time_range(min: &Duration, max: &Duration) -> Duration {
  63. let ret: time_t;
  64. unsafe {
  65. ret = crypto_rand_time_range(min.as_secs() as time_t, max.as_secs() as time_t);
  66. }
  67. Duration::from_secs(ret as u64)
  68. }
  69. /// Return a pseudorandom 64-bit float, chosen uniformly from the range [0.0, 1.0).
  70. pub fn c_tor_crypto_rand_double() -> f64 {
  71. unsafe { crypto_rand_double() }
  72. }