ocb3/
util.rs

1use aead::generic_array::{typenum::U16, ArrayLength, GenericArray};
2
3const BLOCK_SIZE: usize = 16;
4pub(crate) type Block = GenericArray<u8, U16>;
5
6#[inline]
7pub(crate) fn inplace_xor<T, U>(a: &mut GenericArray<T, U>, b: &GenericArray<T, U>)
8where
9    U: ArrayLength<T>,
10    T: core::ops::BitXor<Output = T> + Copy,
11{
12    for (aa, bb) in a.as_mut_slice().iter_mut().zip(b.as_slice()) {
13        *aa = *aa ^ *bb;
14    }
15}
16
17/// Doubles a block, in GF(2^128).
18///
19/// Adapted from https://github.com/RustCrypto/universal-hashes/blob/9b0ac5d1/polyval/src/mulx.rs#L5-L18
20#[inline]
21pub(crate) fn double(block: &Block) -> Block {
22    let mut v = u128::from_be_bytes((*block).into());
23    let v_hi = v >> 127;
24
25    // If v_hi = 0, return (v << 1)
26    // If v_hi = 1, return (v << 1) xor (0b0...010000111)
27    v <<= 1;
28    v ^= v_hi ^ (v_hi << 1) ^ (v_hi << 2) ^ (v_hi << 7);
29    v.to_be_bytes().into()
30}
31
32/// Counts the number of non-trailing zeros in the binary representation.
33///
34/// Defined in https://www.rfc-editor.org/rfc/rfc7253.html#section-2
35#[inline]
36pub(crate) fn ntz(n: usize) -> usize {
37    n.trailing_zeros().try_into().unwrap()
38}
39
40#[inline]
41pub(crate) fn split_into_two_blocks(two_blocks: &mut [u8]) -> [&mut Block; 2] {
42    let (b0, b1) = two_blocks.split_at_mut(BLOCK_SIZE);
43    [b0.into(), b1.into()]
44}