Skip to content

Commit

Permalink
cmov: add ct_eq for slice comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
codahale committed Sep 27, 2023
1 parent 895b4a5 commit 0779475
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
17 changes: 17 additions & 0 deletions cmov/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,20 @@ impl CmovEq for u128 {
tmp.cmoveq(&1, input, output);
}
}

/// A constant-time comparison of two `u8` slices using conditional move instructions. Returns `1`
/// iff the two slices are equal, `0` otherwise.
#[inline(never)] // don't inline to avoid getting optimized into vartime
pub fn ct_eq(a: impl AsRef<[u8]>, b: impl AsRef<[u8]>) -> u8 {
// Compare slice lengths in variable time, since there's no other way to do that.
if a.as_ref().len() != b.as_ref().len() {
return 0;
}

// Iterate through the value pairs, checking for inequality.
let mut res = 1;
for (x, y) in a.as_ref().iter().zip(b.as_ref().iter()) {
x.cmovne(y, 0, &mut res);
}
res
}
9 changes: 9 additions & 0 deletions cmov/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use cmov::ct_eq;

mod u8 {
use cmov::{Cmov, CmovEq};

Expand Down Expand Up @@ -332,3 +334,10 @@ mod u128 {
assert_eq!(o, 55u8);
}
}

#[test]
fn ct_eq_works() {
assert_eq!(ct_eq([1, 2, 3], [1, 2, 3]), 1);
assert_eq!(ct_eq([1, 2, 4], [1, 2, 3]), 0);
assert_eq!(ct_eq([1, 2, 3], [1, 2]), 0);
}

0 comments on commit 0779475

Please sign in to comment.