diff --git a/constant-time/src/compare.rs b/constant-time/src/compare.rs index 301da6e1..0e1db0a0 100644 --- a/constant-time/src/compare.rs +++ b/constant-time/src/compare.rs @@ -1,7 +1,15 @@ +//! Constant-time comparison + use core::ptr; /// Little endian memcmp version of quinier/memsec /// https://github.com/quininer/memsec/blob/bbc647967ff6d20d6dccf1c85f5d9037fcadd3b0/src/lib.rs#L30 +/// +/// # Panic & Safety +/// +/// Both input arrays must be at least of the indicated length. +/// +/// See [std::ptr::read_volatile] on safety. #[inline(never)] pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 { let mut res = 0; @@ -13,6 +21,16 @@ pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 { ((res - 1) >> 8) + (res >> 8) + 1 } +#[test] +pub fn memcmp_le_test() { + // use rosenpass_constant_time::memcmp_le; + let a = [0, 1, 0, 0]; + let b = [0, 0, 0, 1]; + assert_eq!(-1, unsafe { memcmp_le(a.as_ptr(), b.as_ptr(), 4) }); + assert_eq!(0, unsafe { memcmp_le(a.as_ptr(), a.as_ptr(), 4) }); + assert_eq!(1, unsafe { memcmp_le(b.as_ptr(), a.as_ptr(), 4) }); +} + /// compares two slices of memory content and returns an integer indicating the relationship between /// the slices /// @@ -32,6 +50,28 @@ pub unsafe fn memcmp_le(b1: *const u8, b2: *const u8, len: usize) -> i32 { /// ## Tests /// For discussion on how to ensure the constant-time execution of this function, see /// +/// +/// # Examples +/// +/// ```rust +/// use rosenpass_constant_time::compare; +/// let a = [0, 1, 0, 0]; +/// let b = [0, 0, 0, 1]; +/// assert_eq!(-1, compare(&a, &b)); +/// assert_eq!(0, compare(&a, &a)); +/// assert_eq!(1, compare(&b, &a)); +/// ``` +/// +/// # Panic +/// +/// This function will panic if the input arrays are of different lengths. +/// +/// ```should_panic +/// use rosenpass_constant_time::compare; +/// let a = [0, 1, 0]; +/// let b = [0, 0, 0, 1]; +/// compare(&a, &b); +/// ``` #[inline] pub fn compare(a: &[u8], b: &[u8]) -> i32 { assert!(a.len() == b.len()); diff --git a/constant-time/src/increment.rs b/constant-time/src/increment.rs index b1f031aa..7483c9f3 100644 --- a/constant-time/src/increment.rs +++ b/constant-time/src/increment.rs @@ -1,3 +1,5 @@ +//! Incrementing numbers + use core::hint::black_box; /// Interpret the given slice as a little-endian unsigned integer diff --git a/constant-time/src/lib.rs b/constant-time/src/lib.rs index 275a201f..683368c7 100644 --- a/constant-time/src/lib.rs +++ b/constant-time/src/lib.rs @@ -1,3 +1,5 @@ +#![warn(missing_docs)] +#![warn(clippy::missing_docs_in_private_items)] //! constant-time implementations of some primitives //! //! Rosenpass internal library providing basic constant-time operations. diff --git a/constant-time/src/memcmp.rs b/constant-time/src/memcmp.rs index 8039cc8f..20e4712a 100644 --- a/constant-time/src/memcmp.rs +++ b/constant-time/src/memcmp.rs @@ -1,3 +1,5 @@ +//! memcmp + /// compares two sclices of memory content and returns whether they are equal /// /// ## Leaks @@ -7,6 +9,18 @@ /// /// The execution time of the function grows approx. linear with the length of the input. This is /// considered safe. +/// +/// ## Examples +/// +/// ```rust +/// use rosenpass_constant_time::memcmp; +/// let a = [0, 0, 0, 0]; +/// let b = [0, 0, 0, 1]; +/// let c = [0, 0, 0]; +/// assert!(memcmp(&a, &a)); +/// assert!(!memcmp(&a, &b)); +/// assert!(!memcmp(&a, &c)); +/// ``` #[inline] pub fn memcmp(a: &[u8], b: &[u8]) -> bool { a.len() == b.len() && unsafe { memsec::memeq(a.as_ptr(), b.as_ptr(), a.len()) } diff --git a/constant-time/src/xor.rs b/constant-time/src/xor.rs index d347d1b7..ed247219 100644 --- a/constant-time/src/xor.rs +++ b/constant-time/src/xor.rs @@ -1,3 +1,5 @@ +//! xor + use core::hint::black_box; use rosenpass_to::{with_destination, To};