1pub fn ct_eq(a: &[u8], b: &[u8]) -> bool {
5 if a.len() != b.len() {
6 return false;
7 }
8 let mut d = 0u8;
9 for (x, y) in a.iter().zip(b) {
10 d |= x ^ y;
11 }
12 core::hint::black_box(d) == 0
13}
14
15#[inline(always)]
19pub fn ct_mask(flag: u64) -> u64 {
20 simoom_sys::arch::opaque(flag).wrapping_neg()
21}
22
23#[inline(always)]
25pub fn ct_eq_mask(a: u64, b: u64) -> u64 {
26 let d = a ^ b;
27 ct_mask(1 ^ ((d | d.wrapping_neg()) >> 63))
28}
29
30pub fn hex(data: &[u8]) -> String {
32 const D: &[u8; 16] = b"0123456789abcdef";
33 let mut s = String::with_capacity(data.len() * 2);
34 for b in data {
35 s.push(D[(b >> 4) as usize] as char);
36 s.push(D[(b & 15) as usize] as char);
37 }
38 s
39}
40
41pub fn unhex(s: &str) -> Vec<u8> {
43 let digits: Vec<u8> = s.bytes().filter(|c| !c.is_ascii_whitespace() && *c != b':').collect();
44 assert!(digits.len() % 2 == 0, "odd hex length");
45 let val = |c: u8| -> u8 {
46 match c {
47 b'0'..=b'9' => c - b'0',
48 b'a'..=b'f' => c - b'a' + 10,
49 b'A'..=b'F' => c - b'A' + 10,
50 _ => panic!("invalid hex digit"),
51 }
52 };
53 digits.chunks(2).map(|p| val(p[0]) << 4 | val(p[1])).collect()
54}
55
56pub fn zeroize(buf: &mut [u8]) {
58 for b in buf.iter_mut() {
59 *b = 0;
60 }
61 core::hint::black_box(buf);
62}