1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#![no_std]
extern crate libc;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
extern {
    pub fn rust_crypto_util_supports_aesni() -> u32;
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn supports_aesni() -> bool {
    unsafe {
        rust_crypto_util_supports_aesni() != 0
    }
}

extern {
    pub fn rust_crypto_util_fixed_time_eq_asm(
            lhsp: *const u8,
            rhsp: *const u8,
            count: libc::size_t) -> u32;
    pub fn rust_crypto_util_secure_memset(
            dst: *mut u8,
            val: libc::uint8_t,
            count: libc::size_t);
}

pub fn secure_memset(dst: &mut [u8], val: u8) {
    unsafe {
        rust_crypto_util_secure_memset(
            dst.as_mut_ptr(),
            val,
            dst.len() as libc::size_t);
    }
}

/// Compare two vectors using a fixed number of operations. If the two vectors
/// are not of equal length, the function returns false immediately.
pub fn fixed_time_eq(lhs: &[u8], rhs: &[u8]) -> bool {
    if lhs.len() != rhs.len() {
        false
    } else {
        let count = lhs.len() as libc::size_t;

        unsafe {
            let lhsp = lhs.get_unchecked(0);
            let rhsp = rhs.get_unchecked(0);
            rust_crypto_util_fixed_time_eq_asm(lhsp, rhsp, count) == 0
        }
    }
}

#[cfg(test)]
mod test {
    use super::fixed_time_eq;

    #[test]
    pub fn test_fixed_time_eq() {
        let a = [0, 1, 2];
        let b = [0, 1, 2];
        let c = [0, 1, 9];
        let d = [9, 1, 2];
        let e = [2, 1, 0];
        let f = [2, 2, 2];
        let g = [0, 0, 0];

        assert!(fixed_time_eq(&a, &a));
        assert!(fixed_time_eq(&a, &b));

        assert!(!fixed_time_eq(&a, &c));
        assert!(!fixed_time_eq(&a, &d));
        assert!(!fixed_time_eq(&a, &e));
        assert!(!fixed_time_eq(&a, &f));
        assert!(!fixed_time_eq(&a, &g));
    }
}