hacspec_lib/
lib.rs

1mod bytes;
2pub use bytes::*;
3
4mod rng;
5pub use rng::*;
6pub mod hacspec_helper;
7
8/// From [RFC8017]:
9///
10/// I2OSP converts a nonnegative integer to an octet string of a
11/// specified length.
12///
13/// ```text
14///    I2OSP (x, xLen)
15///
16///    Input:
17///
18///       x        nonnegative integer to be converted
19///
20///       xLen     intended length of the resulting octet string
21///
22///    Output:
23///
24///          X corresponding octet string of length xLen
25/// ```
26pub fn i2osp(value: usize, len: usize) -> Vec<u8> {
27    match len {
28        1 => (value as u8).to_be_bytes().to_vec(),
29        2 => (value as u16).to_be_bytes().to_vec(),
30        4 => (value as u32).to_be_bytes().to_vec(),
31        8 => (value as u64).to_be_bytes().to_vec(),
32        _ => panic!("unsupported len {len}"),
33    }
34}
35
36pub fn xor_slice(mut this: Vec<u8>, other: &[u8]) -> Vec<u8> {
37    debug_assert!(this.len() == other.len());
38
39    // error[CE0008]: (Diagnostics.Context.Phase (Reject ArbitraryLhs)): ExplicitRejection { reason: "unknown reason" }
40    //  --> hmac-rust/src/hacspec_helper.rs:5:9
41    //   |
42    // 5 |         *x = *x ^ *o;
43    //   |
44    // for (x, o) in this.iter_mut().zip(other.iter()) {
45    //     *x = *x ^ *o;
46    // }
47    for i in 0..this.len() {
48        this[i] ^= other[i];
49    }
50    this
51}
52
53macro_rules! to_le_u32s_impl {
54    ($name:ident,$l:literal) => {
55        pub fn $name(bytes: &[u8]) -> [u32; $l] {
56            debug_assert_eq!($l, bytes.len() / 4);
57            let mut out = [0; $l];
58            for i in 0..$l {
59                out[i] = u32::from_le_bytes(bytes[4 * i..4 * i + 4].try_into().unwrap());
60            }
61            out
62        }
63    };
64}
65to_le_u32s_impl!(to_le_u32s_3, 3);
66to_le_u32s_impl!(to_le_u32s_8, 8);
67to_le_u32s_impl!(to_le_u32s_16, 16);
68
69pub fn u32s_to_le_bytes(state: &[u32; 16]) -> [u8; 64] {
70    let mut out = [0; 64];
71    for i in 0..state.len() {
72        let tmp = state[i].to_le_bytes();
73        for j in 0..4 {
74            out[i * 4 + j] = tmp[j];
75        }
76    }
77    out
78}
79
80pub fn xor_state(mut state: [u32; 16], other: [u32; 16]) -> [u32; 16] {
81    for i in 0..16 {
82        state[i] ^= other[i];
83    }
84    state
85}
86
87pub fn add_state(mut state: [u32; 16], other: [u32; 16]) -> [u32; 16] {
88    for i in 0..16 {
89        state[i] = state[i].wrapping_add(other[i]);
90    }
91    state
92}
93
94pub fn update_array(mut array: [u8; 64], val: &[u8]) -> [u8; 64] {
95    debug_assert!(64 >= val.len());
96    array[..val.len()].copy_from_slice(val);
97    array
98}