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
76
// -*- mode: rust; -*-
//
// To the extent possible under law, the authors have waived all copyright and
// related or neighboring rights to curve25519-dalek, using the Creative
// Commons "CC0" public domain dedication.  See
// <http://creativecommons.org/publicdomain/zero/.0/> for full details.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>

//! Utility functions and tools for constant-time comparisons.

/// Trait for items which can be conditionally assigned in constant time.
pub trait CTAssignable {
    /// If `choice == 1u8`, assign `other` to `self`.
    /// Otherwise, leave `self` unchanged.
    /// Executes in constant time.
    fn conditional_assign(&mut self, other: &Self, choice: u8);
}

/// Check equality of two bytes in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
pub fn bytes_equal_ct(a: u8, b: u8) -> u8 {
    let mut x: u8;

    x  = !(a ^ b);
    x &= x >> 4;
    x &= x >> 2;
    x &= x >> 1;
    x
}

/// Test if a byte is non-zero in constant time.
///
/// ```rust,ignore
/// let mut x: u8;
/// x = 0;
/// assert!(byte_is_nonzero(x));
/// x = 3;
/// assert!(byte_is_nonzero(x) == 1);
/// ```
///
/// # Return
///
/// * If b != 0, returns 1u8.
/// * If b == 0, returns 0u8.
#[inline(always)]
pub fn byte_is_nonzero(b: u8) -> u8 {
    let mut x = b;
    x |= x >> 4;
    x |= x >> 2;
    x |= x >> 1;
    (x & 1)
}

/// Check equality of two 32-byte arrays in constant time.
///
/// # Return
///
/// Returns 1 if `a == b` and 0 otherwise.
#[inline(always)]
// We don't use this in curve25519-dalek, but it's useful for e.g. an ed25519 implementation.
#[allow(dead_code)]
pub fn arrays_equal_ct(a: &[u8; 32], b: &[u8; 32]) -> u8 {
    let mut x: u8 = 0;

    for i in 0..32 {
        x |= a[i] ^ b[i];
    }
    bytes_equal_ct(x, 0)
}