diff --git a/src/crypto/memcmp.rs b/src/crypto/memcmp.rs new file mode 100644 index 00000000..c30281d4 --- /dev/null +++ b/src/crypto/memcmp.rs @@ -0,0 +1,39 @@ +use libc::size_t; +use ffi; + +/// Returns `true` iff `a` and `b` contain the same bytes. +/// +/// This operation takes an amount of time dependent on the length of the two +/// arrays given, but is independent of the contents of a and b. +/// +/// # Failure +/// +/// This function will fail the current task if `a` and `b` do not have the same +/// length. +pub fn eq(a: &[u8], b: &[u8]) -> bool { + assert!(a.len() == b.len()); + let ret = unsafe { + ffi::CRYPTO_memcmp(a.as_ptr() as *const _, + b.as_ptr() as *const _, + a.len() as size_t) + }; + ret == 0 +} + +#[cfg(test)] +mod tests { + use super::eq; + + #[test] + fn test_eq() { + assert!(eq([], [])); + assert!(eq([1], [1])); + assert!(!eq([1, 2, 3], [1, 2, 4])); + } + + #[test] + #[should_fail] + fn test_diff_lens() { + eq([], [1]); + } +} diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index d7c62f98..e695de33 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -21,3 +21,4 @@ pub mod pkcs5; pub mod pkey; pub mod rand; pub mod symm; +pub mod memcmp; diff --git a/src/ffi.rs b/src/ffi.rs index 5a8f753a..b31dc1bb 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar}; +use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t}; pub type ASN1_INTEGER = c_void; pub type ASN1_STRING = c_void; @@ -265,6 +265,8 @@ extern "C" { file: *const c_char, line: c_int)); pub fn CRYPTO_free(buf: *const c_char); + pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void, + len: size_t) -> c_int; pub fn ERR_get_error() -> c_ulong;