Skip to content

Commit

Permalink
Move constant time comparison to a module outside of |ring::ffi|.
Browse files Browse the repository at this point in the history
Having the constant-time utilities in |ring::ffi| is misleading as
|use ring::ffi| gives the impression that a module was using the FFI
when really it is FFI-free. |ring::hmac| and |ring::pbkdf2| are
examples of that.

At some point, |ring::constant_time| may be added to the public API,
but for now it is private.
  • Loading branch information
briansmith committed Oct 23, 2015
1 parent 377f611 commit 5cb9831
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 29 deletions.
41 changes: 41 additions & 0 deletions src/constant_time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2015 Brian Smith.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

//! Constant-time operations.

use super::c;

/// Returns `Ok(())` of `a == b` and `Err(())` otherwise. The comparison of
/// `a` and `b` is done in constant time with respect to the contents of each,
/// but NOT in constant time with respect to the lengths of `a` and `b`.
pub fn verify_slices_are_equal(a: &[u8], b: &[u8]) -> Result<(), ()> {
if a.len() != b.len() {
return Err(());
}
let result = unsafe {
CRYPTO_memcmp(a.as_ptr(), b.as_ptr(), a.len())
};
match result {
0 => Ok(()),
_ => Err(())
}
}

// XXX: As of Rust 1.4, the compiler will no longer warn about the use of
// `usize` and `isize` in FFI declarations. Remove the `allow(improper_ctypes)`
// when Rust 1.4 is released.
#[allow(improper_ctypes)]
extern {
fn CRYPTO_memcmp(a: *const u8, b: *const u8, len: c::size_t) -> c::int;
}
25 changes: 0 additions & 25 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,3 @@ pub fn map_bssl_ptr_result<T>(bssl_result: *mut T) -> Result<*mut T, ()> {
}
Ok(bssl_result)
}


/// Returns `Ok(())` of `a == b` and `Err(())` otherwise. The comparison of
/// `a` and `b` is done in constant time with respect to the contents of each,
/// but NOT in constant time with respect to the lengths of `a` and `b`.
pub fn verify_slices_are_equal_ct(a: &[u8], b: &[u8]) -> Result<(), ()> {
if a.len() != b.len() {
return Err(());
}
let result = unsafe {
CRYPTO_memcmp(a.as_ptr(), b.as_ptr(), a.len())
};
match result {
0 => Ok(()),
_ => Err(())
}
}

// XXX: As of Rust 1.4, the compiler will no longer warn about the use of
// `usize` and `isize` in FFI declarations. Remove the `allow(improper_ctypes)`
// when Rust 1.4 is released.
#[allow(improper_ctypes)]
extern {
fn CRYPTO_memcmp(a: *const u8, b: *const u8, len: c::size_t) -> c::int;
}
5 changes: 3 additions & 2 deletions src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
//! # fn main() { main_with_result().unwrap() }
//! ```

use super::{digest, ffi};
use super::{constant_time, digest};

/// A key to use for HMAC signing.
pub struct SigningKey {
Expand Down Expand Up @@ -246,7 +246,8 @@ pub fn verify(key: &VerificationKey, data: &[u8], expected_value: &[u8])
let mut ctx = SigningContext::with_key(&key.wrapped);
ctx.update(data);
let actual_value = ctx.sign();
ffi::verify_slices_are_equal_ct(actual_value.as_ref(), expected_value)
constant_time::verify_slices_are_equal(actual_value.as_ref(),
expected_value)
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extern crate rustc_serialize;

pub mod aead;
mod c;
mod constant_time;
pub mod digest;
pub mod ecc;
mod ffi;
Expand Down
4 changes: 2 additions & 2 deletions src/pbkdf2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
//! assert!(db.verify_password("alice", "@74d7]404j|W}6u").is_ok());
//! }

use super::{digest, ffi, hmac};
use super::{constant_time, digest, hmac};

/// Fills `out` with the key derived using PBKDF2 with the given inputs.
///
Expand Down Expand Up @@ -202,7 +202,7 @@ pub fn verify(prf: &'static PRF, iterations: usize, salt: &[u8], secret: &[u8],
}
let derived = &mut derived_buf[0..previously_derived.len()];
derive(prf, iterations, salt, secret, derived);
ffi::verify_slices_are_equal_ct(derived, previously_derived)
constant_time::verify_slices_are_equal(derived, previously_derived)
}

/// A PRF algorithm for use with `derive` and `verify`.
Expand Down

0 comments on commit 5cb9831

Please sign in to comment.