oxicrypto_core/ct.rs
1/// Constant-time byte-slice equality comparison.
2///
3/// Returns `true` if `a` and `b` are equal. The comparison time depends only
4/// on the length of the shorter slice, never on the position of the first
5/// differing byte.
6#[must_use]
7pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
8 use subtle::ConstantTimeEq as _;
9 if a.len() != b.len() {
10 return false;
11 }
12 a.ct_eq(b).into()
13}
14
15/// Constant-time check whether every byte in `data` is zero.
16///
17/// Returns `true` only if all bytes are `0x00`. The runtime is proportional
18/// to `data.len()`, regardless of the actual content.
19#[must_use]
20pub fn ct_is_zero(data: &[u8]) -> bool {
21 use subtle::ConstantTimeEq as _;
22 let mut acc: u8 = 0;
23 for &b in data {
24 acc |= b;
25 }
26 acc.ct_eq(&0u8).into()
27}
28
29/// Constant-time conditional select: returns `a` if `choice` is `0`,
30/// or `b` if `choice` is `1`. Any other `choice` value is treated as `1`.
31#[must_use]
32pub fn ct_select(a: u8, b: u8, choice: u8) -> u8 {
33 use subtle::ConditionallySelectable;
34 let c = subtle::Choice::from(choice & 1);
35 u8::conditional_select(&a, &b, c)
36}