From 59e25236d883e55b95c037d106c050a0da5d7af7 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 16 Jan 2025 15:54:58 +0100 Subject: [PATCH 01/11] add blake2b --- Cargo.toml | 1 + blake2/Cargo.toml | 15 + blake2/src/hacl/hash_blake2b.rs | 1467 ++++++++++++++++++++++ blake2/src/hacl/hash_blake2s.rs | 1263 +++++++++++++++++++ blake2/src/hacl/impl_blake2_constants.rs | 27 + blake2/src/impl_hacl.rs | 196 +++ blake2/src/lib.rs | 13 + hacl-rs/src/util.rs | 1 + hacl-rs/src/util/memzero0.rs | 6 + 9 files changed, 2989 insertions(+) create mode 100644 blake2/Cargo.toml create mode 100644 blake2/src/hacl/hash_blake2b.rs create mode 100644 blake2/src/hacl/hash_blake2s.rs create mode 100644 blake2/src/hacl/impl_blake2_constants.rs create mode 100644 blake2/src/impl_hacl.rs create mode 100644 blake2/src/lib.rs create mode 100644 hacl-rs/src/util/memzero0.rs diff --git a/Cargo.toml b/Cargo.toml index bc214d207..674dd8e68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "poly1305", "chacha20poly1305", "rsa", + "blake2", ] [workspace.package] diff --git a/blake2/Cargo.toml b/blake2/Cargo.toml new file mode 100644 index 000000000..b5c7171ec --- /dev/null +++ b/blake2/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "libcrux-blake2" +description = "Formally verified blake2 hash library" + +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[dependencies] +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/" } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } diff --git a/blake2/src/hacl/hash_blake2b.rs b/blake2/src/hacl/hash_blake2b.rs new file mode 100644 index 000000000..44df297de --- /dev/null +++ b/blake2/src/hacl/hash_blake2b.rs @@ -0,0 +1,1467 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] +#![allow(clippy::match_single_binding)] +#![allow(clippy::needless_lifetimes)] + +use libcrux_hacl_rs::prelude::*; +use libcrux_macros as krml; + +#[derive(PartialEq, Clone, Copy)] +pub struct blake2_params<'a> { + pub digest_length: u8, + pub key_length: u8, + pub fanout: u8, + pub depth: u8, + pub leaf_length: u32, + pub node_offset: u64, + pub node_depth: u8, + pub inner_length: u8, + pub salt: &'a [u8], + pub personal: &'a [u8], +} + +#[derive(PartialEq, Clone, Copy)] +pub struct index { + pub key_length: u8, + pub digest_length: u8, + pub last_node: bool, +} + +#[derive(PartialEq, Clone, Copy)] +pub(crate) struct params_and_key<'a> { + pub fst: &'a [crate::hacl::hash_blake2b::blake2_params<'a>], + pub snd: &'a [u8], +} + +fn update_block( + wv: &mut [u64], + hash: &mut [u64], + flag: bool, + last_node: bool, + totlen: fstar::uint128::uint128, + d: &[u8], +) { + let mut m_w: [u64; 16] = [0u64; 16usize]; + krml::unroll_for!(16, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = d.split_at(i.wrapping_mul(8u32) as usize); + let u: u64 = lowstar::endianness::load64_le(bj.1); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = m_w.split_at_mut(0usize); + os.1[i as usize] = x + }); + let mut mask: [u64; 4] = [0u64; 4usize]; + let wv_14: u64 = if flag { 0xFFFFFFFFFFFFFFFFu64 } else { 0u64 }; + let wv_15: u64 = if last_node { + 0xFFFFFFFFFFFFFFFFu64 + } else { + 0u64 + }; + (&mut mask)[0usize] = fstar::uint128::uint128_to_uint64(totlen); + (&mut mask)[1usize] = + fstar::uint128::uint128_to_uint64(fstar::uint128::shift_right(totlen, 64u32)); + (&mut mask)[2usize] = wv_14; + (&mut mask)[3usize] = wv_15; + (wv[0usize..16usize]).copy_from_slice(&hash[0usize..16usize]); + let wv3: (&mut [u64], &mut [u64]) = wv.split_at_mut(12usize); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u64 = wv3.1[i as usize] ^ (&mask)[i as usize]; + let os: (&mut [u64], &mut [u64]) = wv3.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(12, "i", 0u32, 1u32, { + let start_idx: u32 = i.wrapping_rem(10u32).wrapping_mul(16u32); + let mut m_st: [u64; 16] = [0u64; 16usize]; + let r0: (&mut [u64], &mut [u64]) = m_st.split_at_mut(0usize); + let r1: (&mut [u64], &mut [u64]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u64], &mut [u64]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u64], &mut [u64]) = r2.1.split_at_mut(4usize); + let s0: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(0u32) as usize]; + let s1: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(1u32) as usize]; + let s2: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(2u32) as usize]; + let s3: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(3u32) as usize]; + let s4: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(4u32) as usize]; + let s5: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(5u32) as usize]; + let s6: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(6u32) as usize]; + let s7: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(7u32) as usize]; + let s8: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(8u32) as usize]; + let s9: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(9u32) as usize]; + let s10: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(10u32) as usize]; + let s11: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(11u32) as usize]; + let s12: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(12u32) as usize]; + let s13: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(13u32) as usize]; + let s14: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(14u32) as usize]; + let s15: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(15u32) as usize]; + let uu____0: u64 = (&m_w)[s2 as usize]; + let uu____1: u64 = (&m_w)[s4 as usize]; + let uu____2: u64 = (&m_w)[s6 as usize]; + r1.0[0usize] = (&m_w)[s0 as usize]; + r1.0[1usize] = uu____0; + r1.0[2usize] = uu____1; + r1.0[3usize] = uu____2; + let uu____3: u64 = (&m_w)[s3 as usize]; + let uu____4: u64 = (&m_w)[s5 as usize]; + let uu____5: u64 = (&m_w)[s7 as usize]; + r2.0[0usize] = (&m_w)[s1 as usize]; + r2.0[1usize] = uu____3; + r2.0[2usize] = uu____4; + r2.0[3usize] = uu____5; + let uu____6: u64 = (&m_w)[s10 as usize]; + let uu____7: u64 = (&m_w)[s12 as usize]; + let uu____8: u64 = (&m_w)[s14 as usize]; + r3.0[0usize] = (&m_w)[s8 as usize]; + r3.0[1usize] = uu____6; + r3.0[2usize] = uu____7; + r3.0[3usize] = uu____8; + let uu____9: u64 = (&m_w)[s11 as usize]; + let uu____10: u64 = (&m_w)[s13 as usize]; + let uu____11: u64 = (&m_w)[s15 as usize]; + r3.1[0usize] = (&m_w)[s9 as usize]; + r3.1[1usize] = uu____9; + r3.1[2usize] = uu____10; + r3.1[3usize] = uu____11; + let x: (&[u64], &[u64]) = r1.0.split_at(0usize); + let y: (&[u64], &[u64]) = r2.0.split_at(0usize); + let z: (&[u64], &[u64]) = r3.0.split_at(0usize); + let w: (&[u64], &[u64]) = r3.1.split_at(0usize); + let wv_a: (&mut [u64], &mut [u64]) = wv3.0.split_at_mut(0usize); + let wv_b: (&mut [u64], &mut [u64]) = wv_a.1.split_at_mut(4usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_b.0[i0 as usize]).wrapping_add(wv_b.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_b.0.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_b.0[i0 as usize]).wrapping_add(x.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_b.0.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a0: (&mut [u64], &mut [u64]) = wv3.1.split_at_mut(0usize); + let wv_b0: (&mut [u64], &mut [u64]) = wv_b.0.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = wv_a0.1[i0 as usize] ^ wv_b0.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a0.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r10: &mut [u64] = wv_a0.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = r10[i0 as usize]; + let x10: u64 = x1.wrapping_shr(32u32) | x1.wrapping_shl(32u32); + let os: (&mut [u64], &mut [u64]) = r10.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a1: (&mut [u64], &mut [u64]) = wv_b.1.split_at_mut(4usize); + let wv_b1: (&mut [u64], &mut [u64]) = wv_a0.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_a1.1[i0 as usize]).wrapping_add(wv_b1.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a1.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a2: (&mut [u64], &mut [u64]) = wv_a1.0.split_at_mut(0usize); + let wv_b2: (&mut [u64], &mut [u64]) = wv_a1.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = wv_a2.1[i0 as usize] ^ wv_b2.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a2.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r11: &mut [u64] = wv_a2.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = r11[i0 as usize]; + let x10: u64 = x1.wrapping_shr(24u32) | x1.wrapping_shl(40u32); + let os: (&mut [u64], &mut [u64]) = r11.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a3: (&mut [u64], &mut [u64]) = wv_b0.1.split_at_mut(0usize); + let wv_b3: (&mut [u64], &mut [u64]) = wv_a2.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_a3.1[i0 as usize]).wrapping_add(wv_b3.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a3.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_a3.1[i0 as usize]).wrapping_add(y.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a3.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a4: (&mut [u64], &mut [u64]) = wv_b1.1.split_at_mut(0usize); + let wv_b4: (&mut [u64], &mut [u64]) = wv_a3.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = wv_a4.1[i0 as usize] ^ wv_b4.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a4.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r12: &mut [u64] = wv_a4.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = r12[i0 as usize]; + let x10: u64 = x1.wrapping_shr(16u32) | x1.wrapping_shl(48u32); + let os: (&mut [u64], &mut [u64]) = r12.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a5: (&mut [u64], &mut [u64]) = wv_b2.1.split_at_mut(0usize); + let wv_b5: (&mut [u64], &mut [u64]) = wv_a4.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = (wv_a5.1[i0 as usize]).wrapping_add(wv_b5.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a5.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a6: (&mut [u64], &mut [u64]) = wv_b3.1.split_at_mut(0usize); + let wv_b6: (&mut [u64], &mut [u64]) = wv_a5.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = wv_a6.1[i0 as usize] ^ wv_b6.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a6.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r13: &mut [u64] = wv_a6.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u64 = r13[i0 as usize]; + let x10: u64 = x1.wrapping_shr(63u32) | x1.wrapping_shl(1u32); + let os: (&mut [u64], &mut [u64]) = r13.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let r14: (&mut [u64], &mut [u64]) = wv_a6.1.split_at_mut(0usize); + let r20: (&mut [u64], &mut [u64]) = wv_b6.1.split_at_mut(0usize); + let r30: (&mut [u64], &mut [u64]) = wv_b5.1.split_at_mut(0usize); + let r110: &mut [u64] = r14.1; + let x0: u64 = r110[1usize]; + let x1: u64 = r110[2usize]; + let x2: u64 = r110[3usize]; + let x3: u64 = r110[0usize]; + r110[0usize] = x0; + r110[1usize] = x1; + r110[2usize] = x2; + r110[3usize] = x3; + let r111: &mut [u64] = r20.1; + let x00: u64 = r111[2usize]; + let x10: u64 = r111[3usize]; + let x20: u64 = r111[0usize]; + let x30: u64 = r111[1usize]; + r111[0usize] = x00; + r111[1usize] = x10; + r111[2usize] = x20; + r111[3usize] = x30; + let r112: &mut [u64] = r30.1; + let x01: u64 = r112[3usize]; + let x11: u64 = r112[0usize]; + let x21: u64 = r112[1usize]; + let x31: u64 = r112[2usize]; + r112[0usize] = x01; + r112[1usize] = x11; + r112[2usize] = x21; + r112[3usize] = x31; + let wv_a7: (&mut [u64], &mut [u64]) = wv_b4.1.split_at_mut(0usize); + let wv_b7: (&mut [u64], &mut [u64]) = r14.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a7.1[i0 as usize]).wrapping_add(wv_b7.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a7.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a7.1[i0 as usize]).wrapping_add(z.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a7.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a8: (&mut [u64], &mut [u64]) = r30.1.split_at_mut(0usize); + let wv_b8: (&mut [u64], &mut [u64]) = wv_a7.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = wv_a8.1[i0 as usize] ^ wv_b8.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a8.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r15: &mut [u64] = wv_a8.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = r15[i0 as usize]; + let x13: u64 = x12.wrapping_shr(32u32) | x12.wrapping_shl(32u32); + let os: (&mut [u64], &mut [u64]) = r15.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a9: (&mut [u64], &mut [u64]) = r20.1.split_at_mut(0usize); + let wv_b9: (&mut [u64], &mut [u64]) = wv_a8.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a9.1[i0 as usize]).wrapping_add(wv_b9.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a9.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a10: (&mut [u64], &mut [u64]) = wv_b7.1.split_at_mut(0usize); + let wv_b10: (&mut [u64], &mut [u64]) = wv_a9.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = wv_a10.1[i0 as usize] ^ wv_b10.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a10.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r16: &mut [u64] = wv_a10.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = r16[i0 as usize]; + let x13: u64 = x12.wrapping_shr(24u32) | x12.wrapping_shl(40u32); + let os: (&mut [u64], &mut [u64]) = r16.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a11: (&mut [u64], &mut [u64]) = wv_b8.1.split_at_mut(0usize); + let wv_b11: (&mut [u64], &mut [u64]) = wv_a10.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a11.1[i0 as usize]).wrapping_add(wv_b11.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a11.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a11.1[i0 as usize]).wrapping_add(w.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a11.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a12: (&mut [u64], &mut [u64]) = wv_b9.1.split_at_mut(0usize); + let wv_b12: (&[u64], &[u64]) = wv_a11.1.split_at(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = wv_a12.1[i0 as usize] ^ wv_b12.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a12.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r17: &mut [u64] = wv_a12.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = r17[i0 as usize]; + let x13: u64 = x12.wrapping_shr(16u32) | x12.wrapping_shl(48u32); + let os: (&mut [u64], &mut [u64]) = r17.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a13: (&mut [u64], &mut [u64]) = wv_b10.1.split_at_mut(0usize); + let wv_b13: (&mut [u64], &mut [u64]) = wv_a12.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = (wv_a13.1[i0 as usize]).wrapping_add(wv_b13.1[i0 as usize]); + let os: (&mut [u64], &mut [u64]) = wv_a13.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a14: (&mut [u64], &mut [u64]) = wv_b11.1.split_at_mut(0usize); + let wv_b14: (&mut [u64], &mut [u64]) = wv_a13.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = wv_a14.1[i0 as usize] ^ wv_b14.1[i0 as usize]; + let os: (&mut [u64], &mut [u64]) = wv_a14.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r18: &mut [u64] = wv_a14.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u64 = r18[i0 as usize]; + let x13: u64 = x12.wrapping_shr(63u32) | x12.wrapping_shl(1u32); + let os: (&mut [u64], &mut [u64]) = r18.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let r19: (&mut [u64], &mut [u64]) = wv_a14.1.split_at_mut(0usize); + let r21: (&mut [u64], &mut [u64]) = wv_b14.1.split_at_mut(0usize); + let r31: (&mut [u64], &mut [u64]) = wv_b13.1.split_at_mut(0usize); + let r113: &mut [u64] = r19.1; + let x02: u64 = r113[3usize]; + let x12: u64 = r113[0usize]; + let x22: u64 = r113[1usize]; + let x32: u64 = r113[2usize]; + r113[0usize] = x02; + r113[1usize] = x12; + r113[2usize] = x22; + r113[3usize] = x32; + let r114: &mut [u64] = r21.1; + let x03: u64 = r114[2usize]; + let x13: u64 = r114[3usize]; + let x23: u64 = r114[0usize]; + let x33: u64 = r114[1usize]; + r114[0usize] = x03; + r114[1usize] = x13; + r114[2usize] = x23; + r114[3usize] = x33; + let r115: &mut [u64] = r31.1; + let x04: u64 = r115[1usize]; + let x14: u64 = r115[2usize]; + let x24: u64 = r115[3usize]; + let x34: u64 = r115[0usize]; + r115[0usize] = x04; + r115[1usize] = x14; + r115[2usize] = x24; + r115[3usize] = x34 + }); + let s0: (&mut [u64], &mut [u64]) = hash.split_at_mut(0usize); + let s1: (&mut [u64], &mut [u64]) = s0.1.split_at_mut(4usize); + let r0: (&[u64], &[u64]) = wv3.0.split_at(0usize); + let r1: (&[u64], &[u64]) = r0.1.split_at(4usize); + let r2: (&[u64], &[u64]) = r1.1.split_at(4usize); + let r3: (&[u64], &[u64]) = wv3.1.split_at(0usize); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u64 = s1.0[i as usize] ^ r1.0[i as usize]; + let os: (&mut [u64], &mut [u64]) = s1.0.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u64 = s1.0[i as usize] ^ r2.1[i as usize]; + let os: (&mut [u64], &mut [u64]) = s1.0.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u64 = s1.1[i as usize] ^ r2.0[i as usize]; + let os: (&mut [u64], &mut [u64]) = s1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u64 = s1.1[i as usize] ^ r3.1[i as usize]; + let os: (&mut [u64], &mut [u64]) = s1.1.split_at_mut(0usize); + os.1[i as usize] = x + }) +} + +pub(crate) fn init(hash: &mut [u64], kk: u32, nn: u32) { + let salt: [u8; 16] = [0u8; 16usize]; + let personal: [u8; 16] = [0u8; 16usize]; + let p: crate::hacl::hash_blake2b::blake2_params = crate::hacl::hash_blake2b::blake2_params { + digest_length: 64u8, + key_length: 0u8, + fanout: 1u8, + depth: 1u8, + leaf_length: 0u32, + node_offset: 0u64, + node_depth: 0u8, + inner_length: 0u8, + salt: &salt, + personal: &personal, + }; + let mut tmp: [u64; 8] = [0u64; 8usize]; + let r0: (&mut [u64], &mut [u64]) = hash.split_at_mut(0usize); + let r1: (&mut [u64], &mut [u64]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u64], &mut [u64]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u64], &mut [u64]) = r2.1.split_at_mut(4usize); + let iv0: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[0usize]; + let iv1: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[1usize]; + let iv2: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[2usize]; + let iv3: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[3usize]; + let iv4: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[4usize]; + let iv5: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[5usize]; + let iv6: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[6usize]; + let iv7: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let kk1: u8 = kk as u8; + let nn1: u8 = nn as u8; + let uu____0: (&mut [u64], &mut [u64]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = &p.salt[i.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + let uu____1: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = &p.personal[i.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + (&mut tmp)[0usize] = nn1 as u64 + ^ ((kk1 as u64).wrapping_shl(8u32) + ^ ((p.fanout as u64).wrapping_shl(16u32) + ^ ((p.depth as u64).wrapping_shl(24u32) + ^ (p.leaf_length as u64).wrapping_shl(32u32)))); + (&mut tmp)[1usize] = p.node_offset; + (&mut tmp)[2usize] = p.node_depth as u64 ^ (p.inner_length as u64).wrapping_shl(8u32); + (&mut tmp)[3usize] = 0u64; + let tmp0: u64 = (&tmp)[0usize]; + let tmp1: u64 = (&tmp)[1usize]; + let tmp2: u64 = (&tmp)[2usize]; + let tmp3: u64 = (&tmp)[3usize]; + let tmp4: u64 = (&tmp)[4usize]; + let tmp5: u64 = (&tmp)[5usize]; + let tmp6: u64 = (&tmp)[6usize]; + let tmp7: u64 = (&tmp)[7usize]; + let iv0·: u64 = iv0 ^ tmp0; + let iv1·: u64 = iv1 ^ tmp1; + let iv2·: u64 = iv2 ^ tmp2; + let iv3·: u64 = iv3 ^ tmp3; + let iv4·: u64 = iv4 ^ tmp4; + let iv5·: u64 = iv5 ^ tmp5; + let iv6·: u64 = iv6 ^ tmp6; + let iv7·: u64 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· +} + +fn update_key(wv: &mut [u64], hash: &mut [u64], kk: u32, k: &[u8], ll: u32) { + let lb: fstar::uint128::uint128 = fstar::uint128::uint64_to_uint128(128u32 as u64); + let mut b: [u8; 128] = [0u8; 128usize]; + ((&mut b)[0usize..kk as usize]).copy_from_slice(&k[0usize..kk as usize]); + if ll == 0u32 { + crate::hacl::hash_blake2b::update_block(wv, hash, true, false, lb, &b) + } else { + crate::hacl::hash_blake2b::update_block(wv, hash, false, false, lb, &b) + }; + libcrux_hacl_rs::util::memzero0::memzero::(&mut b, 128u32) +} + +pub(crate) fn update_multi( + len: u32, + wv: &mut [u64], + hash: &mut [u64], + prev: fstar::uint128::uint128, + blocks: &[u8], + nb: u32, +) { + lowstar::ignore::ignore::(len); + for i in 0u32..nb { + let totlen: fstar::uint128::uint128 = fstar::uint128::add_mod( + prev, + fstar::uint128::uint64_to_uint128(i.wrapping_add(1u32).wrapping_mul(128u32) as u64), + ); + let b: (&[u8], &[u8]) = blocks.split_at(i.wrapping_mul(128u32) as usize); + crate::hacl::hash_blake2b::update_block(wv, hash, false, false, totlen, b.1) + } +} + +pub(crate) fn update_last( + len: u32, + wv: &mut [u64], + hash: &mut [u64], + last_node: bool, + prev: fstar::uint128::uint128, + rem: u32, + d: &[u8], +) { + let mut b: [u8; 128] = [0u8; 128usize]; + let last: (&[u8], &[u8]) = d.split_at(len.wrapping_sub(rem) as usize); + ((&mut b)[0usize..rem as usize]).copy_from_slice(&last.1[0usize..rem as usize]); + let totlen: fstar::uint128::uint128 = + fstar::uint128::add_mod(prev, fstar::uint128::uint64_to_uint128(len as u64)); + crate::hacl::hash_blake2b::update_block(wv, hash, true, last_node, totlen, &b); + libcrux_hacl_rs::util::memzero0::memzero::(&mut b, 128u32) +} + +fn update_blocks( + len: u32, + wv: &mut [u64], + hash: &mut [u64], + prev: fstar::uint128::uint128, + blocks: &[u8], +) { + let nb: u32 = len.wrapping_div(128u32); + let rem: u32 = len.wrapping_rem(128u32); + let nb0: u32 = if rem == 0u32 && nb > 0u32 { + nb.wrapping_sub(1u32) + } else { + nb + }; + let rem0: u32 = if rem == 0u32 && nb > 0u32 { + 128u32 + } else { + rem + }; + crate::hacl::hash_blake2b::update_multi(len, wv, hash, prev, blocks, nb0); + crate::hacl::hash_blake2b::update_last(len, wv, hash, false, prev, rem0, blocks) +} + +#[inline] +fn update(wv: &mut [u64], hash: &mut [u64], kk: u32, k: &[u8], ll: u32, d: &[u8]) { + let lb: fstar::uint128::uint128 = fstar::uint128::uint64_to_uint128(128u32 as u64); + if kk > 0u32 { + crate::hacl::hash_blake2b::update_key(wv, hash, kk, k, ll); + if ll != 0u32 { + crate::hacl::hash_blake2b::update_blocks(ll, wv, hash, lb, d) + } + } else { + crate::hacl::hash_blake2b::update_blocks( + ll, + wv, + hash, + fstar::uint128::uint64_to_uint128(0u32 as u64), + d, + ) + } +} + +pub(crate) fn finish(nn: u32, output: &mut [u8], hash: &[u64]) { + let mut b: [u8; 64] = [0u8; 64usize]; + let first: (&mut [u8], &mut [u8]) = b.split_at_mut(0usize); + let second: (&mut [u8], &mut [u8]) = first.1.split_at_mut(32usize); + let row0: (&[u64], &[u64]) = hash.split_at(0usize); + let row1: (&[u64], &[u64]) = row0.1.split_at(4usize); + krml::unroll_for!( + 4, + "i", + 0u32, + 1u32, + lowstar::endianness::store64_le( + &mut second.0[i.wrapping_mul(8u32) as usize..], + row1.0[i as usize] + ) + ); + krml::unroll_for!( + 4, + "i", + 0u32, + 1u32, + lowstar::endianness::store64_le( + &mut second.1[i.wrapping_mul(8u32) as usize..], + row1.1[i as usize] + ) + ); + lowstar::ignore::ignore::<&[u8]>(&b); + let r#final: (&[u8], &[u8]) = b.split_at(0usize); + (output[0usize..nn as usize]).copy_from_slice(&r#final.1[0usize..nn as usize]); + lib::memzero0::memzero::(&mut b, 64u32) +} + +pub const block_bytes: u32 = 128u32; + +pub const out_bytes: u32 = 64u32; + +pub const key_bytes: u32 = 64u32; + +pub const salt_bytes: u32 = 16u32; + +pub const personal_bytes: u32 = 16u32; + +#[derive(PartialEq, Clone)] +pub struct block_state_t { + pub fst: u8, + pub snd: u8, + pub thd: bool, + pub f3: Box<[u64]>, + pub f4: Box<[u64]>, +} + +#[derive(PartialEq, Clone)] +pub struct state_t { + pub block_state: crate::hacl::hash_blake2b::block_state_t, + pub buf: Box<[u8]>, + pub total_len: u64, +} + +pub(crate) fn malloc_raw<'a>( + kk: crate::hacl::hash_blake2b::index, + key: crate::hacl::hash_blake2b::params_and_key<'a>, +) -> Box<[crate::hacl::hash_blake2b::state_t]> { + let mut buf: Box<[u8]> = vec![0u8; 128usize].into_boxed_slice(); + let wv: Box<[u64]> = vec![0u64; 16usize].into_boxed_slice(); + let b: Box<[u64]> = vec![0u64; 16usize].into_boxed_slice(); + let mut block_state: crate::hacl::hash_blake2b::block_state_t = + crate::hacl::hash_blake2b::block_state_t { + fst: kk.key_length, + snd: kk.digest_length, + thd: kk.last_node, + f3: wv, + f4: b, + }; + let p: &[crate::hacl::hash_blake2b::blake2_params] = key.fst; + let kk1: u8 = (p[0usize]).key_length; + let nn: u8 = (p[0usize]).digest_length; + match block_state { + crate::hacl::hash_blake2b::block_state_t { thd: last_node, .. } => { + let i: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }; + let h: &mut [u64] = &mut block_state.f4; + let kk2: u32 = i.key_length as u32; + let k·: &[u8] = key.snd; + if kk2 != 0u32 { + let sub_b: (&mut [u8], &mut [u8]) = buf.split_at_mut(kk2 as usize); + (sub_b.1[0usize..128u32.wrapping_sub(kk2) as usize]).copy_from_slice( + &vec![0u8; 128u32.wrapping_sub(kk2) as usize].into_boxed_slice(), + ); + ((&mut buf)[0usize..kk2 as usize]).copy_from_slice(&k·[0usize..kk2 as usize]) + }; + let pv: crate::hacl::hash_blake2b::blake2_params = p[0usize]; + let mut tmp: [u64; 8] = [0u64; 8usize]; + let r0: (&mut [u64], &mut [u64]) = h.split_at_mut(0usize); + let r1: (&mut [u64], &mut [u64]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u64], &mut [u64]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u64], &mut [u64]) = r2.1.split_at_mut(4usize); + let iv0: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[0usize]; + let iv1: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[1usize]; + let iv2: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[2usize]; + let iv3: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[3usize]; + let iv4: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[4usize]; + let iv5: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[5usize]; + let iv6: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[6usize]; + let iv7: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let kk20: u8 = pv.key_length; + let nn1: u8 = pv.digest_length; + let uu____0: (&mut [u64], &mut [u64]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.salt[i0.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r4: u64 = u; + let x: u64 = r4; + let os: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + let uu____1: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.personal[i0.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r4: u64 = u; + let x: u64 = r4; + let os: (&mut [u64], &mut [u64]) = uu____1.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + (&mut tmp)[0usize] = nn1 as u64 + ^ ((kk20 as u64).wrapping_shl(8u32) + ^ ((pv.fanout as u64).wrapping_shl(16u32) + ^ ((pv.depth as u64).wrapping_shl(24u32) + ^ (pv.leaf_length as u64).wrapping_shl(32u32)))); + (&mut tmp)[1usize] = pv.node_offset; + (&mut tmp)[2usize] = pv.node_depth as u64 ^ (pv.inner_length as u64).wrapping_shl(8u32); + (&mut tmp)[3usize] = 0u64; + let tmp0: u64 = (&tmp)[0usize]; + let tmp1: u64 = (&tmp)[1usize]; + let tmp2: u64 = (&tmp)[2usize]; + let tmp3: u64 = (&tmp)[3usize]; + let tmp4: u64 = (&tmp)[4usize]; + let tmp5: u64 = (&tmp)[5usize]; + let tmp6: u64 = (&tmp)[6usize]; + let tmp7: u64 = (&tmp)[7usize]; + let iv0·: u64 = iv0 ^ tmp0; + let iv1·: u64 = iv1 ^ tmp1; + let iv2·: u64 = iv2 ^ tmp2; + let iv3·: u64 = iv3 ^ tmp3; + let iv4·: u64 = iv4 ^ tmp4; + let iv5·: u64 = iv5 ^ tmp5; + let iv6·: u64 = iv6 ^ tmp6; + let iv7·: u64 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· + } + }; + let kk10: u8 = kk.key_length; + let ite: u32 = if kk10 != 0u8 { 128u32 } else { 0u32 }; + let s: crate::hacl::hash_blake2b::state_t = crate::hacl::hash_blake2b::state_t { + block_state, + buf, + total_len: ite as u64, + }; + let p0: Box<[crate::hacl::hash_blake2b::state_t]> = vec![s].into_boxed_slice(); + p0 +} + +fn index_of_state(s: &[crate::hacl::hash_blake2b::state_t]) -> crate::hacl::hash_blake2b::index { + let block_state: &crate::hacl::hash_blake2b::block_state_t = &(s[0usize]).block_state; + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + } +} + +fn reset_raw<'a>( + state: &'a mut [crate::hacl::hash_blake2b::state_t], + key: crate::hacl::hash_blake2b::params_and_key<'a>, +) { + let block_state: &mut crate::hacl::hash_blake2b::block_state_t = + &mut (state[0usize]).block_state; + let buf: &mut [u8] = &mut (state[0usize]).buf; + let i: crate::hacl::hash_blake2b::index = match *block_state { + crate::hacl::hash_blake2b::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + }; + let p: &[crate::hacl::hash_blake2b::blake2_params] = key.fst; + let kk1: u8 = (p[0usize]).key_length; + let nn: u8 = (p[0usize]).digest_length; + match *block_state { + crate::hacl::hash_blake2b::block_state_t { thd: last_node, .. } => { + let i1: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }; + let h: &mut [u64] = &mut block_state.f4; + let kk2: u32 = i1.key_length as u32; + let k·1: &[u8] = key.snd; + if kk2 != 0u32 { + let sub_b: (&mut [u8], &mut [u8]) = buf.split_at_mut(kk2 as usize); + (sub_b.1[0usize..128u32.wrapping_sub(kk2) as usize]).copy_from_slice( + &vec![0u8; 128u32.wrapping_sub(kk2) as usize].into_boxed_slice(), + ); + (buf[0usize..kk2 as usize]).copy_from_slice(&k·1[0usize..kk2 as usize]) + }; + let pv: crate::hacl::hash_blake2b::blake2_params = p[0usize]; + let mut tmp: [u64; 8] = [0u64; 8usize]; + let r0: (&mut [u64], &mut [u64]) = h.split_at_mut(0usize); + let r1: (&mut [u64], &mut [u64]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u64], &mut [u64]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u64], &mut [u64]) = r2.1.split_at_mut(4usize); + let iv0: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[0usize]; + let iv1: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[1usize]; + let iv2: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[2usize]; + let iv3: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[3usize]; + let iv4: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[4usize]; + let iv5: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[5usize]; + let iv6: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[6usize]; + let iv7: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let kk20: u8 = pv.key_length; + let nn1: u8 = pv.digest_length; + let uu____0: (&mut [u64], &mut [u64]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.salt[i0.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + let uu____1: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.personal[i0.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____1.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + (&mut tmp)[0usize] = nn1 as u64 + ^ ((kk20 as u64).wrapping_shl(8u32) + ^ ((pv.fanout as u64).wrapping_shl(16u32) + ^ ((pv.depth as u64).wrapping_shl(24u32) + ^ (pv.leaf_length as u64).wrapping_shl(32u32)))); + (&mut tmp)[1usize] = pv.node_offset; + (&mut tmp)[2usize] = pv.node_depth as u64 ^ (pv.inner_length as u64).wrapping_shl(8u32); + (&mut tmp)[3usize] = 0u64; + let tmp0: u64 = (&tmp)[0usize]; + let tmp1: u64 = (&tmp)[1usize]; + let tmp2: u64 = (&tmp)[2usize]; + let tmp3: u64 = (&tmp)[3usize]; + let tmp4: u64 = (&tmp)[4usize]; + let tmp5: u64 = (&tmp)[5usize]; + let tmp6: u64 = (&tmp)[6usize]; + let tmp7: u64 = (&tmp)[7usize]; + let iv0·: u64 = iv0 ^ tmp0; + let iv1·: u64 = iv1 ^ tmp1; + let iv2·: u64 = iv2 ^ tmp2; + let iv3·: u64 = iv3 ^ tmp3; + let iv4·: u64 = iv4 ^ tmp4; + let iv5·: u64 = iv5 ^ tmp5; + let iv6·: u64 = iv6 ^ tmp6; + let iv7·: u64 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· + } + }; + let kk10: u8 = i.key_length; + let ite: u32 = if kk10 != 0u8 { 128u32 } else { 0u32 }; + let total_len: u64 = ite as u64; + (state[0usize]).total_len = total_len +} + +/** +General-purpose re-initialization function with parameters and +key. You cannot change digest_length, key_length, or last_node, meaning those values in +the parameters object must be the same as originally decided via one of the +malloc functions. All other values of the parameter can be changed. The behavior +is unspecified if you violate this precondition. +*/ +pub fn reset_with_key_and_params( + s: &mut [crate::hacl::hash_blake2b::state_t], + p: &[crate::hacl::hash_blake2b::blake2_params], + k: &[u8], +) { + let i1: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index_of_state(s); + lowstar::ignore::ignore::(i1); + crate::hacl::hash_blake2b::reset_raw( + s, + crate::hacl::hash_blake2b::params_and_key { fst: p, snd: k }, + ) +} + +/** +Specialized-purpose re-initialization function with no parameters, +and a key. The key length must be the same as originally decided via your choice +of malloc function. All other parameters are reset to their default values. The +original call to malloc MUST have set digest_length to the default value. The +behavior is unspecified if you violate this precondition. +*/ +pub fn reset_with_key(s: &mut [crate::hacl::hash_blake2b::state_t], k: &[u8]) { + let idx: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index_of_state(s); + let salt: [u8; 16] = [0u8; 16usize]; + let personal: [u8; 16] = [0u8; 16usize]; + let p: crate::hacl::hash_blake2b::blake2_params = crate::hacl::hash_blake2b::blake2_params { + digest_length: idx.digest_length, + key_length: idx.key_length, + fanout: 1u8, + depth: 1u8, + leaf_length: 0u32, + node_offset: 0u64, + node_depth: 0u8, + inner_length: 0u8, + salt: &salt, + personal: &personal, + }; + let p0: [crate::hacl::hash_blake2b::blake2_params; 1] = [p; 1usize]; + crate::hacl::hash_blake2b::reset_raw( + s, + crate::hacl::hash_blake2b::params_and_key { fst: &p0, snd: k }, + ) +} + +/** +Specialized-purpose re-initialization function with no parameters +and no key. This is what you want if you intend to use Blake2 as a hash +function. The key length and digest length must have been set to their +respective default values via your choice of malloc function (always true if you +used `malloc`). All other parameters are reset to their default values. The +behavior is unspecified if you violate this precondition. +*/ +pub fn reset(s: &mut [crate::hacl::hash_blake2b::state_t]) { + crate::hacl::hash_blake2b::reset_with_key(s, &[]) +} + +/** +Update function; 0 = success, 1 = max length exceeded +*/ +pub fn update0( + state: &mut [crate::hacl::hash_blake2b::state_t], + chunk: &[u8], + chunk_len: u32, +) -> streaming_types::error_code { + let block_state: &mut crate::hacl::hash_blake2b::block_state_t = + &mut (state[0usize]).block_state; + let total_len: u64 = (state[0usize]).total_len; + if chunk_len as u64 > 0xffffffffffffffffu64.wrapping_sub(total_len) { + streaming_types::error_code::MaximumLengthExceeded + } else { + let sz: u32 = if total_len.wrapping_rem(128u32 as u64) == 0u64 && total_len > 0u64 { + 128u32 + } else { + total_len.wrapping_rem(128u32 as u64) as u32 + }; + if chunk_len <= 128u32.wrapping_sub(sz) { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(128u32 as u64) == 0u64 && total_len1 > 0u64 { + 128u32 + } else { + total_len1.wrapping_rem(128u32 as u64) as u32 + }; + let buf2: (&mut [u8], &mut [u8]) = buf.split_at_mut(sz1 as usize); + (buf2.1[0usize..chunk_len as usize]) + .copy_from_slice(&chunk[0usize..chunk_len as usize]); + let total_len2: u64 = total_len1.wrapping_add(chunk_len as u64); + (state[0usize]).total_len = total_len2 + } else if sz == 0u32 { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(128u32 as u64) == 0u64 && total_len1 > 0u64 { + 128u32 + } else { + total_len1.wrapping_rem(128u32 as u64) as u32 + }; + if sz1 != 0u32 { + let prevlen: u64 = total_len1.wrapping_sub(sz1 as u64); + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = 1u32; + crate::hacl::hash_blake2b::update_multi( + 128u32, + wv, + hash, + fstar::uint128::uint64_to_uint128(prevlen), + buf, + nb, + ) + } + } + }; + let ite: u32 = if (chunk_len as u64).wrapping_rem(128u32 as u64) == 0u64 + && chunk_len as u64 > 0u64 + { + 128u32 + } else { + (chunk_len as u64).wrapping_rem(128u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len.wrapping_sub(ite).wrapping_div(128u32); + let data1_len: u32 = n_blocks.wrapping_mul(128u32); + let data2_len: u32 = chunk_len.wrapping_sub(data1_len); + let data1: (&[u8], &[u8]) = chunk.split_at(0usize); + let data2: (&[u8], &[u8]) = data1.1.split_at(data1_len as usize); + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = data1_len.wrapping_div(128u32); + crate::hacl::hash_blake2b::update_multi( + data1_len, + wv, + hash, + fstar::uint128::uint64_to_uint128(total_len1), + data2.0, + nb, + ) + } + }; + let dst: (&mut [u8], &mut [u8]) = buf.split_at_mut(0usize); + (dst.1[0usize..data2_len as usize]) + .copy_from_slice(&data2.1[0usize..data2_len as usize]); + (state[0usize]).total_len = total_len1.wrapping_add(chunk_len as u64) + } else { + let diff: u32 = 128u32.wrapping_sub(sz); + let chunk1: (&[u8], &[u8]) = chunk.split_at(0usize); + let chunk2: (&[u8], &[u8]) = chunk1.1.split_at(diff as usize); + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(128u32 as u64) == 0u64 && total_len1 > 0u64 { + 128u32 + } else { + total_len1.wrapping_rem(128u32 as u64) as u32 + }; + let buf2: (&mut [u8], &mut [u8]) = buf.split_at_mut(sz1 as usize); + (buf2.1[0usize..diff as usize]).copy_from_slice(&chunk2.0[0usize..diff as usize]); + let total_len2: u64 = total_len1.wrapping_add(diff as u64); + (state[0usize]).total_len = total_len2; + let buf0: &mut [u8] = &mut (state[0usize]).buf; + let total_len10: u64 = (state[0usize]).total_len; + let sz10: u32 = if total_len10.wrapping_rem(128u32 as u64) == 0u64 && total_len10 > 0u64 + { + 128u32 + } else { + total_len10.wrapping_rem(128u32 as u64) as u32 + }; + if sz10 != 0u32 { + let prevlen: u64 = total_len10.wrapping_sub(sz10 as u64); + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = 1u32; + crate::hacl::hash_blake2b::update_multi( + 128u32, + wv, + hash, + fstar::uint128::uint64_to_uint128(prevlen), + buf0, + nb, + ) + } + } + }; + let ite: u32 = if (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(128u32 as u64) + == 0u64 + && chunk_len.wrapping_sub(diff) as u64 > 0u64 + { + 128u32 + } else { + (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(128u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len + .wrapping_sub(diff) + .wrapping_sub(ite) + .wrapping_div(128u32); + let data1_len: u32 = n_blocks.wrapping_mul(128u32); + let data2_len: u32 = chunk_len.wrapping_sub(diff).wrapping_sub(data1_len); + let data1: (&[u8], &[u8]) = chunk2.1.split_at(0usize); + let data2: (&[u8], &[u8]) = data1.1.split_at(data1_len as usize); + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = data1_len.wrapping_div(128u32); + crate::hacl::hash_blake2b::update_multi( + data1_len, + wv, + hash, + fstar::uint128::uint64_to_uint128(total_len10), + data2.0, + nb, + ) + } + }; + let dst: (&mut [u8], &mut [u8]) = buf0.split_at_mut(0usize); + (dst.1[0usize..data2_len as usize]) + .copy_from_slice(&data2.1[0usize..data2_len as usize]); + (state[0usize]).total_len = + total_len10.wrapping_add(chunk_len.wrapping_sub(diff) as u64) + }; + streaming_types::error_code::Success + } +} + +/** +Digest function. This function expects the `output` array to hold +at least `digest_length` bytes, where `digest_length` was determined by your +choice of `malloc` function. Concretely, if you used `malloc` or +`malloc_with_key`, then the expected length is 32 for S, or 64 for B (default +digest length). If you used `malloc_with_params_and_key`, then the expected +length is whatever you chose for the `digest_length` field of your parameters. +For convenience, this function returns `digest_length`. When in doubt, callers +can pass an array of size HACL_BLAKE2B_32_OUT_BYTES, then use the return value +to see how many bytes were actually written. +*/ +pub fn digest(s: &[crate::hacl::hash_blake2b::state_t], dst: &mut [u8]) -> u8 { + let block_state: &crate::hacl::hash_blake2b::block_state_t = &(s[0usize]).block_state; + let i1: crate::hacl::hash_blake2b::index = match *block_state { + crate::hacl::hash_blake2b::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + }; + let block_state0: &crate::hacl::hash_blake2b::block_state_t = &(s[0usize]).block_state; + let buf_: &[u8] = &(s[0usize]).buf; + let total_len: u64 = (s[0usize]).total_len; + let r: u32 = if total_len.wrapping_rem(128u32 as u64) == 0u64 && total_len > 0u64 { + 128u32 + } else { + total_len.wrapping_rem(128u32 as u64) as u32 + }; + let buf_1: (&[u8], &[u8]) = buf_.split_at(0usize); + let wv: [u64; 16] = [0u64; 16usize]; + let b: [u64; 16] = [0u64; 16usize]; + let mut tmp_block_state: crate::hacl::hash_blake2b::block_state_t = + crate::hacl::hash_blake2b::block_state_t { + fst: i1.key_length, + snd: i1.digest_length, + thd: i1.last_node, + f3: Box::new(wv), + f4: Box::new(b), + }; + match *block_state0 { + crate::hacl::hash_blake2b::block_state_t { f4: ref src_b, .. } => match tmp_block_state { + crate::hacl::hash_blake2b::block_state_t { + f4: ref mut dst_b, .. + } => (dst_b[0usize..16usize]).copy_from_slice(&src_b[0usize..16usize]), + }, + }; + let prev_len: u64 = total_len.wrapping_sub(r as u64); + let buf_multi: (&[u8], &[u8]) = buf_1.1.split_at(0usize); + let ite: u32 = if r.wrapping_rem(128u32) == 0u32 && r > 0u32 { + 128u32 + } else { + r.wrapping_rem(128u32) + }; + let buf_last: (&[u8], &[u8]) = buf_multi.1.split_at(r.wrapping_sub(ite) as usize); + match tmp_block_state { + crate::hacl::hash_blake2b::block_state_t { + f3: ref mut wv0, + f4: ref mut hash, + .. + } => { + let nb: u32 = 0u32; + crate::hacl::hash_blake2b::update_multi( + 0u32, + wv0, + hash, + fstar::uint128::uint64_to_uint128(prev_len), + buf_last.0, + nb, + ) + } + }; + let prev_len_last: u64 = total_len.wrapping_sub(r as u64); + match tmp_block_state { + crate::hacl::hash_blake2b::block_state_t { + thd: last_node, + f3: ref mut wv0, + f4: ref mut hash, + .. + } => crate::hacl::hash_blake2b::update_last( + r, + wv0, + hash, + last_node, + fstar::uint128::uint64_to_uint128(prev_len_last), + r, + buf_last.1, + ), + }; + match tmp_block_state { + crate::hacl::hash_blake2b::block_state_t { snd: nn, .. } => { + crate::hacl::hash_blake2b::finish(nn as u32, dst, &tmp_block_state.f4) + } + }; + let block_state1: &crate::hacl::hash_blake2b::block_state_t = &(s[0usize]).block_state; + match *block_state1 { + crate::hacl::hash_blake2b::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + } + .digest_length +} + +pub fn info(s: &[crate::hacl::hash_blake2b::state_t]) -> crate::hacl::hash_blake2b::index { + let block_state: &crate::hacl::hash_blake2b::block_state_t = &(s[0usize]).block_state; + match *block_state { + crate::hacl::hash_blake2b::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + } +} + +/** +Copying. This preserves all parameters. +*/ +pub fn copy( + state: &[crate::hacl::hash_blake2b::state_t], +) -> Box<[crate::hacl::hash_blake2b::state_t]> { + let block_state0: &crate::hacl::hash_blake2b::block_state_t = &(state[0usize]).block_state; + let buf0: &[u8] = &(state[0usize]).buf; + let total_len0: u64 = (state[0usize]).total_len; + let i: crate::hacl::hash_blake2b::index = match *block_state0 { + crate::hacl::hash_blake2b::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + }; + let mut buf: Box<[u8]> = vec![0u8; 128usize].into_boxed_slice(); + ((&mut buf)[0usize..128usize]).copy_from_slice(&buf0[0usize..128usize]); + let wv: Box<[u64]> = vec![0u64; 16usize].into_boxed_slice(); + let b: Box<[u64]> = vec![0u64; 16usize].into_boxed_slice(); + let mut block_state: crate::hacl::hash_blake2b::block_state_t = + crate::hacl::hash_blake2b::block_state_t { + fst: i.key_length, + snd: i.digest_length, + thd: i.last_node, + f3: wv, + f4: b, + }; + match *block_state0 { + crate::hacl::hash_blake2b::block_state_t { f4: ref src_b, .. } => match block_state { + crate::hacl::hash_blake2b::block_state_t { + f4: ref mut dst_b, .. + } => (dst_b[0usize..16usize]).copy_from_slice(&src_b[0usize..16usize]), + }, + }; + let s: crate::hacl::hash_blake2b::state_t = crate::hacl::hash_blake2b::state_t { + block_state, + buf, + total_len: total_len0, + }; + let p: Box<[crate::hacl::hash_blake2b::state_t]> = vec![s].into_boxed_slice(); + p +} + +/** +Write the BLAKE2b digest of message `input` using key `key` into `output`. + +@param output Pointer to `output_len` bytes of memory where the digest is written to. +@param output_len Length of the to-be-generated digest with 1 <= `output_len` <= 64. +@param input Pointer to `input_len` bytes of memory where the input message is read from. +@param input_len Length of the input message. +@param key Pointer to `key_len` bytes of memory where the key is read from. +@param key_len Length of the key. Can be 0. +*/ +pub fn hash_with_key( + output: &mut [u8], + output_len: u32, + input: &[u8], + input_len: u32, + key: &[u8], + key_len: u32, +) { + let mut b: [u64; 16] = [0u64; 16usize]; + let mut b1: [u64; 16] = [0u64; 16usize]; + crate::hacl::hash_blake2b::init(&mut b, key_len, output_len); + crate::hacl::hash_blake2b::update(&mut b1, &mut b, key_len, key, input_len, input); + crate::hacl::hash_blake2b::finish(output_len, output, &b); + lib::memzero0::memzero::(&mut b1, 16u32); + lib::memzero0::memzero::(&mut b, 16u32) +} + +/** +Write the BLAKE2b digest of message `input` using key `key` and +parameters `params` into `output`. The `key` array must be of length +`params.key_length`. The `output` array must be of length +`params.digest_length`. +*/ +pub fn hash_with_key_and_params<'a>( + output: &'a mut [u8], + input: &'a [u8], + input_len: u32, + params: crate::hacl::hash_blake2b::blake2_params<'a>, + key: &'a [u8], +) { + let mut b: [u64; 16] = [0u64; 16usize]; + let mut b1: [u64; 16] = [0u64; 16usize]; + let mut tmp: [u64; 8] = [0u64; 8usize]; + let r0: (&mut [u64], &mut [u64]) = b.split_at_mut(0usize); + let r1: (&mut [u64], &mut [u64]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u64], &mut [u64]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u64], &mut [u64]) = r2.1.split_at_mut(4usize); + let iv0: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[0usize]; + let iv1: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[1usize]; + let iv2: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[2usize]; + let iv3: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[3usize]; + let iv4: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[4usize]; + let iv5: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[5usize]; + let iv6: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[6usize]; + let iv7: u64 = (&crate::hacl::impl_blake2_constants::ivTable_B)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let kk: u8 = params.key_length; + let nn: u8 = params.digest_length; + let uu____0: (&mut [u64], &mut [u64]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = ¶ms.salt[i.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + let uu____1: (&mut [u64], &mut [u64]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = ¶ms.personal[i.wrapping_mul(8u32) as usize..]; + let u: u64 = lowstar::endianness::load64_le(bj); + let r: u64 = u; + let x: u64 = r; + let os: (&mut [u64], &mut [u64]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + (&mut tmp)[0usize] = nn as u64 + ^ ((kk as u64).wrapping_shl(8u32) + ^ ((params.fanout as u64).wrapping_shl(16u32) + ^ ((params.depth as u64).wrapping_shl(24u32) + ^ (params.leaf_length as u64).wrapping_shl(32u32)))); + (&mut tmp)[1usize] = params.node_offset; + (&mut tmp)[2usize] = params.node_depth as u64 ^ (params.inner_length as u64).wrapping_shl(8u32); + (&mut tmp)[3usize] = 0u64; + let tmp0: u64 = (&tmp)[0usize]; + let tmp1: u64 = (&tmp)[1usize]; + let tmp2: u64 = (&tmp)[2usize]; + let tmp3: u64 = (&tmp)[3usize]; + let tmp4: u64 = (&tmp)[4usize]; + let tmp5: u64 = (&tmp)[5usize]; + let tmp6: u64 = (&tmp)[6usize]; + let tmp7: u64 = (&tmp)[7usize]; + let iv0·: u64 = iv0 ^ tmp0; + let iv1·: u64 = iv1 ^ tmp1; + let iv2·: u64 = iv2 ^ tmp2; + let iv3·: u64 = iv3 ^ tmp3; + let iv4·: u64 = iv4 ^ tmp4; + let iv5·: u64 = iv5 ^ tmp5; + let iv6·: u64 = iv6 ^ tmp6; + let iv7·: u64 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7·; + crate::hacl::hash_blake2b::update( + &mut b1, + &mut b, + params.key_length as u32, + key, + input_len, + input, + ); + crate::hacl::hash_blake2b::finish(params.digest_length as u32, output, &b); + lib::memzero0::memzero::(&mut b1, 16u32); + lib::memzero0::memzero::(&mut b, 16u32) +} diff --git a/blake2/src/hacl/hash_blake2s.rs b/blake2/src/hacl/hash_blake2s.rs new file mode 100644 index 000000000..8b6c0e6d4 --- /dev/null +++ b/blake2/src/hacl/hash_blake2s.rs @@ -0,0 +1,1263 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] +#![allow(clippy::match_single_binding)] + +use libcrux_hacl_rs::prelude::*; +use libcrux_macros as krml; + +#[inline] +fn update_block( + wv: &mut [u32], + hash: &mut [u32], + flag: bool, + last_node: bool, + totlen: u64, + d: &[u8], +) { + let mut m_w: [u32; 16] = [0u32; 16usize]; + krml::unroll_for!(16, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = d.split_at(i.wrapping_mul(4u32) as usize); + let u: u32 = lowstar::endianness::load32_le(bj.1); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = m_w.split_at_mut(0usize); + os.1[i as usize] = x + }); + let mut mask: [u32; 4] = [0u32; 4usize]; + let wv_14: u32 = if flag { 0xFFFFFFFFu32 } else { 0u32 }; + let wv_15: u32 = if last_node { 0xFFFFFFFFu32 } else { 0u32 }; + (&mut mask)[0usize] = totlen as u32; + (&mut mask)[1usize] = totlen.wrapping_shr(32u32) as u32; + (&mut mask)[2usize] = wv_14; + (&mut mask)[3usize] = wv_15; + (wv[0usize..16usize]).copy_from_slice(&hash[0usize..16usize]); + let wv3: (&mut [u32], &mut [u32]) = wv.split_at_mut(12usize); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = wv3.1[i as usize] ^ (&mask)[i as usize]; + let os: (&mut [u32], &mut [u32]) = wv3.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(10, "i", 0u32, 1u32, { + let start_idx: u32 = i.wrapping_rem(10u32).wrapping_mul(16u32); + let mut m_st: [u32; 16] = [0u32; 16usize]; + let r0: (&mut [u32], &mut [u32]) = m_st.split_at_mut(0usize); + let r1: (&mut [u32], &mut [u32]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u32], &mut [u32]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u32], &mut [u32]) = r2.1.split_at_mut(4usize); + let s0: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(0u32) as usize]; + let s1: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(1u32) as usize]; + let s2: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(2u32) as usize]; + let s3: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(3u32) as usize]; + let s4: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(4u32) as usize]; + let s5: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(5u32) as usize]; + let s6: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(6u32) as usize]; + let s7: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(7u32) as usize]; + let s8: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(8u32) as usize]; + let s9: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(9u32) as usize]; + let s10: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(10u32) as usize]; + let s11: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(11u32) as usize]; + let s12: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(12u32) as usize]; + let s13: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(13u32) as usize]; + let s14: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(14u32) as usize]; + let s15: u32 = (&crate::hacl::impl_blake2_constants::sigmaTable) + [start_idx.wrapping_add(15u32) as usize]; + let uu____0: u32 = (&m_w)[s2 as usize]; + let uu____1: u32 = (&m_w)[s4 as usize]; + let uu____2: u32 = (&m_w)[s6 as usize]; + r1.0[0usize] = (&m_w)[s0 as usize]; + r1.0[1usize] = uu____0; + r1.0[2usize] = uu____1; + r1.0[3usize] = uu____2; + let uu____3: u32 = (&m_w)[s3 as usize]; + let uu____4: u32 = (&m_w)[s5 as usize]; + let uu____5: u32 = (&m_w)[s7 as usize]; + r2.0[0usize] = (&m_w)[s1 as usize]; + r2.0[1usize] = uu____3; + r2.0[2usize] = uu____4; + r2.0[3usize] = uu____5; + let uu____6: u32 = (&m_w)[s10 as usize]; + let uu____7: u32 = (&m_w)[s12 as usize]; + let uu____8: u32 = (&m_w)[s14 as usize]; + r3.0[0usize] = (&m_w)[s8 as usize]; + r3.0[1usize] = uu____6; + r3.0[2usize] = uu____7; + r3.0[3usize] = uu____8; + let uu____9: u32 = (&m_w)[s11 as usize]; + let uu____10: u32 = (&m_w)[s13 as usize]; + let uu____11: u32 = (&m_w)[s15 as usize]; + r3.1[0usize] = (&m_w)[s9 as usize]; + r3.1[1usize] = uu____9; + r3.1[2usize] = uu____10; + r3.1[3usize] = uu____11; + let x: (&[u32], &[u32]) = r1.0.split_at(0usize); + let y: (&[u32], &[u32]) = r2.0.split_at(0usize); + let z: (&[u32], &[u32]) = r3.0.split_at(0usize); + let w: (&[u32], &[u32]) = r3.1.split_at(0usize); + let wv_a: (&mut [u32], &mut [u32]) = wv3.0.split_at_mut(0usize); + let wv_b: (&mut [u32], &mut [u32]) = wv_a.1.split_at_mut(4usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_b.0[i0 as usize]).wrapping_add(wv_b.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_b.0.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_b.0[i0 as usize]).wrapping_add(x.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_b.0.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a0: (&mut [u32], &mut [u32]) = wv3.1.split_at_mut(0usize); + let wv_b0: (&mut [u32], &mut [u32]) = wv_b.0.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = wv_a0.1[i0 as usize] ^ wv_b0.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a0.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r10: &mut [u32] = wv_a0.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = r10[i0 as usize]; + let x10: u32 = x1.wrapping_shr(16u32) | x1.wrapping_shl(16u32); + let os: (&mut [u32], &mut [u32]) = r10.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a1: (&mut [u32], &mut [u32]) = wv_b.1.split_at_mut(4usize); + let wv_b1: (&mut [u32], &mut [u32]) = wv_a0.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_a1.1[i0 as usize]).wrapping_add(wv_b1.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a1.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a2: (&mut [u32], &mut [u32]) = wv_a1.0.split_at_mut(0usize); + let wv_b2: (&mut [u32], &mut [u32]) = wv_a1.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = wv_a2.1[i0 as usize] ^ wv_b2.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a2.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r11: &mut [u32] = wv_a2.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = r11[i0 as usize]; + let x10: u32 = x1.wrapping_shr(12u32) | x1.wrapping_shl(20u32); + let os: (&mut [u32], &mut [u32]) = r11.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a3: (&mut [u32], &mut [u32]) = wv_b0.1.split_at_mut(0usize); + let wv_b3: (&mut [u32], &mut [u32]) = wv_a2.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_a3.1[i0 as usize]).wrapping_add(wv_b3.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a3.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_a3.1[i0 as usize]).wrapping_add(y.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a3.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a4: (&mut [u32], &mut [u32]) = wv_b1.1.split_at_mut(0usize); + let wv_b4: (&mut [u32], &mut [u32]) = wv_a3.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = wv_a4.1[i0 as usize] ^ wv_b4.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a4.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r12: &mut [u32] = wv_a4.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = r12[i0 as usize]; + let x10: u32 = x1.wrapping_shr(8u32) | x1.wrapping_shl(24u32); + let os: (&mut [u32], &mut [u32]) = r12.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let wv_a5: (&mut [u32], &mut [u32]) = wv_b2.1.split_at_mut(0usize); + let wv_b5: (&mut [u32], &mut [u32]) = wv_a4.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = (wv_a5.1[i0 as usize]).wrapping_add(wv_b5.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a5.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let wv_a6: (&mut [u32], &mut [u32]) = wv_b3.1.split_at_mut(0usize); + let wv_b6: (&mut [u32], &mut [u32]) = wv_a5.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = wv_a6.1[i0 as usize] ^ wv_b6.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a6.1.split_at_mut(0usize); + os.1[i0 as usize] = x1 + }); + let r13: &mut [u32] = wv_a6.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x1: u32 = r13[i0 as usize]; + let x10: u32 = x1.wrapping_shr(7u32) | x1.wrapping_shl(25u32); + let os: (&mut [u32], &mut [u32]) = r13.split_at_mut(0usize); + os.1[i0 as usize] = x10 + }); + let r14: (&mut [u32], &mut [u32]) = wv_a6.1.split_at_mut(0usize); + let r20: (&mut [u32], &mut [u32]) = wv_b6.1.split_at_mut(0usize); + let r30: (&mut [u32], &mut [u32]) = wv_b5.1.split_at_mut(0usize); + let r110: &mut [u32] = r14.1; + let x0: u32 = r110[1usize]; + let x1: u32 = r110[2usize]; + let x2: u32 = r110[3usize]; + let x3: u32 = r110[0usize]; + r110[0usize] = x0; + r110[1usize] = x1; + r110[2usize] = x2; + r110[3usize] = x3; + let r111: &mut [u32] = r20.1; + let x00: u32 = r111[2usize]; + let x10: u32 = r111[3usize]; + let x20: u32 = r111[0usize]; + let x30: u32 = r111[1usize]; + r111[0usize] = x00; + r111[1usize] = x10; + r111[2usize] = x20; + r111[3usize] = x30; + let r112: &mut [u32] = r30.1; + let x01: u32 = r112[3usize]; + let x11: u32 = r112[0usize]; + let x21: u32 = r112[1usize]; + let x31: u32 = r112[2usize]; + r112[0usize] = x01; + r112[1usize] = x11; + r112[2usize] = x21; + r112[3usize] = x31; + let wv_a7: (&mut [u32], &mut [u32]) = wv_b4.1.split_at_mut(0usize); + let wv_b7: (&mut [u32], &mut [u32]) = r14.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a7.1[i0 as usize]).wrapping_add(wv_b7.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a7.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a7.1[i0 as usize]).wrapping_add(z.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a7.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a8: (&mut [u32], &mut [u32]) = r30.1.split_at_mut(0usize); + let wv_b8: (&mut [u32], &mut [u32]) = wv_a7.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = wv_a8.1[i0 as usize] ^ wv_b8.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a8.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r15: &mut [u32] = wv_a8.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = r15[i0 as usize]; + let x13: u32 = x12.wrapping_shr(16u32) | x12.wrapping_shl(16u32); + let os: (&mut [u32], &mut [u32]) = r15.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a9: (&mut [u32], &mut [u32]) = r20.1.split_at_mut(0usize); + let wv_b9: (&mut [u32], &mut [u32]) = wv_a8.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a9.1[i0 as usize]).wrapping_add(wv_b9.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a9.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a10: (&mut [u32], &mut [u32]) = wv_b7.1.split_at_mut(0usize); + let wv_b10: (&mut [u32], &mut [u32]) = wv_a9.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = wv_a10.1[i0 as usize] ^ wv_b10.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a10.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r16: &mut [u32] = wv_a10.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = r16[i0 as usize]; + let x13: u32 = x12.wrapping_shr(12u32) | x12.wrapping_shl(20u32); + let os: (&mut [u32], &mut [u32]) = r16.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a11: (&mut [u32], &mut [u32]) = wv_b8.1.split_at_mut(0usize); + let wv_b11: (&mut [u32], &mut [u32]) = wv_a10.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a11.1[i0 as usize]).wrapping_add(wv_b11.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a11.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a11.1[i0 as usize]).wrapping_add(w.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a11.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a12: (&mut [u32], &mut [u32]) = wv_b9.1.split_at_mut(0usize); + let wv_b12: (&[u32], &[u32]) = wv_a11.1.split_at(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = wv_a12.1[i0 as usize] ^ wv_b12.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a12.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r17: &mut [u32] = wv_a12.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = r17[i0 as usize]; + let x13: u32 = x12.wrapping_shr(8u32) | x12.wrapping_shl(24u32); + let os: (&mut [u32], &mut [u32]) = r17.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let wv_a13: (&mut [u32], &mut [u32]) = wv_b10.1.split_at_mut(0usize); + let wv_b13: (&mut [u32], &mut [u32]) = wv_a12.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = (wv_a13.1[i0 as usize]).wrapping_add(wv_b13.1[i0 as usize]); + let os: (&mut [u32], &mut [u32]) = wv_a13.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let wv_a14: (&mut [u32], &mut [u32]) = wv_b11.1.split_at_mut(0usize); + let wv_b14: (&mut [u32], &mut [u32]) = wv_a13.1.split_at_mut(0usize); + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = wv_a14.1[i0 as usize] ^ wv_b14.1[i0 as usize]; + let os: (&mut [u32], &mut [u32]) = wv_a14.1.split_at_mut(0usize); + os.1[i0 as usize] = x12 + }); + let r18: &mut [u32] = wv_a14.1; + krml::unroll_for!(4, "i0", 0u32, 1u32, { + let x12: u32 = r18[i0 as usize]; + let x13: u32 = x12.wrapping_shr(7u32) | x12.wrapping_shl(25u32); + let os: (&mut [u32], &mut [u32]) = r18.split_at_mut(0usize); + os.1[i0 as usize] = x13 + }); + let r19: (&mut [u32], &mut [u32]) = wv_a14.1.split_at_mut(0usize); + let r21: (&mut [u32], &mut [u32]) = wv_b14.1.split_at_mut(0usize); + let r31: (&mut [u32], &mut [u32]) = wv_b13.1.split_at_mut(0usize); + let r113: &mut [u32] = r19.1; + let x02: u32 = r113[3usize]; + let x12: u32 = r113[0usize]; + let x22: u32 = r113[1usize]; + let x32: u32 = r113[2usize]; + r113[0usize] = x02; + r113[1usize] = x12; + r113[2usize] = x22; + r113[3usize] = x32; + let r114: &mut [u32] = r21.1; + let x03: u32 = r114[2usize]; + let x13: u32 = r114[3usize]; + let x23: u32 = r114[0usize]; + let x33: u32 = r114[1usize]; + r114[0usize] = x03; + r114[1usize] = x13; + r114[2usize] = x23; + r114[3usize] = x33; + let r115: &mut [u32] = r31.1; + let x04: u32 = r115[1usize]; + let x14: u32 = r115[2usize]; + let x24: u32 = r115[3usize]; + let x34: u32 = r115[0usize]; + r115[0usize] = x04; + r115[1usize] = x14; + r115[2usize] = x24; + r115[3usize] = x34 + }); + let s0: (&mut [u32], &mut [u32]) = hash.split_at_mut(0usize); + let s1: (&mut [u32], &mut [u32]) = s0.1.split_at_mut(4usize); + let r0: (&[u32], &[u32]) = wv3.0.split_at(0usize); + let r1: (&[u32], &[u32]) = r0.1.split_at(4usize); + let r2: (&[u32], &[u32]) = r1.1.split_at(4usize); + let r3: (&[u32], &[u32]) = wv3.1.split_at(0usize); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = s1.0[i as usize] ^ r1.0[i as usize]; + let os: (&mut [u32], &mut [u32]) = s1.0.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = s1.0[i as usize] ^ r2.1[i as usize]; + let os: (&mut [u32], &mut [u32]) = s1.0.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = s1.1[i as usize] ^ r2.0[i as usize]; + let os: (&mut [u32], &mut [u32]) = s1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = s1.1[i as usize] ^ r3.1[i as usize]; + let os: (&mut [u32], &mut [u32]) = s1.1.split_at_mut(0usize); + os.1[i as usize] = x + }) +} + +pub(crate) fn init(hash: &mut [u32], kk: u32, nn: u32) { + let salt: [u8; 8] = [0u8; 8usize]; + let personal: [u8; 8] = [0u8; 8usize]; + let p: crate::hacl::hash_blake2b::blake2_params = crate::hacl::hash_blake2b::blake2_params { + digest_length: 32u8, + key_length: 0u8, + fanout: 1u8, + depth: 1u8, + leaf_length: 0u32, + node_offset: 0u64, + node_depth: 0u8, + inner_length: 0u8, + salt: &salt, + personal: &personal, + }; + let mut tmp: [u32; 8] = [0u32; 8usize]; + let r0: (&mut [u32], &mut [u32]) = hash.split_at_mut(0usize); + let r1: (&mut [u32], &mut [u32]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u32], &mut [u32]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u32], &mut [u32]) = r2.1.split_at_mut(4usize); + let iv0: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[0usize]; + let iv1: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[1usize]; + let iv2: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[2usize]; + let iv3: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[3usize]; + let iv4: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[4usize]; + let iv5: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[5usize]; + let iv6: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[6usize]; + let iv7: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let uu____0: (&mut [u32], &mut [u32]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = &p.salt[i.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + let uu____1: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = &p.personal[i.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + (&mut tmp)[0usize] = nn as u8 as u32 + ^ ((kk as u8 as u32).wrapping_shl(8u32) + ^ ((p.fanout as u32).wrapping_shl(16u32) ^ (p.depth as u32).wrapping_shl(24u32))); + (&mut tmp)[1usize] = p.leaf_length; + (&mut tmp)[2usize] = p.node_offset as u32; + (&mut tmp)[3usize] = p.node_offset.wrapping_shr(32u32) as u32 + ^ ((p.node_depth as u32).wrapping_shl(16u32) ^ (p.inner_length as u32).wrapping_shl(24u32)); + let tmp0: u32 = (&tmp)[0usize]; + let tmp1: u32 = (&tmp)[1usize]; + let tmp2: u32 = (&tmp)[2usize]; + let tmp3: u32 = (&tmp)[3usize]; + let tmp4: u32 = (&tmp)[4usize]; + let tmp5: u32 = (&tmp)[5usize]; + let tmp6: u32 = (&tmp)[6usize]; + let tmp7: u32 = (&tmp)[7usize]; + let iv0·: u32 = iv0 ^ tmp0; + let iv1·: u32 = iv1 ^ tmp1; + let iv2·: u32 = iv2 ^ tmp2; + let iv3·: u32 = iv3 ^ tmp3; + let iv4·: u32 = iv4 ^ tmp4; + let iv5·: u32 = iv5 ^ tmp5; + let iv6·: u32 = iv6 ^ tmp6; + let iv7·: u32 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· +} + +fn update_key(wv: &mut [u32], hash: &mut [u32], kk: u32, k: &[u8], ll: u32) { + let lb: u64 = 64u32 as u64; + let mut b: [u8; 64] = [0u8; 64usize]; + ((&mut b)[0usize..kk as usize]).copy_from_slice(&k[0usize..kk as usize]); + if ll == 0u32 { + crate::hacl::hash_blake2s::update_block(wv, hash, true, false, lb, &b) + } else { + crate::hacl::hash_blake2s::update_block(wv, hash, false, false, lb, &b) + }; + lib::memzero0::memzero::(&mut b, 64u32) +} + +pub(crate) fn update_multi( + len: u32, + wv: &mut [u32], + hash: &mut [u32], + prev: u64, + blocks: &[u8], + nb: u32, +) { + lowstar::ignore::ignore::(len); + for i in 0u32..nb { + let totlen: u64 = prev.wrapping_add(i.wrapping_add(1u32).wrapping_mul(64u32) as u64); + let b: (&[u8], &[u8]) = blocks.split_at(i.wrapping_mul(64u32) as usize); + crate::hacl::hash_blake2s::update_block(wv, hash, false, false, totlen, b.1) + } +} + +pub(crate) fn update_last( + len: u32, + wv: &mut [u32], + hash: &mut [u32], + last_node: bool, + prev: u64, + rem: u32, + d: &[u8], +) { + let mut b: [u8; 64] = [0u8; 64usize]; + let last: (&[u8], &[u8]) = d.split_at(len.wrapping_sub(rem) as usize); + ((&mut b)[0usize..rem as usize]).copy_from_slice(&last.1[0usize..rem as usize]); + let totlen: u64 = prev.wrapping_add(len as u64); + crate::hacl::hash_blake2s::update_block(wv, hash, true, last_node, totlen, &b); + lib::memzero0::memzero::(&mut b, 64u32) +} + +fn update_blocks(len: u32, wv: &mut [u32], hash: &mut [u32], prev: u64, blocks: &[u8]) { + let nb: u32 = len.wrapping_div(64u32); + let rem: u32 = len.wrapping_rem(64u32); + let nb0: u32 = if rem == 0u32 && nb > 0u32 { + nb.wrapping_sub(1u32) + } else { + nb + }; + let rem0: u32 = if rem == 0u32 && nb > 0u32 { 64u32 } else { rem }; + crate::hacl::hash_blake2s::update_multi(len, wv, hash, prev, blocks, nb0); + crate::hacl::hash_blake2s::update_last(len, wv, hash, false, prev, rem0, blocks) +} + +#[inline] +fn update(wv: &mut [u32], hash: &mut [u32], kk: u32, k: &[u8], ll: u32, d: &[u8]) { + let lb: u64 = 64u32 as u64; + if kk > 0u32 { + crate::hacl::hash_blake2s::update_key(wv, hash, kk, k, ll); + if ll != 0u32 { + crate::hacl::hash_blake2s::update_blocks(ll, wv, hash, lb, d) + } + } else { + crate::hacl::hash_blake2s::update_blocks(ll, wv, hash, 0u32 as u64, d) + } +} + +pub(crate) fn finish(nn: u32, output: &mut [u8], hash: &[u32]) { + let mut b: [u8; 32] = [0u8; 32usize]; + let first: (&mut [u8], &mut [u8]) = b.split_at_mut(0usize); + let second: (&mut [u8], &mut [u8]) = first.1.split_at_mut(16usize); + let row0: (&[u32], &[u32]) = hash.split_at(0usize); + let row1: (&[u32], &[u32]) = row0.1.split_at(4usize); + krml::unroll_for!( + 4, + "i", + 0u32, + 1u32, + lowstar::endianness::store32_le( + &mut second.0[i.wrapping_mul(4u32) as usize..], + row1.0[i as usize] + ) + ); + krml::unroll_for!( + 4, + "i", + 0u32, + 1u32, + lowstar::endianness::store32_le( + &mut second.1[i.wrapping_mul(4u32) as usize..], + row1.1[i as usize] + ) + ); + lowstar::ignore::ignore::<&[u8]>(&b); + let r#final: (&[u8], &[u8]) = b.split_at(0usize); + (output[0usize..nn as usize]).copy_from_slice(&r#final.1[0usize..nn as usize]); + lib::memzero0::memzero::(&mut b, 32u32) +} + +pub const block_bytes: u32 = 64u32; + +pub const out_bytes: u32 = 32u32; + +pub const key_bytes: u32 = 32u32; + +pub const salt_bytes: u32 = 8u32; + +pub const personal_bytes: u32 = 8u32; + +#[derive(PartialEq, Clone)] +pub struct block_state_t { + pub fst: u8, + pub snd: u8, + pub thd: bool, + pub f3: Box<[u32]>, + pub f4: Box<[u32]>, +} + +#[derive(PartialEq, Clone)] +pub struct state_t { + pub block_state: crate::hacl::hash_blake2s::block_state_t, + pub buf: Box<[u8]>, + pub total_len: u64, +} + +fn index_of_state(s: &[crate::hacl::hash_blake2s::state_t]) -> crate::hacl::hash_blake2b::index { + let block_state: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + } +} + +#[allow(clippy::match_single_binding)] +fn reset_raw<'a>( + state: &'a mut [crate::hacl::hash_blake2s::state_t], + key: crate::hacl::hash_blake2b::params_and_key<'a>, +) { + let block_state: &mut crate::hacl::hash_blake2s::block_state_t = + &mut (state[0usize]).block_state; + let buf: &mut [u8] = &mut (state[0usize]).buf; + let i: crate::hacl::hash_blake2b::index = match *block_state { + crate::hacl::hash_blake2s::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + }; + let p: &[crate::hacl::hash_blake2b::blake2_params] = key.fst; + let kk1: u8 = (p[0usize]).key_length; + let nn: u8 = (p[0usize]).digest_length; + match *block_state { + crate::hacl::hash_blake2s::block_state_t { thd: last_node, .. } => { + let i1: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }; + let h: &mut [u32] = &mut block_state.f4; + let kk2: u32 = i1.key_length as u32; + let k·1: &[u8] = key.snd; + if kk2 != 0u32 { + let sub_b: (&mut [u8], &mut [u8]) = buf.split_at_mut(kk2 as usize); + (sub_b.1[0usize..64u32.wrapping_sub(kk2) as usize]).copy_from_slice( + &vec![0u8; 64u32.wrapping_sub(kk2) as usize].into_boxed_slice(), + ); + (buf[0usize..kk2 as usize]).copy_from_slice(&k·1[0usize..kk2 as usize]) + }; + let pv: crate::hacl::hash_blake2b::blake2_params = p[0usize]; + let mut tmp: [u32; 8] = [0u32; 8usize]; + let r0: (&mut [u32], &mut [u32]) = h.split_at_mut(0usize); + let r1: (&mut [u32], &mut [u32]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u32], &mut [u32]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u32], &mut [u32]) = r2.1.split_at_mut(4usize); + let iv0: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[0usize]; + let iv1: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[1usize]; + let iv2: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[2usize]; + let iv3: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[3usize]; + let iv4: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[4usize]; + let iv5: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[5usize]; + let iv6: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[6usize]; + let iv7: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let uu____0: (&mut [u32], &mut [u32]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.salt[i0.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + let uu____1: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.personal[i0.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____1.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + (&mut tmp)[0usize] = pv.digest_length as u32 + ^ ((pv.key_length as u32).wrapping_shl(8u32) + ^ ((pv.fanout as u32).wrapping_shl(16u32) + ^ (pv.depth as u32).wrapping_shl(24u32))); + (&mut tmp)[1usize] = pv.leaf_length; + (&mut tmp)[2usize] = pv.node_offset as u32; + (&mut tmp)[3usize] = pv.node_offset.wrapping_shr(32u32) as u32 + ^ ((pv.node_depth as u32).wrapping_shl(16u32) + ^ (pv.inner_length as u32).wrapping_shl(24u32)); + let tmp0: u32 = (&tmp)[0usize]; + let tmp1: u32 = (&tmp)[1usize]; + let tmp2: u32 = (&tmp)[2usize]; + let tmp3: u32 = (&tmp)[3usize]; + let tmp4: u32 = (&tmp)[4usize]; + let tmp5: u32 = (&tmp)[5usize]; + let tmp6: u32 = (&tmp)[6usize]; + let tmp7: u32 = (&tmp)[7usize]; + let iv0·: u32 = iv0 ^ tmp0; + let iv1·: u32 = iv1 ^ tmp1; + let iv2·: u32 = iv2 ^ tmp2; + let iv3·: u32 = iv3 ^ tmp3; + let iv4·: u32 = iv4 ^ tmp4; + let iv5·: u32 = iv5 ^ tmp5; + let iv6·: u32 = iv6 ^ tmp6; + let iv7·: u32 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· + } + }; + let kk10: u8 = i.key_length; + let ite: u32 = if kk10 != 0u8 { 64u32 } else { 0u32 }; + let total_len: u64 = ite as u64; + (state[0usize]).total_len = total_len +} + +/** +General-purpose re-initialization function with parameters and +key. You cannot change digest_length, key_length, or last_node, meaning those values in +the parameters object must be the same as originally decided via one of the +malloc functions. All other values of the parameter can be changed. The behavior +is unspecified if you violate this precondition. +*/ +pub fn reset_with_key_and_params( + s: &mut [crate::hacl::hash_blake2s::state_t], + p: &[crate::hacl::hash_blake2b::blake2_params], + k: &[u8], +) { + let i1: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2s::index_of_state(s); + lowstar::ignore::ignore::(i1); + crate::hacl::hash_blake2s::reset_raw( + s, + crate::hacl::hash_blake2b::params_and_key { fst: p, snd: k }, + ) +} + +/** +Specialized-purpose re-initialization function with no parameters, +and a key. The key length must be the same as originally decided via your choice +of malloc function. All other parameters are reset to their default values. The +original call to malloc MUST have set digest_length to the default value. The +behavior is unspecified if you violate this precondition. +*/ +pub fn reset_with_key(s: &mut [crate::hacl::hash_blake2s::state_t], k: &[u8]) { + let idx: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2s::index_of_state(s); + let salt: [u8; 8] = [0u8; 8usize]; + let personal: [u8; 8] = [0u8; 8usize]; + let p: crate::hacl::hash_blake2b::blake2_params = crate::hacl::hash_blake2b::blake2_params { + digest_length: idx.digest_length, + key_length: idx.key_length, + fanout: 1u8, + depth: 1u8, + leaf_length: 0u32, + node_offset: 0u64, + node_depth: 0u8, + inner_length: 0u8, + salt: &salt, + personal: &personal, + }; + let p0: [crate::hacl::hash_blake2b::blake2_params; 1] = [p; 1usize]; + crate::hacl::hash_blake2s::reset_raw( + s, + crate::hacl::hash_blake2b::params_and_key { fst: &p0, snd: k }, + ) +} + +/** +Specialized-purpose re-initialization function with no parameters +and no key. This is what you want if you intend to use Blake2 as a hash +function. The key length and digest length must have been set to their +respective default values via your choice of malloc function (always true if you +used `malloc`). All other parameters are reset to their default values. The +behavior is unspecified if you violate this precondition. +*/ +pub fn reset(s: &mut [crate::hacl::hash_blake2s::state_t]) { + crate::hacl::hash_blake2s::reset_with_key(s, &[]) +} + +/** +Update function; 0 = success, 1 = max length exceeded +*/ +pub fn update0( + state: &mut [crate::hacl::hash_blake2s::state_t], + chunk: &[u8], + chunk_len: u32, +) -> streaming_types::error_code { + let block_state: &mut crate::hacl::hash_blake2s::block_state_t = + &mut (state[0usize]).block_state; + let total_len: u64 = (state[0usize]).total_len; + if chunk_len as u64 > 0xffffffffffffffffu64.wrapping_sub(total_len) { + streaming_types::error_code::MaximumLengthExceeded + } else { + let sz: u32 = if total_len.wrapping_rem(64u32 as u64) == 0u64 && total_len > 0u64 { + 64u32 + } else { + total_len.wrapping_rem(64u32 as u64) as u32 + }; + if chunk_len <= 64u32.wrapping_sub(sz) { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(64u32 as u64) == 0u64 && total_len1 > 0u64 { + 64u32 + } else { + total_len1.wrapping_rem(64u32 as u64) as u32 + }; + let buf2: (&mut [u8], &mut [u8]) = buf.split_at_mut(sz1 as usize); + (buf2.1[0usize..chunk_len as usize]) + .copy_from_slice(&chunk[0usize..chunk_len as usize]); + let total_len2: u64 = total_len1.wrapping_add(chunk_len as u64); + (state[0usize]).total_len = total_len2 + } else if sz == 0u32 { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(64u32 as u64) == 0u64 && total_len1 > 0u64 { + 64u32 + } else { + total_len1.wrapping_rem(64u32 as u64) as u32 + }; + if sz1 != 0u32 { + let prevlen: u64 = total_len1.wrapping_sub(sz1 as u64); + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = 1u32; + crate::hacl::hash_blake2s::update_multi(64u32, wv, hash, prevlen, buf, nb) + } + } + }; + let ite: u32 = if (chunk_len as u64).wrapping_rem(64u32 as u64) == 0u64 + && chunk_len as u64 > 0u64 + { + 64u32 + } else { + (chunk_len as u64).wrapping_rem(64u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len.wrapping_sub(ite).wrapping_div(64u32); + let data1_len: u32 = n_blocks.wrapping_mul(64u32); + let data2_len: u32 = chunk_len.wrapping_sub(data1_len); + let data1: (&[u8], &[u8]) = chunk.split_at(0usize); + let data2: (&[u8], &[u8]) = data1.1.split_at(data1_len as usize); + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = data1_len.wrapping_div(64u32); + crate::hacl::hash_blake2s::update_multi( + data1_len, wv, hash, total_len1, data2.0, nb, + ) + } + }; + let dst: (&mut [u8], &mut [u8]) = buf.split_at_mut(0usize); + (dst.1[0usize..data2_len as usize]) + .copy_from_slice(&data2.1[0usize..data2_len as usize]); + (state[0usize]).total_len = total_len1.wrapping_add(chunk_len as u64) + } else { + let diff: u32 = 64u32.wrapping_sub(sz); + let chunk1: (&[u8], &[u8]) = chunk.split_at(0usize); + let chunk2: (&[u8], &[u8]) = chunk1.1.split_at(diff as usize); + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let sz1: u32 = if total_len1.wrapping_rem(64u32 as u64) == 0u64 && total_len1 > 0u64 { + 64u32 + } else { + total_len1.wrapping_rem(64u32 as u64) as u32 + }; + let buf2: (&mut [u8], &mut [u8]) = buf.split_at_mut(sz1 as usize); + (buf2.1[0usize..diff as usize]).copy_from_slice(&chunk2.0[0usize..diff as usize]); + let total_len2: u64 = total_len1.wrapping_add(diff as u64); + (state[0usize]).total_len = total_len2; + let buf0: &mut [u8] = &mut (state[0usize]).buf; + let total_len10: u64 = (state[0usize]).total_len; + let sz10: u32 = if total_len10.wrapping_rem(64u32 as u64) == 0u64 && total_len10 > 0u64 + { + 64u32 + } else { + total_len10.wrapping_rem(64u32 as u64) as u32 + }; + if sz10 != 0u32 { + let prevlen: u64 = total_len10.wrapping_sub(sz10 as u64); + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = 1u32; + crate::hacl::hash_blake2s::update_multi(64u32, wv, hash, prevlen, buf0, nb) + } + } + }; + let ite: u32 = if (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(64u32 as u64) + == 0u64 + && chunk_len.wrapping_sub(diff) as u64 > 0u64 + { + 64u32 + } else { + (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(64u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len + .wrapping_sub(diff) + .wrapping_sub(ite) + .wrapping_div(64u32); + let data1_len: u32 = n_blocks.wrapping_mul(64u32); + let data2_len: u32 = chunk_len.wrapping_sub(diff).wrapping_sub(data1_len); + let data1: (&[u8], &[u8]) = chunk2.1.split_at(0usize); + let data2: (&[u8], &[u8]) = data1.1.split_at(data1_len as usize); + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + f3: ref mut wv, + f4: ref mut hash, + .. + } => { + let nb: u32 = data1_len.wrapping_div(64u32); + crate::hacl::hash_blake2s::update_multi( + data1_len, + wv, + hash, + total_len10, + data2.0, + nb, + ) + } + }; + let dst: (&mut [u8], &mut [u8]) = buf0.split_at_mut(0usize); + (dst.1[0usize..data2_len as usize]) + .copy_from_slice(&data2.1[0usize..data2_len as usize]); + (state[0usize]).total_len = + total_len10.wrapping_add(chunk_len.wrapping_sub(diff) as u64) + }; + streaming_types::error_code::Success + } +} + +/** +Digest function. This function expects the `output` array to hold +at least `digest_length` bytes, where `digest_length` was determined by your +choice of `malloc` function. Concretely, if you used `malloc` or +`malloc_with_key`, then the expected length is 32 for S, or 64 for B (default +digest length). If you used `malloc_with_params_and_key`, then the expected +length is whatever you chose for the `digest_length` field of your parameters. +For convenience, this function returns `digest_length`. When in doubt, callers +can pass an array of size HACL_BLAKE2S_32_OUT_BYTES, then use the return value +to see how many bytes were actually written. +*/ +pub fn digest(s: &[crate::hacl::hash_blake2s::state_t], dst: &mut [u8]) -> u8 { + let block_state: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; + let i1: crate::hacl::hash_blake2b::index = match *block_state { + crate::hacl::hash_blake2s::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + }; + let block_state0: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; + let buf_: &[u8] = &(s[0usize]).buf; + let total_len: u64 = (s[0usize]).total_len; + let r: u32 = if total_len.wrapping_rem(64u32 as u64) == 0u64 && total_len > 0u64 { + 64u32 + } else { + total_len.wrapping_rem(64u32 as u64) as u32 + }; + let buf_1: (&[u8], &[u8]) = buf_.split_at(0usize); + let wv: [u32; 16] = [0u32; 16usize]; + let b: [u32; 16] = [0u32; 16usize]; + let mut tmp_block_state: crate::hacl::hash_blake2s::block_state_t = + crate::hacl::hash_blake2s::block_state_t { + fst: i1.key_length, + snd: i1.digest_length, + thd: i1.last_node, + f3: Box::new(wv), + f4: Box::new(b), + }; + match *block_state0 { + crate::hacl::hash_blake2s::block_state_t { f4: ref src_b, .. } => match tmp_block_state { + crate::hacl::hash_blake2s::block_state_t { + f4: ref mut dst_b, .. + } => (dst_b[0usize..16usize]).copy_from_slice(&src_b[0usize..16usize]), + }, + }; + let prev_len: u64 = total_len.wrapping_sub(r as u64); + let buf_multi: (&[u8], &[u8]) = buf_1.1.split_at(0usize); + let ite: u32 = if r.wrapping_rem(64u32) == 0u32 && r > 0u32 { + 64u32 + } else { + r.wrapping_rem(64u32) + }; + let buf_last: (&[u8], &[u8]) = buf_multi.1.split_at(r.wrapping_sub(ite) as usize); + match tmp_block_state { + crate::hacl::hash_blake2s::block_state_t { + f3: ref mut wv0, + f4: ref mut hash, + .. + } => { + let nb: u32 = 0u32; + crate::hacl::hash_blake2s::update_multi(0u32, wv0, hash, prev_len, buf_last.0, nb) + } + }; + let prev_len_last: u64 = total_len.wrapping_sub(r as u64); + match tmp_block_state { + crate::hacl::hash_blake2s::block_state_t { + thd: last_node, + f3: ref mut wv0, + f4: ref mut hash, + .. + } => crate::hacl::hash_blake2s::update_last( + r, + wv0, + hash, + last_node, + prev_len_last, + r, + buf_last.1, + ), + }; + match tmp_block_state { + crate::hacl::hash_blake2s::block_state_t { snd: nn, .. } => { + crate::hacl::hash_blake2s::finish(nn as u32, dst, &tmp_block_state.f4) + } + }; + let block_state1: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; + match *block_state1 { + crate::hacl::hash_blake2s::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + } + .digest_length +} + +pub fn info(s: &[crate::hacl::hash_blake2s::state_t]) -> crate::hacl::hash_blake2b::index { + let block_state: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; + match *block_state { + crate::hacl::hash_blake2s::block_state_t { + fst: kk, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk, + digest_length: nn, + last_node, + }, + } +} + +/** +Copying. This preserves all parameters. +*/ +pub fn copy( + state: &[crate::hacl::hash_blake2s::state_t], +) -> Box<[crate::hacl::hash_blake2s::state_t]> { + let block_state0: &crate::hacl::hash_blake2s::block_state_t = &(state[0usize]).block_state; + let buf0: &[u8] = &(state[0usize]).buf; + let total_len0: u64 = (state[0usize]).total_len; + let i: crate::hacl::hash_blake2b::index = match *block_state0 { + crate::hacl::hash_blake2s::block_state_t { + fst: kk1, + snd: nn, + thd: last_node, + .. + } => crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }, + }; + let mut buf: Box<[u8]> = vec![0u8; 64usize].into_boxed_slice(); + ((&mut buf)[0usize..64usize]).copy_from_slice(&buf0[0usize..64usize]); + let wv: Box<[u32]> = vec![0u32; 16usize].into_boxed_slice(); + let b: Box<[u32]> = vec![0u32; 16usize].into_boxed_slice(); + let mut block_state: crate::hacl::hash_blake2s::block_state_t = + crate::hacl::hash_blake2s::block_state_t { + fst: i.key_length, + snd: i.digest_length, + thd: i.last_node, + f3: wv, + f4: b, + }; + match *block_state0 { + crate::hacl::hash_blake2s::block_state_t { f4: ref src_b, .. } => match block_state { + crate::hacl::hash_blake2s::block_state_t { + f4: ref mut dst_b, .. + } => (dst_b[0usize..16usize]).copy_from_slice(&src_b[0usize..16usize]), + }, + }; + let s: crate::hacl::hash_blake2s::state_t = crate::hacl::hash_blake2s::state_t { + block_state, + buf, + total_len: total_len0, + }; + let p: Box<[crate::hacl::hash_blake2s::state_t]> = vec![s].into_boxed_slice(); + p +} + +/** +Write the BLAKE2s digest of message `input` using key `key` into `output`. + +@param output Pointer to `output_len` bytes of memory where the digest is written to. +@param output_len Length of the to-be-generated digest with 1 <= `output_len` <= 64. +@param input Pointer to `input_len` bytes of memory where the input message is read from. +@param input_len Length of the input message. +@param key Pointer to `key_len` bytes of memory where the key is read from. +@param key_len Length of the key. Can be 0. +*/ +pub fn hash_with_key( + output: &mut [u8], + output_len: u32, + input: &[u8], + input_len: u32, + key: &[u8], + key_len: u32, +) { + let mut b: [u32; 16] = [0u32; 16usize]; + let mut b1: [u32; 16] = [0u32; 16usize]; + crate::hacl::hash_blake2s::init(&mut b, key_len, output_len); + crate::hacl::hash_blake2s::update(&mut b1, &mut b, key_len, key, input_len, input); + crate::hacl::hash_blake2s::finish(output_len, output, &b); + lib::memzero0::memzero::(&mut b1, 16u32); + lib::memzero0::memzero::(&mut b, 16u32) +} + +/** +Write the BLAKE2s digest of message `input` using key `key` and +parameters `params` into `output`. The `key` array must be of length +`params.key_length`. The `output` array must be of length +`params.digest_length`. +*/ +pub fn hash_with_key_and_params<'a>( + output: &'a mut [u8], + input: &'a [u8], + input_len: u32, + params: crate::hacl::hash_blake2b::blake2_params<'a>, + key: &'a [u8], +) { + let mut b: [u32; 16] = [0u32; 16usize]; + let mut b1: [u32; 16] = [0u32; 16usize]; + let mut tmp: [u32; 8] = [0u32; 8usize]; + let r0: (&mut [u32], &mut [u32]) = b.split_at_mut(0usize); + let r1: (&mut [u32], &mut [u32]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u32], &mut [u32]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u32], &mut [u32]) = r2.1.split_at_mut(4usize); + let iv0: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[0usize]; + let iv1: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[1usize]; + let iv2: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[2usize]; + let iv3: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[3usize]; + let iv4: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[4usize]; + let iv5: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[5usize]; + let iv6: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[6usize]; + let iv7: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let uu____0: (&mut [u32], &mut [u32]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = ¶ms.salt[i.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + let uu____1: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i", 0u32, 1u32, { + let bj: &[u8] = ¶ms.personal[i.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r: u32 = u; + let x: u32 = r; + let os: (&mut [u32], &mut [u32]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + (&mut tmp)[0usize] = params.digest_length as u32 + ^ ((params.key_length as u32).wrapping_shl(8u32) + ^ ((params.fanout as u32).wrapping_shl(16u32) + ^ (params.depth as u32).wrapping_shl(24u32))); + (&mut tmp)[1usize] = params.leaf_length; + (&mut tmp)[2usize] = params.node_offset as u32; + (&mut tmp)[3usize] = params.node_offset.wrapping_shr(32u32) as u32 + ^ ((params.node_depth as u32).wrapping_shl(16u32) + ^ (params.inner_length as u32).wrapping_shl(24u32)); + let tmp0: u32 = (&tmp)[0usize]; + let tmp1: u32 = (&tmp)[1usize]; + let tmp2: u32 = (&tmp)[2usize]; + let tmp3: u32 = (&tmp)[3usize]; + let tmp4: u32 = (&tmp)[4usize]; + let tmp5: u32 = (&tmp)[5usize]; + let tmp6: u32 = (&tmp)[6usize]; + let tmp7: u32 = (&tmp)[7usize]; + let iv0·: u32 = iv0 ^ tmp0; + let iv1·: u32 = iv1 ^ tmp1; + let iv2·: u32 = iv2 ^ tmp2; + let iv3·: u32 = iv3 ^ tmp3; + let iv4·: u32 = iv4 ^ tmp4; + let iv5·: u32 = iv5 ^ tmp5; + let iv6·: u32 = iv6 ^ tmp6; + let iv7·: u32 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7·; + crate::hacl::hash_blake2s::update( + &mut b1, + &mut b, + params.key_length as u32, + key, + input_len, + input, + ); + crate::hacl::hash_blake2s::finish(params.digest_length as u32, output, &b); + lib::memzero0::memzero::(&mut b1, 16u32); + lib::memzero0::memzero::(&mut b, 16u32) +} diff --git a/blake2/src/hacl/impl_blake2_constants.rs b/blake2/src/hacl/impl_blake2_constants.rs new file mode 100644 index 000000000..87d9e7917 --- /dev/null +++ b/blake2/src/hacl/impl_blake2_constants.rs @@ -0,0 +1,27 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +pub(crate) const sigmaTable: [u32; 160] = + [0u32, 1u32, 2u32, 3u32, 4u32, 5u32, 6u32, 7u32, 8u32, 9u32, 10u32, 11u32, 12u32, 13u32, 14u32, + 15u32, 14u32, 10u32, 4u32, 8u32, 9u32, 15u32, 13u32, 6u32, 1u32, 12u32, 0u32, 2u32, 11u32, + 7u32, 5u32, 3u32, 11u32, 8u32, 12u32, 0u32, 5u32, 2u32, 15u32, 13u32, 10u32, 14u32, 3u32, + 6u32, 7u32, 1u32, 9u32, 4u32, 7u32, 9u32, 3u32, 1u32, 13u32, 12u32, 11u32, 14u32, 2u32, 6u32, + 5u32, 10u32, 4u32, 0u32, 15u32, 8u32, 9u32, 0u32, 5u32, 7u32, 2u32, 4u32, 10u32, 15u32, + 14u32, 1u32, 11u32, 12u32, 6u32, 8u32, 3u32, 13u32, 2u32, 12u32, 6u32, 10u32, 0u32, 11u32, + 8u32, 3u32, 4u32, 13u32, 7u32, 5u32, 15u32, 14u32, 1u32, 9u32, 12u32, 5u32, 1u32, 15u32, + 14u32, 13u32, 4u32, 10u32, 0u32, 7u32, 6u32, 3u32, 9u32, 2u32, 8u32, 11u32, 13u32, 11u32, + 7u32, 14u32, 12u32, 1u32, 3u32, 9u32, 5u32, 0u32, 15u32, 4u32, 8u32, 6u32, 2u32, 10u32, 6u32, + 15u32, 14u32, 9u32, 11u32, 3u32, 0u32, 8u32, 12u32, 2u32, 13u32, 7u32, 1u32, 4u32, 10u32, + 5u32, 10u32, 2u32, 8u32, 4u32, 7u32, 6u32, 1u32, 5u32, 15u32, 11u32, 9u32, 14u32, 3u32, + 12u32, 13u32, 0u32]; + +pub(crate) const ivTable_S: [u32; 8] = + [0x6A09E667u32, 0xBB67AE85u32, 0x3C6EF372u32, 0xA54FF53Au32, 0x510E527Fu32, 0x9B05688Cu32, + 0x1F83D9ABu32, 0x5BE0CD19u32]; + +pub(crate) const ivTable_B: [u64; 8] = + [0x6A09E667F3BCC908u64, 0xBB67AE8584CAA73Bu64, 0x3C6EF372FE94F82Bu64, 0xA54FF53A5F1D36F1u64, + 0x510E527FADE682D1u64, 0x9B05688C2B3E6C1Fu64, 0x1F83D9ABFB41BD6Bu64, 0x5BE0CD19137E2179u64]; diff --git a/blake2/src/impl_hacl.rs b/blake2/src/impl_hacl.rs new file mode 100644 index 000000000..777920d78 --- /dev/null +++ b/blake2/src/impl_hacl.rs @@ -0,0 +1,196 @@ +use crate::hacl::hash_blake2b::{ + blake2_params, digest, index, malloc_raw, params_and_key, reset, reset_with_key, update0, +}; + +extern crate alloc; +use alloc::boxed::Box; +use libcrux_hacl_rs::streaming_types::error_code; + +/// Indicates an error has occurred +#[derive(Debug)] +pub enum Error { + /// The used key length is invalid. + InvalidKeyLength, + /// The used digest length is invalid. + InvalidDigestLength, + ///The maximum input length is exceeded. + MaximumLengthExceeded, + /// The maximum chunk length is exceeded. + InvalidChunkLength, + /// An unexpected error has occurred. + Unexpected, +} + +impl alloc::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let text = match self { + Error::InvalidKeyLength => "The used key length is invalid.", + Error::InvalidDigestLength => "The used digest length is invalid.", + Error::MaximumLengthExceeded => "The maximum input length is exceeded.", + Error::InvalidChunkLength => "The maximum chunk length is exceeded.", + Error::Unexpected => "An unexpected error has occurred.", + }; + + write!(f, "{text}") + } +} + +impl core::error::Error for Error {} + +/// A builder for [`Blake2b`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the +/// range `1..=64`. +pub struct Blake2bBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { + key: &'a [u8; KEY_LEN], + personal: &'a [u8; 16], + salt: &'a [u8; 16], +} + +impl Blake2bBuilder<'_, 0, OUT_LEN> { + /// Creates the builder for an unkeyed hasher and returns an error if the digest length + /// `OUT_LEN` is not in the allowed range. + pub fn new_unkeyed() -> Result { + if OUT_LEN < 1 || OUT_LEN > 64 { + return Err(Error::InvalidDigestLength); + } + + Ok(Self { + key: &[], + personal: &[0; 16], + salt: &[0; 16], + }) + } +} +impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, OUT_LEN> { + /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in + /// the allowed range. + pub fn new() -> Result { + if KEY_LEN > 64 { + return Err(Error::InvalidKeyLength); + } + + if OUT_LEN < 1 || OUT_LEN > 64 { + return Err(Error::InvalidDigestLength); + } + Ok(Self { + key: &[0; KEY_LEN], + personal: &[0; 16], + salt: &[0; 16], + }) + } + + /// Sets the key to be used in the hasher. + pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { + Self { key, ..self } + } + + /// Sets the personalization bytes to be used in the hasher. + pub fn with_personalization(self, personal: &'a [u8; 16]) -> Self { + Self { personal, ..self } + } + + /// Sets the salt to be used in the hasher. + pub fn with_salt(self, salt: &'a [u8; 16]) -> Self { + Self { salt, ..self } + } + + /// Constructs the [`Blake2b`] hasher. + pub fn build(self) -> Blake2b { + // these are safe because they bot are at most 64 + let key_length = KEY_LEN as u8; + let digest_length = OUT_LEN as u8; + + // NOTE: I am not entirely sure that this is the correct value. From reading the spec I + // think it should be `true`, but when comparing with other implementations I only get the + // same values when using `false`. + let last_node = false; + + let kk = index { + key_length, + digest_length, + last_node, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Blake2b { + state: malloc_raw(kk, key), + } + } +} + +/// A hasher struct for the Blake2b (optionally keyed) hash function. +pub struct Blake2b { + state: Box<[crate::hacl::hash_blake2b::state_t]>, +} + +impl Blake2b { + /// Updates the hash state by adding the bytes from `chunk` to the hashed data. + pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { + if chunk.len() > (u32::MAX as usize) { + return Err(Error::InvalidChunkLength); + } + + match update0(self.state.as_mut(), chunk, chunk.len() as u32) { + error_code::Success => Ok(()), + error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), + _ => Err(Error::Unexpected), + } + } + + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + digest(&self.state, dst); + } + + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + reset_with_key(&mut self.state, key); + } +} + +impl Blake2b<0, OUT_LEN> { + /// Reset the hash state. + pub fn reset(&mut self) { + reset(&mut self.state) + } +} + +#[cfg(test)] +mod test { + use super::{Blake2b, Blake2bBuilder}; + + #[test] + fn test_hash() { + let mut got_hash = [0; 32]; + let mut hasher: Blake2b<0, 32> = Blake2bBuilder::new().unwrap().build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; + + assert_eq!(&got_hash, expected_hash); + + let mut got_hash = [0; 64]; + let mut hasher: Blake2b<0, 64> = Blake2bBuilder::new().unwrap().build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; + + assert_eq!(&got_hash, expected_hash); + } +} diff --git a/blake2/src/lib.rs b/blake2/src/lib.rs new file mode 100644 index 000000000..114526c40 --- /dev/null +++ b/blake2/src/lib.rs @@ -0,0 +1,13 @@ +//#![no_std] + +pub mod hacl { + //! This module contains generated hacl code. + + pub mod hash_blake2b; + pub mod hash_blake2s; + pub mod impl_blake2_constants; +} + +mod impl_hacl; + +pub use impl_hacl::*; diff --git a/hacl-rs/src/util.rs b/hacl-rs/src/util.rs index 035d286e2..71efc9ccd 100644 --- a/hacl-rs/src/util.rs +++ b/hacl-rs/src/util.rs @@ -1 +1,2 @@ pub mod inttypes_intrinsics; +pub mod memzero0; diff --git a/hacl-rs/src/util/memzero0.rs b/hacl-rs/src/util/memzero0.rs new file mode 100644 index 000000000..017d117c5 --- /dev/null +++ b/hacl-rs/src/util/memzero0.rs @@ -0,0 +1,6 @@ +pub fn memzero(x: &mut [T], len: u32) { + let zero: T = unsafe { core::mem::zeroed() }; + for i in 0..len { + x[i as usize] = zero; + } +} From e8880fdb27f4b901d62cc4262d2d9df0c25fd2d4 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 16 Jan 2025 16:19:08 +0100 Subject: [PATCH 02/11] add blake2s --- blake2/src/hacl/hash_blake2s.rs | 122 ++++++++++++++++++++++ blake2/src/impl_hacl.rs | 178 +++++++++++++++++++++++++++++--- 2 files changed, 285 insertions(+), 15 deletions(-) diff --git a/blake2/src/hacl/hash_blake2s.rs b/blake2/src/hacl/hash_blake2s.rs index 8b6c0e6d4..f9f0cfd7a 100644 --- a/blake2/src/hacl/hash_blake2s.rs +++ b/blake2/src/hacl/hash_blake2s.rs @@ -4,6 +4,7 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] #![allow(clippy::match_single_binding)] +#![allow(clippy::needless_lifetimes)] use libcrux_hacl_rs::prelude::*; use libcrux_macros as krml; @@ -604,6 +605,127 @@ pub struct state_t { pub total_len: u64, } +pub(crate) fn malloc_raw<'a>( + kk: crate::hacl::hash_blake2b::index, + key: crate::hacl::hash_blake2b::params_and_key<'a>, +) -> Box<[crate::hacl::hash_blake2s::state_t]> { + let mut buf: Box<[u8]> = vec![0u8; 64usize].into_boxed_slice(); + let wv: Box<[u32]> = vec![0u32; 16usize].into_boxed_slice(); + let b: Box<[u32]> = vec![0u32; 16usize].into_boxed_slice(); + let mut block_state: crate::hacl::hash_blake2s::block_state_t = + crate::hacl::hash_blake2s::block_state_t { + fst: kk.key_length, + snd: kk.digest_length, + thd: kk.last_node, + f3: wv, + f4: b, + }; + let p: &[crate::hacl::hash_blake2b::blake2_params] = key.fst; + let kk1: u8 = (p[0usize]).key_length; + let nn: u8 = (p[0usize]).digest_length; + match block_state { + crate::hacl::hash_blake2s::block_state_t { thd: last_node, .. } => { + let i: crate::hacl::hash_blake2b::index = crate::hacl::hash_blake2b::index { + key_length: kk1, + digest_length: nn, + last_node, + }; + let h: &mut [u32] = &mut block_state.f4; + let kk2: u32 = i.key_length as u32; + let k·: &[u8] = key.snd; + if kk2 != 0u32 { + let sub_b: (&mut [u8], &mut [u8]) = buf.split_at_mut(kk2 as usize); + (sub_b.1[0usize..64u32.wrapping_sub(kk2) as usize]).copy_from_slice( + &vec![0u8; 64u32.wrapping_sub(kk2) as usize].into_boxed_slice(), + ); + ((&mut buf)[0usize..kk2 as usize]).copy_from_slice(&k·[0usize..kk2 as usize]) + }; + let pv: crate::hacl::hash_blake2b::blake2_params = p[0usize]; + let mut tmp: [u32; 8] = [0u32; 8usize]; + let r0: (&mut [u32], &mut [u32]) = h.split_at_mut(0usize); + let r1: (&mut [u32], &mut [u32]) = r0.1.split_at_mut(4usize); + let r2: (&mut [u32], &mut [u32]) = r1.1.split_at_mut(4usize); + let r3: (&mut [u32], &mut [u32]) = r2.1.split_at_mut(4usize); + let iv0: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[0usize]; + let iv1: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[1usize]; + let iv2: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[2usize]; + let iv3: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[3usize]; + let iv4: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[4usize]; + let iv5: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[5usize]; + let iv6: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[6usize]; + let iv7: u32 = (&crate::hacl::impl_blake2_constants::ivTable_S)[7usize]; + r3.0[0usize] = iv0; + r3.0[1usize] = iv1; + r3.0[2usize] = iv2; + r3.0[3usize] = iv3; + r3.1[0usize] = iv4; + r3.1[1usize] = iv5; + r3.1[2usize] = iv6; + r3.1[3usize] = iv7; + let uu____0: (&mut [u32], &mut [u32]) = tmp.split_at_mut(4usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.salt[i0.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r4: u32 = u; + let x: u32 = r4; + let os: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + let uu____1: (&mut [u32], &mut [u32]) = uu____0.1.split_at_mut(2usize); + krml::unroll_for!(2, "i0", 0u32, 1u32, { + let bj: &[u8] = &pv.personal[i0.wrapping_mul(4u32) as usize..]; + let u: u32 = lowstar::endianness::load32_le(bj); + let r4: u32 = u; + let x: u32 = r4; + let os: (&mut [u32], &mut [u32]) = uu____1.1.split_at_mut(0usize); + os.1[i0 as usize] = x + }); + (&mut tmp)[0usize] = pv.digest_length as u32 + ^ ((pv.key_length as u32).wrapping_shl(8u32) + ^ ((pv.fanout as u32).wrapping_shl(16u32) + ^ (pv.depth as u32).wrapping_shl(24u32))); + (&mut tmp)[1usize] = pv.leaf_length; + (&mut tmp)[2usize] = pv.node_offset as u32; + (&mut tmp)[3usize] = pv.node_offset.wrapping_shr(32u32) as u32 + ^ ((pv.node_depth as u32).wrapping_shl(16u32) + ^ (pv.inner_length as u32).wrapping_shl(24u32)); + let tmp0: u32 = (&tmp)[0usize]; + let tmp1: u32 = (&tmp)[1usize]; + let tmp2: u32 = (&tmp)[2usize]; + let tmp3: u32 = (&tmp)[3usize]; + let tmp4: u32 = (&tmp)[4usize]; + let tmp5: u32 = (&tmp)[5usize]; + let tmp6: u32 = (&tmp)[6usize]; + let tmp7: u32 = (&tmp)[7usize]; + let iv0·: u32 = iv0 ^ tmp0; + let iv1·: u32 = iv1 ^ tmp1; + let iv2·: u32 = iv2 ^ tmp2; + let iv3·: u32 = iv3 ^ tmp3; + let iv4·: u32 = iv4 ^ tmp4; + let iv5·: u32 = iv5 ^ tmp5; + let iv6·: u32 = iv6 ^ tmp6; + let iv7·: u32 = iv7 ^ tmp7; + r1.0[0usize] = iv0·; + r1.0[1usize] = iv1·; + r1.0[2usize] = iv2·; + r1.0[3usize] = iv3·; + r2.0[0usize] = iv4·; + r2.0[1usize] = iv5·; + r2.0[2usize] = iv6·; + r2.0[3usize] = iv7· + } + }; + let kk10: u8 = kk.key_length; + let ite: u32 = if kk10 != 0u8 { 64u32 } else { 0u32 }; + let s: crate::hacl::hash_blake2s::state_t = crate::hacl::hash_blake2s::state_t { + block_state, + buf, + total_len: ite as u64, + }; + let p0: Box<[crate::hacl::hash_blake2s::state_t]> = vec![s].into_boxed_slice(); + p0 +} + fn index_of_state(s: &[crate::hacl::hash_blake2s::state_t]) -> crate::hacl::hash_blake2b::index { let block_state: &crate::hacl::hash_blake2s::block_state_t = &(s[0usize]).block_state; match *block_state { diff --git a/blake2/src/impl_hacl.rs b/blake2/src/impl_hacl.rs index 777920d78..c0b114cb6 100644 --- a/blake2/src/impl_hacl.rs +++ b/blake2/src/impl_hacl.rs @@ -1,11 +1,25 @@ +use crate::hacl::hash_blake2b::{blake2_params, index, params_and_key}; + use crate::hacl::hash_blake2b::{ - blake2_params, digest, index, malloc_raw, params_and_key, reset, reset_with_key, update0, + digest as blake2b_digest, malloc_raw as blake2b_malloc_raw, reset as blake2b_reset, + reset_with_key as blake2b_reset_with_key, state_t as blake2b_state_t, + update0 as blake2b_update0, +}; + +use crate::hacl::hash_blake2s::{ + digest as blake2s_digest, malloc_raw as blake2s_malloc_raw, reset as blake2s_reset, + reset_with_key as blake2s_reset_with_key, state_t as blake2s_state_t, + update0 as blake2s_update0, }; extern crate alloc; + use alloc::boxed::Box; use libcrux_hacl_rs::streaming_types::error_code; +const BLAKE2B_PARAM_LEN: usize = 16; +const BLAKE2S_PARAM_LEN: usize = 8; + /// Indicates an error has occurred #[derive(Debug)] pub enum Error { @@ -41,8 +55,8 @@ impl core::error::Error for Error {} /// range `1..=64`. pub struct Blake2bBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { key: &'a [u8; KEY_LEN], - personal: &'a [u8; 16], - salt: &'a [u8; 16], + personal: &'a [u8; BLAKE2B_PARAM_LEN], + salt: &'a [u8; BLAKE2B_PARAM_LEN], } impl Blake2bBuilder<'_, 0, OUT_LEN> { @@ -55,8 +69,8 @@ impl Blake2bBuilder<'_, 0, OUT_LEN> { Ok(Self { key: &[], - personal: &[0; 16], - salt: &[0; 16], + personal: &[0; BLAKE2B_PARAM_LEN], + salt: &[0; BLAKE2B_PARAM_LEN], }) } } @@ -73,8 +87,8 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, } Ok(Self { key: &[0; KEY_LEN], - personal: &[0; 16], - salt: &[0; 16], + personal: &[0; BLAKE2B_PARAM_LEN], + salt: &[0; BLAKE2B_PARAM_LEN], }) } @@ -84,12 +98,12 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, } /// Sets the personalization bytes to be used in the hasher. - pub fn with_personalization(self, personal: &'a [u8; 16]) -> Self { + pub fn with_personalization(self, personal: &'a [u8; BLAKE2B_PARAM_LEN]) -> Self { Self { personal, ..self } } /// Sets the salt to be used in the hasher. - pub fn with_salt(self, salt: &'a [u8; 16]) -> Self { + pub fn with_salt(self, salt: &'a [u8; BLAKE2B_PARAM_LEN]) -> Self { Self { salt, ..self } } @@ -129,14 +143,111 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, }; Blake2b { - state: malloc_raw(kk, key), + state: blake2b_malloc_raw(kk, key), + } + } +} + +/// A builder for [`Blake2s`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the +/// range `1..=64`. +pub struct Blake2sBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { + key: &'a [u8; KEY_LEN], + personal: &'a [u8; BLAKE2S_PARAM_LEN], + salt: &'a [u8; BLAKE2S_PARAM_LEN], +} + +impl Blake2sBuilder<'_, 0, OUT_LEN> { + /// Creates the builder for an unkeyed hasher and returns an error if the digest length + /// `OUT_LEN` is not in the allowed range. + pub fn new_unkeyed() -> Result { + if OUT_LEN < 1 || OUT_LEN > 64 { + return Err(Error::InvalidDigestLength); + } + + Ok(Self { + key: &[], + personal: &[0; BLAKE2S_PARAM_LEN], + salt: &[0; BLAKE2S_PARAM_LEN], + }) + } +} +impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2sBuilder<'a, KEY_LEN, OUT_LEN> { + /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in + /// the allowed range. + pub fn new() -> Result { + if KEY_LEN > 64 { + return Err(Error::InvalidKeyLength); + } + + if OUT_LEN < 1 || OUT_LEN > 64 { + return Err(Error::InvalidDigestLength); + } + Ok(Self { + key: &[0; KEY_LEN], + personal: &[0; BLAKE2S_PARAM_LEN], + salt: &[0; BLAKE2S_PARAM_LEN], + }) + } + + /// Sets the key to be used in the hasher. + pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { + Self { key, ..self } + } + + /// Sets the personalization bytes to be used in the hasher. + pub fn with_personalization(self, personal: &'a [u8; BLAKE2S_PARAM_LEN]) -> Self { + Self { personal, ..self } + } + + /// Sets the salt to be used in the hasher. + pub fn with_salt(self, salt: &'a [u8; BLAKE2S_PARAM_LEN]) -> Self { + Self { salt, ..self } + } + + /// Constructs the [`Blake2s`] hasher. + pub fn build(self) -> Blake2s { + // these are safe because they bot are at most 64 + let key_length = KEY_LEN as u8; + let digest_length = OUT_LEN as u8; + + // NOTE: I am not entirely sure that this is the correct value. From reading the spec I + // think it should be `true`, but when comparing with other implementations I only get the + // same values when using `false`. + let last_node = false; + + let kk = index { + key_length, + digest_length, + last_node, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Blake2s { + state: blake2s_malloc_raw(kk, key), } } } /// A hasher struct for the Blake2b (optionally keyed) hash function. pub struct Blake2b { - state: Box<[crate::hacl::hash_blake2b::state_t]>, + state: Box<[blake2b_state_t]>, } impl Blake2b { @@ -146,7 +257,7 @@ impl Blake2b { return Err(Error::InvalidChunkLength); } - match update0(self.state.as_mut(), chunk, chunk.len() as u32) { + match blake2b_update0(self.state.as_mut(), chunk, chunk.len() as u32) { error_code::Success => Ok(()), error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), _ => Err(Error::Unexpected), @@ -155,19 +266,56 @@ impl Blake2b { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { - digest(&self.state, dst); + blake2b_digest(&self.state, dst); } /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { - reset_with_key(&mut self.state, key); + blake2b_reset_with_key(&mut self.state, key); } } impl Blake2b<0, OUT_LEN> { /// Reset the hash state. pub fn reset(&mut self) { - reset(&mut self.state) + blake2b_reset(&mut self.state) + } +} + +/// A hasher struct for the Blake2s (optionally keyed) hash function. +pub struct Blake2s { + state: Box<[blake2s_state_t]>, +} + +impl Blake2s { + /// Updates the hash state by adding the bytes from `chunk` to the hashed data. + pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { + if chunk.len() > (u32::MAX as usize) { + return Err(Error::InvalidChunkLength); + } + + match blake2s_update0(self.state.as_mut(), chunk, chunk.len() as u32) { + error_code::Success => Ok(()), + error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), + _ => Err(Error::Unexpected), + } + } + + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + blake2s_digest(&self.state, dst); + } + + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + blake2s_reset_with_key(&mut self.state, key); + } +} + +impl Blake2s<0, OUT_LEN> { + /// Reset the hash state. + pub fn reset(&mut self) { + blake2s_reset(&mut self.state) } } From 9ee4d196a726ea0032dbcb9da6706fada45e83fa Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 16 Jan 2025 16:31:07 +0100 Subject: [PATCH 03/11] fix blake2s constants --- blake2/src/impl_hacl.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/blake2/src/impl_hacl.rs b/blake2/src/impl_hacl.rs index c0b114cb6..5f8e6d98a 100644 --- a/blake2/src/impl_hacl.rs +++ b/blake2/src/impl_hacl.rs @@ -20,6 +20,9 @@ use libcrux_hacl_rs::streaming_types::error_code; const BLAKE2B_PARAM_LEN: usize = 16; const BLAKE2S_PARAM_LEN: usize = 8; +const BLAKE2B_MAX_LEN: usize = 64; +const BLAKE2S_MAX_LEN: usize = 32; + /// Indicates an error has occurred #[derive(Debug)] pub enum Error { @@ -63,7 +66,7 @@ impl Blake2bBuilder<'_, 0, OUT_LEN> { /// Creates the builder for an unkeyed hasher and returns an error if the digest length /// `OUT_LEN` is not in the allowed range. pub fn new_unkeyed() -> Result { - if OUT_LEN < 1 || OUT_LEN > 64 { + if OUT_LEN < 1 || OUT_LEN > BLAKE2B_MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -78,11 +81,11 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in /// the allowed range. pub fn new() -> Result { - if KEY_LEN > 64 { + if KEY_LEN > BLAKE2B_MAX_LEN { return Err(Error::InvalidKeyLength); } - if OUT_LEN < 1 || OUT_LEN > 64 { + if OUT_LEN < 1 || OUT_LEN > BLAKE2B_MAX_LEN { return Err(Error::InvalidDigestLength); } Ok(Self { @@ -175,11 +178,11 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2sBuilder<'a, KEY_LEN, /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in /// the allowed range. pub fn new() -> Result { - if KEY_LEN > 64 { + if KEY_LEN > BLAKE2S_MAX_LEN { return Err(Error::InvalidKeyLength); } - if OUT_LEN < 1 || OUT_LEN > 64 { + if OUT_LEN < 1 || OUT_LEN > BLAKE2S_MAX_LEN { return Err(Error::InvalidDigestLength); } Ok(Self { @@ -206,7 +209,7 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2sBuilder<'a, KEY_LEN, /// Constructs the [`Blake2s`] hasher. pub fn build(self) -> Blake2s { - // these are safe because they bot are at most 64 + // these are safe because they bot are at most 32 let key_length = KEY_LEN as u8; let digest_length = OUT_LEN as u8; From 15ea6805a3a14c5bd04745a76cab89b98a41c0c0 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 16 Jan 2025 16:36:11 +0100 Subject: [PATCH 04/11] reduce visibility of hacl modules --- blake2/src/lib.rs | 8 ++++---- ed25519/src/lib.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blake2/src/lib.rs b/blake2/src/lib.rs index 114526c40..946bfcbc8 100644 --- a/blake2/src/lib.rs +++ b/blake2/src/lib.rs @@ -1,11 +1,11 @@ //#![no_std] -pub mod hacl { +mod hacl { //! This module contains generated hacl code. - pub mod hash_blake2b; - pub mod hash_blake2s; - pub mod impl_blake2_constants; + pub(crate) mod hash_blake2b; + pub(crate) mod hash_blake2s; + pub(crate) mod impl_blake2_constants; } mod impl_hacl; diff --git a/ed25519/src/lib.rs b/ed25519/src/lib.rs index 706bde8a0..bcdc79d8a 100644 --- a/ed25519/src/lib.rs +++ b/ed25519/src/lib.rs @@ -1,10 +1,10 @@ #![no_std] -pub mod hacl { +mod hacl { //! This module contains generated hacl code. - pub mod ed25519; - pub mod ed25519_precomptable; + pub(crate) mod ed25519; + pub(crate) mod ed25519_precomptable; } mod impl_hacl; From 8a88614f81dcbf3fa6640278afa2435a5327bb8d Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 16 Jan 2025 16:51:17 +0100 Subject: [PATCH 05/11] add tests --- blake2/src/impl_hacl.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/blake2/src/impl_hacl.rs b/blake2/src/impl_hacl.rs index 5f8e6d98a..70f8160d2 100644 --- a/blake2/src/impl_hacl.rs +++ b/blake2/src/impl_hacl.rs @@ -324,10 +324,12 @@ impl Blake2s<0, OUT_LEN> { #[cfg(test)] mod test { + use crate::{Blake2s, Blake2sBuilder}; + use super::{Blake2b, Blake2bBuilder}; #[test] - fn test_hash() { + fn test_blake2b() { let mut got_hash = [0; 32]; let mut hasher: Blake2b<0, 32> = Blake2bBuilder::new().unwrap().build(); hasher.update(b"this is a test").unwrap(); @@ -336,6 +338,14 @@ mod test { assert_eq!(&got_hash, expected_hash); + let mut got_hash = [0; 32]; + let mut hasher: Blake2b<4, 32> = Blake2bBuilder::new().unwrap().with_key(b"test").build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; + + assert_eq!(&got_hash, expected_hash); + let mut got_hash = [0; 64]; let mut hasher: Blake2b<0, 64> = Blake2bBuilder::new().unwrap().build(); hasher.update(b"this is a test").unwrap(); @@ -344,4 +354,23 @@ mod test { assert_eq!(&got_hash, expected_hash); } + + #[test] + fn test_blake2s() { + let mut got_hash = [0; 32]; + + let mut hasher: Blake2s<0, 32> = Blake2sBuilder::new().unwrap().build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; + + assert_eq!(&got_hash, expected_hash); + + let mut hasher: Blake2s<4, 32> = Blake2sBuilder::new().unwrap().with_key(b"test").build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; + + assert_eq!(&got_hash, expected_hash); + } } From 88fbe4ea2939d19b9cc7df193f26d7e2b4462fe6 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Tue, 21 Jan 2025 17:50:11 +0100 Subject: [PATCH 06/11] restructure blake2, add support for both static and dynamic sizes for blake2s --- blake2/src/impl_hacl.rs | 376 -------------------------- blake2/src/impl_hacl/blake2b.rs | 145 ++++++++++ blake2/src/impl_hacl/blake2s.rs | 464 ++++++++++++++++++++++++++++++++ blake2/src/impl_hacl/error.rs | 32 +++ blake2/src/impl_hacl/mod.rs | 151 +++++++++++ 5 files changed, 792 insertions(+), 376 deletions(-) delete mode 100644 blake2/src/impl_hacl.rs create mode 100644 blake2/src/impl_hacl/blake2b.rs create mode 100644 blake2/src/impl_hacl/blake2s.rs create mode 100644 blake2/src/impl_hacl/error.rs create mode 100644 blake2/src/impl_hacl/mod.rs diff --git a/blake2/src/impl_hacl.rs b/blake2/src/impl_hacl.rs deleted file mode 100644 index 70f8160d2..000000000 --- a/blake2/src/impl_hacl.rs +++ /dev/null @@ -1,376 +0,0 @@ -use crate::hacl::hash_blake2b::{blake2_params, index, params_and_key}; - -use crate::hacl::hash_blake2b::{ - digest as blake2b_digest, malloc_raw as blake2b_malloc_raw, reset as blake2b_reset, - reset_with_key as blake2b_reset_with_key, state_t as blake2b_state_t, - update0 as blake2b_update0, -}; - -use crate::hacl::hash_blake2s::{ - digest as blake2s_digest, malloc_raw as blake2s_malloc_raw, reset as blake2s_reset, - reset_with_key as blake2s_reset_with_key, state_t as blake2s_state_t, - update0 as blake2s_update0, -}; - -extern crate alloc; - -use alloc::boxed::Box; -use libcrux_hacl_rs::streaming_types::error_code; - -const BLAKE2B_PARAM_LEN: usize = 16; -const BLAKE2S_PARAM_LEN: usize = 8; - -const BLAKE2B_MAX_LEN: usize = 64; -const BLAKE2S_MAX_LEN: usize = 32; - -/// Indicates an error has occurred -#[derive(Debug)] -pub enum Error { - /// The used key length is invalid. - InvalidKeyLength, - /// The used digest length is invalid. - InvalidDigestLength, - ///The maximum input length is exceeded. - MaximumLengthExceeded, - /// The maximum chunk length is exceeded. - InvalidChunkLength, - /// An unexpected error has occurred. - Unexpected, -} - -impl alloc::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let text = match self { - Error::InvalidKeyLength => "The used key length is invalid.", - Error::InvalidDigestLength => "The used digest length is invalid.", - Error::MaximumLengthExceeded => "The maximum input length is exceeded.", - Error::InvalidChunkLength => "The maximum chunk length is exceeded.", - Error::Unexpected => "An unexpected error has occurred.", - }; - - write!(f, "{text}") - } -} - -impl core::error::Error for Error {} - -/// A builder for [`Blake2b`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the -/// range `1..=64`. -pub struct Blake2bBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { - key: &'a [u8; KEY_LEN], - personal: &'a [u8; BLAKE2B_PARAM_LEN], - salt: &'a [u8; BLAKE2B_PARAM_LEN], -} - -impl Blake2bBuilder<'_, 0, OUT_LEN> { - /// Creates the builder for an unkeyed hasher and returns an error if the digest length - /// `OUT_LEN` is not in the allowed range. - pub fn new_unkeyed() -> Result { - if OUT_LEN < 1 || OUT_LEN > BLAKE2B_MAX_LEN { - return Err(Error::InvalidDigestLength); - } - - Ok(Self { - key: &[], - personal: &[0; BLAKE2B_PARAM_LEN], - salt: &[0; BLAKE2B_PARAM_LEN], - }) - } -} -impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, OUT_LEN> { - /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in - /// the allowed range. - pub fn new() -> Result { - if KEY_LEN > BLAKE2B_MAX_LEN { - return Err(Error::InvalidKeyLength); - } - - if OUT_LEN < 1 || OUT_LEN > BLAKE2B_MAX_LEN { - return Err(Error::InvalidDigestLength); - } - Ok(Self { - key: &[0; KEY_LEN], - personal: &[0; BLAKE2B_PARAM_LEN], - salt: &[0; BLAKE2B_PARAM_LEN], - }) - } - - /// Sets the key to be used in the hasher. - pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { - Self { key, ..self } - } - - /// Sets the personalization bytes to be used in the hasher. - pub fn with_personalization(self, personal: &'a [u8; BLAKE2B_PARAM_LEN]) -> Self { - Self { personal, ..self } - } - - /// Sets the salt to be used in the hasher. - pub fn with_salt(self, salt: &'a [u8; BLAKE2B_PARAM_LEN]) -> Self { - Self { salt, ..self } - } - - /// Constructs the [`Blake2b`] hasher. - pub fn build(self) -> Blake2b { - // these are safe because they bot are at most 64 - let key_length = KEY_LEN as u8; - let digest_length = OUT_LEN as u8; - - // NOTE: I am not entirely sure that this is the correct value. From reading the spec I - // think it should be `true`, but when comparing with other implementations I only get the - // same values when using `false`. - let last_node = false; - - let kk = index { - key_length, - digest_length, - last_node, - }; - - let params = blake2_params { - digest_length, - key_length, - fanout: 1, - depth: 1, - leaf_length: 0, - node_offset: 0, - node_depth: 0, - inner_length: 0, - salt: self.salt, - personal: self.personal, - }; - - let key = params_and_key { - fst: &[params], - snd: self.key, - }; - - Blake2b { - state: blake2b_malloc_raw(kk, key), - } - } -} - -/// A builder for [`Blake2s`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the -/// range `1..=64`. -pub struct Blake2sBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { - key: &'a [u8; KEY_LEN], - personal: &'a [u8; BLAKE2S_PARAM_LEN], - salt: &'a [u8; BLAKE2S_PARAM_LEN], -} - -impl Blake2sBuilder<'_, 0, OUT_LEN> { - /// Creates the builder for an unkeyed hasher and returns an error if the digest length - /// `OUT_LEN` is not in the allowed range. - pub fn new_unkeyed() -> Result { - if OUT_LEN < 1 || OUT_LEN > 64 { - return Err(Error::InvalidDigestLength); - } - - Ok(Self { - key: &[], - personal: &[0; BLAKE2S_PARAM_LEN], - salt: &[0; BLAKE2S_PARAM_LEN], - }) - } -} -impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2sBuilder<'a, KEY_LEN, OUT_LEN> { - /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in - /// the allowed range. - pub fn new() -> Result { - if KEY_LEN > BLAKE2S_MAX_LEN { - return Err(Error::InvalidKeyLength); - } - - if OUT_LEN < 1 || OUT_LEN > BLAKE2S_MAX_LEN { - return Err(Error::InvalidDigestLength); - } - Ok(Self { - key: &[0; KEY_LEN], - personal: &[0; BLAKE2S_PARAM_LEN], - salt: &[0; BLAKE2S_PARAM_LEN], - }) - } - - /// Sets the key to be used in the hasher. - pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { - Self { key, ..self } - } - - /// Sets the personalization bytes to be used in the hasher. - pub fn with_personalization(self, personal: &'a [u8; BLAKE2S_PARAM_LEN]) -> Self { - Self { personal, ..self } - } - - /// Sets the salt to be used in the hasher. - pub fn with_salt(self, salt: &'a [u8; BLAKE2S_PARAM_LEN]) -> Self { - Self { salt, ..self } - } - - /// Constructs the [`Blake2s`] hasher. - pub fn build(self) -> Blake2s { - // these are safe because they bot are at most 32 - let key_length = KEY_LEN as u8; - let digest_length = OUT_LEN as u8; - - // NOTE: I am not entirely sure that this is the correct value. From reading the spec I - // think it should be `true`, but when comparing with other implementations I only get the - // same values when using `false`. - let last_node = false; - - let kk = index { - key_length, - digest_length, - last_node, - }; - - let params = blake2_params { - digest_length, - key_length, - fanout: 1, - depth: 1, - leaf_length: 0, - node_offset: 0, - node_depth: 0, - inner_length: 0, - salt: self.salt, - personal: self.personal, - }; - - let key = params_and_key { - fst: &[params], - snd: self.key, - }; - - Blake2s { - state: blake2s_malloc_raw(kk, key), - } - } -} - -/// A hasher struct for the Blake2b (optionally keyed) hash function. -pub struct Blake2b { - state: Box<[blake2b_state_t]>, -} - -impl Blake2b { - /// Updates the hash state by adding the bytes from `chunk` to the hashed data. - pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { - if chunk.len() > (u32::MAX as usize) { - return Err(Error::InvalidChunkLength); - } - - match blake2b_update0(self.state.as_mut(), chunk, chunk.len() as u32) { - error_code::Success => Ok(()), - error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), - _ => Err(Error::Unexpected), - } - } - - /// Compute the hash for the current hash state and write it to `dst`. - pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { - blake2b_digest(&self.state, dst); - } - - /// Reset the hash state and update the key to the contents of `key`. - pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { - blake2b_reset_with_key(&mut self.state, key); - } -} - -impl Blake2b<0, OUT_LEN> { - /// Reset the hash state. - pub fn reset(&mut self) { - blake2b_reset(&mut self.state) - } -} - -/// A hasher struct for the Blake2s (optionally keyed) hash function. -pub struct Blake2s { - state: Box<[blake2s_state_t]>, -} - -impl Blake2s { - /// Updates the hash state by adding the bytes from `chunk` to the hashed data. - pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { - if chunk.len() > (u32::MAX as usize) { - return Err(Error::InvalidChunkLength); - } - - match blake2s_update0(self.state.as_mut(), chunk, chunk.len() as u32) { - error_code::Success => Ok(()), - error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), - _ => Err(Error::Unexpected), - } - } - - /// Compute the hash for the current hash state and write it to `dst`. - pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { - blake2s_digest(&self.state, dst); - } - - /// Reset the hash state and update the key to the contents of `key`. - pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { - blake2s_reset_with_key(&mut self.state, key); - } -} - -impl Blake2s<0, OUT_LEN> { - /// Reset the hash state. - pub fn reset(&mut self) { - blake2s_reset(&mut self.state) - } -} - -#[cfg(test)] -mod test { - use crate::{Blake2s, Blake2sBuilder}; - - use super::{Blake2b, Blake2bBuilder}; - - #[test] - fn test_blake2b() { - let mut got_hash = [0; 32]; - let mut hasher: Blake2b<0, 32> = Blake2bBuilder::new().unwrap().build(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; - - assert_eq!(&got_hash, expected_hash); - - let mut got_hash = [0; 32]; - let mut hasher: Blake2b<4, 32> = Blake2bBuilder::new().unwrap().with_key(b"test").build(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; - - assert_eq!(&got_hash, expected_hash); - - let mut got_hash = [0; 64]; - let mut hasher: Blake2b<0, 64> = Blake2bBuilder::new().unwrap().build(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; - - assert_eq!(&got_hash, expected_hash); - } - - #[test] - fn test_blake2s() { - let mut got_hash = [0; 32]; - - let mut hasher: Blake2s<0, 32> = Blake2sBuilder::new().unwrap().build(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; - - assert_eq!(&got_hash, expected_hash); - - let mut hasher: Blake2s<4, 32> = Blake2sBuilder::new().unwrap().with_key(b"test").build(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; - - assert_eq!(&got_hash, expected_hash); - } -} diff --git a/blake2/src/impl_hacl/blake2b.rs b/blake2/src/impl_hacl/blake2b.rs new file mode 100644 index 000000000..0796926ca --- /dev/null +++ b/blake2/src/impl_hacl/blake2b.rs @@ -0,0 +1,145 @@ +use libcrux_hacl_rs::streaming_types::error_code; + +use crate::hacl::hash_blake2b::{ + blake2_params, digest, index, malloc_raw, params_and_key, reset, reset_with_key, state_t, + update0, +}; + +use crate::impl_hacl::Error; + +const PARAM_LEN: usize = 16; +const MAX_LEN: usize = 64; + +/// A builder for [`Blake2b`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the +/// range `1..=64`. +pub struct Blake2bBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { + key: &'a [u8; KEY_LEN], + personal: &'a [u8; PARAM_LEN], + salt: &'a [u8; PARAM_LEN], +} + +impl Blake2bBuilder<'_, 0, OUT_LEN> { + /// Creates the builder for an unkeyed hasher and returns an error if the digest length + /// `OUT_LEN` is not in the allowed range. + pub fn new_unkeyed() -> Result { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + Ok(Self { + key: &[], + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } +} +impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, OUT_LEN> { + /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in + /// the allowed range. + pub fn new() -> Result { + if KEY_LEN > MAX_LEN { + return Err(Error::InvalidKeyLength); + } + + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + Ok(Self { + key: &[0; KEY_LEN], + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } + + /// Sets the key to be used in the hasher. + pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { + Self { key, ..self } + } + + /// Sets the personalization bytes to be used in the hasher. + pub fn with_personalization(self, personal: &'a [u8; PARAM_LEN]) -> Self { + Self { personal, ..self } + } + + /// Sets the salt to be used in the hasher. + pub fn with_salt(self, salt: &'a [u8; PARAM_LEN]) -> Self { + Self { salt, ..self } + } + + /// Constructs the [`Blake2b`] hasher. + pub fn build(self) -> Blake2b { + // these are safe because they bot are at most 64 + let key_length = KEY_LEN as u8; + let digest_length = OUT_LEN as u8; + + // NOTE: I am not entirely sure that this is the correct value. From reading the spec I + // think it should be `true`, but when comparing with other implementations I only get the + // same values when using `false`. + let last_node = false; + + let kk = index { + key_length, + digest_length, + last_node, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Blake2b { + state: malloc_raw(kk, key), + } + } +} + +/// A hasher struct for the Blake2b (optionally keyed) hash function. +pub struct Blake2b { + state: Box<[state_t]>, +} + +impl Blake2b { + /// Updates the hash state by adding the bytes from `chunk` to the hashed data. + pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { + if chunk.len() > (u32::MAX as usize) { + return Err(Error::InvalidChunkLength); + } + + match update0(self.state.as_mut(), chunk, chunk.len() as u32) { + error_code::Success => Ok(()), + error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), + _ => Err(Error::Unexpected), + } + } + + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + digest(&self.state, dst); + } + + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + reset_with_key(&mut self.state, key); + } +} + +impl Blake2b<0, OUT_LEN> { + /// Reset the hash state. + pub fn reset(&mut self) { + reset(&mut self.state) + } +} diff --git a/blake2/src/impl_hacl/blake2s.rs b/blake2/src/impl_hacl/blake2s.rs new file mode 100644 index 000000000..5e83172e1 --- /dev/null +++ b/blake2/src/impl_hacl/blake2s.rs @@ -0,0 +1,464 @@ +use std::marker::PhantomData; + +use crate::hacl::hash_blake2b::{blake2_params, index, params_and_key}; +use crate::hacl::hash_blake2s::{digest, malloc_raw, reset, reset_with_key, state_t, update0}; + +const PARAM_LEN: usize = 8; +const MAX_LEN: usize = 32; + +use super::*; + +/// A builder for [`Blake2s`]. `KEY_LEN`` must be in the range `0..=x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9``, `OUT_LEN`` must be in the +/// range `1..=32`. +pub struct Blake2sBuilder<'a, T> { + key: T, + personal: &'a [u8; PARAM_LEN], + salt: &'a [u8; PARAM_LEN], +} + +impl<'a> Blake2sBuilder<'a, &'a ()> { + /// Creates the builder for an unkeyed hasher. + pub fn new_unkeyed() -> Result { + Ok(Self { + key: &(), + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } + + /// Constructs the [`Blake2sK`] hasher. + pub fn build(self, digest_length: u8) -> Result>, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + let key_length = 0; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: &[], + }; + + Ok(Blake2s { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } + + /// Constructs the [`Blake2s`] hasher. + pub fn build_static( + self, + ) -> Result>, Error> { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + let key_length = 0; + + // This is safe because it's at most 32, enforced at the start of the function. + let digest_length = OUT_LEN as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: &[], + }; + + Ok(Blake2s { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } +} + +impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { + /// Creates the builder for an keyed hasher for keys where the length is known at compile + /// time. + pub fn new_keyed_static(key: &'a [u8; KEY_LEN]) -> Result { + if KEY_LEN > MAX_LEN { + return Err(Error::InvalidKeyLength); + } + + Ok(Self { + key, + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } + + /// Constructs the [`Blake2sK`] hasher. + pub fn build(self, digest_length: u8) -> Result, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // This is safe because it's at most 32, enforced in the constructor. + let key_length = KEY_LEN as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2s:: { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } + + /// Constructs the [`Blake2s`] hasher. + pub fn build_static( + self, + ) -> Result>, Error> { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // These are safe because they both are at most 32, enforced either above or in the + // constructor. + let key_length = KEY_LEN as u8; + let digest_length = OUT_LEN as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2s::> { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } +} + +impl<'a> Blake2sBuilder<'a, &'a [u8]> { + /// Creates the builder for an keyed hasher for keys where the length is not known at compile + /// time. + pub fn new_keyed_dynamic(key: &'a [u8]) -> Result { + if key.len() > MAX_LEN { + return Err(Error::InvalidKeyLength); + } + + Ok(Self { + key, + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } + + /// Constructs the [`Blake2sK`] hasher. + pub fn build(self, digest_length: u8) -> Result, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // This is safe because it's at most 32, enforced in the constructor. + let key_length = self.key.len() as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2s { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } + + /// Constructs the [`Blake2s`] hasher. + pub fn build_static( + self, + ) -> Result>, Error> { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // these are safe because they both are at most 32 + let key_length = self.key.len() as u8; + let digest_length = OUT_LEN as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2s { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } +} + +impl<'a, T> Blake2sBuilder<'a, T> { + /// Sets the personalization bytes to be used in the hasher. + pub fn with_personalization(self, personal: &'a [u8; PARAM_LEN]) -> Self { + Self { personal, ..self } + } + + /// Sets the salt to be used in the hasher. + pub fn with_salt(self, salt: &'a [u8; PARAM_LEN]) -> Self { + Self { salt, ..self } + } +} + +pub struct Blake2sStaticKeyStaticOut; +pub struct Blake2sStaticKey; +pub struct Blake2sStaticOut; +pub struct Blake2sDynamic; + +/// A hasher struct for the Blake2s (optionally keyed) hash function. +pub struct Blake2s { + state: Box<[state_t]>, + _phantom: PhantomData, +} + +impl Blake2s { + /// Updates the hash state by adding the bytes from `chunk` to the hashed data. + pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { + if chunk.len() > (u32::MAX as usize) { + return Err(Error::InvalidChunkLength); + } + + match update0(self.state.as_mut(), chunk, chunk.len() as u32) { + error_code::Success => Ok(()), + error_code::MaximumLengthExceeded => Err(Error::MaximumLengthExceeded), + _ => Err(Error::Unexpected), + } + } +} + +impl Blake2s> { + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8]) -> Result { + let digest_len = self.state[0].block_state.snd; + if dst.len() < digest_len as usize { + return Err(Error::InvalidDigestLength); + } + + Ok(digest(&self.state, dst) as usize) + } +} + +impl Blake2s { + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8]) -> Result { + let digest_len = self.state[0].block_state.snd; + if dst.len() < digest_len as usize { + return Err(Error::InvalidDigestLength); + } + + Ok(digest(&self.state, dst) as usize) + } +} + +impl + Blake2s> +{ + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + digest(&self.state, dst); + } +} + +impl Blake2s> { + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + digest(&self.state, dst); + } +} + +impl + Blake2s> +{ + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + reset_with_key(&mut self.state, key); + } +} + +impl Blake2s> { + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + reset_with_key(&mut self.state, key); + } +} + +impl Blake2s> { + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst as usize != key.len() { + return Err(Error::InvalidKeyLength); + } + + reset_with_key(&mut self.state, key); + Ok(()) + } +} + +impl Blake2s { + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { + // check that the key length matches + if self.state[0].block_state.fst as usize != key.len() { + return Err(Error::InvalidKeyLength); + } + + reset_with_key(&mut self.state, key); + Ok(()) + } +} + +impl Blake2s> { + /// Reset the hash state. + pub fn reset(&mut self) { + reset(&mut self.state) + } +} + +impl Blake2s> { + /// Reset the hash state. + pub fn reset(&mut self) { + reset(&mut self.state) + } +} + +impl Blake2s> { + /// Reset the hash state. + pub fn reset(&mut self) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst != 0 { + return Err(Error::InvalidKeyLength); + } + + reset(&mut self.state); + Ok(()) + } +} + +impl Blake2s { + /// Reset the hash state. + pub fn reset(&mut self) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst != 0 { + return Err(Error::InvalidKeyLength); + } + + reset(&mut self.state); + Ok(()) + } +} diff --git a/blake2/src/impl_hacl/error.rs b/blake2/src/impl_hacl/error.rs new file mode 100644 index 000000000..46f0863dd --- /dev/null +++ b/blake2/src/impl_hacl/error.rs @@ -0,0 +1,32 @@ +extern crate alloc; + +/// Indicates an error has occurred +#[derive(Debug)] +pub enum Error { + /// The used key length is invalid. + InvalidKeyLength, + /// The used digest length is invalid. + InvalidDigestLength, + ///The maximum input length is exceeded. + MaximumLengthExceeded, + /// The maximum chunk length is exceeded. + InvalidChunkLength, + /// An unexpected error has occurred. + Unexpected, +} + +impl alloc::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let text = match self { + Error::InvalidKeyLength => "The used key length is invalid.", + Error::InvalidDigestLength => "The used digest length is invalid.", + Error::MaximumLengthExceeded => "The maximum input length is exceeded.", + Error::InvalidChunkLength => "The maximum chunk length is exceeded.", + Error::Unexpected => "An unexpected error has occurred.", + }; + + write!(f, "{text}") + } +} + +impl core::error::Error for Error {} diff --git a/blake2/src/impl_hacl/mod.rs b/blake2/src/impl_hacl/mod.rs new file mode 100644 index 000000000..4aa39e7f0 --- /dev/null +++ b/blake2/src/impl_hacl/mod.rs @@ -0,0 +1,151 @@ +extern crate alloc; + +use alloc::boxed::Box; +use libcrux_hacl_rs::streaming_types::error_code; + +mod blake2b; +mod blake2s; +mod error; + +pub use blake2b::{Blake2b, Blake2bBuilder}; +pub use blake2s::{Blake2s, Blake2sBuilder}; +pub use error::Error; + +#[cfg(test)] +mod test { + use crate::{Blake2s, Blake2sBuilder}; + + use super::{Blake2b, Blake2bBuilder}; + + #[test] + fn test_blake2b() { + let mut got_hash = [0; 32]; + let mut hasher: Blake2b<0, 32> = Blake2bBuilder::new().unwrap().build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; + + assert_eq!(&got_hash, expected_hash); + + let mut got_hash = [0; 32]; + let mut hasher: Blake2b<4, 32> = Blake2bBuilder::new().unwrap().with_key(b"test").build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; + + assert_eq!(&got_hash, expected_hash); + + let mut got_hash = [0; 64]; + let mut hasher: Blake2b<0, 64> = Blake2bBuilder::new().unwrap().build(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; + + assert_eq!(&got_hash, expected_hash); + } + + #[test] + fn test_blake2s() { + let mut got_hash = [0; 32]; + + // test unkeyed, with static key and digest len + let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; + let mut hasher: Blake2s<_> = Blake2sBuilder::new_unkeyed() + .unwrap() + .build_static() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test unkeyed, with static key len and dynamic digest len + let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; + let mut hasher: Blake2s<_> = Blake2sBuilder::new_unkeyed().unwrap().build(32).unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with static key and digest len + let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; + let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_static(b"test") + .unwrap() + .build_static() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with static key len and dynamic digest len + let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_static(b"test") + .unwrap() + .build(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + + // test keyed, with dynamic key len and static digest len + let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_static() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with dynamic key digest len + let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + } +} From cf942d33416b4167cc794d5444436ea85ce8f825 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Wed, 22 Jan 2025 09:27:04 +0100 Subject: [PATCH 07/11] fix and improve comments --- blake2/src/impl_hacl/blake2s.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/blake2/src/impl_hacl/blake2s.rs b/blake2/src/impl_hacl/blake2s.rs index 5e83172e1..2d017b022 100644 --- a/blake2/src/impl_hacl/blake2s.rs +++ b/blake2/src/impl_hacl/blake2s.rs @@ -26,7 +26,7 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { }) } - /// Constructs the [`Blake2sK`] hasher. + /// Constructs the [`Blake2s`] hasher for unkeyed hashes and dynamic digest length. pub fn build(self, digest_length: u8) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); @@ -64,7 +64,7 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { }) } - /// Constructs the [`Blake2s`] hasher. + /// Constructs the [`Blake2s`] hasher for unkeyed hashes and static digest length. pub fn build_static( self, ) -> Result>, Error> { @@ -123,8 +123,8 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { }) } - /// Constructs the [`Blake2sK`] hasher. - pub fn build(self, digest_length: u8) -> Result, Error> { + /// Constructs the [`Blake2s`] hasher for hashes with static key length and dynamic digest length. + pub fn build(self, digest_length: u8) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -162,7 +162,7 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { }) } - /// Constructs the [`Blake2s`] hasher. + /// Constructs the [`Blake2s`] hasher for hashes with static key length and static digest length. pub fn build_static( self, ) -> Result>, Error> { @@ -221,7 +221,7 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { }) } - /// Constructs the [`Blake2sK`] hasher. + /// Constructs the fully dynamic [`Blake2s`] hasher. pub fn build(self, digest_length: u8) -> Result, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); @@ -260,7 +260,7 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { }) } - /// Constructs the [`Blake2s`] hasher. + /// Constructs the [`Blake2s`] hasher with dynamic key length and static digest length. pub fn build_static( self, ) -> Result>, Error> { From 14f43725ba8e17310941c469608dae4fbba68245 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Wed, 22 Jan 2025 13:02:56 +0100 Subject: [PATCH 08/11] update Blake2b to new pattern and apply fixes --- blake2/src/impl_hacl/blake2b.rs | 416 ++++++++++++++++++++++++++++---- blake2/src/impl_hacl/blake2s.rs | 85 ++++--- blake2/src/impl_hacl/error.rs | 2 +- blake2/src/impl_hacl/mod.rs | 146 +++++++++-- blake2/src/lib.rs | 4 +- 5 files changed, 543 insertions(+), 110 deletions(-) diff --git a/blake2/src/impl_hacl/blake2b.rs b/blake2/src/impl_hacl/blake2b.rs index 0796926ca..89fbd7f1f 100644 --- a/blake2/src/impl_hacl/blake2b.rs +++ b/blake2/src/impl_hacl/blake2b.rs @@ -1,3 +1,8 @@ +extern crate alloc; + +use alloc::boxed::Box; +use core::marker::PhantomData; + use libcrux_hacl_rs::streaming_types::error_code; use crate::hacl::hash_blake2b::{ @@ -5,82 +10,240 @@ use crate::hacl::hash_blake2b::{ update0, }; -use crate::impl_hacl::Error; +use super::{ConstsDynamic, ConstsStaticKey, ConstsStaticKeyStaticOut, ConstsStaticOut, Error}; const PARAM_LEN: usize = 16; const MAX_LEN: usize = 64; -/// A builder for [`Blake2b`]. `KEY_LEN`` must be in the range `0..=64``, `OUT_LEN`` must be in the -/// range `1..=64`. -pub struct Blake2bBuilder<'a, const KEY_LEN: usize, const OUT_LEN: usize> { - key: &'a [u8; KEY_LEN], +/// A builder for [`Blake2b`]. `T` determines whether +pub struct Blake2bBuilder<'a, T> { + key: T, personal: &'a [u8; PARAM_LEN], salt: &'a [u8; PARAM_LEN], } -impl Blake2bBuilder<'_, 0, OUT_LEN> { - /// Creates the builder for an unkeyed hasher and returns an error if the digest length - /// `OUT_LEN` is not in the allowed range. - pub fn new_unkeyed() -> Result { +impl<'a> Blake2bBuilder<'a, &'a ()> { + /// Creates the builder for an unkeyed hasher. + pub fn new_unkeyed() -> Self { + Self { + key: &(), + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + } + } + + /// Constructs the [`Blake2b`] hasher for unkeyed hashes and dynamic digest length. + pub fn build_var_digest_len( + self, + digest_length: u8, + ) -> Result>, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + let key_length = 0; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: &[], + }; + + Ok(Blake2b { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } + + /// Constructs the [`Blake2b`] hasher for unkeyed hashes and static digest length. + pub fn build_const_digest_len( + self, + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } - Ok(Self { - key: &[], - personal: &[0; PARAM_LEN], - salt: &[0; PARAM_LEN], + let digest_length = OUT_LEN as u8; + let key_length = 0; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: &[], + }; + + Ok(Blake2b { + state: malloc_raw(kk, key), + _phantom: PhantomData, }) } } -impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, OUT_LEN> { - /// Creates the builder and returns an error if the lengths `KEY_LEN` or `OUT_LEN` are not in - /// the allowed range. - pub fn new() -> Result { + +impl<'a, const KEY_LEN: usize> Blake2bBuilder<'a, &'a [u8; KEY_LEN]> { + /// Creates the builder for an keyed hasher for keys where the length is known at compile + /// time. + pub fn new_keyed_static(key: &'a [u8; KEY_LEN]) -> Result { if KEY_LEN > MAX_LEN { return Err(Error::InvalidKeyLength); } - if OUT_LEN < 1 || OUT_LEN > MAX_LEN { - return Err(Error::InvalidDigestLength); - } Ok(Self { - key: &[0; KEY_LEN], + key, personal: &[0; PARAM_LEN], salt: &[0; PARAM_LEN], }) } - /// Sets the key to be used in the hasher. - pub fn with_key(self, key: &'a [u8; KEY_LEN]) -> Self { - Self { key, ..self } - } + /// Constructs the [`Blake2b`] hasher for hashes with static key length and dynamic digest length. + pub fn build_var_digest_len( + self, + digest_length: u8, + ) -> Result>, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } - /// Sets the personalization bytes to be used in the hasher. - pub fn with_personalization(self, personal: &'a [u8; PARAM_LEN]) -> Self { - Self { personal, ..self } - } + // This is safe because it's at most 64, enforced in the constructor. + let key_length = KEY_LEN as u8; - /// Sets the salt to be used in the hasher. - pub fn with_salt(self, salt: &'a [u8; PARAM_LEN]) -> Self { - Self { salt, ..self } + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2b::> { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) } - /// Constructs the [`Blake2b`] hasher. - pub fn build(self) -> Blake2b { - // these are safe because they bot are at most 64 + /// Constructs the [`Blake2b`] hasher for hashes with static key length and static digest length. + pub fn build_const_digest_len( + self, + ) -> Result>, Error> { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // These are safe because they both are at most 64, enforced either above or in the + // constructor. let key_length = KEY_LEN as u8; let digest_length = OUT_LEN as u8; - // NOTE: I am not entirely sure that this is the correct value. From reading the spec I - // think it should be `true`, but when comparing with other implementations I only get the - // same values when using `false`. - let last_node = false; + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2b::> { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } +} + +impl<'a> Blake2bBuilder<'a, &'a [u8]> { + /// Creates the builder for an keyed hasher for keys where the length is not known at compile + /// time. + pub fn new_keyed_dynamic(key: &'a [u8]) -> Result { + if key.len() > MAX_LEN { + return Err(Error::InvalidKeyLength); + } + + Ok(Self { + key, + personal: &[0; PARAM_LEN], + salt: &[0; PARAM_LEN], + }) + } + + /// Constructs the fully dynamic [`Blake2b`] hasher. + pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { + if digest_length < 1 || digest_length as usize > MAX_LEN { + return Err(Error::InvalidDigestLength); + } + + // This is safe because it's at most 64, enforced in the constructor. + let key_length = self.key.len() as u8; let kk = index { key_length, digest_length, - last_node, + last_node: false, }; let params = blake2_params { @@ -101,18 +264,74 @@ impl<'a, const KEY_LEN: usize, const OUT_LEN: usize> Blake2bBuilder<'a, KEY_LEN, snd: self.key, }; - Blake2b { + Ok(Blake2b { state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } + + /// Constructs the [`Blake2b`] hasher with dynamic key length and static digest length. + pub fn build_const_digest_len( + self, + ) -> Result>, Error> { + if OUT_LEN < 1 || OUT_LEN > MAX_LEN { + return Err(Error::InvalidDigestLength); } + + // these are safe because they both are at most 64 + let key_length = self.key.len() as u8; + let digest_length = OUT_LEN as u8; + + let kk = index { + key_length, + digest_length, + last_node: false, + }; + + let params = blake2_params { + digest_length, + key_length, + fanout: 1, + depth: 1, + leaf_length: 0, + node_offset: 0, + node_depth: 0, + inner_length: 0, + salt: self.salt, + personal: self.personal, + }; + + let key = params_and_key { + fst: &[params], + snd: self.key, + }; + + Ok(Blake2b { + state: malloc_raw(kk, key), + _phantom: PhantomData, + }) + } +} + +impl<'a, T> Blake2bBuilder<'a, T> { + /// Sets the personalization bytes to be used in the hasher. + pub fn with_personalization(self, personal: &'a [u8; PARAM_LEN]) -> Self { + Self { personal, ..self } + } + + /// Sets the salt to be used in the hasher. + pub fn with_salt(self, salt: &'a [u8; PARAM_LEN]) -> Self { + Self { salt, ..self } } } /// A hasher struct for the Blake2b (optionally keyed) hash function. -pub struct Blake2b { +pub struct Blake2b { state: Box<[state_t]>, + _phantom: PhantomData, } -impl Blake2b { +impl Blake2b { /// Updates the hash state by adding the bytes from `chunk` to the hashed data. pub fn update(&mut self, chunk: &[u8]) -> Result<(), Error> { if chunk.len() > (u32::MAX as usize) { @@ -125,21 +344,130 @@ impl Blake2b { _ => Err(Error::Unexpected), } } +} + +impl Blake2b> { + /// Compute the hash for the current hash state and write it to `dst`. + /// + /// Returns a `Result` that contains the length of the digest on success. + pub fn finalize(&self, dst: &mut [u8]) -> Result { + let digest_len = self.state[0].block_state.snd; + if dst.len() < digest_len as usize { + return Err(Error::InvalidDigestLength); + } + + Ok(digest(&self.state, dst) as usize) + } +} + +impl Blake2b { + /// Compute the hash for the current hash state and write it to `dst`. + /// + /// Returns a `Result` that contains the length of the digest on success. + pub fn finalize(&self, dst: &mut [u8]) -> Result { + let digest_len = self.state[0].block_state.snd; + if dst.len() < digest_len as usize { + return Err(Error::InvalidDigestLength); + } + + Ok(digest(&self.state, dst) as usize) + } +} + +impl + Blake2b> +{ + /// Compute the hash for the current hash state and write it to `dst`. + pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { + digest(&self.state, dst); + } +} +impl Blake2b> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { digest(&self.state, dst); } +} + +impl + Blake2b> +{ + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { + reset_with_key(&mut self.state, key); + } +} +impl Blake2b> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { reset_with_key(&mut self.state, key); } } -impl Blake2b<0, OUT_LEN> { +impl Blake2b> { + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst as usize != key.len() { + return Err(Error::InvalidKeyLength); + } + + reset_with_key(&mut self.state, key); + Ok(()) + } +} + +impl Blake2b { + /// Reset the hash state and update the key to the contents of `key`. + pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { + // check that the key length matches + if self.state[0].block_state.fst as usize != key.len() { + return Err(Error::InvalidKeyLength); + } + + reset_with_key(&mut self.state, key); + Ok(()) + } +} + +impl Blake2b> { + /// Reset the hash state. + pub fn reset(&mut self) { + reset(&mut self.state) + } +} + +impl Blake2b> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } + +impl Blake2b> { + /// Reset the hash state. + pub fn reset(&mut self) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst != 0 { + return Err(Error::InvalidKeyLength); + } + + reset(&mut self.state); + Ok(()) + } +} + +impl Blake2b { + /// Reset the hash state. + pub fn reset(&mut self) -> Result<(), Error> { + // check that the key length matches + if self.state.as_ref()[0].block_state.fst != 0 { + return Err(Error::InvalidKeyLength); + } + + reset(&mut self.state); + Ok(()) + } +} diff --git a/blake2/src/impl_hacl/blake2s.rs b/blake2/src/impl_hacl/blake2s.rs index 2d017b022..1b3616e8f 100644 --- a/blake2/src/impl_hacl/blake2s.rs +++ b/blake2/src/impl_hacl/blake2s.rs @@ -1,15 +1,19 @@ -use std::marker::PhantomData; +extern crate alloc; + +use alloc::boxed::Box; +use core::marker::PhantomData; + +use libcrux_hacl_rs::streaming_types::error_code; use crate::hacl::hash_blake2b::{blake2_params, index, params_and_key}; use crate::hacl::hash_blake2s::{digest, malloc_raw, reset, reset_with_key, state_t, update0}; +use super::{ConstsDynamic, ConstsStaticKey, ConstsStaticKeyStaticOut, ConstsStaticOut, Error}; + const PARAM_LEN: usize = 8; const MAX_LEN: usize = 32; -use super::*; - -/// A builder for [`Blake2s`]. `KEY_LEN`` must be in the range `0..=x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9``, `OUT_LEN`` must be in the -/// range `1..=32`. +/// A builder for [`Blake2s`]. `T` determines whether pub struct Blake2sBuilder<'a, T> { key: T, personal: &'a [u8; PARAM_LEN], @@ -18,16 +22,19 @@ pub struct Blake2sBuilder<'a, T> { impl<'a> Blake2sBuilder<'a, &'a ()> { /// Creates the builder for an unkeyed hasher. - pub fn new_unkeyed() -> Result { - Ok(Self { + pub fn new_unkeyed() -> Self { + Self { key: &(), personal: &[0; PARAM_LEN], salt: &[0; PARAM_LEN], - }) + } } /// Constructs the [`Blake2s`] hasher for unkeyed hashes and dynamic digest length. - pub fn build(self, digest_length: u8) -> Result>, Error> { + pub fn build_var_digest_len( + self, + digest_length: u8, + ) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -65,17 +72,15 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { } /// Constructs the [`Blake2s`] hasher for unkeyed hashes and static digest length. - pub fn build_static( + pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } - let key_length = 0; - - // This is safe because it's at most 32, enforced at the start of the function. let digest_length = OUT_LEN as u8; + let key_length = 0; let kk = index { key_length, @@ -124,7 +129,10 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { } /// Constructs the [`Blake2s`] hasher for hashes with static key length and dynamic digest length. - pub fn build(self, digest_length: u8) -> Result>, Error> { + pub fn build_var_digest_len( + self, + digest_length: u8, + ) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -156,16 +164,16 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2s:: { + Ok(Blake2s::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) } /// Constructs the [`Blake2s`] hasher for hashes with static key length and static digest length. - pub fn build_static( + pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -199,7 +207,7 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2s::> { + Ok(Blake2s::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) @@ -222,7 +230,7 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { } /// Constructs the fully dynamic [`Blake2s`] hasher. - pub fn build(self, digest_length: u8) -> Result, Error> { + pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -261,9 +269,9 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { } /// Constructs the [`Blake2s`] hasher with dynamic key length and static digest length. - pub fn build_static( + pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -315,11 +323,6 @@ impl<'a, T> Blake2sBuilder<'a, T> { } } -pub struct Blake2sStaticKeyStaticOut; -pub struct Blake2sStaticKey; -pub struct Blake2sStaticOut; -pub struct Blake2sDynamic; - /// A hasher struct for the Blake2s (optionally keyed) hash function. pub struct Blake2s { state: Box<[state_t]>, @@ -341,8 +344,10 @@ impl Blake2s { } } -impl Blake2s> { +impl Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. + /// + /// Returns a `Result` that contains the length of the digest on success. pub fn finalize(&self, dst: &mut [u8]) -> Result { let digest_len = self.state[0].block_state.snd; if dst.len() < digest_len as usize { @@ -353,8 +358,10 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Compute the hash for the current hash state and write it to `dst`. + /// + /// Returns a `Result` that contains the length of the digest on success. pub fn finalize(&self, dst: &mut [u8]) -> Result { let digest_len = self.state[0].block_state.snd; if dst.len() < digest_len as usize { @@ -366,7 +373,7 @@ impl Blake2s { } impl - Blake2s> + Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { @@ -374,7 +381,7 @@ impl } } -impl Blake2s> { +impl Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { digest(&self.state, dst); @@ -382,7 +389,7 @@ impl Blake2s> { } impl - Blake2s> + Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { @@ -390,14 +397,14 @@ impl } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { reset_with_key(&mut self.state, key); } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -410,7 +417,7 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -423,21 +430,21 @@ impl Blake2s { } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches @@ -450,7 +457,7 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches diff --git a/blake2/src/impl_hacl/error.rs b/blake2/src/impl_hacl/error.rs index 46f0863dd..7e095035d 100644 --- a/blake2/src/impl_hacl/error.rs +++ b/blake2/src/impl_hacl/error.rs @@ -16,7 +16,7 @@ pub enum Error { } impl alloc::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut alloc::fmt::Formatter<'_>) -> alloc::fmt::Result { let text = match self { Error::InvalidKeyLength => "The used key length is invalid.", Error::InvalidDigestLength => "The used digest length is invalid.", diff --git a/blake2/src/impl_hacl/mod.rs b/blake2/src/impl_hacl/mod.rs index 4aa39e7f0..1cb7ea87d 100644 --- a/blake2/src/impl_hacl/mod.rs +++ b/blake2/src/impl_hacl/mod.rs @@ -1,8 +1,5 @@ extern crate alloc; -use alloc::boxed::Box; -use libcrux_hacl_rs::streaming_types::error_code; - mod blake2b; mod blake2s; mod error; @@ -11,32 +8,132 @@ pub use blake2b::{Blake2b, Blake2bBuilder}; pub use blake2s::{Blake2s, Blake2sBuilder}; pub use error::Error; +/// Type that holds the constants in case both key length and digest length are known at compile +/// time. +pub struct ConstsStaticKeyStaticOut; + +/// Type that holds the constant in case just the key length is known at compile time. +pub struct ConstsStaticKey; + +/// Type that holds the constant in case just the digest length is known at compile time. +pub struct ConstsStaticOut; + +/// Type that holds the constant in case neither the key length nor the digest length is known at +/// compile time. +pub struct ConstsDynamic; + #[cfg(test)] mod test { - use crate::{Blake2s, Blake2sBuilder}; - - use super::{Blake2b, Blake2bBuilder}; + use super::{Blake2bBuilder, Blake2sBuilder}; #[test] fn test_blake2b() { let mut got_hash = [0; 32]; - let mut hasher: Blake2b<0, 32> = Blake2bBuilder::new().unwrap().build(); + + // test unkeyed, with static key and digest len + let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_const_digest_len() + .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); - let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; assert_eq!(&got_hash, expected_hash); - let mut got_hash = [0; 32]; - let mut hasher: Blake2b<4, 32> = Blake2bBuilder::new().unwrap().with_key(b"test").build(); + hasher.reset(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test unkeyed, with static key len and dynamic digest len + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with static key and digest len let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; + let mut hasher = Blake2bBuilder::new_keyed_static(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); assert_eq!(&got_hash, expected_hash); + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with static key len and dynamic digest len + let mut hasher = Blake2bBuilder::new_keyed_static(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + + // test keyed, with dynamic key len and static digest len + let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with dynamic key digest len + let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + let mut got_hash = [0; 64]; - let mut hasher: Blake2b<0, 64> = Blake2bBuilder::new().unwrap().build(); + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_const_digest_len() + .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; @@ -50,9 +147,8 @@ mod test { // test unkeyed, with static key and digest len let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; - let mut hasher: Blake2s<_> = Blake2sBuilder::new_unkeyed() - .unwrap() - .build_static() + let mut hasher = Blake2sBuilder::new_unkeyed() + .build_const_digest_len() .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); @@ -67,7 +163,9 @@ mod test { // test unkeyed, with static key len and dynamic digest len let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; - let mut hasher: Blake2s<_> = Blake2sBuilder::new_unkeyed().unwrap().build(32).unwrap(); + let mut hasher = Blake2sBuilder::new_unkeyed() + .build_var_digest_len(32) + .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash).unwrap(); @@ -81,9 +179,9 @@ mod test { // test keyed, with static key and digest len let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; - let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_static(b"test") + let mut hasher = Blake2sBuilder::new_keyed_static(b"test") .unwrap() - .build_static() + .build_const_digest_len() .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); @@ -97,9 +195,9 @@ mod test { assert_eq!(&got_hash, expected_hash); // test keyed, with static key len and dynamic digest len - let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_static(b"test") + let mut hasher = Blake2sBuilder::new_keyed_static(b"test") .unwrap() - .build(32) + .build_var_digest_len(32) .unwrap(); hasher.update(b"this is a test").unwrap(); let len = hasher.finalize(&mut got_hash).unwrap(); @@ -107,7 +205,7 @@ mod test { assert_eq!(len, 32); assert_eq!(&got_hash, expected_hash); - hasher.reset_with_key(b"test").unwrap(); + hasher.reset_with_key(b"test"); hasher.update(b"this is a test").unwrap(); let len = hasher.finalize(&mut got_hash).unwrap(); @@ -115,9 +213,9 @@ mod test { assert_eq!(len, 32); // test keyed, with dynamic key len and static digest len - let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_dynamic(b"test") + let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") .unwrap() - .build_static() + .build_const_digest_len() .unwrap(); hasher.update(b"this is a test").unwrap(); hasher.finalize(&mut got_hash); @@ -131,9 +229,9 @@ mod test { assert_eq!(&got_hash, expected_hash); // test keyed, with dynamic key digest len - let mut hasher: Blake2s<_> = Blake2sBuilder::new_keyed_dynamic(b"test") + let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") .unwrap() - .build(32) + .build_var_digest_len(32) .unwrap(); hasher.update(b"this is a test").unwrap(); let len = hasher.finalize(&mut got_hash).unwrap(); diff --git a/blake2/src/lib.rs b/blake2/src/lib.rs index 946bfcbc8..0bd2c8426 100644 --- a/blake2/src/lib.rs +++ b/blake2/src/lib.rs @@ -1,4 +1,4 @@ -//#![no_std] +#![no_std] mod hacl { //! This module contains generated hacl code. @@ -10,4 +10,4 @@ mod hacl { mod impl_hacl; -pub use impl_hacl::*; +pub use impl_hacl::{Blake2b, Blake2bBuilder, Blake2s, Blake2sBuilder, Error}; From 490d006192024f4f32884b7c4ae1a5789168c99c Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Wed, 22 Jan 2025 14:01:52 +0100 Subject: [PATCH 09/11] fmt generated code --- blake2/src/hacl/impl_blake2_constants.rs | 52 +++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/blake2/src/hacl/impl_blake2_constants.rs b/blake2/src/hacl/impl_blake2_constants.rs index 87d9e7917..55d37b611 100644 --- a/blake2/src/hacl/impl_blake2_constants.rs +++ b/blake2/src/hacl/impl_blake2_constants.rs @@ -4,24 +4,38 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] -pub(crate) const sigmaTable: [u32; 160] = - [0u32, 1u32, 2u32, 3u32, 4u32, 5u32, 6u32, 7u32, 8u32, 9u32, 10u32, 11u32, 12u32, 13u32, 14u32, - 15u32, 14u32, 10u32, 4u32, 8u32, 9u32, 15u32, 13u32, 6u32, 1u32, 12u32, 0u32, 2u32, 11u32, - 7u32, 5u32, 3u32, 11u32, 8u32, 12u32, 0u32, 5u32, 2u32, 15u32, 13u32, 10u32, 14u32, 3u32, - 6u32, 7u32, 1u32, 9u32, 4u32, 7u32, 9u32, 3u32, 1u32, 13u32, 12u32, 11u32, 14u32, 2u32, 6u32, - 5u32, 10u32, 4u32, 0u32, 15u32, 8u32, 9u32, 0u32, 5u32, 7u32, 2u32, 4u32, 10u32, 15u32, - 14u32, 1u32, 11u32, 12u32, 6u32, 8u32, 3u32, 13u32, 2u32, 12u32, 6u32, 10u32, 0u32, 11u32, - 8u32, 3u32, 4u32, 13u32, 7u32, 5u32, 15u32, 14u32, 1u32, 9u32, 12u32, 5u32, 1u32, 15u32, - 14u32, 13u32, 4u32, 10u32, 0u32, 7u32, 6u32, 3u32, 9u32, 2u32, 8u32, 11u32, 13u32, 11u32, - 7u32, 14u32, 12u32, 1u32, 3u32, 9u32, 5u32, 0u32, 15u32, 4u32, 8u32, 6u32, 2u32, 10u32, 6u32, - 15u32, 14u32, 9u32, 11u32, 3u32, 0u32, 8u32, 12u32, 2u32, 13u32, 7u32, 1u32, 4u32, 10u32, - 5u32, 10u32, 2u32, 8u32, 4u32, 7u32, 6u32, 1u32, 5u32, 15u32, 11u32, 9u32, 14u32, 3u32, - 12u32, 13u32, 0u32]; +pub(crate) const sigmaTable: [u32; 160] = [ + 0u32, 1u32, 2u32, 3u32, 4u32, 5u32, 6u32, 7u32, 8u32, 9u32, 10u32, 11u32, 12u32, 13u32, 14u32, + 15u32, 14u32, 10u32, 4u32, 8u32, 9u32, 15u32, 13u32, 6u32, 1u32, 12u32, 0u32, 2u32, 11u32, + 7u32, 5u32, 3u32, 11u32, 8u32, 12u32, 0u32, 5u32, 2u32, 15u32, 13u32, 10u32, 14u32, 3u32, 6u32, + 7u32, 1u32, 9u32, 4u32, 7u32, 9u32, 3u32, 1u32, 13u32, 12u32, 11u32, 14u32, 2u32, 6u32, 5u32, + 10u32, 4u32, 0u32, 15u32, 8u32, 9u32, 0u32, 5u32, 7u32, 2u32, 4u32, 10u32, 15u32, 14u32, 1u32, + 11u32, 12u32, 6u32, 8u32, 3u32, 13u32, 2u32, 12u32, 6u32, 10u32, 0u32, 11u32, 8u32, 3u32, 4u32, + 13u32, 7u32, 5u32, 15u32, 14u32, 1u32, 9u32, 12u32, 5u32, 1u32, 15u32, 14u32, 13u32, 4u32, + 10u32, 0u32, 7u32, 6u32, 3u32, 9u32, 2u32, 8u32, 11u32, 13u32, 11u32, 7u32, 14u32, 12u32, 1u32, + 3u32, 9u32, 5u32, 0u32, 15u32, 4u32, 8u32, 6u32, 2u32, 10u32, 6u32, 15u32, 14u32, 9u32, 11u32, + 3u32, 0u32, 8u32, 12u32, 2u32, 13u32, 7u32, 1u32, 4u32, 10u32, 5u32, 10u32, 2u32, 8u32, 4u32, + 7u32, 6u32, 1u32, 5u32, 15u32, 11u32, 9u32, 14u32, 3u32, 12u32, 13u32, 0u32, +]; -pub(crate) const ivTable_S: [u32; 8] = - [0x6A09E667u32, 0xBB67AE85u32, 0x3C6EF372u32, 0xA54FF53Au32, 0x510E527Fu32, 0x9B05688Cu32, - 0x1F83D9ABu32, 0x5BE0CD19u32]; +pub(crate) const ivTable_S: [u32; 8] = [ + 0x6A09E667u32, + 0xBB67AE85u32, + 0x3C6EF372u32, + 0xA54FF53Au32, + 0x510E527Fu32, + 0x9B05688Cu32, + 0x1F83D9ABu32, + 0x5BE0CD19u32, +]; -pub(crate) const ivTable_B: [u64; 8] = - [0x6A09E667F3BCC908u64, 0xBB67AE8584CAA73Bu64, 0x3C6EF372FE94F82Bu64, 0xA54FF53A5F1D36F1u64, - 0x510E527FADE682D1u64, 0x9B05688C2B3E6C1Fu64, 0x1F83D9ABFB41BD6Bu64, 0x5BE0CD19137E2179u64]; +pub(crate) const ivTable_B: [u64; 8] = [ + 0x6A09E667F3BCC908u64, + 0xBB67AE8584CAA73Bu64, + 0x3C6EF372FE94F82Bu64, + 0xA54FF53A5F1D36F1u64, + 0x510E527FADE682D1u64, + 0x9B05688C2B3E6C1Fu64, + 0x1F83D9ABFB41BD6Bu64, + 0x5BE0CD19137E2179u64, +]; From 090fdf12cfcd271452a002e50a2283f4eb7d3c79 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Wed, 22 Jan 2025 17:22:35 +0100 Subject: [PATCH 10/11] Rename instances of 'static' to 'const', move tests to integration tests --- blake2/src/impl_hacl/blake2b.rs | 55 ++++---- blake2/src/impl_hacl/blake2s.rs | 55 ++++---- blake2/src/impl_hacl/mod.rs | 234 +------------------------------- blake2/tests/blake2.rs | 222 ++++++++++++++++++++++++++++++ 4 files changed, 278 insertions(+), 288 deletions(-) create mode 100644 blake2/tests/blake2.rs diff --git a/blake2/src/impl_hacl/blake2b.rs b/blake2/src/impl_hacl/blake2b.rs index 89fbd7f1f..e092b4f5e 100644 --- a/blake2/src/impl_hacl/blake2b.rs +++ b/blake2/src/impl_hacl/blake2b.rs @@ -10,7 +10,7 @@ use crate::hacl::hash_blake2b::{ update0, }; -use super::{ConstsDynamic, ConstsStaticKey, ConstsStaticKeyStaticOut, ConstsStaticOut, Error}; +use super::{ConstDigestLen, ConstKeyLen, ConstKeyLenConstDigestLen, Dynamic, Error}; const PARAM_LEN: usize = 16; const MAX_LEN: usize = 64; @@ -33,10 +33,7 @@ impl<'a> Blake2bBuilder<'a, &'a ()> { } /// Constructs the [`Blake2b`] hasher for unkeyed hashes and dynamic digest length. - pub fn build_var_digest_len( - self, - digest_length: u8, - ) -> Result>, Error> { + pub fn build_var_digest_len(self, digest_length: u8) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -73,10 +70,10 @@ impl<'a> Blake2bBuilder<'a, &'a ()> { }) } - /// Constructs the [`Blake2b`] hasher for unkeyed hashes and static digest length. + /// Constructs the [`Blake2b`] hasher for unkeyed hashes and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -118,7 +115,7 @@ impl<'a> Blake2bBuilder<'a, &'a ()> { impl<'a, const KEY_LEN: usize> Blake2bBuilder<'a, &'a [u8; KEY_LEN]> { /// Creates the builder for an keyed hasher for keys where the length is known at compile /// time. - pub fn new_keyed_static(key: &'a [u8; KEY_LEN]) -> Result { + pub fn new_keyed_const(key: &'a [u8; KEY_LEN]) -> Result { if KEY_LEN > MAX_LEN { return Err(Error::InvalidKeyLength); } @@ -130,11 +127,11 @@ impl<'a, const KEY_LEN: usize> Blake2bBuilder<'a, &'a [u8; KEY_LEN]> { }) } - /// Constructs the [`Blake2b`] hasher for hashes with static key length and dynamic digest length. + /// Constructs the [`Blake2b`] hasher for hashes with const key length and dynamic digest length. pub fn build_var_digest_len( self, digest_length: u8, - ) -> Result>, Error> { + ) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -166,16 +163,16 @@ impl<'a, const KEY_LEN: usize> Blake2bBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2b::> { + Ok(Blake2b::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) } - /// Constructs the [`Blake2b`] hasher for hashes with static key length and static digest length. + /// Constructs the [`Blake2b`] hasher for hashes with const key length and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -209,7 +206,7 @@ impl<'a, const KEY_LEN: usize> Blake2bBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2b::> { + Ok(Blake2b::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) @@ -232,7 +229,7 @@ impl<'a> Blake2bBuilder<'a, &'a [u8]> { } /// Constructs the fully dynamic [`Blake2b`] hasher. - pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { + pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -270,10 +267,10 @@ impl<'a> Blake2bBuilder<'a, &'a [u8]> { }) } - /// Constructs the [`Blake2b`] hasher with dynamic key length and static digest length. + /// Constructs the [`Blake2b`] hasher with dynamic key length and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -346,7 +343,7 @@ impl Blake2b { } } -impl Blake2b> { +impl Blake2b> { /// Compute the hash for the current hash state and write it to `dst`. /// /// Returns a `Result` that contains the length of the digest on success. @@ -360,7 +357,7 @@ impl Blake2b> { } } -impl Blake2b { +impl Blake2b { /// Compute the hash for the current hash state and write it to `dst`. /// /// Returns a `Result` that contains the length of the digest on success. @@ -375,7 +372,7 @@ impl Blake2b { } impl - Blake2b> + Blake2b> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { @@ -383,7 +380,7 @@ impl } } -impl Blake2b> { +impl Blake2b> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { digest(&self.state, dst); @@ -391,7 +388,7 @@ impl Blake2b> { } impl - Blake2b> + Blake2b> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { @@ -399,14 +396,14 @@ impl } } -impl Blake2b> { +impl Blake2b> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { reset_with_key(&mut self.state, key); } } -impl Blake2b> { +impl Blake2b> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -419,7 +416,7 @@ impl Blake2b> { } } -impl Blake2b { +impl Blake2b { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -432,21 +429,21 @@ impl Blake2b { } } -impl Blake2b> { +impl Blake2b> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2b> { +impl Blake2b> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2b> { +impl Blake2b> { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches @@ -459,7 +456,7 @@ impl Blake2b> { } } -impl Blake2b { +impl Blake2b { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches diff --git a/blake2/src/impl_hacl/blake2s.rs b/blake2/src/impl_hacl/blake2s.rs index 1b3616e8f..fcf8206e6 100644 --- a/blake2/src/impl_hacl/blake2s.rs +++ b/blake2/src/impl_hacl/blake2s.rs @@ -8,7 +8,7 @@ use libcrux_hacl_rs::streaming_types::error_code; use crate::hacl::hash_blake2b::{blake2_params, index, params_and_key}; use crate::hacl::hash_blake2s::{digest, malloc_raw, reset, reset_with_key, state_t, update0}; -use super::{ConstsDynamic, ConstsStaticKey, ConstsStaticKeyStaticOut, ConstsStaticOut, Error}; +use super::{ConstDigestLen, ConstKeyLen, ConstKeyLenConstDigestLen, Dynamic, Error}; const PARAM_LEN: usize = 8; const MAX_LEN: usize = 32; @@ -31,10 +31,7 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { } /// Constructs the [`Blake2s`] hasher for unkeyed hashes and dynamic digest length. - pub fn build_var_digest_len( - self, - digest_length: u8, - ) -> Result>, Error> { + pub fn build_var_digest_len(self, digest_length: u8) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -71,10 +68,10 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { }) } - /// Constructs the [`Blake2s`] hasher for unkeyed hashes and static digest length. + /// Constructs the [`Blake2s`] hasher for unkeyed hashes and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -116,7 +113,7 @@ impl<'a> Blake2sBuilder<'a, &'a ()> { impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { /// Creates the builder for an keyed hasher for keys where the length is known at compile /// time. - pub fn new_keyed_static(key: &'a [u8; KEY_LEN]) -> Result { + pub fn new_keyed_const(key: &'a [u8; KEY_LEN]) -> Result { if KEY_LEN > MAX_LEN { return Err(Error::InvalidKeyLength); } @@ -128,11 +125,11 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { }) } - /// Constructs the [`Blake2s`] hasher for hashes with static key length and dynamic digest length. + /// Constructs the [`Blake2s`] hasher for hashes with constant key length and dynamic digest length. pub fn build_var_digest_len( self, digest_length: u8, - ) -> Result>, Error> { + ) -> Result>, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -164,16 +161,16 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2s::> { + Ok(Blake2s::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) } - /// Constructs the [`Blake2s`] hasher for hashes with static key length and static digest length. + /// Constructs the [`Blake2s`] hasher for hashes with constant key length and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -207,7 +204,7 @@ impl<'a, const KEY_LEN: usize> Blake2sBuilder<'a, &'a [u8; KEY_LEN]> { snd: self.key, }; - Ok(Blake2s::> { + Ok(Blake2s::> { state: malloc_raw(kk, key), _phantom: PhantomData, }) @@ -230,7 +227,7 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { } /// Constructs the fully dynamic [`Blake2s`] hasher. - pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { + pub fn build_var_digest_len(self, digest_length: u8) -> Result, Error> { if digest_length < 1 || digest_length as usize > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -268,10 +265,10 @@ impl<'a> Blake2sBuilder<'a, &'a [u8]> { }) } - /// Constructs the [`Blake2s`] hasher with dynamic key length and static digest length. + /// Constructs the [`Blake2s`] hasher with dynamic key length and constant digest length. pub fn build_const_digest_len( self, - ) -> Result>, Error> { + ) -> Result>, Error> { if OUT_LEN < 1 || OUT_LEN > MAX_LEN { return Err(Error::InvalidDigestLength); } @@ -344,7 +341,7 @@ impl Blake2s { } } -impl Blake2s> { +impl Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. /// /// Returns a `Result` that contains the length of the digest on success. @@ -358,7 +355,7 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Compute the hash for the current hash state and write it to `dst`. /// /// Returns a `Result` that contains the length of the digest on success. @@ -373,7 +370,7 @@ impl Blake2s { } impl - Blake2s> + Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { @@ -381,7 +378,7 @@ impl } } -impl Blake2s> { +impl Blake2s> { /// Compute the hash for the current hash state and write it to `dst`. pub fn finalize(&self, dst: &mut [u8; OUT_LEN]) { digest(&self.state, dst); @@ -389,7 +386,7 @@ impl Blake2s> { } impl - Blake2s> + Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { @@ -397,14 +394,14 @@ impl } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8; KEY_LEN]) { reset_with_key(&mut self.state, key); } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -417,7 +414,7 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Reset the hash state and update the key to the contents of `key`. pub fn reset_with_key(&mut self, key: &[u8]) -> Result<(), Error> { // check that the key length matches @@ -430,21 +427,21 @@ impl Blake2s { } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) { reset(&mut self.state) } } -impl Blake2s> { +impl Blake2s> { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches @@ -457,7 +454,7 @@ impl Blake2s> { } } -impl Blake2s { +impl Blake2s { /// Reset the hash state. pub fn reset(&mut self) -> Result<(), Error> { // check that the key length matches diff --git a/blake2/src/impl_hacl/mod.rs b/blake2/src/impl_hacl/mod.rs index 1cb7ea87d..26ad95ecc 100644 --- a/blake2/src/impl_hacl/mod.rs +++ b/blake2/src/impl_hacl/mod.rs @@ -10,240 +10,14 @@ pub use error::Error; /// Type that holds the constants in case both key length and digest length are known at compile /// time. -pub struct ConstsStaticKeyStaticOut; +pub struct ConstKeyLenConstDigestLen; /// Type that holds the constant in case just the key length is known at compile time. -pub struct ConstsStaticKey; +pub struct ConstKeyLen; /// Type that holds the constant in case just the digest length is known at compile time. -pub struct ConstsStaticOut; +pub struct ConstDigestLen; /// Type that holds the constant in case neither the key length nor the digest length is known at /// compile time. -pub struct ConstsDynamic; - -#[cfg(test)] -mod test { - use super::{Blake2bBuilder, Blake2sBuilder}; - - #[test] - fn test_blake2b() { - let mut got_hash = [0; 32]; - - // test unkeyed, with static key and digest len - let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; - let mut hasher = Blake2bBuilder::new_unkeyed() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test unkeyed, with static key len and dynamic digest len - let mut hasher = Blake2bBuilder::new_unkeyed() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with static key and digest len - let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; - let mut hasher = Blake2bBuilder::new_keyed_static(b"test") - .unwrap() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test"); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with static key len and dynamic digest len - let mut hasher = Blake2bBuilder::new_keyed_static(b"test") - .unwrap() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(len, 32); - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test"); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - assert_eq!(len, 32); - - // test keyed, with dynamic key len and static digest len - let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") - .unwrap() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test").unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with dynamic key digest len - let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") - .unwrap() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(len, 32); - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test").unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - assert_eq!(len, 32); - - let mut got_hash = [0; 64]; - let mut hasher = Blake2bBuilder::new_unkeyed() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; - - assert_eq!(&got_hash, expected_hash); - } - - #[test] - fn test_blake2s() { - let mut got_hash = [0; 32]; - - // test unkeyed, with static key and digest len - let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; - let mut hasher = Blake2sBuilder::new_unkeyed() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test unkeyed, with static key len and dynamic digest len - let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; - let mut hasher = Blake2sBuilder::new_unkeyed() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with static key and digest len - let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; - let mut hasher = Blake2sBuilder::new_keyed_static(b"test") - .unwrap() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test"); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with static key len and dynamic digest len - let mut hasher = Blake2sBuilder::new_keyed_static(b"test") - .unwrap() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(len, 32); - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test"); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - assert_eq!(len, 32); - - // test keyed, with dynamic key len and static digest len - let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") - .unwrap() - .build_const_digest_len() - .unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test").unwrap(); - hasher.update(b"this is a test").unwrap(); - hasher.finalize(&mut got_hash); - - assert_eq!(&got_hash, expected_hash); - - // test keyed, with dynamic key digest len - let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") - .unwrap() - .build_var_digest_len(32) - .unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(len, 32); - assert_eq!(&got_hash, expected_hash); - - hasher.reset_with_key(b"test").unwrap(); - hasher.update(b"this is a test").unwrap(); - let len = hasher.finalize(&mut got_hash).unwrap(); - - assert_eq!(&got_hash, expected_hash); - assert_eq!(len, 32); - } -} +pub struct Dynamic; diff --git a/blake2/tests/blake2.rs b/blake2/tests/blake2.rs new file mode 100644 index 000000000..430156097 --- /dev/null +++ b/blake2/tests/blake2.rs @@ -0,0 +1,222 @@ +use libcrux_blake2::{Blake2bBuilder, Blake2sBuilder}; + +#[test] +fn test_blake2b() { + let mut got_hash = [0; 32]; + + // test unkeyed, with const key and digest len + let expected_hash = b"\xe9\xed\x14\x1d\xf1\xce\xbf\xc8\x9e\x46\x6c\xe0\x89\xee\xdd\x4f\x12\x5a\xa7\x57\x15\x01\xa0\xaf\x87\x1f\xab\x60\x59\x71\x17\xb7"; + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test unkeyed, with const key len and dynamic digest len + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with const key and digest len + let expected_hash = b"\x2a\xbb\x86\x16\xc6\x99\xe5\x1d\xa3\x65\xca\xb7\xad\xe0\x53\x92\xaf\xa2\xc3\xc6\x13\x08\x7f\x84\xb0\xd1\x6e\x5a\x4f\xab\xa7\xb8"; + let mut hasher = Blake2bBuilder::new_keyed_const(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with const key len and dynamic digest len + let mut hasher = Blake2bBuilder::new_keyed_const(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + + // test keyed, with dynamic key len and const digest len + let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with dynamic key digest len + let mut hasher = Blake2bBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + + let mut got_hash = [0; 64]; + let mut hasher = Blake2bBuilder::new_unkeyed() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + let expected_hash = b"\x61\xa5\x48\xf2\xde\x1c\x31\x8b\xa9\x1d\x52\x07\x00\x78\x61\x01\x0f\x69\xa4\x3e\xc6\x63\xfe\x48\x7d\x84\x03\x28\x2c\x93\x4e\xa7\x25\xdc\x0b\xb1\x72\x25\x6a\xc9\x96\x25\xad\x64\xcc\xa6\xa2\xc4\xd6\x1c\x65\x0a\x35\xaf\xab\x47\x87\xdc\x67\x8e\x19\x07\x1e\xf9"; + + assert_eq!(&got_hash, expected_hash); +} + +#[test] +fn test_blake2s() { + let mut got_hash = [0; 32]; + + // test unkeyed, with const key and digest len + let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; + let mut hasher = Blake2sBuilder::new_unkeyed() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test unkeyed, with const key len and dynamic digest len + let expected_hash = b"\xf2\x01\x46\xc0\x54\xf9\xdd\x6b\x67\x64\xb6\xc0\x93\x57\xf7\xcd\x75\x51\xdf\xbc\xba\x54\x59\x72\xa4\xc8\x16\x6d\xf8\xaf\xde\x60"; + let mut hasher = Blake2sBuilder::new_unkeyed() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with const key and digest len + let expected_hash = b"\x98\xfb\xfa\x89\xb3\xee\x07\x51\x9e\xe6\x2c\x18\xfe\x9d\x85\xdc\xf0\x83\x7b\x12\xae\x4d\xe7\x29\xf0\x7b\x55\xa9\x1a\x94\x80\xe8"; + let mut hasher = Blake2sBuilder::new_keyed_const(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with const key len and dynamic digest len + let mut hasher = Blake2sBuilder::new_keyed_const(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test"); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); + + // test keyed, with dynamic key len and const digest len + let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_const_digest_len() + .unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + hasher.finalize(&mut got_hash); + + assert_eq!(&got_hash, expected_hash); + + // test keyed, with dynamic key digest len + let mut hasher = Blake2sBuilder::new_keyed_dynamic(b"test") + .unwrap() + .build_var_digest_len(32) + .unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(len, 32); + assert_eq!(&got_hash, expected_hash); + + hasher.reset_with_key(b"test").unwrap(); + hasher.update(b"this is a test").unwrap(); + let len = hasher.finalize(&mut got_hash).unwrap(); + + assert_eq!(&got_hash, expected_hash); + assert_eq!(len, 32); +} From 052ee6c3289cd26a337df8fa098ef7b8caf0d5c6 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 23 Jan 2025 09:10:26 +0100 Subject: [PATCH 11/11] comment out useless memory zeroization --- hacl-rs/src/util/memzero0.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hacl-rs/src/util/memzero0.rs b/hacl-rs/src/util/memzero0.rs index 017d117c5..9a0dc0990 100644 --- a/hacl-rs/src/util/memzero0.rs +++ b/hacl-rs/src/util/memzero0.rs @@ -1,6 +1,11 @@ -pub fn memzero(x: &mut [T], len: u32) { +// TODO: Implement proper memory zeroiation (#765). The hacl-rs code sometimes calls the memzero +// function, but unfortunately the memzero implementation that is extracted doesn't work well in +// Rust. +pub fn memzero(_x: &mut [T], _len: u32) { + /* let zero: T = unsafe { core::mem::zeroed() }; for i in 0..len { x[i as usize] = zero; } + */ }