     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66

    //! Utilities for secure random number generation.
    //!
    //! # Examples
    //!
    //! To generate a buffer with cryptographically strong bytes:
    //!
    //! ```
    //! use openssl::rand::rand_bytes;
    //!
    //! let mut buf = [0; 256];
    //! rand_bytes(&mut buf).unwrap();
    //! ```
    use ffi;
    use libc::c_int;

    use cvt;
    use error::ErrorStack;

    /// Fill buffer with cryptographically strong pseudo-random bytes.
    ///
    /// This corresponds to [`RAND_bytes`].
    ///
    /// # Examples
    ///
    /// To generate a buffer with cryptographically strong bytes:
    ///
    /// ```
    /// use openssl::rand::rand_bytes;
    ///
    /// let mut buf = [0; 256];
    /// rand_bytes(&mut buf).unwrap();
    /// ```
    ///
    /// [`RAND_bytes`]: https://www.openssl.org/docs/man1.1.0/crypto/RAND_bytes.html
    pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> {
        unsafe {
            ffi::init();
            assert!(buf.len() <= c_int::max_value() as usize);
            cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int)).map(|_| ())
        }
    }

    /// Controls random device file descriptor behavior.
    ///
    /// Requires OpenSSL 1.1.1 or newer.
    ///
    /// This corresponds to [`RAND_keep_random_devices_open`].
    ///
    /// [`RAND_keep_random_devices_open`]: https://www.openssl.org/docs/manmaster/man3/RAND_keep_random_devices_open.html
    #[cfg(ossl111)]
    pub fn keep_random_devices_open(keep: bool) {
        unsafe {
            ffi::RAND_keep_random_devices_open(keep as c_int);
        }
    }

    #[cfg(test)]
    mod tests {
        use super::rand_bytes;

        #[test]
        fn test_rand_bytes() {
            let mut buf = [0; 32];
            rand_bytes(&mut buf).unwrap();
        }
    }