Reworking bssl_crypto: rand
Change-Id: I49e1b11b6eba1f2ddc190c5c070f133cce10b2f7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65175
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/rust/bssl-crypto/src/lib.rs b/rust/bssl-crypto/src/lib.rs
index 61a8dbc..753cc79 100644
--- a/rust/bssl-crypto/src/lib.rs
+++ b/rust/bssl-crypto/src/lib.rs
@@ -50,9 +50,6 @@
pub mod hmac;
-/// Random number generation.
-pub mod rand;
-
pub mod x25519;
pub mod ec;
@@ -63,6 +60,9 @@
mod mem;
pub use mem::constant_time_compare;
+mod rand;
+pub use rand::{rand_array, rand_bytes};
+
#[cfg(test)]
mod test_helpers;
diff --git a/rust/bssl-crypto/src/rand.rs b/rust/bssl-crypto/src/rand.rs
index 9fdbe0a..c6d419f 100644
--- a/rust/bssl-crypto/src/rand.rs
+++ b/rust/bssl-crypto/src/rand.rs
@@ -13,29 +13,56 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-use crate::CSliceMut;
+//! Getting random bytes.
-/// Fills buf with random bytes. In the event that sufficient random data can not be obtained,
-/// BoringSSL will abort, so the assert will never be hit.
+use crate::{with_output_array, FfiMutSlice};
+
+/// Fills `buf` with random bytes.
pub fn rand_bytes(buf: &mut [u8]) {
- let mut ffi_buf = CSliceMut::from(buf);
- let result = unsafe { bssl_sys::RAND_bytes(ffi_buf.as_mut_ptr(), ffi_buf.len()) };
- assert_eq!(result, 1, "BoringSSL RAND_bytes API failed unexpectedly");
+ // Safety: `RAND_bytes` writes exactly `buf.len()` bytes.
+ let ret = unsafe { bssl_sys::RAND_bytes(buf.as_mut_ffi_ptr(), buf.len()) };
+
+ // BoringSSL's `RAND_bytes` always succeeds returning 1, or crashes the
+ // address space if the PRNG can not provide random data.
+ debug_assert!(ret == 1);
+}
+
+/// Returns an array of random bytes.
+pub fn rand_array<const N: usize>() -> [u8; N] {
+ unsafe {
+ with_output_array(|out, out_len| {
+ // Safety: `RAND_bytes` writes exactly `out_len` bytes, as required.
+ let ret = bssl_sys::RAND_bytes(out, out_len);
+ // BoringSSL RAND_bytes always succeeds returning 1, or crashes the
+ // address space if the PRNG can not provide random data.
+ debug_assert!(ret == 1);
+ })
+ }
}
#[cfg(test)]
mod tests {
- use super::rand_bytes;
+ use super::*;
#[test]
- fn test_rand_bytes() {
+ fn fill() {
let mut buf = [0; 32];
rand_bytes(&mut buf);
}
#[test]
- fn test_rand_bytes_empty() {
+ fn fill_empty() {
let mut buf = [];
rand_bytes(&mut buf);
}
+
+ #[test]
+ fn array() {
+ let _rand: [u8; 32] = rand_array();
+ }
+
+ #[test]
+ fn empty_array() {
+ let _rand: [u8; 0] = rand_array();
+ }
}