crypto_rand.rs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright (c) 2018, 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_char;
  12. use libc::c_double;
  13. use libc::c_int;
  14. use libc::c_uint;
  15. use libc::c_void;
  16. use libc::size_t;
  17. use libc::time_t;
  18. use libc::uint8_t;
  19. use libc::uint64_t;
  20. extern "C" {
  21. fn crypto_seed_rng() -> c_int;
  22. fn crypto_strongest_rand(out: *mut uint8_t, out_len: size_t);
  23. fn crypto_rand_time_range(min: time_t, max: time_t) -> time_t;
  24. fn crypto_rand_double() -> c_double;
  25. // fn crypto_random_hostname(min_rand_len: c_int, max_rand_len: c_int,
  26. // prefix: *const c_char, suffix: *const c_char) -> *mut c_char;
  27. }
  28. /// Seed OpenSSL's random number generator with bytes from the operating
  29. /// system.
  30. ///
  31. /// # Returns
  32. ///
  33. /// `true` on success; `false` on failure.
  34. pub fn c_tor_crypto_seed_rng() -> bool {
  35. let ret: c_int;
  36. unsafe {
  37. ret = crypto_seed_rng();
  38. }
  39. match ret {
  40. 0 => return true,
  41. _ => return false,
  42. }
  43. }
  44. /// Fill the bytes of `dest` with strong random data.
  45. pub fn c_tor_crypto_strongest_rand(dest: &mut [u8]) {
  46. // We'll let the C side panic if the len is larger than
  47. // MAX_STRONGEST_RAND_SIZE, rather than potentially panicking here. A
  48. // paranoid caller should assert on the length of dest *before* calling this
  49. // function.
  50. unsafe {
  51. crypto_strongest_rand(dest.as_mut_ptr(), dest.len() as size_t);
  52. }
  53. }
  54. /// Get a random time, in seconds since the Unix Epoch.
  55. ///
  56. /// # Returns
  57. ///
  58. /// A `std::time::Duration` of seconds since the Unix Epoch.
  59. pub fn c_tor_crypto_rand_time_range(min: &Duration, max: &Duration) -> Duration {
  60. let ret: time_t;
  61. unsafe {
  62. ret = crypto_rand_time_range(min.as_secs() as time_t, max.as_secs() as time_t);
  63. }
  64. Duration::from_secs(ret as u64)
  65. }
  66. /// Return a pseudorandom 64-bit float, chosen uniformly from the range [0.0, 1.0).
  67. pub fn c_tor_crypto_rand_double() -> f64 {
  68. unsafe {
  69. crypto_rand_double()
  70. }
  71. }
  72. #[cfg(test)]
  73. mod test {
  74. use super::*;
  75. #[test]
  76. fn test_layout_tor_weak_rng_t() {
  77. assert_eq!(::std::mem::size_of::<tor_weak_rng_t>(), 0usize,
  78. concat!("Size of: ", stringify!(tor_weak_rng_t)));
  79. assert_eq!(::std::mem::align_of::<tor_weak_rng_t>(), 1usize,
  80. concat!("Alignment of ", stringify!(tor_weak_rng_t)));
  81. }
  82. }