pub fn fixed_time_eq(a: &[u8], b: &[u8]) -> bool {
#[cfg(hashes_fuzz)]
{
a == b
}
#[cfg(not(hashes_fuzz))]
{
assert!(a.len() == b.len());
let count = a.len();
let lhs = &a[..count];
let rhs = &b[..count];
let mut r: u8 = 0;
for i in 0..count {
let mut rs = unsafe { core::ptr::read_volatile(&r) };
rs |= lhs[i] ^ rhs[i];
unsafe {
core::ptr::write_volatile(&mut r, rs);
}
}
{
let mut t = unsafe { core::ptr::read_volatile(&r) };
t |= t >> 4;
unsafe {
core::ptr::write_volatile(&mut r, t);
}
}
{
let mut t = unsafe { core::ptr::read_volatile(&r) };
t |= t >> 2;
unsafe {
core::ptr::write_volatile(&mut r, t);
}
}
{
let mut t = unsafe { core::ptr::read_volatile(&r) };
t |= t >> 1;
unsafe {
core::ptr::write_volatile(&mut r, t);
}
}
unsafe { (::core::ptr::read_volatile(&r) & 1) == 0 }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eq_test() {
assert!(fixed_time_eq(&[0b00000000], &[0b00000000]));
assert!(fixed_time_eq(&[0b00000001], &[0b00000001]));
assert!(fixed_time_eq(&[0b00000010], &[0b00000010]));
assert!(fixed_time_eq(&[0b00000100], &[0b00000100]));
assert!(fixed_time_eq(&[0b00001000], &[0b00001000]));
assert!(fixed_time_eq(&[0b00010000], &[0b00010000]));
assert!(fixed_time_eq(&[0b00100000], &[0b00100000]));
assert!(fixed_time_eq(&[0b01000000], &[0b01000000]));
assert!(fixed_time_eq(&[0b10000000], &[0b10000000]));
assert!(fixed_time_eq(&[0b11111111], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00000001], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00000001], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00000010], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00000010], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00000100], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00000100], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00001000], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00001000], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00010000], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00010000], &[0b11111111]));
assert!(!fixed_time_eq(&[0b00100000], &[0b00000000]));
assert!(!fixed_time_eq(&[0b00100000], &[0b11111111]));
assert!(!fixed_time_eq(&[0b01000000], &[0b00000000]));
assert!(!fixed_time_eq(&[0b01000000], &[0b11111111]));
assert!(!fixed_time_eq(&[0b10000000], &[0b00000000]));
assert!(!fixed_time_eq(&[0b10000000], &[0b11111111]));
assert!(fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000000, 0b00000000]));
assert!(!fixed_time_eq(&[0b00000001, 0b00000000], &[0b00000000, 0b00000000]));
assert!(!fixed_time_eq(&[0b00000000, 0b00000001], &[0b00000000, 0b00000000]));
assert!(!fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000001, 0b00000000]));
assert!(!fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000001, 0b00000001]));
}
}