From 97918f67fb8e1c1bb52c0d505feb6cf592846e2f Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Mon, 2 Dec 2024 11:32:27 +0100 Subject: [PATCH 01/13] refactor hacl feature flags - drop portable_hacl feature - don't export hacl modules when hacl feature is set - (on some) add an expose-hacl feature to export hacl module --- curve25519/Cargo.toml | 3 +-- curve25519/src/impl_hacl.rs | 22 +++++++++++++++++----- curve25519/src/lib.rs | 16 +++------------- ed25519/Cargo.toml | 3 +-- ed25519/src/lib.rs | 2 +- libcrux-hkdf/Cargo.toml | 5 +++-- libcrux-hkdf/src/hkdf.rs | 4 ++++ libcrux-hmac/Cargo.toml | 6 +++--- libcrux-hmac/src/hmac.rs | 10 ++++++++-- sha2/Cargo.toml | 4 ++-- sha2/src/lib.rs | 7 +++++-- 11 files changed, 48 insertions(+), 34 deletions(-) diff --git a/curve25519/Cargo.toml b/curve25519/Cargo.toml index 47e26ec85..fccb866f3 100644 --- a/curve25519/Cargo.toml +++ b/curve25519/Cargo.toml @@ -11,8 +11,7 @@ repository.workspace = true readme.workspace = true [features] -default = ["portable_hacl"] -portable_hacl = ["hacl"] +default = ["hacl"] hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] [dependencies] diff --git a/curve25519/src/impl_hacl.rs b/curve25519/src/impl_hacl.rs index 5ff924a40..af5e263c0 100644 --- a/curve25519/src/impl_hacl.rs +++ b/curve25519/src/impl_hacl.rs @@ -7,15 +7,27 @@ impl Curve25519 for HaclCurve25519 { // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]) { - crate::hacl::secret_to_public(pk, sk) + secret_to_public(pk, sk) } // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error> { - match crate::hacl::ecdh(out, sk, pk) { - true => Ok(()), - false => Err(Error), - } + ecdh(out, pk, sk) + } +} + +// The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using +// types. +pub fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]) { + crate::hacl::secret_to_public(pk, sk) +} + +// The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using +// types. +pub fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error> { + match crate::hacl::ecdh(out, sk, pk) { + true => Ok(()), + false => Err(Error), } } diff --git a/curve25519/src/lib.rs b/curve25519/src/lib.rs index f24e7f59a..5e697f9c1 100644 --- a/curve25519/src/lib.rs +++ b/curve25519/src/lib.rs @@ -6,8 +6,8 @@ pub use libcrux_hacl_rs::curve25519_51 as hacl; #[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "portable_hacl")] -pub use impl_hacl::HaclCurve25519 as Impl; +#[cfg(feature = "hacl")] +pub use impl_hacl::{ecdh, secret_to_public}; /// The length of Curve25519 secret keys. pub const SK_LEN: usize = 32; @@ -23,7 +23,7 @@ pub struct Error; /// This trait is implemented by the backing implementations. /// Only used for implementation agility. -trait Curve25519 { +pub trait Curve25519 { /// Computes a public key from a secret key. fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]); @@ -31,13 +31,3 @@ trait Curve25519 { /// error if the result is 0. fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error>; } - -/// Computes and writes the public key from the secret key `sk` and writes it into `pk`. -pub fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]) { - Impl::secret_to_public(pk, sk) -} - -/// Performs the ECDH computation and writes the key shared betweem `pk` and `sk` into `shk`. -pub fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error> { - Impl::ecdh(out, pk, sk) -} diff --git a/ed25519/Cargo.toml b/ed25519/Cargo.toml index 879fcb49b..18fd3021d 100644 --- a/ed25519/Cargo.toml +++ b/ed25519/Cargo.toml @@ -11,8 +11,7 @@ repository.workspace = true readme.workspace = true [features] -default = ["portable_hacl"] -portable_hacl = ["hacl"] +default = ["hacl"] hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] [dependencies] diff --git a/ed25519/src/lib.rs b/ed25519/src/lib.rs index c8338d8f6..9dfd36fa8 100644 --- a/ed25519/src/lib.rs +++ b/ed25519/src/lib.rs @@ -11,5 +11,5 @@ pub mod hacl { #[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "portable_hacl")] +#[cfg(feature = "hacl")] pub use impl_hacl::*; diff --git a/libcrux-hkdf/Cargo.toml b/libcrux-hkdf/Cargo.toml index 5c02eeec0..c1b9e2839 100644 --- a/libcrux-hkdf/Cargo.toml +++ b/libcrux-hkdf/Cargo.toml @@ -13,12 +13,13 @@ description = "Libcrux HKDF implementation" path = "src/hkdf.rs" [features] -default = ["portable_hacl"] -portable_hacl = ["hacl"] +default = ["hacl"] hacl = ["dep:libcrux-hmac", "dep:libcrux-hacl-rs"] [dependencies] libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } libcrux-hmac = { version = "=0.0.2-beta.2", path = "../libcrux-hmac", optional = true, features = [ "hacl", + "expose-hacl", + ] } diff --git a/libcrux-hkdf/src/hkdf.rs b/libcrux-hkdf/src/hkdf.rs index caf1ad9b0..fe8ebf09d 100644 --- a/libcrux-hkdf/src/hkdf.rs +++ b/libcrux-hkdf/src/hkdf.rs @@ -13,6 +13,7 @@ pub mod hacl; #[cfg(feature = "hacl")] mod impl_hacl; +#[cfg(feature = "hacl")] pub use impl_hacl::{HkdfSha2_256, HkdfSha2_384, HkdfSha2_512}; pub trait HkdfMode { @@ -112,6 +113,7 @@ pub enum Error { /// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`. /// Returns the pre-key material in a vector of tag length. +#[cfg(feature = "hacl")] pub fn extract( alg: Algorithm, salt: impl AsRef<[u8]>, @@ -129,6 +131,7 @@ pub fn extract( /// HKDF expand using hash function `mode`, pre-key material `prk`, `info`, and output length `okm_len`. /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. +#[cfg(feature = "hacl")] pub fn expand( alg: Algorithm, prk: impl AsRef<[u8]>, @@ -148,6 +151,7 @@ pub fn expand( /// Calls `extract` and `expand` with the given input. /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. +#[cfg(feature = "hacl")] pub fn hkdf( mode: Algorithm, salt: impl AsRef<[u8]>, diff --git a/libcrux-hmac/Cargo.toml b/libcrux-hmac/Cargo.toml index f2cd55674..99fc53231 100644 --- a/libcrux-hmac/Cargo.toml +++ b/libcrux-hmac/Cargo.toml @@ -13,13 +13,13 @@ description = "Libcrux HMAC implementation" path = "src/hmac.rs" [features] -default = ["portable_hacl"] -portable_hacl = ["hacl"] +default = ["hacl"] hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] +expose-hacl = ["hacl"] [dependencies] libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", optional = true, features = [ - "hacl", + "expose-hacl", ] } libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } diff --git a/libcrux-hmac/src/hmac.rs b/libcrux-hmac/src/hmac.rs index 6f5f41e4c..02d24a30f 100644 --- a/libcrux-hmac/src/hmac.rs +++ b/libcrux-hmac/src/hmac.rs @@ -7,7 +7,13 @@ extern crate alloc; use alloc::vec::Vec; -#[cfg(feature = "hacl")] +#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +mod hacl { + pub(crate) mod hash_sha1; + pub(crate) mod hmac; +} + +#[cfg(feature = "expose-hacl")] pub mod hacl { pub mod hash_sha1; pub mod hmac; @@ -16,7 +22,7 @@ pub mod hacl { #[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "portable_hacl")] +#[cfg(feature = "hacl")] pub use impl_hacl::*; /// The HMAC algorithm defining the used hash function. diff --git a/sha2/Cargo.toml b/sha2/Cargo.toml index 1c17ba859..a216d3c7e 100644 --- a/sha2/Cargo.toml +++ b/sha2/Cargo.toml @@ -11,9 +11,9 @@ repository.workspace = true readme.workspace = true [features] -default = ["portable_hacl"] -portable_hacl = ["hacl"] +default = ["hacl"] hacl = ["dep:libcrux-hacl-rs"] +expose-hacl = ["hacl"] [dependencies] libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs", optional = true } diff --git a/sha2/src/lib.rs b/sha2/src/lib.rs index 8f34d57c5..0231fd743 100644 --- a/sha2/src/lib.rs +++ b/sha2/src/lib.rs @@ -13,7 +13,10 @@ pub const SHA384_LENGTH: usize = 48; pub const SHA512_LENGTH: usize = 64; /// The generated hacl code -#[cfg(feature = "hacl")] +#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +mod hacl; + +#[cfg(feature = "expose-hacl")] pub mod hacl; /// The implementation of our types using that hacl code @@ -21,5 +24,5 @@ pub mod hacl; mod impl_hacl; /// use it if we want to use hacl -#[cfg(feature = "portable_hacl")] +#[cfg(feature = "hacl")] pub use impl_hacl::*; From c31979a65f7ecf0e5ff6db29fcffa79a9052d75c Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Mon, 2 Dec 2024 14:25:10 +0100 Subject: [PATCH 02/13] add comments to indicate generated files --- ed25519/src/hacl/ed25519.rs | 2 ++ ed25519/src/hacl/ed25519_precomptable.rs | 2 ++ libcrux-hmac/src/hacl/hash_sha1.rs | 2 ++ libcrux-hmac/src/hacl/hmac.rs | 2 ++ macros/src/lib.rs | 2 ++ sha2/src/hacl.rs | 2 ++ 6 files changed, 12 insertions(+) diff --git a/ed25519/src/hacl/ed25519.rs b/ed25519/src/hacl/ed25519.rs index c62622781..d4d612873 100644 --- a/ed25519/src/hacl/ed25519.rs +++ b/ed25519/src/hacl/ed25519.rs @@ -4,6 +4,8 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] +//! This module contains generated hacl code. + use libcrux_macros as krml; use libcrux_hacl_rs::prelude::*; diff --git a/ed25519/src/hacl/ed25519_precomptable.rs b/ed25519/src/hacl/ed25519_precomptable.rs index f0e8def64..d41e822c4 100644 --- a/ed25519/src/hacl/ed25519_precomptable.rs +++ b/ed25519/src/hacl/ed25519_precomptable.rs @@ -4,6 +4,8 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] +//! This module contains generated hacl code. + pub(crate) const precomp_basepoint_table_w4: [u64; 320] = [ 0u64, 0u64, diff --git a/libcrux-hmac/src/hacl/hash_sha1.rs b/libcrux-hmac/src/hacl/hash_sha1.rs index 16b5273e2..5afa7aece 100644 --- a/libcrux-hmac/src/hacl/hash_sha1.rs +++ b/libcrux-hmac/src/hacl/hash_sha1.rs @@ -4,6 +4,8 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] +//! This module contains generated hacl code. + use libcrux_hacl_rs::prelude::*; use libcrux_macros as krml; diff --git a/libcrux-hmac/src/hacl/hmac.rs b/libcrux-hmac/src/hacl/hmac.rs index 556bc1b7b..dbcbd3f8d 100644 --- a/libcrux-hmac/src/hacl/hmac.rs +++ b/libcrux-hmac/src/hacl/hmac.rs @@ -4,6 +4,8 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] +//! This module contains generated hacl code. + use libcrux_hacl_rs::prelude::*; use libcrux_macros as krml; use libcrux_sha2::hacl as hash_sha2; diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 30896bf7f..bb3f4ea55 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,3 +1,5 @@ +//! This module contains code from HACL. + use proc_macro::{Delimiter, TokenStream, TokenTree}; fn skip_comma>(ts: &mut T) { diff --git a/sha2/src/hacl.rs b/sha2/src/hacl.rs index 17401712a..23c1ae443 100644 --- a/sha2/src/hacl.rs +++ b/sha2/src/hacl.rs @@ -4,6 +4,8 @@ #![allow(unused_assignments)] #![allow(unreachable_patterns)] +//! This module contains generated hacl code. + use libcrux_hacl_rs::prelude::*; use libcrux_macros as krml; From 0f5da7297eb81e979136349a5b41909ed199c772 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Mon, 2 Dec 2024 15:18:31 +0100 Subject: [PATCH 03/13] Add inline annotations This commit adds inlines: - plain inline inside hacl-rs code (sometimes) - inline(always) for functions that call hacl-rs code This way our wrapper functions get inlined away and the caller just calls the hacl-rs function, and inside the hacl-rs function there are few calls to internal functions (where it makes sense). --- curve25519/src/impl_hacl.rs | 4 ++++ ed25519/src/hacl/ed25519.rs | 1 + ed25519/src/impl_hacl.rs | 3 +++ hacl-rs/src/lowstar/endianness.rs | 12 ++++++++++++ libcrux-hkdf/src/hkdf.rs | 6 ++++++ libcrux-hkdf/src/impl_hacl.rs | 8 ++++++++ libcrux-hmac/src/hacl/hmac.rs | 4 ++++ libcrux-hmac/src/hmac.rs | 1 + libcrux-hmac/src/impl_hacl.rs | 1 + sha2/src/impl_hacl.rs | 10 ++++++++++ 10 files changed, 50 insertions(+) diff --git a/curve25519/src/impl_hacl.rs b/curve25519/src/impl_hacl.rs index af5e263c0..8c0b469db 100644 --- a/curve25519/src/impl_hacl.rs +++ b/curve25519/src/impl_hacl.rs @@ -6,12 +6,14 @@ pub struct HaclCurve25519; impl Curve25519 for HaclCurve25519 { // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. + #[inline(always)] fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]) { secret_to_public(pk, sk) } // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. + #[inline(always)] fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error> { ecdh(out, pk, sk) } @@ -19,12 +21,14 @@ impl Curve25519 for HaclCurve25519 { // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. +#[inline(always)] pub fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]) { crate::hacl::secret_to_public(pk, sk) } // The hacl::ecdh function requires all parameters to be 32 byte long, which we enforce using // types. +#[inline(always)] pub fn ecdh(out: &mut [u8; SHK_LEN], pk: &[u8; PK_LEN], sk: &[u8; SK_LEN]) -> Result<(), Error> { match crate::hacl::ecdh(out, sk, pk) { true => Ok(()), diff --git a/ed25519/src/hacl/ed25519.rs b/ed25519/src/hacl/ed25519.rs index d4d612873..ff7997cca 100644 --- a/ed25519/src/hacl/ed25519.rs +++ b/ed25519/src/hacl/ed25519.rs @@ -118,6 +118,7 @@ fn fsquare_times_inplace(output: &mut [u64], count: u32) { libcrux_hacl_rs::curve25519_51::fsquare_times(output, &input, &tmp, count) } +#[inline] pub(crate) fn inverse(out: &mut [u64], a: &[u64]) { let tmp: [fstar::uint128::uint128; 10] = [fstar::uint128::uint64_to_uint128(0u64); 10usize]; libcrux_hacl_rs::curve25519_51::finv(out, a, &tmp) diff --git a/ed25519/src/impl_hacl.rs b/ed25519/src/impl_hacl.rs index bb61db011..675025665 100644 --- a/ed25519/src/impl_hacl.rs +++ b/ed25519/src/impl_hacl.rs @@ -12,6 +12,7 @@ pub enum Error { /// We enforce the first two using types, and the latter by using `payload.len()` and `payload_len`. /// This has the caveat that `payload_len` must be <= u32::MAX, so we return an error if that is /// not the case. +#[inline(always)] pub fn sign(payload: &[u8], private_key: &[u8; 32]) -> Result<[u8; 64], Error> { let mut signature = [0u8; 64]; crate::hacl::ed25519::sign( @@ -33,6 +34,7 @@ pub fn sign(payload: &[u8], private_key: &[u8; 32]) -> Result<[u8; 64], Error> { /// This has the caveat that `payload_len` must be <= u32::MAX, so we return an error if that is /// not the case. /// +#[inline(always)] pub fn verify(payload: &[u8], public_key: &[u8; 32], signature: &[u8; 64]) -> Result<(), Error> { if crate::hacl::ed25519::verify( public_key, @@ -49,6 +51,7 @@ pub fn verify(payload: &[u8], public_key: &[u8; 32], signature: &[u8; 64]) -> Re /// Compute the public point for the given secret key `sk`. /// The hacl implementation requires that these are both 32 byte buffers, which we enforce through /// types. +#[inline(always)] pub fn secret_to_public(pk: &mut [u8; 32], sk: &[u8; 32]) { crate::hacl::ed25519::secret_to_public(pk, sk) } diff --git a/hacl-rs/src/lowstar/endianness.rs b/hacl-rs/src/lowstar/endianness.rs index 051027f6c..adaae98b7 100644 --- a/hacl-rs/src/lowstar/endianness.rs +++ b/hacl-rs/src/lowstar/endianness.rs @@ -2,52 +2,64 @@ use core::convert::TryInto; // Little Endian +#[inline] pub fn load16_le(bytes: &[u8]) -> u16 { u16::from_le_bytes(bytes[0..2].try_into().unwrap()) } +#[inline] pub fn store16_le(bytes: &mut [u8], x: u16) { bytes[0..2].copy_from_slice(&u16::to_le_bytes(x)) } +#[inline] pub fn load32_le(bytes: &[u8]) -> u32 { u32::from_le_bytes(bytes[0..4].try_into().unwrap()) } +#[inline] pub fn store32_le(bytes: &mut [u8], x: u32) { bytes[0..4].copy_from_slice(&u32::to_le_bytes(x)) } +#[inline] pub fn load64_le(bytes: &[u8]) -> u64 { u64::from_le_bytes(bytes[0..8].try_into().unwrap()) } +#[inline] pub fn store64_le(bytes: &mut [u8], x: u64) { bytes[0..8].copy_from_slice(&u64::to_le_bytes(x)) } // Big Endian +#[inline] pub fn load32_be(bytes: &[u8]) -> u32 { u32::from_be_bytes(bytes[0..4].try_into().unwrap()) } +#[inline] pub fn store32_be(bytes: &mut [u8], x: u32) { bytes[0..4].copy_from_slice(&u32::to_be_bytes(x)) } +#[inline] pub fn load64_be(bytes: &[u8]) -> u64 { u64::from_be_bytes(bytes[0..8].try_into().unwrap()) } +#[inline] pub fn store64_be(bytes: &mut [u8], x: u64) { bytes[0..8].copy_from_slice(&u64::to_be_bytes(x)) } +#[inline] pub fn load128_be(bytes: &[u8]) -> u128 { u128::from_be_bytes(bytes[0..16].try_into().unwrap()) } +#[inline] pub fn store128_be(bytes: &mut [u8], x: u128) { bytes[0..16].copy_from_slice(&u128::to_be_bytes(x)) } diff --git a/libcrux-hkdf/src/hkdf.rs b/libcrux-hkdf/src/hkdf.rs index fe8ebf09d..6c912b352 100644 --- a/libcrux-hkdf/src/hkdf.rs +++ b/libcrux-hkdf/src/hkdf.rs @@ -57,6 +57,7 @@ pub trait HkdfMode { /// Returns [`Error::OkmTooLarge`] if the requested `OKM_LEN` is too large. /// Returns [`Error::ArgumentsTooLarge`] if one of `ikm`, `salt` or `info` is longer than /// [`u32::MAX`] bytes. + #[inline(always)] fn hkdf( okm: &mut [u8; OKM_LEN], salt: &[u8], @@ -75,6 +76,7 @@ pub trait HkdfMode { /// Returns the key material in a [`Vec`] of length `okm_len` on success. /// Returns [`Error::OkmTooLarge`] if the requested `okm_len` is too large. /// Returns [`Error::ArgumentsTooLarge`] if `salt`, `ikm` or `info` is longer than [`u32::MAX`] bytes. + #[inline(always)] fn hkdf_vec(salt: &[u8], ikm: &[u8], info: &[u8], okm_len: usize) -> Result, Error> { let mut prk = [0u8; HASH_LEN]; Self::extract(&mut prk, salt, ikm)?; @@ -114,6 +116,7 @@ pub enum Error { /// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`. /// Returns the pre-key material in a vector of tag length. #[cfg(feature = "hacl")] +#[inline(always)] pub fn extract( alg: Algorithm, salt: impl AsRef<[u8]>, @@ -132,6 +135,7 @@ pub fn extract( /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. #[cfg(feature = "hacl")] +#[inline(always)] pub fn expand( alg: Algorithm, prk: impl AsRef<[u8]>, @@ -152,6 +156,7 @@ pub fn expand( /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. #[cfg(feature = "hacl")] +#[inline(always)] pub fn hkdf( mode: Algorithm, salt: impl AsRef<[u8]>, @@ -170,6 +175,7 @@ pub fn hkdf( } } +#[inline(always)] fn allocbuf Result>(f: F) -> Result, E> { let mut buf = [0u8; N]; diff --git a/libcrux-hkdf/src/impl_hacl.rs b/libcrux-hkdf/src/impl_hacl.rs index 4600235c9..8c034d926 100644 --- a/libcrux-hkdf/src/impl_hacl.rs +++ b/libcrux-hkdf/src/impl_hacl.rs @@ -15,6 +15,7 @@ macro_rules! impl_hkdf { impl HkdfMode<$hash_len> for $struct_name { const MODE: Algorithm = $mode; + #[inline(always)] fn extract( prk: &mut [u8; $hash_len], salt: &[u8], @@ -23,6 +24,7 @@ macro_rules! impl_hkdf { extract(prk, salt, ikm) } + #[inline(always)] fn expand( okm: &mut [u8; OKM_LEN], prk: &[u8], @@ -31,6 +33,7 @@ macro_rules! impl_hkdf { expand(okm, prk, info) } + #[inline(always)] fn expand_vec(prk: &[u8], info: &[u8], okm_len: usize) -> Result, Error> { expand_vec(prk, info, okm_len) } @@ -42,6 +45,7 @@ macro_rules! impl_hkdf { /// Returns nothing on success. /// Returns [`Error::ArgumentsTooLarge`] if one of `ikm` or `salt` is longer than /// [`u32::MAX`] bytes. + #[inline(always)] pub fn extract( prk: &mut [u8; $hash_len], salt: &[u8], @@ -63,6 +67,7 @@ macro_rules! impl_hkdf { /// Returns [`Error::OkmTooLarge`] if the requested `OKM_LEN` is large. /// Returns [`Error::ArgumentsTooLarge`] if one of `prk` or `info` is longer than /// [`u32::MAX`] bytes. + #[inline(always)] pub fn expand( okm: &mut [u8; OKM_LEN], prk: &[u8], @@ -89,6 +94,7 @@ macro_rules! impl_hkdf { /// Returns the key material in a [`Vec`] of length `okm_len` on success. /// Returns [`Error::OkmTooLarge`] if the requested `okm_len` is too large. /// Returns [`Error::ArgumentsTooLarge`] if `prk` or `info` is longer than [`u32::MAX`] bytes. + #[inline(always)] pub fn expand_vec(prk: &[u8], info: &[u8], okm_len: usize) -> Result, Error> { if okm_len > 255 * $hash_len { // Output size is too large. HACL doesn't catch this. @@ -116,6 +122,7 @@ macro_rules! impl_hkdf { /// Returns [`Error::OkmTooLarge`] if the requested `OKM_LEN` is too large. /// Returns [`Error::ArgumentsTooLarge`] if one of `ikm`, `salt` or `info` is longer /// than [`u32::MAX`] bytes. + #[inline(always)] pub fn hkdf( okm: &mut [u8; OKM_LEN], salt: &[u8], @@ -134,6 +141,7 @@ macro_rules! impl_hkdf { /// Returns the key material in a [`Vec`] of length `okm_len` on success. /// Returns [`Error::OkmTooLarge`] if the requested `okm_len` is too large. /// Returns [`Error::ArgumentsTooLarge`] if `salt`, `ikm` or `info` is longer than [`u32::MAX`] bytes. + #[inline(always)] pub fn hkdf_vec( salt: &[u8], ikm: &[u8], diff --git a/libcrux-hmac/src/hacl/hmac.rs b/libcrux-hmac/src/hacl/hmac.rs index dbcbd3f8d..21b5a84d5 100644 --- a/libcrux-hmac/src/hacl/hmac.rs +++ b/libcrux-hmac/src/hacl/hmac.rs @@ -22,6 +22,7 @@ Write the HMAC-SHA-1 MAC of a message (`data`) by using a key (`key`) into `dst` The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 byte. `dst` must point to 20 bytes of memory. */ +#[inline(always)] pub fn compute_sha1(dst: &mut [u8], key: &[u8], key_len: u32, data: &[u8], data_len: u32) { let l: u32 = 64u32; let mut key_block: Box<[u8]> = vec![0x00u8; l as usize].into_boxed_slice(); @@ -126,6 +127,7 @@ Write the HMAC-SHA-2-256 MAC of a message (`data`) by using a key (`key`) into ` The key can be any length and will be hashed if it is longer and padded if it is shorter than 64 bytes. `dst` must point to 32 bytes of memory. */ +#[inline(always)] pub fn compute_sha2_256(dst: &mut [u8], key: &[u8], key_len: u32, data: &[u8], data_len: u32) { let l: u32 = 64u32; let mut key_block: Box<[u8]> = vec![0x00u8; l as usize].into_boxed_slice(); @@ -234,6 +236,7 @@ Write the HMAC-SHA-2-384 MAC of a message (`data`) by using a key (`key`) into ` The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes. `dst` must point to 48 bytes of memory. */ +#[inline(always)] pub fn compute_sha2_384(dst: &mut [u8], key: &[u8], key_len: u32, data: &[u8], data_len: u32) { let l: u32 = 128u32; let mut key_block: Box<[u8]> = vec![0x00u8; l as usize].into_boxed_slice(); @@ -358,6 +361,7 @@ Write the HMAC-SHA-2-512 MAC of a message (`data`) by using a key (`key`) into ` The key can be any length and will be hashed if it is longer and padded if it is shorter than 128 bytes. `dst` must point to 64 bytes of memory. */ +#[inline(always)] pub fn compute_sha2_512(dst: &mut [u8], key: &[u8], key_len: u32, data: &[u8], data_len: u32) { let l: u32 = 128u32; let mut key_block: Box<[u8]> = vec![0x00u8; l as usize].into_boxed_slice(); diff --git a/libcrux-hmac/src/hmac.rs b/libcrux-hmac/src/hmac.rs index 02d24a30f..1f0243a99 100644 --- a/libcrux-hmac/src/hmac.rs +++ b/libcrux-hmac/src/hmac.rs @@ -66,6 +66,7 @@ pub fn hmac(alg: Algorithm, key: &[u8], data: &[u8], tag_length: Option) dst } +#[inline(always)] fn wrap_bufalloc(f: F) -> Vec { let mut buf = [0u8; N]; f(&mut buf); diff --git a/libcrux-hmac/src/impl_hacl.rs b/libcrux-hmac/src/impl_hacl.rs index a5d90d31a..4e882e549 100644 --- a/libcrux-hmac/src/impl_hacl.rs +++ b/libcrux-hmac/src/impl_hacl.rs @@ -4,6 +4,7 @@ macro_rules! impl_hmac { /// /// Note that this function panics if `key` or `data` is larger than 2**32 bytes. /// This ensures that all values are in the range valid to be consumed by hacl-rs. + #[inline(always)] pub fn $name(dst: &mut [u8; $tag_len], key: &[u8], data: &[u8]) { $fun( dst, diff --git a/sha2/src/impl_hacl.rs b/sha2/src/impl_hacl.rs index 208a92152..79f69be55 100644 --- a/sha2/src/impl_hacl.rs +++ b/sha2/src/impl_hacl.rs @@ -5,6 +5,7 @@ use libcrux_traits::Digest; /// SHA2 224 /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. +#[inline(always)] pub fn sha224(payload: &[u8]) -> [u8; SHA224_LENGTH] { let mut digest = [0u8; SHA224_LENGTH]; Sha224::hash(&mut digest, payload); @@ -14,6 +15,7 @@ pub fn sha224(payload: &[u8]) -> [u8; SHA224_LENGTH] { /// SHA2 256 /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. +#[inline(always)] pub fn sha256(payload: &[u8]) -> [u8; SHA256_LENGTH] { let mut digest = [0u8; SHA256_LENGTH]; Sha256::hash(&mut digest, payload); @@ -23,6 +25,7 @@ pub fn sha256(payload: &[u8]) -> [u8; SHA256_LENGTH] { /// SHA2 384 /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. +#[inline(always)] pub fn sha384(payload: &[u8]) -> [u8; SHA384_LENGTH] { let mut digest = [0u8; SHA384_LENGTH]; Sha384::hash(&mut digest, payload); @@ -32,6 +35,7 @@ pub fn sha384(payload: &[u8]) -> [u8; SHA384_LENGTH] { /// SHA2 512 /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. +#[inline(always)] pub fn sha512(payload: &[u8]) -> [u8; SHA512_LENGTH] { let mut digest = [0u8; SHA512_LENGTH]; Sha512::hash(&mut digest, payload); @@ -58,6 +62,7 @@ macro_rules! impl_hash { /// Return the digest for the given input byte slice, in immediate mode. /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. + #[inline(always)] fn hash(digest: &mut [u8; $digest_size], payload: &[u8]) { let payload_len = payload.len().try_into().unwrap(); $hash(digest, payload, payload_len) @@ -66,6 +71,7 @@ macro_rules! impl_hash { /// Add the `payload` to the digest. /// Will panic if `payload` is longer than `u32::MAX` to ensure that hacl-rs can /// process it. + #[inline(always)] fn update(&mut self, payload: &[u8]) { let payload_len = payload.len().try_into().unwrap(); $update(self.state.as_mut(), payload, payload_len); @@ -75,23 +81,27 @@ macro_rules! impl_hash { /// /// Note that the digest state can be continued to be used, to extend the /// digest. + #[inline(always)] fn finish(&self, digest: &mut [u8; $digest_size]) { $finish(self.state.as_ref(), digest); } /// Reset the digest state. + #[inline(always)] fn reset(&mut self) { $reset(self.state.as_mut()); } } impl Default for $name { + #[inline(always)] fn default() -> Self { Self::new() } } impl Clone for $name { + #[inline(always)] fn clone(&self) -> Self { Self { state: $copy(self.state.as_ref()), From 74e719e0315d70f8f93f66efb9ba968d2eae4590 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Mon, 2 Dec 2024 18:51:07 +0100 Subject: [PATCH 04/13] Add Poly1305 MAC and ChaCha20Poly1305 AEAD --- Cargo.toml | 2 + chacha20poly1305/Cargo.toml | 22 + .../src/hacl/aead_chacha20poly1305.rs | 610 +++++++++++++++++ chacha20poly1305/src/hacl/chacha20.rs | 190 ++++++ chacha20poly1305/src/hacl/chacha20_vec32.rs | 252 ++++++++ chacha20poly1305/src/impl_hacl.rs | 112 ++++ chacha20poly1305/src/lib.rs | 51 ++ poly1305/Cargo.toml | 20 + poly1305/src/hacl/mac_poly1305.rs | 612 ++++++++++++++++++ poly1305/src/impl_hacl.rs | 12 + poly1305/src/lib.rs | 32 + 11 files changed, 1915 insertions(+) create mode 100644 chacha20poly1305/Cargo.toml create mode 100644 chacha20poly1305/src/hacl/aead_chacha20poly1305.rs create mode 100644 chacha20poly1305/src/hacl/chacha20.rs create mode 100644 chacha20poly1305/src/hacl/chacha20_vec32.rs create mode 100644 chacha20poly1305/src/impl_hacl.rs create mode 100644 chacha20poly1305/src/lib.rs create mode 100644 poly1305/Cargo.toml create mode 100644 poly1305/src/hacl/mac_poly1305.rs create mode 100644 poly1305/src/impl_hacl.rs create mode 100644 poly1305/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 153cf07a2..b133be888 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,8 @@ members = [ "sha2", "ed25519", "curve25519", + "poly1305", + "chacha20poly1305", ] [workspace.package] diff --git a/chacha20poly1305/Cargo.toml b/chacha20poly1305/Cargo.toml new file mode 100644 index 000000000..43b02128c --- /dev/null +++ b/chacha20poly1305/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "libcrux-chacha20poly1305" +description = "Formally verified ChaCha20-Poly1305 AEAD library" + +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[features] +default = ["hacl"] +hacl = ["dep:libcrux-poly1305", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] + +[dependencies] +libcrux-poly1305 = { version = "=0.0.2-beta.2", path = "../poly1305/", features = [ + "expose-hacl", +], optional = true } +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } diff --git a/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs b/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs new file mode 100644 index 000000000..6d8c27212 --- /dev/null +++ b/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs @@ -0,0 +1,610 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +//! This module contains generated hacl code. + +use libcrux_hacl_rs::prelude::*; +use libcrux_macros as krml; + +#[inline] +fn poly1305_padded_32(ctx: &mut [u64], len: u32, text: &[u8]) { + let n: u32 = len.wrapping_div(16u32); + let r: u32 = len.wrapping_rem(16u32); + let blocks: (&[u8], &[u8]) = text.split_at(0usize); + let rem: (&[u8], &[u8]) = blocks.1.split_at(n.wrapping_mul(16u32) as usize); + let pre: (&mut [u64], &mut [u64]) = ctx.split_at_mut(5usize); + let acc: (&mut [u64], &mut [u64]) = pre.0.split_at_mut(0usize); + let nb: u32 = n.wrapping_mul(16u32).wrapping_div(16u32); + let rem1: u32 = n.wrapping_mul(16u32).wrapping_rem(16u32); + for i in 0u32..nb { + let block: (&[u8], &[u8]) = rem.0.split_at(i.wrapping_mul(16u32) as usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let u: u64 = lowstar::endianness::load64_le(&block.1[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&block.1[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 0x1000000u64; + let mask: u64 = b; + let f41: u64 = (&e)[4usize]; + (&mut e)[4usize] = f41 | mask; + let r1: (&[u64], &[u64]) = pre.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r1.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r11: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc.1[0usize]; + let a1: u64 = acc.1[1usize]; + let a2: u64 = acc.1[2usize]; + let a3: u64 = acc.1[3usize]; + let a4: u64 = acc.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r11.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r11.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r11.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r11.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc.1[0usize] = o0; + acc.1[1usize] = o1; + acc.1[2usize] = o2; + acc.1[3usize] = o3; + acc.1[4usize] = o4 + } + if rem1 > 0u32 { + let last: (&[u8], &[u8]) = rem.0.split_at(nb.wrapping_mul(16u32) as usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let mut tmp: [u8; 16] = [0u8; 16usize]; + ((&mut tmp)[0usize..rem1 as usize]).copy_from_slice(&last.1[0usize..rem1 as usize]); + let u: u64 = lowstar::endianness::load64_le(&(&tmp)[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&(&tmp)[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 1u64.wrapping_shl(rem1.wrapping_mul(8u32).wrapping_rem(26u32)); + let mask: u64 = b; + let fi: u64 = (&e)[rem1.wrapping_mul(8u32).wrapping_div(26u32) as usize]; + (&mut e)[rem1.wrapping_mul(8u32).wrapping_div(26u32) as usize] = fi | mask; + let r1: (&[u64], &[u64]) = pre.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r1.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r11: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc.1[0usize]; + let a1: u64 = acc.1[1usize]; + let a2: u64 = acc.1[2usize]; + let a3: u64 = acc.1[3usize]; + let a4: u64 = acc.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r11.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r11.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r11.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r11.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc.1[0usize] = o0; + acc.1[1usize] = o1; + acc.1[2usize] = o2; + acc.1[3usize] = o3; + acc.1[4usize] = o4 + }; + let mut tmp: [u8; 16] = [0u8; 16usize]; + ((&mut tmp)[0usize..r as usize]).copy_from_slice(&rem.1[0usize..r as usize]); + if r > 0u32 { + let pre0: (&[u64], &[u64]) = pre.1.split_at(0usize); + let acc0: (&mut [u64], &mut [u64]) = acc.1.split_at_mut(0usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let u: u64 = lowstar::endianness::load64_le(&(&tmp)[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&(&tmp)[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 0x1000000u64; + let mask: u64 = b; + let f41: u64 = (&e)[4usize]; + (&mut e)[4usize] = f41 | mask; + let r1: (&[u64], &[u64]) = pre0.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r1.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r11: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc0.1[0usize]; + let a1: u64 = acc0.1[1usize]; + let a2: u64 = acc0.1[2usize]; + let a3: u64 = acc0.1[3usize]; + let a4: u64 = acc0.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r11.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r11.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r11.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r11.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc0.1[0usize] = o0; + acc0.1[1usize] = o1; + acc0.1[2usize] = o2; + acc0.1[3usize] = o3; + acc0.1[4usize] = o4 + } +} + +#[inline] +fn poly1305_do_32(k: &[u8], aadlen: u32, aad: &[u8], mlen: u32, m: &[u8], out: &mut [u8]) { + let mut ctx: [u64; 25] = [0u64; 25usize]; + let mut block: [u8; 16] = [0u8; 16usize]; + crate::hacl::mac_poly1305::poly1305_init(&mut ctx, k); + if aadlen != 0u32 { + crate::hacl::aead_chacha20poly1305::poly1305_padded_32(&mut ctx, aadlen, aad) + }; + if mlen != 0u32 { + crate::hacl::aead_chacha20poly1305::poly1305_padded_32(&mut ctx, mlen, m) + }; + lowstar::endianness::store64_le(&mut (&mut block)[0usize..], aadlen as u64); + lowstar::endianness::store64_le(&mut (&mut block)[8usize..], mlen as u64); + let pre: (&mut [u64], &mut [u64]) = ctx.split_at_mut(5usize); + let acc: (&mut [u64], &mut [u64]) = pre.0.split_at_mut(0usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let u: u64 = lowstar::endianness::load64_le(&(&block)[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&(&block)[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 0x1000000u64; + let mask: u64 = b; + let f41: u64 = (&e)[4usize]; + (&mut e)[4usize] = f41 | mask; + let r: (&[u64], &[u64]) = pre.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r1: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc.1[0usize]; + let a1: u64 = acc.1[1usize]; + let a2: u64 = acc.1[2usize]; + let a3: u64 = acc.1[3usize]; + let a4: u64 = acc.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r1.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r1.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r1.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r1.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc.1[0usize] = o0; + acc.1[1usize] = o1; + acc.1[2usize] = o2; + acc.1[3usize] = o3; + acc.1[4usize] = o4; + crate::hacl::mac_poly1305::poly1305_finish(out, k, &mut ctx) +} + +/** +Encrypt a message `input` with key `key`. + +The arguments `key`, `nonce`, `data`, and `data_len` are same in encryption/decryption. +Note: Encryption and decryption can be executed in-place, i.e., `input` and `output` can point to the same memory. + +@param output Pointer to `input_len` bytes of memory where the ciphertext is written to. +@param tag Pointer to 16 bytes of memory where the mac is written to. +@param input Pointer to `input_len` bytes of memory where the message is read from. +@param input_len Length of the message. +@param data Pointer to `data_len` bytes of memory where the associated data is read from. +@param data_len Length of the associated data. +@param key Pointer to 32 bytes of memory where the AEAD key is read from. +@param nonce Pointer to 12 bytes of memory where the AEAD nonce is read from. +*/ +pub fn encrypt( + output: &mut [u8], + tag: &mut [u8], + input: &[u8], + input_len: u32, + data: &[u8], + data_len: u32, + key: &[u8], + nonce: &[u8], +) { + crate::hacl::chacha20::chacha20_encrypt(input_len, output, input, key, nonce, 1u32); + let mut tmp: [u8; 64] = [0u8; 64usize]; + let tmp_copy: [u8; 64] = [0u8; 64usize]; + crate::hacl::chacha20::chacha20_encrypt(64u32, &mut tmp, &tmp_copy, key, nonce, 0u32); + let key1: (&[u8], &[u8]) = tmp.split_at(0usize); + crate::hacl::aead_chacha20poly1305::poly1305_do_32( + key1.1, data_len, data, input_len, output, tag, + ) +} + +/** +Decrypt a ciphertext `input` with key `key`. + +The arguments `key`, `nonce`, `data`, and `data_len` are same in encryption/decryption. +Note: Encryption and decryption can be executed in-place, i.e., `output` and `input` can point to the same memory. + +If decryption succeeds, the resulting plaintext is stored in `output` and the function returns the success code 0. +If decryption fails, the array `output` remains unchanged and the function returns the error code 1. + +@param output Pointer to `input_len` bytes of memory where the message is written to. +@param input Pointer to `input_len` bytes of memory where the ciphertext is read from. +@param input_len Length of the ciphertext. +@param data Pointer to `data_len` bytes of memory where the associated data is read from. +@param data_len Length of the associated data. +@param key Pointer to 32 bytes of memory where the AEAD key is read from. +@param nonce Pointer to 12 bytes of memory where the AEAD nonce is read from. +@param tag Pointer to 16 bytes of memory where the mac is read from. + +@returns 0 on succeess; 1 on failure. +*/ +pub fn decrypt( + output: &mut [u8], + input: &[u8], + input_len: u32, + data: &[u8], + data_len: u32, + key: &[u8], + nonce: &[u8], + tag: &[u8], +) -> u32 { + let mut computed_tag: [u8; 16] = [0u8; 16usize]; + let mut tmp: [u8; 64] = [0u8; 64usize]; + let tmp_copy: [u8; 64] = [0u8; 64usize]; + crate::hacl::chacha20::chacha20_encrypt(64u32, &mut tmp, &tmp_copy, key, nonce, 0u32); + let key1: (&[u8], &[u8]) = tmp.split_at(0usize); + crate::hacl::aead_chacha20poly1305::poly1305_do_32( + key1.1, + data_len, + data, + input_len, + input, + &mut computed_tag, + ); + let mut res: [u8; 1] = [255u8; 1usize]; + krml::unroll_for!(16, "i", 0u32, 1u32, { + let uu____0: u8 = fstar::uint8::eq_mask((&computed_tag)[i as usize], tag[i as usize]); + (&mut res)[0usize] = uu____0 & (&res)[0usize] + }); + let z: u8 = (&res)[0usize]; + if z == 255u8 { + crate::hacl::chacha20::chacha20_encrypt(input_len, output, input, key, nonce, 1u32); + 0u32 + } else { + 1u32 + } +} diff --git a/chacha20poly1305/src/hacl/chacha20.rs b/chacha20poly1305/src/hacl/chacha20.rs new file mode 100644 index 000000000..88f0adb71 --- /dev/null +++ b/chacha20poly1305/src/hacl/chacha20.rs @@ -0,0 +1,190 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +//! This module contains generated hacl code. + +use libcrux_hacl_rs::prelude::*; +use libcrux_macros as krml; + +pub(crate) const chacha20_constants: [u32; 4] = + [0x61707865u32, 0x3320646eu32, 0x79622d32u32, 0x6b206574u32]; + +#[inline] +fn quarter_round(st: &mut [u32], a: u32, b: u32, c: u32, d: u32) { + let sta: u32 = st[a as usize]; + let stb: u32 = st[b as usize]; + let std: u32 = st[d as usize]; + let sta1: u32 = sta.wrapping_add(stb); + let std1: u32 = std ^ sta1; + let std2: u32 = std1.wrapping_shl(16u32) | std1.wrapping_shr(16u32); + st[a as usize] = sta1; + st[d as usize] = std2; + let sta0: u32 = st[c as usize]; + let stb0: u32 = st[d as usize]; + let std0: u32 = st[b as usize]; + let sta10: u32 = sta0.wrapping_add(stb0); + let std10: u32 = std0 ^ sta10; + let std20: u32 = std10.wrapping_shl(12u32) | std10.wrapping_shr(20u32); + st[c as usize] = sta10; + st[b as usize] = std20; + let sta2: u32 = st[a as usize]; + let stb1: u32 = st[b as usize]; + let std3: u32 = st[d as usize]; + let sta11: u32 = sta2.wrapping_add(stb1); + let std11: u32 = std3 ^ sta11; + let std21: u32 = std11.wrapping_shl(8u32) | std11.wrapping_shr(24u32); + st[a as usize] = sta11; + st[d as usize] = std21; + let sta3: u32 = st[c as usize]; + let stb2: u32 = st[d as usize]; + let std4: u32 = st[b as usize]; + let sta12: u32 = sta3.wrapping_add(stb2); + let std12: u32 = std4 ^ sta12; + let std22: u32 = std12.wrapping_shl(7u32) | std12.wrapping_shr(25u32); + st[c as usize] = sta12; + st[b as usize] = std22 +} + +#[inline] +fn double_round(st: &mut [u32]) { + crate::hacl::chacha20::quarter_round(st, 0u32, 4u32, 8u32, 12u32); + crate::hacl::chacha20::quarter_round(st, 1u32, 5u32, 9u32, 13u32); + crate::hacl::chacha20::quarter_round(st, 2u32, 6u32, 10u32, 14u32); + crate::hacl::chacha20::quarter_round(st, 3u32, 7u32, 11u32, 15u32); + crate::hacl::chacha20::quarter_round(st, 0u32, 5u32, 10u32, 15u32); + crate::hacl::chacha20::quarter_round(st, 1u32, 6u32, 11u32, 12u32); + crate::hacl::chacha20::quarter_round(st, 2u32, 7u32, 8u32, 13u32); + crate::hacl::chacha20::quarter_round(st, 3u32, 4u32, 9u32, 14u32) +} + +#[inline] +fn rounds(st: &mut [u32]) { + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st); + crate::hacl::chacha20::double_round(st) +} + +#[inline] +fn chacha20_core(k: &mut [u32], ctx: &[u32], ctr: u32) { + (k[0usize..16usize]).copy_from_slice(&ctx[0usize..16usize]); + let ctr_u32: u32 = ctr; + k[12usize] = (k[12usize]).wrapping_add(ctr_u32); + crate::hacl::chacha20::rounds(k); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let x: u32 = (k[i as usize]).wrapping_add(ctx[i as usize]); + let os: (&mut [u32], &mut [u32]) = k.split_at_mut(0usize); + os.1[i as usize] = x + }); + k[12usize] = (k[12usize]).wrapping_add(ctr_u32) +} + +fn chacha20_init(ctx: &mut [u32], k: &[u8], n: &[u8], ctr: u32) { + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = (&crate::hacl::chacha20::chacha20_constants)[i as usize]; + let os: &mut [u32] = &mut (&mut ctx[0usize..])[0usize..]; + os[i as usize] = x + }); + let uu____0: (&mut [u32], &mut [u32]) = ctx.split_at_mut(4usize); + krml::unroll_for!(8, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = k.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]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + ctx[12usize] = ctr; + let uu____1: (&mut [u32], &mut [u32]) = ctx.split_at_mut(13usize); + krml::unroll_for!(3, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = n.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]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }) +} + +fn chacha20_encrypt_block(ctx: &[u32], out: &mut [u8], incr: u32, text: &[u8]) { + let mut k: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20::chacha20_core(&mut k, ctx, incr); + let mut bl: [u32; 16] = [0u32; 16usize]; + krml::unroll_for!(16, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = text.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]) = bl.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let x: u32 = (&bl)[i as usize] ^ (&k)[i as usize]; + let os: (&mut [u32], &mut [u32]) = bl.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!( + 16, + "i", + 0u32, + 1u32, + lowstar::endianness::store32_le( + &mut out[i.wrapping_mul(4u32) as usize..], + (&bl)[i as usize] + ) + ) +} + +#[inline] +fn chacha20_encrypt_last(ctx: &[u32], len: u32, out: &mut [u8], incr: u32, text: &[u8]) { + let mut plain: [u8; 64] = [0u8; 64usize]; + ((&mut plain)[0usize..len as usize]).copy_from_slice(&text[0usize..len as usize]); + let mut plain_copy: [u8; 64] = [0u8; 64usize]; + ((&mut plain_copy)[0usize..64usize]).copy_from_slice(&(&plain)[0usize..64usize]); + crate::hacl::chacha20::chacha20_encrypt_block(ctx, &mut plain, incr, &plain_copy); + (out[0usize..len as usize]).copy_from_slice(&(&(&plain)[0usize..])[0usize..len as usize]) +} + +fn chacha20_update(ctx: &[u32], len: u32, out: &mut [u8], text: &[u8]) { + let rem: u32 = len.wrapping_rem(64u32); + let nb: u32 = len.wrapping_div(64u32); + let rem1: u32 = len.wrapping_rem(64u32); + for i in 0u32..nb { + crate::hacl::chacha20::chacha20_encrypt_block( + ctx, + &mut out[i.wrapping_mul(64u32) as usize..], + i, + &text[i.wrapping_mul(64u32) as usize..], + ) + } + if rem1 > 0u32 { + crate::hacl::chacha20::chacha20_encrypt_last( + ctx, + rem, + &mut out[nb.wrapping_mul(64u32) as usize..], + nb, + &text[nb.wrapping_mul(64u32) as usize..], + ) + } +} + +pub fn chacha20_encrypt(len: u32, out: &mut [u8], text: &[u8], key: &[u8], n: &[u8], ctr: u32) { + let mut ctx: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20::chacha20_init(&mut ctx, key, n, ctr); + crate::hacl::chacha20::chacha20_update(&ctx, len, out, text) +} + +pub fn chacha20_decrypt(len: u32, out: &mut [u8], cipher: &[u8], key: &[u8], n: &[u8], ctr: u32) { + let mut ctx: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20::chacha20_init(&mut ctx, key, n, ctr); + crate::hacl::chacha20::chacha20_update(&ctx, len, out, cipher) +} diff --git a/chacha20poly1305/src/hacl/chacha20_vec32.rs b/chacha20poly1305/src/hacl/chacha20_vec32.rs new file mode 100644 index 000000000..e78d2bfa1 --- /dev/null +++ b/chacha20poly1305/src/hacl/chacha20_vec32.rs @@ -0,0 +1,252 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +//! This module contains generated hacl code. + +use libcrux_hacl_rs::prelude::*; +use libcrux_macros as krml; + +#[inline] +fn double_round_32(st: &mut [u32]) { + st[0usize] = (st[0usize]).wrapping_add(st[4usize]); + let std: u32 = st[12usize] ^ st[0usize]; + st[12usize] = std.wrapping_shl(16u32) | std.wrapping_shr(16u32); + st[8usize] = (st[8usize]).wrapping_add(st[12usize]); + let std0: u32 = st[4usize] ^ st[8usize]; + st[4usize] = std0.wrapping_shl(12u32) | std0.wrapping_shr(20u32); + st[0usize] = (st[0usize]).wrapping_add(st[4usize]); + let std1: u32 = st[12usize] ^ st[0usize]; + st[12usize] = std1.wrapping_shl(8u32) | std1.wrapping_shr(24u32); + st[8usize] = (st[8usize]).wrapping_add(st[12usize]); + let std2: u32 = st[4usize] ^ st[8usize]; + st[4usize] = std2.wrapping_shl(7u32) | std2.wrapping_shr(25u32); + st[1usize] = (st[1usize]).wrapping_add(st[5usize]); + let std3: u32 = st[13usize] ^ st[1usize]; + st[13usize] = std3.wrapping_shl(16u32) | std3.wrapping_shr(16u32); + st[9usize] = (st[9usize]).wrapping_add(st[13usize]); + let std4: u32 = st[5usize] ^ st[9usize]; + st[5usize] = std4.wrapping_shl(12u32) | std4.wrapping_shr(20u32); + st[1usize] = (st[1usize]).wrapping_add(st[5usize]); + let std5: u32 = st[13usize] ^ st[1usize]; + st[13usize] = std5.wrapping_shl(8u32) | std5.wrapping_shr(24u32); + st[9usize] = (st[9usize]).wrapping_add(st[13usize]); + let std6: u32 = st[5usize] ^ st[9usize]; + st[5usize] = std6.wrapping_shl(7u32) | std6.wrapping_shr(25u32); + st[2usize] = (st[2usize]).wrapping_add(st[6usize]); + let std7: u32 = st[14usize] ^ st[2usize]; + st[14usize] = std7.wrapping_shl(16u32) | std7.wrapping_shr(16u32); + st[10usize] = (st[10usize]).wrapping_add(st[14usize]); + let std8: u32 = st[6usize] ^ st[10usize]; + st[6usize] = std8.wrapping_shl(12u32) | std8.wrapping_shr(20u32); + st[2usize] = (st[2usize]).wrapping_add(st[6usize]); + let std9: u32 = st[14usize] ^ st[2usize]; + st[14usize] = std9.wrapping_shl(8u32) | std9.wrapping_shr(24u32); + st[10usize] = (st[10usize]).wrapping_add(st[14usize]); + let std10: u32 = st[6usize] ^ st[10usize]; + st[6usize] = std10.wrapping_shl(7u32) | std10.wrapping_shr(25u32); + st[3usize] = (st[3usize]).wrapping_add(st[7usize]); + let std11: u32 = st[15usize] ^ st[3usize]; + st[15usize] = std11.wrapping_shl(16u32) | std11.wrapping_shr(16u32); + st[11usize] = (st[11usize]).wrapping_add(st[15usize]); + let std12: u32 = st[7usize] ^ st[11usize]; + st[7usize] = std12.wrapping_shl(12u32) | std12.wrapping_shr(20u32); + st[3usize] = (st[3usize]).wrapping_add(st[7usize]); + let std13: u32 = st[15usize] ^ st[3usize]; + st[15usize] = std13.wrapping_shl(8u32) | std13.wrapping_shr(24u32); + st[11usize] = (st[11usize]).wrapping_add(st[15usize]); + let std14: u32 = st[7usize] ^ st[11usize]; + st[7usize] = std14.wrapping_shl(7u32) | std14.wrapping_shr(25u32); + st[0usize] = (st[0usize]).wrapping_add(st[5usize]); + let std15: u32 = st[15usize] ^ st[0usize]; + st[15usize] = std15.wrapping_shl(16u32) | std15.wrapping_shr(16u32); + st[10usize] = (st[10usize]).wrapping_add(st[15usize]); + let std16: u32 = st[5usize] ^ st[10usize]; + st[5usize] = std16.wrapping_shl(12u32) | std16.wrapping_shr(20u32); + st[0usize] = (st[0usize]).wrapping_add(st[5usize]); + let std17: u32 = st[15usize] ^ st[0usize]; + st[15usize] = std17.wrapping_shl(8u32) | std17.wrapping_shr(24u32); + st[10usize] = (st[10usize]).wrapping_add(st[15usize]); + let std18: u32 = st[5usize] ^ st[10usize]; + st[5usize] = std18.wrapping_shl(7u32) | std18.wrapping_shr(25u32); + st[1usize] = (st[1usize]).wrapping_add(st[6usize]); + let std19: u32 = st[12usize] ^ st[1usize]; + st[12usize] = std19.wrapping_shl(16u32) | std19.wrapping_shr(16u32); + st[11usize] = (st[11usize]).wrapping_add(st[12usize]); + let std20: u32 = st[6usize] ^ st[11usize]; + st[6usize] = std20.wrapping_shl(12u32) | std20.wrapping_shr(20u32); + st[1usize] = (st[1usize]).wrapping_add(st[6usize]); + let std21: u32 = st[12usize] ^ st[1usize]; + st[12usize] = std21.wrapping_shl(8u32) | std21.wrapping_shr(24u32); + st[11usize] = (st[11usize]).wrapping_add(st[12usize]); + let std22: u32 = st[6usize] ^ st[11usize]; + st[6usize] = std22.wrapping_shl(7u32) | std22.wrapping_shr(25u32); + st[2usize] = (st[2usize]).wrapping_add(st[7usize]); + let std23: u32 = st[13usize] ^ st[2usize]; + st[13usize] = std23.wrapping_shl(16u32) | std23.wrapping_shr(16u32); + st[8usize] = (st[8usize]).wrapping_add(st[13usize]); + let std24: u32 = st[7usize] ^ st[8usize]; + st[7usize] = std24.wrapping_shl(12u32) | std24.wrapping_shr(20u32); + st[2usize] = (st[2usize]).wrapping_add(st[7usize]); + let std25: u32 = st[13usize] ^ st[2usize]; + st[13usize] = std25.wrapping_shl(8u32) | std25.wrapping_shr(24u32); + st[8usize] = (st[8usize]).wrapping_add(st[13usize]); + let std26: u32 = st[7usize] ^ st[8usize]; + st[7usize] = std26.wrapping_shl(7u32) | std26.wrapping_shr(25u32); + st[3usize] = (st[3usize]).wrapping_add(st[4usize]); + let std27: u32 = st[14usize] ^ st[3usize]; + st[14usize] = std27.wrapping_shl(16u32) | std27.wrapping_shr(16u32); + st[9usize] = (st[9usize]).wrapping_add(st[14usize]); + let std28: u32 = st[4usize] ^ st[9usize]; + st[4usize] = std28.wrapping_shl(12u32) | std28.wrapping_shr(20u32); + st[3usize] = (st[3usize]).wrapping_add(st[4usize]); + let std29: u32 = st[14usize] ^ st[3usize]; + st[14usize] = std29.wrapping_shl(8u32) | std29.wrapping_shr(24u32); + st[9usize] = (st[9usize]).wrapping_add(st[14usize]); + let std30: u32 = st[4usize] ^ st[9usize]; + st[4usize] = std30.wrapping_shl(7u32) | std30.wrapping_shr(25u32) +} + +#[inline] +fn chacha20_core_32(k: &mut [u32], ctx: &[u32], ctr: u32) { + (k[0usize..16usize]).copy_from_slice(&ctx[0usize..16usize]); + let ctr_u32: u32 = 1u32.wrapping_mul(ctr); + let cv: u32 = ctr_u32; + k[12usize] = (k[12usize]).wrapping_add(cv); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + crate::hacl::chacha20_vec32::double_round_32(k); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let x: u32 = (k[i as usize]).wrapping_add(ctx[i as usize]); + let os: (&mut [u32], &mut [u32]) = k.split_at_mut(0usize); + os.1[i as usize] = x + }); + k[12usize] = (k[12usize]).wrapping_add(cv) +} + +#[inline] +fn chacha20_init_32(ctx: &mut [u32], k: &[u8], n: &[u8], ctr: u32) { + let mut ctx1: [u32; 16] = [0u32; 16usize]; + krml::unroll_for!(4, "i", 0u32, 1u32, { + let x: u32 = (&crate::hacl::chacha20::chacha20_constants)[i as usize]; + let os: &mut [u32] = &mut (&mut (&mut ctx1)[0usize..])[0usize..]; + os[i as usize] = x + }); + let uu____0: (&mut [u32], &mut [u32]) = ctx1.split_at_mut(4usize); + krml::unroll_for!(8, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = k.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]) = uu____0.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + (&mut ctx1)[12usize] = ctr; + let uu____1: (&mut [u32], &mut [u32]) = ctx1.split_at_mut(13usize); + krml::unroll_for!(3, "i", 0u32, 1u32, { + let bj: (&[u8], &[u8]) = n.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]) = uu____1.1.split_at_mut(0usize); + os.1[i as usize] = x + }); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let x: u32 = (&ctx1)[i as usize]; + let os: (&mut [u32], &mut [u32]) = ctx.split_at_mut(0usize); + os.1[i as usize] = x + }); + let ctr1: u32 = 0u32; + let c12: u32 = ctx[12usize]; + ctx[12usize] = c12.wrapping_add(ctr1) +} + +pub fn chacha20_encrypt_32(len: u32, out: &mut [u8], text: &[u8], key: &[u8], n: &[u8], ctr: u32) { + let mut ctx: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_init_32(&mut ctx, key, n, ctr); + let rem: u32 = len.wrapping_rem(64u32); + let nb: u32 = len.wrapping_div(64u32); + let rem1: u32 = len.wrapping_rem(64u32); + for i in 0u32..nb { + let uu____0: (&mut [u8], &mut [u8]) = out.split_at_mut(i.wrapping_mul(64u32) as usize); + let uu____1: (&[u8], &[u8]) = text.split_at(i.wrapping_mul(64u32) as usize); + let mut k: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, i); + krml::unroll_for!(16, "i0", 0u32, 1u32, { + let u: u32 = + lowstar::endianness::load32_le(&uu____1.1[i0.wrapping_mul(4u32) as usize..]); + let x: u32 = u; + let y: u32 = x ^ (&k)[i0 as usize]; + lowstar::endianness::store32_le(&mut uu____0.1[i0.wrapping_mul(4u32) as usize..], y) + }) + } + if rem1 > 0u32 { + let uu____2: (&mut [u8], &mut [u8]) = out.split_at_mut(nb.wrapping_mul(64u32) as usize); + let mut plain: [u8; 64] = [0u8; 64usize]; + ((&mut plain)[0usize..rem as usize]) + .copy_from_slice(&(&text[nb.wrapping_mul(64u32) as usize..])[0usize..rem as usize]); + let mut k: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, nb); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let u: u32 = lowstar::endianness::load32_le(&(&plain)[i.wrapping_mul(4u32) as usize..]); + let x: u32 = u; + let y: u32 = x ^ (&k)[i as usize]; + lowstar::endianness::store32_le(&mut (&mut plain)[i.wrapping_mul(4u32) as usize..], y) + }); + (uu____2.1[0usize..rem as usize]) + .copy_from_slice(&(&(&plain)[0usize..])[0usize..rem as usize]) + } +} + +pub fn chacha20_decrypt_32( + len: u32, + out: &mut [u8], + cipher: &[u8], + key: &[u8], + n: &[u8], + ctr: u32, +) { + let mut ctx: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_init_32(&mut ctx, key, n, ctr); + let rem: u32 = len.wrapping_rem(64u32); + let nb: u32 = len.wrapping_div(64u32); + let rem1: u32 = len.wrapping_rem(64u32); + for i in 0u32..nb { + let uu____0: (&mut [u8], &mut [u8]) = out.split_at_mut(i.wrapping_mul(64u32) as usize); + let uu____1: (&[u8], &[u8]) = cipher.split_at(i.wrapping_mul(64u32) as usize); + let mut k: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, i); + krml::unroll_for!(16, "i0", 0u32, 1u32, { + let u: u32 = + lowstar::endianness::load32_le(&uu____1.1[i0.wrapping_mul(4u32) as usize..]); + let x: u32 = u; + let y: u32 = x ^ (&k)[i0 as usize]; + lowstar::endianness::store32_le(&mut uu____0.1[i0.wrapping_mul(4u32) as usize..], y) + }) + } + if rem1 > 0u32 { + let uu____2: (&mut [u8], &mut [u8]) = out.split_at_mut(nb.wrapping_mul(64u32) as usize); + let mut plain: [u8; 64] = [0u8; 64usize]; + ((&mut plain)[0usize..rem as usize]) + .copy_from_slice(&(&cipher[nb.wrapping_mul(64u32) as usize..])[0usize..rem as usize]); + let mut k: [u32; 16] = [0u32; 16usize]; + crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, nb); + krml::unroll_for!(16, "i", 0u32, 1u32, { + let u: u32 = lowstar::endianness::load32_le(&(&plain)[i.wrapping_mul(4u32) as usize..]); + let x: u32 = u; + let y: u32 = x ^ (&k)[i as usize]; + lowstar::endianness::store32_le(&mut (&mut plain)[i.wrapping_mul(4u32) as usize..], y) + }); + (uu____2.1[0usize..rem as usize]) + .copy_from_slice(&(&(&plain)[0usize..])[0usize..rem as usize]) + } +} diff --git a/chacha20poly1305/src/impl_hacl.rs b/chacha20poly1305/src/impl_hacl.rs new file mode 100644 index 000000000..44223e6bf --- /dev/null +++ b/chacha20poly1305/src/impl_hacl.rs @@ -0,0 +1,112 @@ +use crate::{AeadError, MacError, KEY_LEN, NONCE_LEN, TAG_LEN}; + +/// The ChaCha20-Poly1305 AEAD encryption function. Writes the concatenation of the ciphertexoft +/// produced by ChaCha20 and the MAC tag into `ctxt` and returns the two pieces separately. +/// +/// This implementation is backed by hacl-rs and can only handle inputs up to a length of `u32::MAX`. +/// When provided longer values, this function will return an error. +pub fn encrypt<'a>( + key: &[u8; KEY_LEN], + ptxt: &[u8], + ctxt: &'a mut [u8], + aad: &[u8], + nonce: &[u8; NONCE_LEN], +) -> Result<(&'a [u8], &'a [u8; TAG_LEN]), AeadError> { + let ptxt_len: u32 = ptxt + .len() + .try_into() + .map_err(|_| AeadError::PlaintextTooLarge)?; + + let aad_len: u32 = aad.len().try_into().map_err(|_| AeadError::AadTooLarge)?; + + if ctxt.len() < ptxt.len() + TAG_LEN { + return Err(AeadError::CiphertextTooShort); + } + + // ensure destination slice has just the right length + let ctxt_len = ptxt.len() + TAG_LEN; + let ctxtu32 = &mut ctxt[..ctxt_len]; + + let (ctxt_cpa, tag) = ctxt.split_at_mut(ptxt.len()); + let tag: &mut [u8; TAG_LEN] = tag.try_into().unwrap(); + + crate::hacl::aead_chacha20poly1305::encrypt( + ctxt_cpa, tag, ptxt, ptxt_len, aad, aad_len, key, nonce, + ); + + Ok((ctxt_cpa, tag)) +} + +/// The ChaCha20-Poly1305 AEAD decryption function. Writes the result of the decryption to `ptxt`, +/// and returns the slice of appropriate length. +/// +/// This implementation is backed by hacl-rs and can only handle inputs up to a length of `u32::MAX`. +/// When provided longer values, this function will return an error. +pub fn decrypt<'a>( + key: &[u8; KEY_LEN], + ptxt: &'a mut [u8], + ctxt: &[u8], + aad: &[u8], + nonce: &[u8; NONCE_LEN], +) -> Result<&'a [u8], AeadError> { + if ctxt.len() < TAG_LEN { + return Err(AeadError::InvalidCiphertext); + } + + if ptxt.len() < ctxt.len() - TAG_LEN { + return Err(AeadError::PlaintextTooShort); + } + + let ctxt_len: u32 = ctxt + .len() + .try_into() + .map_err(|_| AeadError::CiphertextTooLarge)?; + + let aad_len: u32 = aad.len().try_into().map_err(|_| AeadError::AadTooLarge)?; + + let (ctxt_cpa, tag) = ctxt.split_at(ctxt.len() - TAG_LEN); + let ptxt = &mut ptxt[..ctxt_cpa.len()]; + + // this call should only ever produce 0 or 1, where 0 is success and 1 is error + match crate::hacl::aead_chacha20poly1305::decrypt( + ptxt, ctxt_cpa, ctxt_len, aad, aad_len, key, nonce, tag, + ) { + 0 => Ok(ptxt), + _ => Err(AeadError::InvalidCiphertext), + } +} + +/// The ChaCha20-Poly1305 AEAD decryption function. Writes the result of the decryption to `ptxt`, +/// and returns the slice of appropriate length. +/// +/// This implementation is backed by hacl-rs and can only handle inputs up to a length of `u32::MAX`. +/// When provided longer values, this function will return an error. +pub fn decrypt_detached<'a>( + key: &[u8; KEY_LEN], + ptxt: &'a mut [u8], + ctxt: &[u8], + tag: &[u8; TAG_LEN], + aad: &[u8], + nonce: &[u8; NONCE_LEN], +) -> Result<&'a [u8], AeadError> { + if ptxt.len() < ctxt.len() { + return Err(AeadError::PlaintextTooShort); + } + + let ctxt_len: u32 = ctxt + .len() + .try_into() + .map_err(|_| AeadError::CiphertextTooLarge)?; + + let aad_len: u32 = aad.len().try_into().map_err(|_| AeadError::AadTooLarge)?; + + let ptxt = &mut ptxt[..ctxt.len()]; + + // this call should only ever produce 0 or 1, where 0 is success and 1 is error + match crate::hacl::aead_chacha20poly1305::decrypt( + ptxt, ctxt, ctxt_len, aad, aad_len, key, nonce, tag, + ) { + 0 => Ok(ptxt), + _ => Err(AeadError::InvalidCiphertext), + } +} diff --git a/chacha20poly1305/src/lib.rs b/chacha20poly1305/src/lib.rs new file mode 100644 index 000000000..c4cd612c7 --- /dev/null +++ b/chacha20poly1305/src/lib.rs @@ -0,0 +1,51 @@ +#![no_std] + +/// The length of ChaCha20-Poly1305 keys. +pub const KEY_LEN: usize = 32; + +/// The length of Poly1305 MAC tags. +pub const TAG_LEN: usize = 16; + +/// The length of ChaCha20-Poly1305 nonces. +pub const NONCE_LEN: usize = 12; + +/// Describes the error conditions of the ChaCha20-Poly1305 AEAD. +pub enum AeadError { + /// Indicates that the plaintext argument is too large for the library to handle. + PlaintextTooLarge, + /// Indicates that the ciphertext argument is too large for the library to handle. + CiphertextTooLarge, + /// Indicates that the associated data argument is too large for the library to handle. + AadTooLarge, + /// This indicates that the provided destination ciphertext does not fit the ciphertext and tag. + CiphertextTooShort, + /// This indicates that the provided destination plaintext is shorter than `ctxt.len() - TAG_LEN` + /// and thus will not fit the decrypted plaintext + PlaintextTooShort, + /// Indicates that the ciphertext is not a valid encryption under the given key and nonce. + InvalidCiphertext, +} + +/// Describes the error conditions of the Poly1305 MAC. +pub enum MacError { + /// Indicates that the message argument is too large for the library to handle. + MessageTooLarge, + + /// Indicates that the MAC tag is invalid for that key and message. + InvalidMacTag, +} + +#[cfg(feature = "hacl")] +mod hacl { + pub(crate) use libcrux_poly1305::hacl::mac_poly1305; + + pub(crate) mod aead_chacha20poly1305; + pub(crate) mod chacha20; + pub(crate) mod chacha20_vec32; +} + +#[cfg(feature = "hacl")] +mod impl_hacl; + +#[cfg(feature = "hacl")] +pub use impl_hacl::*; diff --git a/poly1305/Cargo.toml b/poly1305/Cargo.toml new file mode 100644 index 000000000..e7300cf29 --- /dev/null +++ b/poly1305/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "libcrux-poly1305" +description = "Formally verified Poly1305 MAC library" + +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[features] +default = ["hacl"] +hacl = ["dep:libcrux-hacl-rs", "dep:libcrux-macros"] +expose-hacl = ["hacl"] + +[dependencies] +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } diff --git a/poly1305/src/hacl/mac_poly1305.rs b/poly1305/src/hacl/mac_poly1305.rs new file mode 100644 index 000000000..cb964e4d7 --- /dev/null +++ b/poly1305/src/hacl/mac_poly1305.rs @@ -0,0 +1,612 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +//! This module contains generated hacl code. + +use libcrux_hacl_rs::prelude::*; + +pub fn poly1305_init(ctx: &mut [u64], key: &[u8]) { + let acc: (&mut [u64], &mut [u64]) = ctx.split_at_mut(0usize); + let pre: (&mut [u64], &mut [u64]) = acc.1.split_at_mut(5usize); + let kr: (&[u8], &[u8]) = key.split_at(0usize); + pre.0[0usize] = 0u64; + pre.0[1usize] = 0u64; + pre.0[2usize] = 0u64; + pre.0[3usize] = 0u64; + pre.0[4usize] = 0u64; + let u: u64 = lowstar::endianness::load64_le(&kr.1[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&kr.1[8usize..]); + let hi: u64 = u0; + let mask0: u64 = 0x0ffffffc0fffffffu64; + let mask1: u64 = 0x0ffffffc0ffffffcu64; + let lo1: u64 = lo & mask0; + let hi1: u64 = hi & mask1; + let r: (&mut [u64], &mut [u64]) = pre.1.split_at_mut(0usize); + let r5: (&mut [u64], &mut [u64]) = r.1.split_at_mut(5usize); + let rn: (&mut [u64], &mut [u64]) = r5.1.split_at_mut(5usize); + let rn_5: (&mut [u64], &mut [u64]) = rn.1.split_at_mut(5usize); + let r_vec0: u64 = lo1; + let r_vec1: u64 = hi1; + let f0: u64 = r_vec0 & 0x3ffffffu64; + let f1: u64 = r_vec0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = r_vec0.wrapping_shr(52u32) | (r_vec1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = r_vec1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = r_vec1.wrapping_shr(40u32); + let f00: u64 = f0; + let f10: u64 = f1; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + r5.0[0usize] = f00; + r5.0[1usize] = f10; + r5.0[2usize] = f20; + r5.0[3usize] = f30; + r5.0[4usize] = f40; + let f200: u64 = r5.0[0usize]; + let f21: u64 = r5.0[1usize]; + let f22: u64 = r5.0[2usize]; + let f23: u64 = r5.0[3usize]; + let f24: u64 = r5.0[4usize]; + rn.0[0usize] = f200.wrapping_mul(5u64); + rn.0[1usize] = f21.wrapping_mul(5u64); + rn.0[2usize] = f22.wrapping_mul(5u64); + rn.0[3usize] = f23.wrapping_mul(5u64); + rn.0[4usize] = f24.wrapping_mul(5u64); + rn_5.0[0usize] = r5.0[0usize]; + rn_5.0[1usize] = r5.0[1usize]; + rn_5.0[2usize] = r5.0[2usize]; + rn_5.0[3usize] = r5.0[3usize]; + rn_5.0[4usize] = r5.0[4usize]; + rn_5.1[0usize] = rn.0[0usize]; + rn_5.1[1usize] = rn.0[1usize]; + rn_5.1[2usize] = rn.0[2usize]; + rn_5.1[3usize] = rn.0[3usize]; + rn_5.1[4usize] = rn.0[4usize] +} + +fn poly1305_update(ctx: &mut [u64], len: u32, text: &[u8]) { + let pre: (&mut [u64], &mut [u64]) = ctx.split_at_mut(5usize); + let acc: (&mut [u64], &mut [u64]) = pre.0.split_at_mut(0usize); + let nb: u32 = len.wrapping_div(16u32); + let rem: u32 = len.wrapping_rem(16u32); + for i in 0u32..nb { + let block: (&[u8], &[u8]) = text.split_at(i.wrapping_mul(16u32) as usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let u: u64 = lowstar::endianness::load64_le(&block.1[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&block.1[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 0x1000000u64; + let mask: u64 = b; + let f41: u64 = (&e)[4usize]; + (&mut e)[4usize] = f41 | mask; + let r: (&[u64], &[u64]) = pre.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r1: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc.1[0usize]; + let a1: u64 = acc.1[1usize]; + let a2: u64 = acc.1[2usize]; + let a3: u64 = acc.1[3usize]; + let a4: u64 = acc.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r1.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r1.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r1.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r1.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc.1[0usize] = o0; + acc.1[1usize] = o1; + acc.1[2usize] = o2; + acc.1[3usize] = o3; + acc.1[4usize] = o4 + } + if rem > 0u32 { + let last: (&[u8], &[u8]) = text.split_at(nb.wrapping_mul(16u32) as usize); + let mut e: [u64; 5] = [0u64; 5usize]; + let mut tmp: [u8; 16] = [0u8; 16usize]; + ((&mut tmp)[0usize..rem as usize]).copy_from_slice(&last.1[0usize..rem as usize]); + let u: u64 = lowstar::endianness::load64_le(&(&tmp)[0usize..]); + let lo: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&(&tmp)[8usize..]); + let hi: u64 = u0; + let f0: u64 = lo; + let f1: u64 = hi; + let f01: u64 = f0 & 0x3ffffffu64; + let f11: u64 = f0.wrapping_shr(26u32) & 0x3ffffffu64; + let f2: u64 = f0.wrapping_shr(52u32) | (f1 & 0x3fffu64).wrapping_shl(12u32); + let f3: u64 = f1.wrapping_shr(14u32) & 0x3ffffffu64; + let f4: u64 = f1.wrapping_shr(40u32); + let f010: u64 = f01; + let f110: u64 = f11; + let f20: u64 = f2; + let f30: u64 = f3; + let f40: u64 = f4; + (&mut e)[0usize] = f010; + (&mut e)[1usize] = f110; + (&mut e)[2usize] = f20; + (&mut e)[3usize] = f30; + (&mut e)[4usize] = f40; + let b: u64 = 1u64.wrapping_shl(rem.wrapping_mul(8u32).wrapping_rem(26u32)); + let mask: u64 = b; + let fi: u64 = (&e)[rem.wrapping_mul(8u32).wrapping_div(26u32) as usize]; + (&mut e)[rem.wrapping_mul(8u32).wrapping_div(26u32) as usize] = fi | mask; + let r: (&[u64], &[u64]) = pre.1.split_at(0usize); + let r5: (&[u64], &[u64]) = r.1.split_at(5usize); + let r0: u64 = r5.0[0usize]; + let r1: u64 = r5.0[1usize]; + let r2: u64 = r5.0[2usize]; + let r3: u64 = r5.0[3usize]; + let r4: u64 = r5.0[4usize]; + let r51: u64 = r5.1[1usize]; + let r52: u64 = r5.1[2usize]; + let r53: u64 = r5.1[3usize]; + let r54: u64 = r5.1[4usize]; + let f10: u64 = (&e)[0usize]; + let f111: u64 = (&e)[1usize]; + let f12: u64 = (&e)[2usize]; + let f13: u64 = (&e)[3usize]; + let f14: u64 = (&e)[4usize]; + let a0: u64 = acc.1[0usize]; + let a1: u64 = acc.1[1usize]; + let a2: u64 = acc.1[2usize]; + let a3: u64 = acc.1[3usize]; + let a4: u64 = acc.1[4usize]; + let a01: u64 = a0.wrapping_add(f10); + let a11: u64 = a1.wrapping_add(f111); + let a21: u64 = a2.wrapping_add(f12); + let a31: u64 = a3.wrapping_add(f13); + let a41: u64 = a4.wrapping_add(f14); + let a02: u64 = r0.wrapping_mul(a01); + let a12: u64 = r1.wrapping_mul(a01); + let a22: u64 = r2.wrapping_mul(a01); + let a32: u64 = r3.wrapping_mul(a01); + let a42: u64 = r4.wrapping_mul(a01); + let a03: u64 = a02.wrapping_add(r54.wrapping_mul(a11)); + let a13: u64 = a12.wrapping_add(r0.wrapping_mul(a11)); + let a23: u64 = a22.wrapping_add(r1.wrapping_mul(a11)); + let a33: u64 = a32.wrapping_add(r2.wrapping_mul(a11)); + let a43: u64 = a42.wrapping_add(r3.wrapping_mul(a11)); + let a04: u64 = a03.wrapping_add(r53.wrapping_mul(a21)); + let a14: u64 = a13.wrapping_add(r54.wrapping_mul(a21)); + let a24: u64 = a23.wrapping_add(r0.wrapping_mul(a21)); + let a34: u64 = a33.wrapping_add(r1.wrapping_mul(a21)); + let a44: u64 = a43.wrapping_add(r2.wrapping_mul(a21)); + let a05: u64 = a04.wrapping_add(r52.wrapping_mul(a31)); + let a15: u64 = a14.wrapping_add(r53.wrapping_mul(a31)); + let a25: u64 = a24.wrapping_add(r54.wrapping_mul(a31)); + let a35: u64 = a34.wrapping_add(r0.wrapping_mul(a31)); + let a45: u64 = a44.wrapping_add(r1.wrapping_mul(a31)); + let a06: u64 = a05.wrapping_add(r51.wrapping_mul(a41)); + let a16: u64 = a15.wrapping_add(r52.wrapping_mul(a41)); + let a26: u64 = a25.wrapping_add(r53.wrapping_mul(a41)); + let a36: u64 = a35.wrapping_add(r54.wrapping_mul(a41)); + let a46: u64 = a45.wrapping_add(r0.wrapping_mul(a41)); + let t0: u64 = a06; + let t1: u64 = a16; + let t2: u64 = a26; + let t3: u64 = a36; + let t4: u64 = a46; + let mask26: u64 = 0x3ffffffu64; + let z0: u64 = t0.wrapping_shr(26u32); + let z1: u64 = t3.wrapping_shr(26u32); + let x0: u64 = t0 & mask26; + let x3: u64 = t3 & mask26; + let x1: u64 = t1.wrapping_add(z0); + let x4: u64 = t4.wrapping_add(z1); + let z01: u64 = x1.wrapping_shr(26u32); + let z11: u64 = x4.wrapping_shr(26u32); + let t: u64 = z11.wrapping_shl(2u32); + let z12: u64 = z11.wrapping_add(t); + let x11: u64 = x1 & mask26; + let x41: u64 = x4 & mask26; + let x2: u64 = t2.wrapping_add(z01); + let x01: u64 = x0.wrapping_add(z12); + let z02: u64 = x2.wrapping_shr(26u32); + let z13: u64 = x01.wrapping_shr(26u32); + let x21: u64 = x2 & mask26; + let x02: u64 = x01 & mask26; + let x31: u64 = x3.wrapping_add(z02); + let x12: u64 = x11.wrapping_add(z13); + let z03: u64 = x31.wrapping_shr(26u32); + let x32: u64 = x31 & mask26; + let x42: u64 = x41.wrapping_add(z03); + let o0: u64 = x02; + let o1: u64 = x12; + let o2: u64 = x21; + let o3: u64 = x32; + let o4: u64 = x42; + acc.1[0usize] = o0; + acc.1[1usize] = o1; + acc.1[2usize] = o2; + acc.1[3usize] = o3; + acc.1[4usize] = o4 + } +} + +pub fn poly1305_finish(tag: &mut [u8], key: &[u8], ctx: &mut [u64]) { + let acc: (&mut [u64], &mut [u64]) = ctx.split_at_mut(0usize); + let ks: (&[u8], &[u8]) = key.split_at(16usize); + let f0: u64 = acc.1[0usize]; + let f1: u64 = acc.1[1usize]; + let f2: u64 = acc.1[2usize]; + let f3: u64 = acc.1[3usize]; + let f4: u64 = acc.1[4usize]; + let l: u64 = f0.wrapping_add(0u64); + let tmp0: u64 = l & 0x3ffffffu64; + let c0: u64 = l.wrapping_shr(26u32); + let l0: u64 = f1.wrapping_add(c0); + let tmp1: u64 = l0 & 0x3ffffffu64; + let c1: u64 = l0.wrapping_shr(26u32); + let l1: u64 = f2.wrapping_add(c1); + let tmp2: u64 = l1 & 0x3ffffffu64; + let c2: u64 = l1.wrapping_shr(26u32); + let l2: u64 = f3.wrapping_add(c2); + let tmp3: u64 = l2 & 0x3ffffffu64; + let c3: u64 = l2.wrapping_shr(26u32); + let l3: u64 = f4.wrapping_add(c3); + let tmp4: u64 = l3 & 0x3ffffffu64; + let c4: u64 = l3.wrapping_shr(26u32); + let f01: u64 = tmp0.wrapping_add(c4.wrapping_mul(5u64)); + let f11: u64 = tmp1; + let f21: u64 = tmp2; + let f31: u64 = tmp3; + let f41: u64 = tmp4; + let l4: u64 = f01.wrapping_add(0u64); + let tmp00: u64 = l4 & 0x3ffffffu64; + let c00: u64 = l4.wrapping_shr(26u32); + let l5: u64 = f11.wrapping_add(c00); + let tmp10: u64 = l5 & 0x3ffffffu64; + let c10: u64 = l5.wrapping_shr(26u32); + let l6: u64 = f21.wrapping_add(c10); + let tmp20: u64 = l6 & 0x3ffffffu64; + let c20: u64 = l6.wrapping_shr(26u32); + let l7: u64 = f31.wrapping_add(c20); + let tmp30: u64 = l7 & 0x3ffffffu64; + let c30: u64 = l7.wrapping_shr(26u32); + let l8: u64 = f41.wrapping_add(c30); + let tmp40: u64 = l8 & 0x3ffffffu64; + let c40: u64 = l8.wrapping_shr(26u32); + let f02: u64 = tmp00.wrapping_add(c40.wrapping_mul(5u64)); + let f12: u64 = tmp10; + let f22: u64 = tmp20; + let f32: u64 = tmp30; + let f42: u64 = tmp40; + let mh: u64 = 0x3ffffffu64; + let ml: u64 = 0x3fffffbu64; + let mask: u64 = fstar::uint64::eq_mask(f42, mh); + let mask1: u64 = mask & fstar::uint64::eq_mask(f32, mh); + let mask2: u64 = mask1 & fstar::uint64::eq_mask(f22, mh); + let mask3: u64 = mask2 & fstar::uint64::eq_mask(f12, mh); + let mask4: u64 = mask3 & !!fstar::uint64::gte_mask(f02, ml); + let ph: u64 = mask4 & mh; + let pl: u64 = mask4 & ml; + let o0: u64 = f02.wrapping_sub(pl); + let o1: u64 = f12.wrapping_sub(ph); + let o2: u64 = f22.wrapping_sub(ph); + let o3: u64 = f32.wrapping_sub(ph); + let o4: u64 = f42.wrapping_sub(ph); + let f010: u64 = o0; + let f110: u64 = o1; + let f210: u64 = o2; + let f310: u64 = o3; + let f410: u64 = o4; + acc.1[0usize] = f010; + acc.1[1usize] = f110; + acc.1[2usize] = f210; + acc.1[3usize] = f310; + acc.1[4usize] = f410; + let f00: u64 = acc.1[0usize]; + let f10: u64 = acc.1[1usize]; + let f20: u64 = acc.1[2usize]; + let f30: u64 = acc.1[3usize]; + let f40: u64 = acc.1[4usize]; + let f011: u64 = f00; + let f111: u64 = f10; + let f211: u64 = f20; + let f311: u64 = f30; + let f411: u64 = f40; + let lo: u64 = f011 | f111.wrapping_shl(26u32) | f211.wrapping_shl(52u32); + let hi: u64 = f211.wrapping_shr(12u32) | f311.wrapping_shl(14u32) | f411.wrapping_shl(40u32); + let f100: u64 = lo; + let f112: u64 = hi; + let u: u64 = lowstar::endianness::load64_le(&ks.1[0usize..]); + let lo0: u64 = u; + let u0: u64 = lowstar::endianness::load64_le(&ks.1[8usize..]); + let hi0: u64 = u0; + let f200: u64 = lo0; + let f212: u64 = hi0; + let r0: u64 = f100.wrapping_add(f200); + let r1: u64 = f112.wrapping_add(f212); + let c: u64 = (r0 ^ (r0 ^ f200 | r0.wrapping_sub(f200) ^ f200)).wrapping_shr(63u32); + let r11: u64 = r1.wrapping_add(c); + let f300: u64 = r0; + let f312: u64 = r11; + lowstar::endianness::store64_le(&mut tag[0usize..], f300); + lowstar::endianness::store64_le(&mut tag[8usize..], f312) +} + +#[derive(PartialEq, Clone)] +pub struct state_t { + pub block_state: Box<[u64]>, + pub buf: Box<[u8]>, + pub total_len: u64, + pub p_key: Box<[u8]>, +} + +pub fn malloc(key: &[u8]) -> Box<[crate::hacl::mac_poly1305::state_t]> { + let buf: Box<[u8]> = vec![0u8; 16usize].into_boxed_slice(); + let mut r1: Box<[u64]> = vec![0u64; 25usize].into_boxed_slice(); + let block_state: &mut [u64] = &mut r1; + crate::hacl::mac_poly1305::poly1305_init(block_state, key); + let mut k·: Box<[u8]> = vec![0u8; 32usize].into_boxed_slice(); + ((&mut k·)[0usize..32usize]).copy_from_slice(&key[0usize..32usize]); + let k·0: &[u8] = &k·; + let s: crate::hacl::mac_poly1305::state_t = crate::hacl::mac_poly1305::state_t { + block_state: (*block_state).into(), + buf, + total_len: 0u32 as u64, + p_key: (*k·0).into(), + }; + let p: Box<[crate::hacl::mac_poly1305::state_t]> = vec![s].into_boxed_slice(); + p +} + +pub fn reset(state: &mut [crate::hacl::mac_poly1305::state_t], key: &[u8]) { + let block_state: &mut [u64] = &mut (state[0usize]).block_state; + let k·: &mut [u8] = &mut (state[0usize]).p_key; + crate::hacl::mac_poly1305::poly1305_init(block_state, key); + (k·[0usize..32usize]).copy_from_slice(&key[0usize..32usize]); + let k·1: &[u8] = k·; + let total_len: u64 = 0u32 as u64; + (state[0usize]).total_len = total_len; + (state[0usize]).p_key = (*k·1).into() +} + +/** +0 = success, 1 = max length exceeded +*/ +pub fn update( + state: &mut [crate::hacl::mac_poly1305::state_t], + chunk: &[u8], + chunk_len: u32, +) -> streaming_types::error_code { + let block_state: &mut [u64] = &mut (state[0usize]).block_state; + let total_len: u64 = (state[0usize]).total_len; + if chunk_len as u64 > 0xffffffffu64.wrapping_sub(total_len) { + streaming_types::error_code::MaximumLengthExceeded + } else { + let sz: u32 = if total_len.wrapping_rem(16u32 as u64) == 0u64 && total_len > 0u64 { + 16u32 + } else { + total_len.wrapping_rem(16u32 as u64) as u32 + }; + if chunk_len <= 16u32.wrapping_sub(sz) { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let k·1: &[u8] = &(state[0usize]).p_key; + let sz1: u32 = if total_len1.wrapping_rem(16u32 as u64) == 0u64 && total_len1 > 0u64 { + 16u32 + } else { + total_len1.wrapping_rem(16u32 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; + (state[0usize]).p_key = (*k·1).into() + } else if sz == 0u32 { + let buf: &mut [u8] = &mut (state[0usize]).buf; + let total_len1: u64 = (state[0usize]).total_len; + let k·1: &[u8] = &(state[0usize]).p_key; + let sz1: u32 = if total_len1.wrapping_rem(16u32 as u64) == 0u64 && total_len1 > 0u64 { + 16u32 + } else { + total_len1.wrapping_rem(16u32 as u64) as u32 + }; + if sz1 != 0u32 { + crate::hacl::mac_poly1305::poly1305_update(block_state, 16u32, buf) + }; + let ite: u32 = if (chunk_len as u64).wrapping_rem(16u32 as u64) == 0u64 + && chunk_len as u64 > 0u64 + { + 16u32 + } else { + (chunk_len as u64).wrapping_rem(16u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len.wrapping_sub(ite).wrapping_div(16u32); + let data1_len: u32 = n_blocks.wrapping_mul(16u32); + 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); + crate::hacl::mac_poly1305::poly1305_update(block_state, data1_len, data2.0); + 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); + (state[0usize]).p_key = (*k·1).into() + } else { + let diff: u32 = 16u32.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 k·1: &[u8] = &(state[0usize]).p_key; + let sz1: u32 = if total_len1.wrapping_rem(16u32 as u64) == 0u64 && total_len1 > 0u64 { + 16u32 + } else { + total_len1.wrapping_rem(16u32 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; + (state[0usize]).p_key = (*k·1).into() + }; + let buf0: &mut [u8] = &mut (state[0usize]).buf; + let total_len10: u64 = (state[0usize]).total_len; + let k·10: &[u8] = &(state[0usize]).p_key; + let sz10: u32 = if total_len10.wrapping_rem(16u32 as u64) == 0u64 && total_len10 > 0u64 + { + 16u32 + } else { + total_len10.wrapping_rem(16u32 as u64) as u32 + }; + if sz10 != 0u32 { + crate::hacl::mac_poly1305::poly1305_update(block_state, 16u32, buf0) + }; + let ite: u32 = if (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(16u32 as u64) + == 0u64 + && chunk_len.wrapping_sub(diff) as u64 > 0u64 + { + 16u32 + } else { + (chunk_len.wrapping_sub(diff) as u64).wrapping_rem(16u32 as u64) as u32 + }; + let n_blocks: u32 = chunk_len + .wrapping_sub(diff) + .wrapping_sub(ite) + .wrapping_div(16u32); + let data1_len: u32 = n_blocks.wrapping_mul(16u32); + 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); + crate::hacl::mac_poly1305::poly1305_update(block_state, data1_len, data2.0); + 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); + (state[0usize]).p_key = (*k·10).into() + }; + streaming_types::error_code::Success + } +} + +pub fn digest(state: &[crate::hacl::mac_poly1305::state_t], output: &mut [u8]) { + let block_state: &[u64] = &(state[0usize]).block_state; + let buf_: &[u8] = &(state[0usize]).buf; + let total_len: u64 = (state[0usize]).total_len; + let k·: &[u8] = &(state[0usize]).p_key; + let r: u32 = if total_len.wrapping_rem(16u32 as u64) == 0u64 && total_len > 0u64 { + 16u32 + } else { + total_len.wrapping_rem(16u32 as u64) as u32 + }; + let buf_1: (&[u8], &[u8]) = buf_.split_at(0usize); + let mut r1: [u64; 25] = [0u64; 25usize]; + let tmp_block_state: &mut [u64] = &mut r1; + (tmp_block_state[0usize..25usize]).copy_from_slice(&block_state[0usize..25usize]); + let buf_multi: (&[u8], &[u8]) = buf_1.1.split_at(0usize); + let ite: u32 = if r.wrapping_rem(16u32) == 0u32 && r > 0u32 { + 16u32 + } else { + r.wrapping_rem(16u32) + }; + let buf_last: (&[u8], &[u8]) = buf_multi.1.split_at(r.wrapping_sub(ite) as usize); + crate::hacl::mac_poly1305::poly1305_update(tmp_block_state, 0u32, buf_last.0); + crate::hacl::mac_poly1305::poly1305_update(tmp_block_state, r, buf_last.1); + let mut tmp: [u64; 25] = [0u64; 25usize]; + ((&mut tmp)[0usize..25usize]).copy_from_slice(&tmp_block_state[0usize..25usize]); + crate::hacl::mac_poly1305::poly1305_finish(output, k·, &mut tmp) +} + +pub fn mac(output: &mut [u8], input: &[u8], input_len: u32, key: &[u8]) { + let mut ctx: [u64; 25] = [0u64; 25usize]; + crate::hacl::mac_poly1305::poly1305_init(&mut ctx, key); + crate::hacl::mac_poly1305::poly1305_update(&mut ctx, input_len, input); + crate::hacl::mac_poly1305::poly1305_finish(output, key, &mut ctx) +} diff --git a/poly1305/src/impl_hacl.rs b/poly1305/src/impl_hacl.rs new file mode 100644 index 000000000..48607ad18 --- /dev/null +++ b/poly1305/src/impl_hacl.rs @@ -0,0 +1,12 @@ +use crate::{Error, KEY_LEN, TAG_LEN}; + +/// Computes the Poly1305 MAC tag for the provided `key` and `msg` and writes it into `tag`. +/// +/// Returns an error if `msg` is longer than u32::MAX. +pub fn mac(key: &[u8; KEY_LEN], msg: &[u8], tag: &mut [u8; TAG_LEN]) -> Result<(), Error> { + let msg_len: u32 = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; + + crate::hacl::mac_poly1305::mac(tag, msg, msg_len, key); + + Ok(()) +} diff --git a/poly1305/src/lib.rs b/poly1305/src/lib.rs new file mode 100644 index 000000000..d940f8aae --- /dev/null +++ b/poly1305/src/lib.rs @@ -0,0 +1,32 @@ +#![no_std] + +/// The length of ChaCha20-Poly1305 keys. +pub const KEY_LEN: usize = 16; + +/// The length of Poly1305 MAC tags. +pub const TAG_LEN: usize = 16; + +/// Describes the error conditions of the Poly1305 MAC. +pub enum Error { + /// Indicates that the message argument is too large for the library to handle. + MessageTooLarge, + + /// Indicates that the MAC tag is invalid for that key and message. + InvalidMacTag, +} + +#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +mod hacl { + pub(crate) mod mac_poly1305; +} + +#[cfg(feature = "expose-hacl")] +pub mod hacl { + pub mod mac_poly1305; +} + +#[cfg(feature = "hacl")] +mod impl_hacl; + +#[cfg(feature = "hacl")] +pub use impl_hacl::*; From 8b97b582b63224bd73285a0fc61667b9a5c7dd65 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Tue, 3 Dec 2024 18:30:40 +0100 Subject: [PATCH 05/13] Start work on RSA - extraction might be wrong --- Cargo.toml | 2 +- rsa/Cargo.toml | 24 ++ rsa/src/hacl/rsapss.rs | 936 +++++++++++++++++++++++++++++++++++++++++ rsa/src/impl_hacl.rs | 159 +++++++ rsa/src/lib.rs | 24 ++ 5 files changed, 1144 insertions(+), 1 deletion(-) create mode 100644 rsa/Cargo.toml create mode 100644 rsa/src/hacl/rsapss.rs create mode 100644 rsa/src/impl_hacl.rs create mode 100644 rsa/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index b133be888..0598cf2c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ members = [ "ed25519", "curve25519", "poly1305", - "chacha20poly1305", + "chacha20poly1305", "rsa", ] [workspace.package] diff --git a/rsa/Cargo.toml b/rsa/Cargo.toml new file mode 100644 index 000000000..268526ea3 --- /dev/null +++ b/rsa/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "libcrux-rsa" +description = "Formally verified RSA signature library" + +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[features] +default = ["hacl"] +hacl = ["dep:libcrux-hacl-rs"] +expose-hacl = ["hacl"] + +[dependencies] +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs", optional = true } +libcrux-traits = { version = "=0.0.2-beta.2", path = "../traits/" } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } +libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", features = [ + "expose-hacl", +] } diff --git a/rsa/src/hacl/rsapss.rs b/rsa/src/hacl/rsapss.rs new file mode 100644 index 000000000..ac233ded7 --- /dev/null +++ b/rsa/src/hacl/rsapss.rs @@ -0,0 +1,936 @@ +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(unused_assignments)] +#![allow(unreachable_patterns)] + +use libcrux_hacl_rs::prelude::{bignum, fstar}; + +#[inline] +fn hash_len(a: crate::hacl::streaming_types::hash_alg) -> u32 { + match a { + crate::hacl::streaming_types::hash_alg::MD5 => 16u32, + crate::hacl::streaming_types::hash_alg::SHA1 => 20u32, + crate::hacl::streaming_types::hash_alg::SHA2_224 => 28u32, + crate::hacl::streaming_types::hash_alg::SHA2_256 => 32u32, + crate::hacl::streaming_types::hash_alg::SHA2_384 => 48u32, + crate::hacl::streaming_types::hash_alg::SHA2_512 => 64u32, + crate::hacl::streaming_types::hash_alg::Blake2S => 32u32, + crate::hacl::streaming_types::hash_alg::Blake2B => 64u32, + crate::hacl::streaming_types::hash_alg::SHA3_224 => 28u32, + crate::hacl::streaming_types::hash_alg::SHA3_256 => 32u32, + crate::hacl::streaming_types::hash_alg::SHA3_384 => 48u32, + crate::hacl::streaming_types::hash_alg::SHA3_512 => 64u32, + _ => panic!("Precondition of the function most likely violated"), + } +} + +#[inline] +fn hash(a: crate::hacl::streaming_types::hash_alg, mHash: &mut [u8], msgLen: u32, msg: &[u8]) { + match a { + crate::hacl::streaming_types::hash_alg::SHA2_256 => { + crate::hacl::hash_sha2::hash_256(mHash, msg, msgLen) + } + crate::hacl::streaming_types::hash_alg::SHA2_384 => { + crate::hacl::hash_sha2::hash_384(mHash, msg, msgLen) + } + crate::hacl::streaming_types::hash_alg::SHA2_512 => { + crate::hacl::hash_sha2::hash_512(mHash, msg, msgLen) + } + _ => panic!("Precondition of the function most likely violated"), + } +} + +#[inline] +fn mgf_hash( + a: crate::hacl::streaming_types::hash_alg, + len: u32, + mgfseed: &[u8], + maskLen: u32, + res: &mut [u8], +) { + let mut mgfseed_counter: Box<[u8]> = + vec![0u8; len.wrapping_add(4u32) as usize].into_boxed_slice(); + ((&mut mgfseed_counter)[0usize..len as usize]).copy_from_slice(&mgfseed[0usize..len as usize]); + let hLen: u32 = crate::hacl::rsapss::hash_len(a); + let n: u32 = maskLen + .wrapping_sub(1u32) + .wrapping_div(hLen) + .wrapping_add(1u32); + let accLen: u32 = n.wrapping_mul(hLen); + let mut acc: Box<[u8]> = vec![0u8; accLen as usize].into_boxed_slice(); + for i in 0u32..n { + let acc_i: (&mut [u8], &mut [u8]) = acc.split_at_mut(i.wrapping_mul(hLen) as usize); + let c: (&mut [u8], &mut [u8]) = mgfseed_counter.split_at_mut(len as usize); + c.1[0usize] = i.wrapping_shr(24u32) as u8; + c.1[1usize] = i.wrapping_shr(16u32) as u8; + c.1[2usize] = i.wrapping_shr(8u32) as u8; + c.1[3usize] = i as u8; + crate::hacl::rsapss::hash(a, acc_i.1, len.wrapping_add(4u32), &mgfseed_counter) + } + (res[0usize..maskLen as usize]).copy_from_slice(&(&(&acc)[0usize..])[0usize..maskLen as usize]) +} + +#[inline] +fn check_num_bits_u64(bs: u32, b: &[u64]) -> u64 { + let bLen: u32 = bs.wrapping_sub(1u32).wrapping_div(64u32).wrapping_add(1u32); + if bs == 64u32.wrapping_mul(bLen) { + 0xFFFFFFFFFFFFFFFFu64 + } else { + let mut b2: Box<[u64]> = vec![0u64; bLen as usize].into_boxed_slice(); + let i: u32 = bs.wrapping_div(64u32); + let j: u32 = bs.wrapping_rem(64u32); + (&mut b2)[i as usize] = (&b2)[i as usize] | 1u64.wrapping_shl(j); + let mut acc: [u64; 1] = [0u64; 1usize]; + for i0 in 0u32..bLen { + let beq: u64 = fstar::uint64::eq_mask(b[i0 as usize], (&b2)[i0 as usize]); + let blt: u64 = !fstar::uint64::gte_mask(b[i0 as usize], (&b2)[i0 as usize]); + (&mut acc)[0usize] = beq & (&acc)[0usize] | !beq & blt + } + let res: u64 = (&acc)[0usize]; + res + } +} + +#[inline] +fn check_modulus_u64(modBits: u32, n: &[u64]) -> u64 { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let bits0: u64 = n[0usize] & 1u64; + let m0: u64 = 0u64.wrapping_sub(bits0); + let mut b2: Box<[u64]> = vec![0u64; nLen as usize].into_boxed_slice(); + let i: u32 = modBits.wrapping_sub(1u32).wrapping_div(64u32); + let j: u32 = modBits.wrapping_sub(1u32).wrapping_rem(64u32); + (&mut b2)[i as usize] = (&b2)[i as usize] | 1u64.wrapping_shl(j); + let mut acc: [u64; 1] = [0u64; 1usize]; + for i0 in 0u32..nLen { + let beq: u64 = fstar::uint64::eq_mask((&b2)[i0 as usize], n[i0 as usize]); + let blt: u64 = !fstar::uint64::gte_mask((&b2)[i0 as usize], n[i0 as usize]); + (&mut acc)[0usize] = beq & (&acc)[0usize] | !beq & blt + } + let res: u64 = (&acc)[0usize]; + let m1: u64 = res; + let m2: u64 = crate::hacl::rsapss::check_num_bits_u64(modBits, n); + m0 & (m1 & m2) +} + +#[inline] +fn check_exponent_u64(eBits: u32, e: &[u64]) -> u64 { + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let bn_zero: Box<[u64]> = vec![0u64; eLen as usize].into_boxed_slice(); + let mut mask: [u64; 1] = [0xFFFFFFFFFFFFFFFFu64; 1usize]; + for i in 0u32..eLen { + let uu____0: u64 = fstar::uint64::eq_mask(e[i as usize], (&bn_zero)[i as usize]); + (&mut mask)[0usize] = uu____0 & (&mask)[0usize] + } + let mask1: u64 = (&mask)[0usize]; + let res: u64 = mask1; + let m0: u64 = res; + let m1: u64 = crate::hacl::rsapss::check_num_bits_u64(eBits, e); + !m0 & m1 +} + +#[inline] +fn pss_encode( + a: crate::hacl::streaming_types::hash_alg, + saltLen: u32, + salt: &[u8], + msgLen: u32, + msg: &[u8], + emBits: u32, + em: &mut [u8], +) { + let hLen: u32 = crate::hacl::rsapss::hash_len(a); + let mut m1Hash: Box<[u8]> = vec![0u8; hLen as usize].into_boxed_slice(); + let m1Len: u32 = 8u32.wrapping_add(hLen).wrapping_add(saltLen); + let mut m1: Box<[u8]> = vec![0u8; m1Len as usize].into_boxed_slice(); + crate::hacl::rsapss::hash(a, &mut (&mut m1)[8usize..], msgLen, msg); + ((&mut m1) + [8u32.wrapping_add(hLen) as usize..8u32.wrapping_add(hLen) as usize + saltLen as usize]) + .copy_from_slice(&salt[0usize..saltLen as usize]); + crate::hacl::rsapss::hash(a, &mut m1Hash, m1Len, &m1); + let emLen: u32 = emBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let dbLen: u32 = emLen.wrapping_sub(hLen).wrapping_sub(1u32); + let mut db: Box<[u8]> = vec![0u8; dbLen as usize].into_boxed_slice(); + let last_before_salt: u32 = dbLen.wrapping_sub(saltLen).wrapping_sub(1u32); + (&mut db)[last_before_salt as usize] = 1u8; + ((&mut db)[last_before_salt.wrapping_add(1u32) as usize + ..last_before_salt.wrapping_add(1u32) as usize + saltLen as usize]) + .copy_from_slice(&salt[0usize..saltLen as usize]); + let mut dbMask: Box<[u8]> = vec![0u8; dbLen as usize].into_boxed_slice(); + crate::hacl::rsapss::mgf_hash(a, hLen, &m1Hash, dbLen, &mut dbMask); + for i in 0u32..dbLen { + let x: u8 = (&db)[i as usize] ^ (&dbMask)[i as usize]; + let os: (&mut [u8], &mut [u8]) = db.split_at_mut(0usize); + os.1[i as usize] = x + } + let msBits: u32 = emBits.wrapping_rem(8u32); + if msBits > 0u32 { + (&mut db)[0usize] = (&db)[0usize] & 0xffu8.wrapping_shr(8u32.wrapping_sub(msBits)) + }; + (em[0usize..dbLen as usize]).copy_from_slice(&(&db)[0usize..dbLen as usize]); + (em[dbLen as usize..dbLen as usize + hLen as usize]) + .copy_from_slice(&(&m1Hash)[0usize..hLen as usize]); + em[emLen.wrapping_sub(1u32) as usize] = 0xbcu8 +} + +#[inline] +fn pss_verify( + a: crate::hacl::streaming_types::hash_alg, + saltLen: u32, + msgLen: u32, + msg: &[u8], + emBits: u32, + em: &[u8], +) -> bool { + let emLen: u32 = emBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let msBits: u32 = emBits.wrapping_rem(8u32); + let em_0: u8 = if msBits > 0u32 { + em[0usize] & 0xffu8.wrapping_shl(msBits) + } else { + 0u8 + }; + let em_last: u8 = em[emLen.wrapping_sub(1u32) as usize]; + if emLen + < saltLen + .wrapping_add(crate::hacl::rsapss::hash_len(a)) + .wrapping_add(2u32) + || !(em_last == 0xbcu8 && em_0 == 0u8) + { + false + } else { + let emLen1: u32 = emBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let hLen: u32 = crate::hacl::rsapss::hash_len(a); + let mut m1Hash0: Box<[u8]> = vec![0u8; hLen as usize].into_boxed_slice(); + let dbLen: u32 = emLen1.wrapping_sub(hLen).wrapping_sub(1u32); + let maskedDB: (&[u8], &[u8]) = em.split_at(0usize); + let m1Hash: (&[u8], &[u8]) = maskedDB.1.split_at(dbLen as usize); + let mut dbMask: Box<[u8]> = vec![0u8; dbLen as usize].into_boxed_slice(); + crate::hacl::rsapss::mgf_hash(a, hLen, m1Hash.1, dbLen, &mut dbMask); + for i in 0u32..dbLen { + let x: u8 = (&dbMask)[i as usize] ^ m1Hash.0[i as usize]; + let os: (&mut [u8], &mut [u8]) = dbMask.split_at_mut(0usize); + os.1[i as usize] = x + } + let msBits1: u32 = emBits.wrapping_rem(8u32); + if msBits1 > 0u32 { + (&mut dbMask)[0usize] = + (&dbMask)[0usize] & 0xffu8.wrapping_shr(8u32.wrapping_sub(msBits1)) + }; + let padLen: u32 = emLen1 + .wrapping_sub(saltLen) + .wrapping_sub(hLen) + .wrapping_sub(1u32); + let mut pad2: Box<[u8]> = vec![0u8; padLen as usize].into_boxed_slice(); + (&mut pad2)[padLen.wrapping_sub(1u32) as usize] = 0x01u8; + let pad: (&[u8], &[u8]) = dbMask.split_at(0usize); + let salt: (&[u8], &[u8]) = pad.1.split_at(padLen as usize); + let mut res: [u8; 1] = [255u8; 1usize]; + for i in 0u32..padLen { + let uu____0: u8 = fstar::uint8::eq_mask(salt.0[i as usize], (&pad2)[i as usize]); + (&mut res)[0usize] = uu____0 & (&res)[0usize] + } + let z: u8 = (&res)[0usize]; + if z != 255u8 { + false + } else { + let m1Len: u32 = 8u32.wrapping_add(hLen).wrapping_add(saltLen); + let mut m1: Box<[u8]> = vec![0u8; m1Len as usize].into_boxed_slice(); + crate::hacl::rsapss::hash(a, &mut (&mut m1)[8usize..], msgLen, msg); + ((&mut m1)[8u32.wrapping_add(hLen) as usize + ..8u32.wrapping_add(hLen) as usize + saltLen as usize]) + .copy_from_slice(&salt.1[0usize..saltLen as usize]); + crate::hacl::rsapss::hash(a, &mut m1Hash0, m1Len, &m1); + let mut res0: [u8; 1] = [255u8; 1usize]; + for i in 0u32..hLen { + let uu____1: u8 = + fstar::uint8::eq_mask((&m1Hash0)[i as usize], m1Hash.1[i as usize]); + (&mut res0)[0usize] = uu____1 & (&res0)[0usize] + } + let z0: u8 = (&res0)[0usize]; + z0 == 255u8 + } + } +} + +#[inline] +fn load_pkey(modBits: u32, eBits: u32, nb: &[u8], eb: &[u8], pkey: &mut [u64]) -> bool { + let nbLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let ebLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let n: (&mut [u64], &mut [u64]) = pkey.split_at_mut(0usize); + let r2: (&mut [u64], &mut [u64]) = n.1.split_at_mut(nLen as usize); + let e: (&mut [u64], &mut [u64]) = + r2.1.split_at_mut(nLen.wrapping_add(nLen) as usize - nLen as usize); + bignum::bignum_base::bn_from_bytes_be_uint64(nbLen, nb, r2.0); + bignum::base::bn_precomp_r2_mod_n_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + modBits.wrapping_sub(1u32), + r2.0, + e.0, + ); + bignum::bignum_base::bn_from_bytes_be_uint64(ebLen, eb, e.1); + let m0: u64 = crate::hacl::rsapss::check_modulus_u64(modBits, r2.0); + let m1: u64 = crate::hacl::rsapss::check_exponent_u64(eBits, e.1); + let m: u64 = m0 & m1; + m == 0xFFFFFFFFFFFFFFFFu64 +} + +#[inline] +fn load_skey( + modBits: u32, + eBits: u32, + dBits: u32, + nb: &[u8], + eb: &[u8], + db: &[u8], + skey: &mut [u64], +) -> bool { + let dbLen: u32 = dBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let pkeyLen: u32 = nLen.wrapping_add(nLen).wrapping_add(eLen); + let pkey: (&mut [u64], &mut [u64]) = skey.split_at_mut(0usize); + let d: (&mut [u64], &mut [u64]) = pkey.1.split_at_mut(pkeyLen as usize); + let b: bool = crate::hacl::rsapss::load_pkey(modBits, eBits, nb, eb, d.0); + bignum::bignum_base::bn_from_bytes_be_uint64(dbLen, db, d.1); + let m1: u64 = crate::hacl::rsapss::check_exponent_u64(dBits, d.1); + b && m1 == 0xFFFFFFFFFFFFFFFFu64 +} + +/** +Sign a message `msg` and write the signature to `sgnt`. + +@param a Hash algorithm to use. Allowed values for `a` are ... + - Spec_Hash_Definitions_SHA2_256, + - Spec_Hash_Definitions_SHA2_384, and + - Spec_Hash_Definitions_SHA2_512. +@param modBits Count of bits in the modulus (`n`). +@param eBits Count of bits in `e` value. +@param dBits Count of bits in `d` value. +@param skey Pointer to secret key created by `Hacl_RSAPSS_new_rsapss_load_skey`. +@param saltLen Length of salt. +@param salt Pointer to `saltLen` bytes where the salt is read from. +@param msgLen Length of message. +@param msg Pointer to `msgLen` bytes where the message is read from. +@param sgnt Pointer to `ceil(modBits / 8)` bytes where the signature is written to. + +@return Returns true if and only if signing was successful. +*/ +pub fn rsapss_sign( + a: crate::hacl::streaming_types::hash_alg, + modBits: u32, + eBits: u32, + dBits: u32, + skey: &[u64], + saltLen: u32, + salt: &[u8], + msgLen: u32, + msg: &[u8], + sgnt: &mut [u8], +) -> bool { + let hLen: u32 = crate::hacl::rsapss::hash_len(a); + let b: bool = saltLen <= 0xffffffffu32.wrapping_sub(hLen).wrapping_sub(8u32) + && saltLen.wrapping_add(hLen).wrapping_add(2u32) + <= modBits + .wrapping_sub(1u32) + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + if b { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let mut m: Box<[u64]> = vec![0u64; nLen as usize].into_boxed_slice(); + let emBits: u32 = modBits.wrapping_sub(1u32); + let emLen: u32 = emBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let mut em: Box<[u8]> = vec![0u8; emLen as usize].into_boxed_slice(); + crate::hacl::rsapss::pss_encode(a, saltLen, salt, msgLen, msg, emBits, &mut em); + bignum::bignum_base::bn_from_bytes_be_uint64(emLen, &em, &mut (&mut m)[0usize..]); + let nLen1: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let k: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let mut s: Box<[u64]> = vec![0u64; nLen1 as usize].into_boxed_slice(); + let mut m·: Box<[u64]> = vec![0u64; nLen1 as usize].into_boxed_slice(); + let nLen2: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let n: (&[u64], &[u64]) = skey.split_at(0usize); + let r2: (&[u64], &[u64]) = n.1.split_at(nLen2 as usize); + let e: (&[u64], &[u64]) = + r2.1.split_at(nLen2.wrapping_add(nLen2) as usize - nLen2 as usize); + let d: (&[u64], &[u64]) = e.1.split_at( + nLen2.wrapping_add(nLen2).wrapping_add(eLen) as usize + - nLen2.wrapping_add(nLen2) as usize, + ); + let mu: u64 = bignum::base::mod_inv_uint64(r2.0[0usize]); + bignum::base::bn_mod_exp_consttime_precomp_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + r2.0, + mu, + e.0, + &m, + dBits, + d.1, + &mut s, + ); + let mu0: u64 = bignum::base::mod_inv_uint64(r2.0[0usize]); + bignum::base::bn_mod_exp_vartime_precomp_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + r2.0, + mu0, + e.0, + &s, + eBits, + d.0, + &mut m·, + ); + let mut mask: [u64; 1] = [0xFFFFFFFFFFFFFFFFu64; 1usize]; + for i in 0u32..nLen2 { + let uu____0: u64 = fstar::uint64::eq_mask((&m)[i as usize], (&m·)[i as usize]); + (&mut mask)[0usize] = uu____0 & (&mask)[0usize] + } + let mask1: u64 = (&mask)[0usize]; + let eq_m: u64 = mask1; + for i in 0u32..nLen2 { + let x: u64 = (&s)[i as usize]; + let x0: u64 = eq_m & x; + let os: (&mut [u64], &mut [u64]) = s.split_at_mut(0usize); + os.1[i as usize] = x0 + } + let eq_b: bool = eq_m == 0xFFFFFFFFFFFFFFFFu64; + bignum::bignum_base::bn_to_bytes_be_uint64(k, &s, sgnt); + let eq_b0: bool = eq_b; + eq_b0 + } else { + false + } +} + +/** +Verify the signature `sgnt` of a message `msg`. + +@param a Hash algorithm to use. Allowed values for `a` are ... + - Spec_Hash_Definitions_SHA2_256, + - Spec_Hash_Definitions_SHA2_384, and + - Spec_Hash_Definitions_SHA2_512. +@param modBits Count of bits in the modulus (`n`). +@param eBits Count of bits in `e` value. +@param pkey Pointer to public key created by `Hacl_RSAPSS_new_rsapss_load_pkey`. +@param saltLen Length of salt. +@param sgntLen Length of signature. +@param sgnt Pointer to `sgntLen` bytes where the signature is read from. +@param msgLen Length of message. +@param msg Pointer to `msgLen` bytes where the message is read from. + +@return Returns true if and only if the signature is valid. +*/ +pub fn rsapss_verify( + a: crate::hacl::streaming_types::hash_alg, + modBits: u32, + eBits: u32, + pkey: &[u64], + saltLen: u32, + sgntLen: u32, + sgnt: &[u8], + msgLen: u32, + msg: &[u8], +) -> bool { + let hLen: u32 = crate::hacl::rsapss::hash_len(a); + let b: bool = saltLen <= 0xffffffffu32.wrapping_sub(hLen).wrapping_sub(8u32) + && sgntLen + == modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + if b { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let mut m: Box<[u64]> = vec![0u64; nLen as usize].into_boxed_slice(); + let nLen1: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let k: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let mut s: Box<[u64]> = vec![0u64; nLen1 as usize].into_boxed_slice(); + bignum::bignum_base::bn_from_bytes_be_uint64(k, sgnt, &mut s); + let nLen2: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let n: (&[u64], &[u64]) = pkey.split_at(0usize); + let r2: (&[u64], &[u64]) = n.1.split_at(nLen2 as usize); + let e: (&[u64], &[u64]) = + r2.1.split_at(nLen2.wrapping_add(nLen2) as usize - nLen2 as usize); + let mut acc: [u64; 1] = [0u64; 1usize]; + for i in 0u32..nLen2 { + let beq: u64 = fstar::uint64::eq_mask((&s)[i as usize], r2.0[i as usize]); + let blt: u64 = !fstar::uint64::gte_mask((&s)[i as usize], r2.0[i as usize]); + (&mut acc)[0usize] = beq & (&acc)[0usize] | !beq & blt + } + let mask: u64 = (&acc)[0usize]; + let res: bool = if mask == 0xFFFFFFFFFFFFFFFFu64 { + let mu: u64 = bignum::base::mod_inv_uint64(r2.0[0usize]); + bignum::base::bn_mod_exp_vartime_precomp_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + r2.0, + mu, + e.0, + &s, + eBits, + e.1, + &mut m, + ); + if modBits.wrapping_sub(1u32).wrapping_rem(8u32) != 0u32 { + true + } else { + let i: u32 = modBits.wrapping_sub(1u32).wrapping_div(64u32); + let j: u32 = modBits.wrapping_sub(1u32).wrapping_rem(64u32); + let tmp: u64 = (&m)[i as usize]; + let get_bit: u64 = tmp.wrapping_shr(j) & 1u64; + get_bit == 0u64 + } + } else { + false + }; + let b1: bool = res; + let b10: bool = b1; + if b10 { + let emBits: u32 = modBits.wrapping_sub(1u32); + let emLen: u32 = emBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let mut em: Box<[u8]> = vec![0u8; emLen as usize].into_boxed_slice(); + let m1: (&[u64], &[u64]) = m.split_at(0usize); + bignum::bignum_base::bn_to_bytes_be_uint64(emLen, m1.1, &mut em); + let res0: bool = crate::hacl::rsapss::pss_verify(a, saltLen, msgLen, msg, emBits, &em); + res0 + } else { + false + } + } else { + false + } +} + +/** +Load a public key from key parts. + +@param modBits Count of bits in modulus (`n`). +@param eBits Count of bits in `e` value. +@param nb Pointer to `ceil(modBits / 8)` bytes where the modulus (`n`), in big-endian byte order, is read from. +@param eb Pointer to `ceil(modBits / 8)` bytes where the `e` value, in big-endian byte order, is read from. + +@return Returns an allocated public key upon success, otherwise, `NULL` if key part arguments are invalid or memory allocation fails. Note: caller must take care to `free()` the created key. +*/ +pub fn new_rsapss_load_pkey(modBits: u32, eBits: u32, nb: &[u8], eb: &[u8]) -> Box<[u64]> { + let ite: bool = if 1u32 < modBits && 0u32 < eBits { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + nLen <= 33554431u32 + && eLen <= 67108863u32 + && nLen.wrapping_add(nLen) <= 0xffffffffu32.wrapping_sub(eLen) + } else { + false + }; + if !ite { + [].into() + } else { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let pkeyLen: u32 = nLen.wrapping_add(nLen).wrapping_add(eLen); + let mut pkey: Box<[u64]> = vec![0u64; pkeyLen as usize].into_boxed_slice(); + if false { + pkey + } else { + let pkey1: &mut [u64] = &mut pkey; + let pkey2: &mut [u64] = pkey1; + let nbLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let ebLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let nLen1: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let n: (&mut [u64], &mut [u64]) = pkey2.split_at_mut(0usize); + let r2: (&mut [u64], &mut [u64]) = n.1.split_at_mut(nLen1 as usize); + let e: (&mut [u64], &mut [u64]) = + r2.1.split_at_mut(nLen1.wrapping_add(nLen1) as usize - nLen1 as usize); + bignum::bignum_base::bn_from_bytes_be_uint64(nbLen, nb, r2.0); + bignum::base::bn_precomp_r2_mod_n_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + modBits.wrapping_sub(1u32), + r2.0, + e.0, + ); + bignum::bignum_base::bn_from_bytes_be_uint64(ebLen, eb, e.1); + let m0: u64 = crate::hacl::rsapss::check_modulus_u64(modBits, r2.0); + let m1: u64 = crate::hacl::rsapss::check_exponent_u64(eBits, e.1); + let m: u64 = m0 & m1; + let b: bool = m == 0xFFFFFFFFFFFFFFFFu64; + if b { + (*pkey2).into() + } else { + [].into() + } + } + } +} + +/** +Load a secret key from key parts. + +@param modBits Count of bits in modulus (`n`). +@param eBits Count of bits in `e` value. +@param dBits Count of bits in `d` value. +@param nb Pointer to `ceil(modBits / 8)` bytes where the modulus (`n`), in big-endian byte order, is read from. +@param eb Pointer to `ceil(modBits / 8)` bytes where the `e` value, in big-endian byte order, is read from. +@param db Pointer to `ceil(modBits / 8)` bytes where the `d` value, in big-endian byte order, is read from. + +@return Returns an allocated secret key upon success, otherwise, `NULL` if key part arguments are invalid or memory allocation fails. Note: caller must take care to `free()` the created key. +*/ +pub fn new_rsapss_load_skey( + modBits: u32, + eBits: u32, + dBits: u32, + nb: &[u8], + eb: &[u8], + db: &[u8], +) -> Box<[u64]> { + let ite: bool = if 1u32 < modBits && 0u32 < eBits { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + nLen <= 33554431u32 + && eLen <= 67108863u32 + && nLen.wrapping_add(nLen) <= 0xffffffffu32.wrapping_sub(eLen) + } else { + false + }; + let ite0: bool = if ite && 0u32 < dBits { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let dLen: u32 = dBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + dLen <= 67108863u32 + && 2u32.wrapping_mul(nLen) <= 0xffffffffu32.wrapping_sub(eLen).wrapping_sub(dLen) + } else { + false + }; + if !ite0 { + [].into() + } else { + let nLen: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let dLen: u32 = dBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let skeyLen: u32 = nLen + .wrapping_add(nLen) + .wrapping_add(eLen) + .wrapping_add(dLen); + let mut skey: Box<[u64]> = vec![0u64; skeyLen as usize].into_boxed_slice(); + if false { + skey + } else { + let skey1: &mut [u64] = &mut skey; + let skey2: &mut [u64] = skey1; + let dbLen: u32 = dBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let nLen1: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let eLen1: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let pkeyLen: u32 = nLen1.wrapping_add(nLen1).wrapping_add(eLen1); + let pkey: (&mut [u64], &mut [u64]) = skey2.split_at_mut(0usize); + let d: (&mut [u64], &mut [u64]) = pkey.1.split_at_mut(pkeyLen as usize); + let nbLen1: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let ebLen1: u32 = eBits + .wrapping_sub(1u32) + .wrapping_div(8u32) + .wrapping_add(1u32); + let nLen2: u32 = modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32); + let n: (&mut [u64], &mut [u64]) = d.0.split_at_mut(0usize); + let r2: (&mut [u64], &mut [u64]) = n.1.split_at_mut(nLen2 as usize); + let e: (&mut [u64], &mut [u64]) = + r2.1.split_at_mut(nLen2.wrapping_add(nLen2) as usize - nLen2 as usize); + bignum::bignum_base::bn_from_bytes_be_uint64(nbLen1, nb, r2.0); + bignum::base::bn_precomp_r2_mod_n_u64( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32), + modBits.wrapping_sub(1u32), + r2.0, + e.0, + ); + bignum::bignum_base::bn_from_bytes_be_uint64(ebLen1, eb, e.1); + let m0: u64 = crate::hacl::rsapss::check_modulus_u64(modBits, r2.0); + let m1: u64 = crate::hacl::rsapss::check_exponent_u64(eBits, e.1); + let m: u64 = m0 & m1; + let b: bool = m == 0xFFFFFFFFFFFFFFFFu64; + bignum::bignum_base::bn_from_bytes_be_uint64(dbLen, db, d.1); + let m10: u64 = crate::hacl::rsapss::check_exponent_u64(dBits, d.1); + let b0: bool = b && m10 == 0xFFFFFFFFFFFFFFFFu64; + if b0 { + (*skey2).into() + } else { + [].into() + } + } + } +} + +/** +Sign a message `msg` and write the signature to `sgnt`. + +@param a Hash algorithm to use. Allowed values for `a` are ... + - Spec_Hash_Definitions_SHA2_256, + - Spec_Hash_Definitions_SHA2_384, and + - Spec_Hash_Definitions_SHA2_512. +@param modBits Count of bits in the modulus (`n`). +@param eBits Count of bits in `e` value. +@param dBits Count of bits in `d` value. +@param nb Pointer to `ceil(modBits / 8)` bytes where the modulus (`n`), in big-endian byte order, is read from. +@param eb Pointer to `ceil(modBits / 8)` bytes where the `e` value, in big-endian byte order, is read from. +@param db Pointer to `ceil(modBits / 8)` bytes where the `d` value, in big-endian byte order, is read from. +@param saltLen Length of salt. +@param salt Pointer to `saltLen` bytes where the salt is read from. +@param msgLen Length of message. +@param msg Pointer to `msgLen` bytes where the message is read from. +@param sgnt Pointer to `ceil(modBits / 8)` bytes where the signature is written to. + +@return Returns true if and only if signing was successful. +*/ +pub fn rsapss_skey_sign( + a: crate::hacl::streaming_types::hash_alg, + modBits: u32, + eBits: u32, + dBits: u32, + nb: &[u8], + eb: &[u8], + db: &[u8], + saltLen: u32, + salt: &[u8], + msgLen: u32, + msg: &[u8], + sgnt: &mut [u8], +) -> bool { + let mut skey: Box<[u64]> = vec![ + 0u64; + 2u32.wrapping_mul( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32) + ) + .wrapping_add( + eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32) + ) + .wrapping_add( + dBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32) + ) as usize + ] + .into_boxed_slice(); + let b: bool = crate::hacl::rsapss::load_skey(modBits, eBits, dBits, nb, eb, db, &mut skey); + if b { + crate::hacl::rsapss::rsapss_sign( + a, modBits, eBits, dBits, &skey, saltLen, salt, msgLen, msg, sgnt, + ) + } else { + false + } +} + +/** +Verify the signature `sgnt` of a message `msg`. + +@param a Hash algorithm to use. Allowed values for `a` are ... + - Spec_Hash_Definitions_SHA2_256, + - Spec_Hash_Definitions_SHA2_384, and + - Spec_Hash_Definitions_SHA2_512. +@param modBits Count of bits in the modulus (`n`). +@param eBits Count of bits in `e` value. +@param nb Pointer to `ceil(modBits / 8)` bytes where the modulus (`n`), in big-endian byte order, is read from. +@param eb Pointer to `ceil(modBits / 8)` bytes where the `e` value, in big-endian byte order, is read from. +@param saltLen Length of salt. +@param sgntLen Length of signature. +@param sgnt Pointer to `sgntLen` bytes where the signature is read from. +@param msgLen Length of message. +@param msg Pointer to `msgLen` bytes where the message is read from. + +@return Returns true if and only if the signature is valid. +*/ +pub fn rsapss_pkey_verify( + a: crate::hacl::streaming_types::hash_alg, + modBits: u32, + eBits: u32, + nb: &[u8], + eb: &[u8], + saltLen: u32, + sgntLen: u32, + sgnt: &[u8], + msgLen: u32, + msg: &[u8], +) -> bool { + let mut pkey: Box<[u64]> = vec![ + 0u64; + 2u32.wrapping_mul( + modBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32) + ) + .wrapping_add( + eBits + .wrapping_sub(1u32) + .wrapping_div(64u32) + .wrapping_add(1u32) + ) as usize + ] + .into_boxed_slice(); + let b: bool = crate::hacl::rsapss::load_pkey(modBits, eBits, nb, eb, &mut pkey); + if b { + crate::hacl::rsapss::rsapss_verify( + a, modBits, eBits, &pkey, saltLen, sgntLen, sgnt, msgLen, msg, + ) + } else { + false + } +} + +/** +The mask generation function defined in the Public Key Cryptography Standard #1 + (https://www.ietf.org/rfc/rfc2437.txt Section 10.2.1) +*/ +pub fn mgf_hash0( + a: crate::hacl::streaming_types::hash_alg, + len: u32, + mgfseed: &[u8], + maskLen: u32, + res: &mut [u8], +) { + crate::hacl::rsapss::mgf_hash(a, len, mgfseed, maskLen, res) +} diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs new file mode 100644 index 000000000..2b41d2a1a --- /dev/null +++ b/rsa/src/impl_hacl.rs @@ -0,0 +1,159 @@ +use crate::Error; + +#[derive(Debug)] +pub struct Signature([u8; LEN]); + +#[derive(Debug, Clone)] +struct PublicKey { + n: [u8; LEN], +} + +pub struct PrivateKey { + pk: PublicKey, + d: [u8; LEN], +} + +const E_BITS: u32 = 17; +const E: [u8; 3] = [1, 0, 1]; + +fn hacl_hash_alg(alg: crate::DigestAlgorithm) -> libcrux_hacl_rs::streaming_types::hash_alg { + match alg { + crate::DigestAlgorithm::Sha2_256 => libcrux_hacl_rs::streaming_types::hash_alg::SHA2_256, + crate::DigestAlgorithm::Sha2_384 => libcrux_hacl_rs::streaming_types::hash_alg::SHA2_384, + crate::DigestAlgorithm::Sha2_512 => libcrux_hacl_rs::streaming_types::hash_alg::SHA2_512, + } +} + +// next up: generate these in macros + +macro_rules! impl_rsapss { + ($sign_fn:ident, $verify_fn:ident, $bits:literal, $bytes:literal) => { + fn $sign_fn( + alg: crate::DigestAlgorithm, + sk: &PrivateKey<$bytes>, + msg: &[u8], + salt: &[u8], + sig: &mut Signature<$bytes>, + ) -> Result<(), Error> { + let alg = hacl_hash_alg(alg); + + let salt_len = salt.len().try_into().map_err(|_| Error::SaltTooLarge)?; + let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; + + let skey = crate::hacl::rsapss::new_rsapss_load_skey( + $bits, E_BITS, $bits, &sk.pk.n, &E, &sk.d, + ); + + match crate::hacl::rsapss::rsapss_sign( + alg, $bits, E_BITS, $bits, &skey, salt_len, salt, msg_len, msg, &mut sig.0, + ) { + true => Ok(()), + false => Err(Error::SigningFailed), + } + } + + fn $verify_fn( + alg: crate::DigestAlgorithm, + pk: &PublicKey<$bytes>, + msg: &[u8], + salt_len: u32, + sig: &Signature<$bytes>, + ) -> Result<(), Error> { + let alg = hacl_hash_alg(alg); + + let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; + + let pkey = crate::hacl::rsapss::new_rsapss_load_pkey($bits, E_BITS, &pk.n, &E); + + match crate::hacl::rsapss::rsapss_pkey_verify( + alg, $bits, E_BITS, &pkey, &E, salt_len, $bytes, /*signature length*/ + &sig.0, msg_len, msg, + ) { + true => Ok(()), + false => Err(Error::VerificationFailed), + } + } + }; +} + +impl_rsapss!(sign_2048, verify_2048, 2048, 256); +impl_rsapss!(sign_3072, verify_3072, 3072, 384); +impl_rsapss!(sign_4096, verify_4096, 4096, 512); +impl_rsapss!(sign_6144, verify_6144, 6144, 768); +impl_rsapss!(sign_8192, verify_8192, 8192, 1024); + +#[cfg(test)] +mod tests { + use super::*; + + const MODULUS: [u8; 256] = [ + 0xd2, 0x78, 0x16, 0xcb, 0x72, 0xbb, 0x6e, 0x27, 0xdb, 0x10, 0x1a, 0x6f, 0x3e, 0x64, 0x62, + 0x93, 0xd9, 0xec, 0xa7, 0xb3, 0x98, 0xe3, 0x36, 0x6c, 0x9e, 0x69, 0x31, 0xc4, 0x5d, 0xd7, + 0x24, 0xd3, 0xf8, 0x90, 0xb0, 0xd0, 0x57, 0x78, 0x3e, 0xdd, 0xee, 0xf0, 0xc9, 0x0e, 0x98, + 0x6d, 0xad, 0xe9, 0x46, 0x47, 0xc5, 0xcb, 0x4d, 0xa4, 0xc6, 0x9c, 0x83, 0x1a, 0x13, 0x9f, + 0xb7, 0x8d, 0xe7, 0xe3, 0x79, 0x97, 0xf2, 0x9e, 0x36, 0x5c, 0x96, 0xaa, 0xf6, 0x29, 0xfe, + 0x6e, 0x3c, 0x0d, 0xb0, 0xcb, 0x04, 0x7d, 0x35, 0xd3, 0xeb, 0xf7, 0xee, 0x36, 0x59, 0xda, + 0xb5, 0xb2, 0x34, 0x08, 0x86, 0x87, 0x27, 0x02, 0x4b, 0x49, 0xb3, 0x85, 0x33, 0x9b, 0x63, + 0x8f, 0x28, 0x3b, 0x27, 0x83, 0x65, 0xf9, 0x62, 0x23, 0xe0, 0x8b, 0x15, 0x1d, 0xd3, 0x00, + 0xb1, 0xd6, 0x37, 0x3e, 0x7b, 0xa7, 0x1d, 0xc7, 0x63, 0x79, 0xe2, 0xa2, 0xca, 0x2d, 0xa4, + 0xb6, 0xcd, 0xef, 0x8d, 0x73, 0xec, 0x56, 0xfc, 0x0b, 0xac, 0xcb, 0x80, 0x53, 0xcf, 0x34, + 0x2f, 0x29, 0xb0, 0xe7, 0xf0, 0xb9, 0x24, 0xf4, 0xe4, 0x99, 0xb2, 0x58, 0xc0, 0x9e, 0x1f, + 0xf5, 0x43, 0x6e, 0xca, 0xc6, 0xeb, 0x65, 0xd0, 0x5f, 0xdb, 0x13, 0x4c, 0x8c, 0xca, 0x82, + 0xd9, 0xad, 0xc1, 0xfd, 0x7a, 0xd9, 0x78, 0xc7, 0xed, 0xdf, 0xc9, 0x70, 0x54, 0xd3, 0x80, + 0x5f, 0x06, 0x48, 0x11, 0x6e, 0xfb, 0x9b, 0x46, 0xfa, 0x02, 0x65, 0xde, 0xcc, 0xe9, 0x6e, + 0x91, 0x98, 0x93, 0x3d, 0x3d, 0x6d, 0xb1, 0x99, 0xa4, 0x73, 0xc1, 0x2c, 0xa2, 0x16, 0x55, + 0x97, 0xf3, 0x0f, 0x67, 0xf7, 0x9a, 0x78, 0x74, 0x15, 0x66, 0xb1, 0xd4, 0xdc, 0x98, 0x47, + 0x8a, 0x50, 0xb6, 0x2d, 0x63, 0xf9, 0xce, 0xa2, 0x76, 0x70, 0x91, 0xa8, 0x3b, 0x00, 0x28, + 0x01, + ]; + + const PRIVATE_EXPONENT: [u8; 256] = [ + 0x5a, 0x90, 0x21, 0xfe, 0xd9, 0x17, 0x9d, 0x86, 0xb8, 0xd4, 0x6d, 0x0b, 0x81, 0x25, 0x60, + 0xe5, 0x8d, 0xd8, 0x2f, 0x31, 0x30, 0x90, 0x54, 0x52, 0xd8, 0xb7, 0x1b, 0x1b, 0x0b, 0xe6, + 0x0f, 0x8a, 0xc6, 0x62, 0x3c, 0x32, 0xe9, 0xf0, 0x6b, 0xdc, 0xc3, 0x7c, 0x08, 0x87, 0xa7, + 0x3f, 0x4a, 0x9e, 0x1e, 0x07, 0xb4, 0x2c, 0x8e, 0xf4, 0x60, 0x21, 0xe8, 0xa7, 0xc7, 0xd9, + 0xe9, 0xf9, 0xbd, 0xd6, 0x3b, 0xf4, 0x0e, 0x09, 0xd6, 0x0a, 0x71, 0x2a, 0x8f, 0x51, 0xf2, + 0x91, 0x2c, 0x76, 0x17, 0xa4, 0xc4, 0x01, 0xbc, 0xaf, 0xbb, 0xd1, 0xab, 0x46, 0xe7, 0xd3, + 0x1c, 0x6b, 0xd9, 0xc7, 0xf1, 0x5b, 0x26, 0x85, 0xee, 0x2f, 0x80, 0x77, 0xc8, 0x85, 0x0c, + 0x8a, 0x05, 0x1d, 0xaf, 0x1a, 0xf3, 0x3e, 0x23, 0xe4, 0x9c, 0x32, 0x3c, 0x9b, 0xe0, 0xb7, + 0x63, 0xce, 0x71, 0x67, 0x09, 0x7e, 0x17, 0x69, 0x74, 0x9a, 0xec, 0x2a, 0x71, 0xf4, 0xeb, + 0xe2, 0x84, 0x23, 0x8b, 0xa8, 0x27, 0x69, 0x19, 0x53, 0x52, 0x8f, 0xc3, 0x62, 0xd5, 0x2a, + 0x43, 0xb0, 0x78, 0x90, 0x54, 0x98, 0x22, 0x12, 0x2d, 0x32, 0x28, 0xcf, 0xf9, 0x04, 0x1c, + 0x4f, 0x28, 0xb7, 0xad, 0x98, 0x1a, 0xdf, 0x2e, 0xdb, 0x94, 0xd5, 0x3d, 0xe2, 0xa9, 0x29, + 0x3c, 0x3e, 0xaa, 0x81, 0x2a, 0x61, 0x8d, 0x4b, 0x41, 0x2f, 0xda, 0x99, 0x8b, 0x78, 0x7a, + 0xd5, 0xec, 0x93, 0x53, 0x5a, 0x84, 0x43, 0x47, 0x1a, 0xaf, 0x68, 0xa7, 0x5f, 0x4e, 0x62, + 0xe5, 0xcf, 0x07, 0xc9, 0x2b, 0x67, 0x34, 0x82, 0x27, 0xf6, 0xe0, 0x6d, 0x51, 0xca, 0x21, + 0xea, 0xfa, 0x32, 0xf0, 0x9f, 0x84, 0xb4, 0xfb, 0xaf, 0x25, 0x1e, 0x91, 0x08, 0x94, 0x5e, + 0x83, 0x7f, 0x0f, 0x6a, 0x86, 0x98, 0x77, 0xb8, 0xb0, 0xca, 0xd0, 0x34, 0x10, 0x69, 0x59, + 0x21, + ]; + + #[test] + fn self_test_rsa_pss() { + let pk = PublicKey { n: MODULUS }; + let sk = PrivateKey { + pk: pk.clone(), + d: PRIVATE_EXPONENT, + }; + let salt = [1, 2, 3, 4, 5]; + let msg = [7, 8, 9, 10]; + let mut signature = Signature([0u8; 256]); + sign_2048( + crate::DigestAlgorithm::Sha2_256, + &sk, + &salt, + &msg, + &mut signature, + ) + .unwrap(); + println!("signature: {:x?}", signature); + verify_2048( + crate::DigestAlgorithm::Sha2_256, + &pk, + &msg, + salt.len() as u32, + &signature, + ) + .expect("Error verifying signature"); + } +} diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs new file mode 100644 index 000000000..e9248f7a9 --- /dev/null +++ b/rsa/src/lib.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "hacl")] +mod hacl { + pub(crate) mod rsapss; + + use libcrux_hacl_rs::streaming_types; + use libcrux_sha2::hacl as hash_sha2; +} + +pub enum DigestAlgorithm { + Sha2_256, + Sha2_384, + Sha2_512, +} + +#[derive(Debug)] +pub enum Error { + SaltTooLarge, + MessageTooLarge, + SigningFailed, + VerificationFailed, +} + +#[cfg(feature = "hacl")] +mod impl_hacl; From 8b7c2371bda08d0cb4b82e9e662cd8807fb7088b Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Tue, 3 Dec 2024 18:37:43 +0100 Subject: [PATCH 06/13] Let Hacl build the Pkey value itself --- rsa/src/impl_hacl.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs index 2b41d2a1a..6611baae2 100644 --- a/rsa/src/impl_hacl.rs +++ b/rsa/src/impl_hacl.rs @@ -63,10 +63,8 @@ macro_rules! impl_rsapss { let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; - let pkey = crate::hacl::rsapss::new_rsapss_load_pkey($bits, E_BITS, &pk.n, &E); - match crate::hacl::rsapss::rsapss_pkey_verify( - alg, $bits, E_BITS, &pkey, &E, salt_len, $bytes, /*signature length*/ + alg, $bits, E_BITS, &pk.n, &E, salt_len, $bytes, /*signature length*/ &sig.0, msg_len, msg, ) { true => Ok(()), From 944029fed47fda17982f9dc054df367d641abfa6 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Mon, 9 Dec 2024 11:28:42 +0100 Subject: [PATCH 07/13] Fix RSA test, clean up --- Cargo.toml | 3 ++- rsa/src/hacl/rsapss.rs | 16 +++++++++++++++- rsa/src/impl_hacl.rs | 35 +++++++++++++++++++---------------- rsa/src/lib.rs | 15 ++++++++++++++- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0598cf2c3..2bd593587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,8 @@ members = [ "ed25519", "curve25519", "poly1305", - "chacha20poly1305", "rsa", + "chacha20poly1305", + "rsa", ] [workspace.package] diff --git a/rsa/src/hacl/rsapss.rs b/rsa/src/hacl/rsapss.rs index ac233ded7..41c54f9e8 100644 --- a/rsa/src/hacl/rsapss.rs +++ b/rsa/src/hacl/rsapss.rs @@ -3,8 +3,11 @@ #![allow(non_camel_case_types)] #![allow(unused_assignments)] #![allow(unreachable_patterns)] +#![allow(clippy::too_many_arguments)] -use libcrux_hacl_rs::prelude::{bignum, fstar}; +//! This module contains generated hacl code. + +use libcrux_hacl_rs::prelude::{bignum, fstar, vec, Box}; #[inline] fn hash_len(a: crate::hacl::streaming_types::hash_alg) -> u32 { @@ -340,6 +343,7 @@ Sign a message `msg` and write the signature to `sgnt`. - Spec_Hash_Definitions_SHA2_256, - Spec_Hash_Definitions_SHA2_384, and - Spec_Hash_Definitions_SHA2_512. + @param modBits Count of bits in the modulus (`n`). @param eBits Count of bits in `e` value. @param dBits Count of bits in `d` value. @@ -352,6 +356,7 @@ Sign a message `msg` and write the signature to `sgnt`. @return Returns true if and only if signing was successful. */ +#[allow(dead_code)] pub fn rsapss_sign( a: crate::hacl::streaming_types::hash_alg, modBits: u32, @@ -469,6 +474,7 @@ Verify the signature `sgnt` of a message `msg`. - Spec_Hash_Definitions_SHA2_256, - Spec_Hash_Definitions_SHA2_384, and - Spec_Hash_Definitions_SHA2_512. + @param modBits Count of bits in the modulus (`n`). @param eBits Count of bits in `e` value. @param pkey Pointer to public key created by `Hacl_RSAPSS_new_rsapss_load_pkey`. @@ -480,6 +486,7 @@ Verify the signature `sgnt` of a message `msg`. @return Returns true if and only if the signature is valid. */ +#[allow(dead_code)] pub fn rsapss_verify( a: crate::hacl::streaming_types::hash_alg, modBits: u32, @@ -587,6 +594,7 @@ Load a public key from key parts. @return Returns an allocated public key upon success, otherwise, `NULL` if key part arguments are invalid or memory allocation fails. Note: caller must take care to `free()` the created key. */ +#[allow(dead_code)] pub fn new_rsapss_load_pkey(modBits: u32, eBits: u32, nb: &[u8], eb: &[u8]) -> Box<[u64]> { let ite: bool = if 1u32 < modBits && 0u32 < eBits { let nLen: u32 = modBits @@ -673,6 +681,7 @@ Load a secret key from key parts. @return Returns an allocated secret key upon success, otherwise, `NULL` if key part arguments are invalid or memory allocation fails. Note: caller must take care to `free()` the created key. */ +#[allow(dead_code)] pub fn new_rsapss_load_skey( modBits: u32, eBits: u32, @@ -804,6 +813,7 @@ Sign a message `msg` and write the signature to `sgnt`. - Spec_Hash_Definitions_SHA2_256, - Spec_Hash_Definitions_SHA2_384, and - Spec_Hash_Definitions_SHA2_512. + @param modBits Count of bits in the modulus (`n`). @param eBits Count of bits in `e` value. @param dBits Count of bits in `d` value. @@ -818,6 +828,7 @@ Sign a message `msg` and write the signature to `sgnt`. @return Returns true if and only if signing was successful. */ +#[allow(dead_code)] pub fn rsapss_skey_sign( a: crate::hacl::streaming_types::hash_alg, modBits: u32, @@ -871,6 +882,7 @@ Verify the signature `sgnt` of a message `msg`. - Spec_Hash_Definitions_SHA2_256, - Spec_Hash_Definitions_SHA2_384, and - Spec_Hash_Definitions_SHA2_512. + @param modBits Count of bits in the modulus (`n`). @param eBits Count of bits in `e` value. @param nb Pointer to `ceil(modBits / 8)` bytes where the modulus (`n`), in big-endian byte order, is read from. @@ -883,6 +895,7 @@ Verify the signature `sgnt` of a message `msg`. @return Returns true if and only if the signature is valid. */ +#[allow(dead_code)] pub fn rsapss_pkey_verify( a: crate::hacl::streaming_types::hash_alg, modBits: u32, @@ -925,6 +938,7 @@ pub fn rsapss_pkey_verify( The mask generation function defined in the Public Key Cryptography Standard #1 (https://www.ietf.org/rfc/rfc2437.txt Section 10.2.1) */ +#[allow(dead_code)] pub fn mgf_hash0( a: crate::hacl::streaming_types::hash_alg, len: u32, diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs index 6611baae2..8f2f3daa3 100644 --- a/rsa/src/impl_hacl.rs +++ b/rsa/src/impl_hacl.rs @@ -4,7 +4,7 @@ use crate::Error; pub struct Signature([u8; LEN]); #[derive(Debug, Clone)] -struct PublicKey { +pub struct PublicKey { n: [u8; LEN], } @@ -28,44 +28,48 @@ fn hacl_hash_alg(alg: crate::DigestAlgorithm) -> libcrux_hacl_rs::streaming_type macro_rules! impl_rsapss { ($sign_fn:ident, $verify_fn:ident, $bits:literal, $bytes:literal) => { - fn $sign_fn( + pub fn $sign_fn( alg: crate::DigestAlgorithm, sk: &PrivateKey<$bytes>, msg: &[u8], salt: &[u8], sig: &mut Signature<$bytes>, ) -> Result<(), Error> { - let alg = hacl_hash_alg(alg); - let salt_len = salt.len().try_into().map_err(|_| Error::SaltTooLarge)?; let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; - let skey = crate::hacl::rsapss::new_rsapss_load_skey( - $bits, E_BITS, $bits, &sk.pk.n, &E, &sk.d, - ); + let a = hacl_hash_alg(alg); + let mod_bits = $bits; + let e_bits = E_BITS; + let d_bits = $bits; + let sgnt = &mut sig.0; - match crate::hacl::rsapss::rsapss_sign( - alg, $bits, E_BITS, $bits, &skey, salt_len, salt, msg_len, msg, &mut sig.0, + match crate::hacl::rsapss::rsapss_skey_sign( + a, mod_bits, e_bits, d_bits, &sk.pk.n, &E, &sk.d, salt_len, salt, msg_len, msg, + sgnt, ) { true => Ok(()), false => Err(Error::SigningFailed), } } - fn $verify_fn( + pub fn $verify_fn( alg: crate::DigestAlgorithm, pk: &PublicKey<$bytes>, msg: &[u8], salt_len: u32, sig: &Signature<$bytes>, ) -> Result<(), Error> { - let alg = hacl_hash_alg(alg); - let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; + let a = hacl_hash_alg(alg); + let mod_bits = $bits; + let e_bits = E_BITS; + let sgnt = &sig.0; + match crate::hacl::rsapss::rsapss_pkey_verify( - alg, $bits, E_BITS, &pk.n, &E, salt_len, $bytes, /*signature length*/ - &sig.0, msg_len, msg, + a, mod_bits, e_bits, &pk.n, &E, salt_len, $bytes, /*signature length*/ + sgnt, msg_len, msg, ) { true => Ok(()), false => Err(Error::VerificationFailed), @@ -139,12 +143,11 @@ mod tests { sign_2048( crate::DigestAlgorithm::Sha2_256, &sk, - &salt, &msg, + &salt, &mut signature, ) .unwrap(); - println!("signature: {:x?}", signature); verify_2048( crate::DigestAlgorithm::Sha2_256, &pk, diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs index e9248f7a9..cf5500196 100644 --- a/rsa/src/lib.rs +++ b/rsa/src/lib.rs @@ -1,4 +1,6 @@ -#[cfg(feature = "hacl")] +#![no_std] + +#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] mod hacl { pub(crate) mod rsapss; @@ -6,6 +8,14 @@ mod hacl { use libcrux_sha2::hacl as hash_sha2; } +#[cfg(feature = "expose-hacl")] +pub mod hacl { + pub mod rsapss; + + use libcrux_hacl_rs::streaming_types; + use libcrux_sha2::hacl as hash_sha2; +} + pub enum DigestAlgorithm { Sha2_256, Sha2_384, @@ -22,3 +32,6 @@ pub enum Error { #[cfg(feature = "hacl")] mod impl_hacl; + +#[cfg(feature = "hacl")] +pub use impl_hacl::*; From 3666c35f5bb28028a5f644120e9cad2dd4fe6d08 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 19 Dec 2024 15:42:43 +0100 Subject: [PATCH 08/13] add constructors, checks and comments --- rsa/src/impl_hacl.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++ rsa/src/lib.rs | 12 ++++++++ 2 files changed, 83 insertions(+) diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs index 8f2f3daa3..5e910b618 100644 --- a/rsa/src/impl_hacl.rs +++ b/rsa/src/impl_hacl.rs @@ -8,11 +8,27 @@ pub struct PublicKey { n: [u8; LEN], } +impl From<[u8; LEN]> for PublicKey { + fn from(n: [u8; LEN]) -> Self { + Self { n } + } +} + pub struct PrivateKey { pk: PublicKey, d: [u8; LEN], } +impl PrivateKey { + pub fn from_components(n: [u8; LEN], d: [u8; LEN]) -> Self { + Self { pk: n.into(), d } + } + + pub fn pk(&self) -> &PublicKey { + &self.pk + } +} + const E_BITS: u32 = 17; const E: [u8; 3] = [1, 0, 1]; @@ -28,6 +44,26 @@ fn hacl_hash_alg(alg: crate::DigestAlgorithm) -> libcrux_hacl_rs::streaming_type macro_rules! impl_rsapss { ($sign_fn:ident, $verify_fn:ident, $bits:literal, $bytes:literal) => { + /// Computes a signature over `msg` using `sk` and writes it to `sig`. + /// Returns `Ok(())` on success. + /// + /// Returns an error in any of the following cases: + /// - the secret key is invalid + /// - the length of `msg` exceeds `u32::MAX` + /// - `salt_len` exceeds `u32::MAX - alg.hash_len() - 8` + /// + /// Ensures that the preconditions to hacl functions hold: + /// + /// - `sLen + Hash.hash_length a + 8 <= max_size_t` + /// - checked explicitly + /// - `(sLen + Hash.hash_length a + 8) less_than_max_input_length a` + /// - `max_input_length` is at least `2^62 - 1`, can't be reached since everyting + /// is less than `u32::MAX`. + /// - `sLen + Hash.hash_length a + 2 <= blocks (modBits - 1) 8` + /// - `blocks a b = (a - 1) / b + 1`, i.e. `ceil(div(a, b))` + /// - checked explicitly + /// - `msgLen `less_than_max_input_length` a` + /// - follows from the check that messages are shorter than `u32::MAX`. pub fn $sign_fn( alg: crate::DigestAlgorithm, sk: &PrivateKey<$bytes>, @@ -38,12 +74,24 @@ macro_rules! impl_rsapss { let salt_len = salt.len().try_into().map_err(|_| Error::SaltTooLarge)?; let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; + // required by precondition to verify, see + // https://github.com/hacl-star/hacl-star/blob/efbf82f29190e2aecdac8899e4f42c8cb9defc98/code/rsapss/Hacl.Spec.RSAPSS.fst#L162 + if (salt_len as u64) + alg.hash_len() as u64 + 8 > u32::MAX as u64 { + return Err(Error::SaltTooLarge); + } + let a = hacl_hash_alg(alg); let mod_bits = $bits; let e_bits = E_BITS; let d_bits = $bits; let sgnt = &mut sig.0; + // required by precondition to verify, see + // https://github.com/hacl-star/hacl-star/blob/main/code/rsapss/Hacl.Spec.RSAPSS.fst#L164 + if salt_len as u64 + alg.hash_len() as u64 + 2 > (mod_bits as u64 - 1) / 8 + 1 { + return Err(Error::SaltTooLarge); + } + match crate::hacl::rsapss::rsapss_skey_sign( a, mod_bits, e_bits, d_bits, &sk.pk.n, &E, &sk.d, salt_len, salt, msg_len, msg, sgnt, @@ -53,6 +101,23 @@ macro_rules! impl_rsapss { } } + /// Returns `Ok(())` if the provided signature is valid. + /// + /// Returns an error in any of the following cases: + /// - the public key is invalid + /// - the signature verification fails + /// - the length of `msg` exceeds `u32::MAX` + /// - `salt_len` exceeds `u32::MAX - alg.hash_len() - 8` + /// + /// Ensures that the preconditions to hacl functions hold: + /// + /// - `sLen + Hash.hash_length a + 8 <= max_size_t` + /// - checked explicitly + /// - `(sLen + Hash.hash_length a + 8) less_than_max_input_length a` + /// - `max_input_length` is at least `2^62 - 1`, can't be reached since everyting + /// is less than `u32::MAX`. + /// - `msgLen less_than_max_input_length a` + /// - follows from the check that messages are shorter than `u32::MAX`. pub fn $verify_fn( alg: crate::DigestAlgorithm, pk: &PublicKey<$bytes>, @@ -60,6 +125,12 @@ macro_rules! impl_rsapss { salt_len: u32, sig: &Signature<$bytes>, ) -> Result<(), Error> { + // required by precondition to verify, see + // https://github.com/hacl-star/hacl-star/blob/efbf82f29190e2aecdac8899e4f42c8cb9defc98/code/rsapss/Hacl.Spec.RSAPSS.fst#L236 + if (salt_len as u64) + alg.hash_len() as u64 + 8 > u32::MAX as u64 { + return Err(Error::SaltTooLarge); + } + let msg_len = msg.len().try_into().map_err(|_| Error::MessageTooLarge)?; let a = hacl_hash_alg(alg); diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs index cf5500196..c67d40d9d 100644 --- a/rsa/src/lib.rs +++ b/rsa/src/lib.rs @@ -16,12 +16,24 @@ pub mod hacl { use libcrux_sha2::hacl as hash_sha2; } +#[derive(Clone, Copy, Debug)] pub enum DigestAlgorithm { Sha2_256, Sha2_384, Sha2_512, } +impl DigestAlgorithm { + // using u8 so it can be safely coerced into any uint type + fn hash_len(&self) -> u8 { + match self { + DigestAlgorithm::Sha2_256 => 32, + DigestAlgorithm::Sha2_384 => 48, + DigestAlgorithm::Sha2_512 => 64, + } + } +} + #[derive(Debug)] pub enum Error { SaltTooLarge, From d7b13daf05401a80c3e8e148d4c0ee9c4f59290c Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 19 Dec 2024 16:18:40 +0100 Subject: [PATCH 09/13] address review feedback --- chacha20poly1305/Cargo.toml | 10 +++------- chacha20poly1305/src/impl_hacl.rs | 5 +---- chacha20poly1305/src/lib.rs | 3 --- curve25519/Cargo.toml | 11 ++--------- curve25519/src/lib.rs | 8 +++----- ed25519/Cargo.toml | 12 ++++-------- ed25519/src/lib.rs | 3 --- libcrux-ecdh/Cargo.toml | 4 +--- libcrux-hkdf/Cargo.toml | 9 ++------- libcrux-hkdf/src/hkdf.rs | 6 ------ libcrux-hmac/Cargo.toml | 10 ++++------ libcrux-hmac/src/hmac.rs | 4 +--- poly1305/Cargo.toml | 8 +++----- poly1305/src/lib.rs | 4 +--- rsa/Cargo.toml | 6 ++---- rsa/src/lib.rs | 6 ++---- sha2/Cargo.toml | 6 ++---- sha2/src/lib.rs | 5 ++--- 18 files changed, 33 insertions(+), 87 deletions(-) diff --git a/chacha20poly1305/Cargo.toml b/chacha20poly1305/Cargo.toml index 43b02128c..94036cab5 100644 --- a/chacha20poly1305/Cargo.toml +++ b/chacha20poly1305/Cargo.toml @@ -10,13 +10,9 @@ edition.workspace = true repository.workspace = true readme.workspace = true -[features] -default = ["hacl"] -hacl = ["dep:libcrux-poly1305", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] - [dependencies] libcrux-poly1305 = { version = "=0.0.2-beta.2", path = "../poly1305/", features = [ "expose-hacl", -], optional = true } -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } +] } +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/chacha20poly1305/src/impl_hacl.rs b/chacha20poly1305/src/impl_hacl.rs index 44223e6bf..dcec76bcd 100644 --- a/chacha20poly1305/src/impl_hacl.rs +++ b/chacha20poly1305/src/impl_hacl.rs @@ -1,4 +1,4 @@ -use crate::{AeadError, MacError, KEY_LEN, NONCE_LEN, TAG_LEN}; +use crate::{AeadError, KEY_LEN, NONCE_LEN, TAG_LEN}; /// The ChaCha20-Poly1305 AEAD encryption function. Writes the concatenation of the ciphertexoft /// produced by ChaCha20 and the MAC tag into `ctxt` and returns the two pieces separately. @@ -24,9 +24,6 @@ pub fn encrypt<'a>( } // ensure destination slice has just the right length - let ctxt_len = ptxt.len() + TAG_LEN; - let ctxtu32 = &mut ctxt[..ctxt_len]; - let (ctxt_cpa, tag) = ctxt.split_at_mut(ptxt.len()); let tag: &mut [u8; TAG_LEN] = tag.try_into().unwrap(); diff --git a/chacha20poly1305/src/lib.rs b/chacha20poly1305/src/lib.rs index c4cd612c7..90852f83f 100644 --- a/chacha20poly1305/src/lib.rs +++ b/chacha20poly1305/src/lib.rs @@ -35,7 +35,6 @@ pub enum MacError { InvalidMacTag, } -#[cfg(feature = "hacl")] mod hacl { pub(crate) use libcrux_poly1305::hacl::mac_poly1305; @@ -44,8 +43,6 @@ mod hacl { pub(crate) mod chacha20_vec32; } -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::*; diff --git a/curve25519/Cargo.toml b/curve25519/Cargo.toml index fccb866f3..c7e990139 100644 --- a/curve25519/Cargo.toml +++ b/curve25519/Cargo.toml @@ -10,13 +10,6 @@ edition.workspace = true repository.workspace = true readme.workspace = true -[features] -default = ["hacl"] -hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] - [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", optional = true, features = [ - "hacl", -] } -libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } +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/curve25519/src/lib.rs b/curve25519/src/lib.rs index 5e697f9c1..e61317202 100644 --- a/curve25519/src/lib.rs +++ b/curve25519/src/lib.rs @@ -1,12 +1,9 @@ #![no_std] -#[cfg(feature = "hacl")] pub use libcrux_hacl_rs::curve25519_51 as hacl; -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::{ecdh, secret_to_public}; /// The length of Curve25519 secret keys. @@ -22,8 +19,9 @@ pub const SHK_LEN: usize = 32; pub struct Error; /// This trait is implemented by the backing implementations. -/// Only used for implementation agility. -pub trait Curve25519 { +/// Only used for ensuring implementations follow the same interface, not really consumed. +#[allow(dead_code)] +trait Curve25519 { /// Computes a public key from a secret key. fn secret_to_public(pk: &mut [u8; PK_LEN], sk: &[u8; SK_LEN]); diff --git a/ed25519/Cargo.toml b/ed25519/Cargo.toml index 18fd3021d..3eaae4193 100644 --- a/ed25519/Cargo.toml +++ b/ed25519/Cargo.toml @@ -10,13 +10,9 @@ edition.workspace = true repository.workspace = true readme.workspace = true -[features] -default = ["hacl"] -hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] - [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", optional = true, features = [ - "hacl", +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/" } +libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", features = [ + "expose-hacl", ] } -libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } diff --git a/ed25519/src/lib.rs b/ed25519/src/lib.rs index 9dfd36fa8..706bde8a0 100644 --- a/ed25519/src/lib.rs +++ b/ed25519/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] -#[cfg(feature = "hacl")] pub mod hacl { //! This module contains generated hacl code. @@ -8,8 +7,6 @@ pub mod hacl { pub mod ed25519_precomptable; } -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::*; diff --git a/libcrux-ecdh/Cargo.toml b/libcrux-ecdh/Cargo.toml index 3fa7eb40c..fdd85df6c 100644 --- a/libcrux-ecdh/Cargo.toml +++ b/libcrux-ecdh/Cargo.toml @@ -15,9 +15,7 @@ path = "src/ecdh.rs" [dependencies] rand = { version = "0.8" } libcrux-hacl = { version = "=0.0.2-beta.2", path = "../sys/hacl" } -libcrux-curve25519 = { version = "=0.0.2-beta.2", path = "../curve25519", features = [ - "hacl", -] } +libcrux-curve25519 = { version = "=0.0.2-beta.2", path = "../curve25519" } [dev-dependencies] rand_core = { version = "0.6" } diff --git a/libcrux-hkdf/Cargo.toml b/libcrux-hkdf/Cargo.toml index c1b9e2839..a317bf967 100644 --- a/libcrux-hkdf/Cargo.toml +++ b/libcrux-hkdf/Cargo.toml @@ -13,13 +13,8 @@ description = "Libcrux HKDF implementation" path = "src/hkdf.rs" [features] -default = ["hacl"] -hacl = ["dep:libcrux-hmac", "dep:libcrux-hacl-rs"] - [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-hmac = { version = "=0.0.2-beta.2", path = "../libcrux-hmac", optional = true, features = [ - "hacl", +libcrux-hmac = { version = "=0.0.2-beta.2", path = "../libcrux-hmac", features = [ "expose-hacl", - ] } +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/" } diff --git a/libcrux-hkdf/src/hkdf.rs b/libcrux-hkdf/src/hkdf.rs index 6c912b352..e77d598d2 100644 --- a/libcrux-hkdf/src/hkdf.rs +++ b/libcrux-hkdf/src/hkdf.rs @@ -7,13 +7,10 @@ extern crate alloc; use alloc::vec::Vec; -#[cfg(feature = "hacl")] pub mod hacl; -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::{HkdfSha2_256, HkdfSha2_384, HkdfSha2_512}; pub trait HkdfMode { @@ -115,7 +112,6 @@ pub enum Error { /// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`. /// Returns the pre-key material in a vector of tag length. -#[cfg(feature = "hacl")] #[inline(always)] pub fn extract( alg: Algorithm, @@ -134,7 +130,6 @@ pub fn extract( /// HKDF expand using hash function `mode`, pre-key material `prk`, `info`, and output length `okm_len`. /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. -#[cfg(feature = "hacl")] #[inline(always)] pub fn expand( alg: Algorithm, @@ -155,7 +150,6 @@ pub fn expand( /// Calls `extract` and `expand` with the given input. /// Returns the key material in a vector of length `okm_len` or [`Error::OkmLengthTooLarge`] /// if the requested output length is too large. -#[cfg(feature = "hacl")] #[inline(always)] pub fn hkdf( mode: Algorithm, diff --git a/libcrux-hmac/Cargo.toml b/libcrux-hmac/Cargo.toml index 99fc53231..bb3bc108d 100644 --- a/libcrux-hmac/Cargo.toml +++ b/libcrux-hmac/Cargo.toml @@ -13,13 +13,11 @@ description = "Libcrux HMAC implementation" path = "src/hmac.rs" [features] -default = ["hacl"] -hacl = ["dep:libcrux-sha2", "dep:libcrux-hacl-rs", "dep:libcrux-macros"] -expose-hacl = ["hacl"] +expose-hacl = [] [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", optional = true, features = [ +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/" } +libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", features = [ "expose-hacl", ] } -libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } +libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } diff --git a/libcrux-hmac/src/hmac.rs b/libcrux-hmac/src/hmac.rs index 1f0243a99..8b9207712 100644 --- a/libcrux-hmac/src/hmac.rs +++ b/libcrux-hmac/src/hmac.rs @@ -7,7 +7,7 @@ extern crate alloc; use alloc::vec::Vec; -#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +#[cfg(not(feature = "expose-hacl"))] mod hacl { pub(crate) mod hash_sha1; pub(crate) mod hmac; @@ -19,10 +19,8 @@ pub mod hacl { pub mod hmac; } -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::*; /// The HMAC algorithm defining the used hash function. diff --git a/poly1305/Cargo.toml b/poly1305/Cargo.toml index e7300cf29..575bcc697 100644 --- a/poly1305/Cargo.toml +++ b/poly1305/Cargo.toml @@ -11,10 +11,8 @@ repository.workspace = true readme.workspace = true [features] -default = ["hacl"] -hacl = ["dep:libcrux-hacl-rs", "dep:libcrux-macros"] -expose-hacl = ["hacl"] +expose-hacl = [] [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/", optional = true } -libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros", optional = true } +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/poly1305/src/lib.rs b/poly1305/src/lib.rs index d940f8aae..ea06d97cf 100644 --- a/poly1305/src/lib.rs +++ b/poly1305/src/lib.rs @@ -15,7 +15,7 @@ pub enum Error { InvalidMacTag, } -#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +#[cfg(not(feature = "expose-hacl"))] mod hacl { pub(crate) mod mac_poly1305; } @@ -25,8 +25,6 @@ pub mod hacl { pub mod mac_poly1305; } -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::*; diff --git a/rsa/Cargo.toml b/rsa/Cargo.toml index 268526ea3..fcc1f3faf 100644 --- a/rsa/Cargo.toml +++ b/rsa/Cargo.toml @@ -11,12 +11,10 @@ repository.workspace = true readme.workspace = true [features] -default = ["hacl"] -hacl = ["dep:libcrux-hacl-rs"] -expose-hacl = ["hacl"] +expose-hacl = [] [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs", optional = true } +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs" } libcrux-traits = { version = "=0.0.2-beta.2", path = "../traits/" } libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } libcrux-sha2 = { version = "=0.0.2-beta.2", path = "../sha2", features = [ diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs index c67d40d9d..058222358 100644 --- a/rsa/src/lib.rs +++ b/rsa/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +#[cfg(not(feature = "expose-hacl"))] mod hacl { pub(crate) mod rsapss; @@ -38,12 +38,10 @@ impl DigestAlgorithm { pub enum Error { SaltTooLarge, MessageTooLarge, - SigningFailed, VerificationFailed, + SigningFailed, } -#[cfg(feature = "hacl")] mod impl_hacl; -#[cfg(feature = "hacl")] pub use impl_hacl::*; diff --git a/sha2/Cargo.toml b/sha2/Cargo.toml index a216d3c7e..9460ea2df 100644 --- a/sha2/Cargo.toml +++ b/sha2/Cargo.toml @@ -11,11 +11,9 @@ repository.workspace = true readme.workspace = true [features] -default = ["hacl"] -hacl = ["dep:libcrux-hacl-rs"] -expose-hacl = ["hacl"] +expose-hacl = [] [dependencies] -libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs", optional = true } +libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs" } libcrux-traits = { version = "=0.0.2-beta.2", path = "../traits/" } libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } diff --git a/sha2/src/lib.rs b/sha2/src/lib.rs index 0231fd743..7e2407b18 100644 --- a/sha2/src/lib.rs +++ b/sha2/src/lib.rs @@ -13,16 +13,15 @@ pub const SHA384_LENGTH: usize = 48; pub const SHA512_LENGTH: usize = 64; /// The generated hacl code -#[cfg(all(feature = "hacl", not(feature = "expose-hacl")))] +#[cfg(not(feature = "expose-hacl"))] mod hacl; +/// The generated hacl code #[cfg(feature = "expose-hacl")] pub mod hacl; /// The implementation of our types using that hacl code -#[cfg(feature = "hacl")] mod impl_hacl; /// use it if we want to use hacl -#[cfg(feature = "hacl")] pub use impl_hacl::*; From 1d5588cbb205d648577478ba40709ee6c4b0c4c9 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 19 Dec 2024 17:23:03 +0100 Subject: [PATCH 10/13] address review feedback --- chacha20poly1305/src/impl_hacl.rs | 2 ++ rsa/src/impl_hacl.rs | 10 +++++++++- rsa/src/lib.rs | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/chacha20poly1305/src/impl_hacl.rs b/chacha20poly1305/src/impl_hacl.rs index dcec76bcd..460377e0f 100644 --- a/chacha20poly1305/src/impl_hacl.rs +++ b/chacha20poly1305/src/impl_hacl.rs @@ -19,6 +19,7 @@ pub fn encrypt<'a>( let aad_len: u32 = aad.len().try_into().map_err(|_| AeadError::AadTooLarge)?; + // we already knwo that ptxt.len() < u32::MAX, so we can safely add here. if ctxt.len() < ptxt.len() + TAG_LEN { return Err(AeadError::CiphertextTooShort); } @@ -50,6 +51,7 @@ pub fn decrypt<'a>( return Err(AeadError::InvalidCiphertext); } + // we know that ctxt.len() >= TAG_LEN, so we can subtract if ptxt.len() < ctxt.len() - TAG_LEN { return Err(AeadError::PlaintextTooShort); } diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs index 5e910b618..5faead7a9 100644 --- a/rsa/src/impl_hacl.rs +++ b/rsa/src/impl_hacl.rs @@ -1,8 +1,10 @@ use crate::Error; +/// An RSA Signature that is `LEN` bytes long. #[derive(Debug)] pub struct Signature([u8; LEN]); +/// An RSA Public Key that is `LEN` bytes long. #[derive(Debug, Clone)] pub struct PublicKey { n: [u8; LEN], @@ -14,16 +16,19 @@ impl From<[u8; LEN]> for PublicKey { } } +/// An RSA Private Key that is `LEN` bytes long. pub struct PrivateKey { pk: PublicKey, d: [u8; LEN], } impl PrivateKey { + /// Constructor for the private key based on `n` and `d`. pub fn from_components(n: [u8; LEN], d: [u8; LEN]) -> Self { Self { pk: n.into(), d } } + /// Returns the public key of the private key. pub fn pk(&self) -> &PublicKey { &self.pk } @@ -76,6 +81,7 @@ macro_rules! impl_rsapss { // required by precondition to verify, see // https://github.com/hacl-star/hacl-star/blob/efbf82f29190e2aecdac8899e4f42c8cb9defc98/code/rsapss/Hacl.Spec.RSAPSS.fst#L162 + // all operands are at most u32, so coercing to u64 and then adding is safe. if (salt_len as u64) + alg.hash_len() as u64 + 8 > u32::MAX as u64 { return Err(Error::SaltTooLarge); } @@ -87,7 +93,8 @@ macro_rules! impl_rsapss { let sgnt = &mut sig.0; // required by precondition to verify, see - // https://github.com/hacl-star/hacl-star/blob/main/code/rsapss/Hacl.Spec.RSAPSS.fst#L164 + // https://github.com/hacl-star/hacl-star/blob/efbf82f29190e2aecdac8899e4f42c8cb9defc98/code/rsapss/Hacl.Spec.RSAPSS.fst#L164 + // all operands are at most u32, so coercing to u64 and then adding is safe. if salt_len as u64 + alg.hash_len() as u64 + 2 > (mod_bits as u64 - 1) / 8 + 1 { return Err(Error::SaltTooLarge); } @@ -127,6 +134,7 @@ macro_rules! impl_rsapss { ) -> Result<(), Error> { // required by precondition to verify, see // https://github.com/hacl-star/hacl-star/blob/efbf82f29190e2aecdac8899e4f42c8cb9defc98/code/rsapss/Hacl.Spec.RSAPSS.fst#L236 + // all operands are at most u32, so coercing to u64 and then adding is safe. if (salt_len as u64) + alg.hash_len() as u64 + 8 > u32::MAX as u64 { return Err(Error::SaltTooLarge); } diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs index 058222358..2747273a6 100644 --- a/rsa/src/lib.rs +++ b/rsa/src/lib.rs @@ -8,14 +8,17 @@ mod hacl { use libcrux_sha2::hacl as hash_sha2; } +/// The hacl-rs code for RSA signatures #[cfg(feature = "expose-hacl")] pub mod hacl { + /// The RSA-PSS signature code. pub mod rsapss; use libcrux_hacl_rs::streaming_types; use libcrux_sha2::hacl as hash_sha2; } +/// The hash algorithm used for signing or verifying. #[derive(Clone, Copy, Debug)] pub enum DigestAlgorithm { Sha2_256, @@ -34,11 +37,19 @@ impl DigestAlgorithm { } } +/// Represents errors that occurred during signing or verifying. #[derive(Debug)] pub enum Error { + /// Indicates that the salt is too large. SaltTooLarge, + + /// Indicates that the message is too large. MessageTooLarge, + + /// Indicates that the verification of a signature failed. VerificationFailed, + + /// Indicates that signing a message failed. SigningFailed, } From 15b5b012c9fa12b02c35d9a0ef8a479ca12c7c33 Mon Sep 17 00:00:00 2001 From: "Jan Winkelmann (keks)" Date: Thu, 19 Dec 2024 17:43:06 +0100 Subject: [PATCH 11/13] more review --- .../src/hacl/aead_chacha20poly1305.rs | 2 + chacha20poly1305/src/hacl/chacha20.rs | 1 + chacha20poly1305/src/hacl/chacha20_vec32.rs | 252 ------------------ chacha20poly1305/src/impl_hacl.rs | 4 +- chacha20poly1305/src/lib.rs | 1 - rsa/src/lib.rs | 5 + 6 files changed, 10 insertions(+), 255 deletions(-) delete mode 100644 chacha20poly1305/src/hacl/chacha20_vec32.rs diff --git a/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs b/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs index 6d8c27212..2b9e5addd 100644 --- a/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs +++ b/chacha20poly1305/src/hacl/aead_chacha20poly1305.rs @@ -532,6 +532,7 @@ Note: Encryption and decryption can be executed in-place, i.e., `input` and `out @param key Pointer to 32 bytes of memory where the AEAD key is read from. @param nonce Pointer to 12 bytes of memory where the AEAD nonce is read from. */ +#[allow(clippy::too_many_arguments)] pub fn encrypt( output: &mut [u8], tag: &mut [u8], @@ -572,6 +573,7 @@ If decryption fails, the array `output` remains unchanged and the function retur @returns 0 on succeess; 1 on failure. */ +#[allow(clippy::too_many_arguments)] pub fn decrypt( output: &mut [u8], input: &[u8], diff --git a/chacha20poly1305/src/hacl/chacha20.rs b/chacha20poly1305/src/hacl/chacha20.rs index 88f0adb71..a78c6fe8d 100644 --- a/chacha20poly1305/src/hacl/chacha20.rs +++ b/chacha20poly1305/src/hacl/chacha20.rs @@ -183,6 +183,7 @@ pub fn chacha20_encrypt(len: u32, out: &mut [u8], text: &[u8], key: &[u8], n: &[ crate::hacl::chacha20::chacha20_update(&ctx, len, out, text) } +#[allow(dead_code)] pub fn chacha20_decrypt(len: u32, out: &mut [u8], cipher: &[u8], key: &[u8], n: &[u8], ctr: u32) { let mut ctx: [u32; 16] = [0u32; 16usize]; crate::hacl::chacha20::chacha20_init(&mut ctx, key, n, ctr); diff --git a/chacha20poly1305/src/hacl/chacha20_vec32.rs b/chacha20poly1305/src/hacl/chacha20_vec32.rs deleted file mode 100644 index e78d2bfa1..000000000 --- a/chacha20poly1305/src/hacl/chacha20_vec32.rs +++ /dev/null @@ -1,252 +0,0 @@ -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(unused_assignments)] -#![allow(unreachable_patterns)] - -//! This module contains generated hacl code. - -use libcrux_hacl_rs::prelude::*; -use libcrux_macros as krml; - -#[inline] -fn double_round_32(st: &mut [u32]) { - st[0usize] = (st[0usize]).wrapping_add(st[4usize]); - let std: u32 = st[12usize] ^ st[0usize]; - st[12usize] = std.wrapping_shl(16u32) | std.wrapping_shr(16u32); - st[8usize] = (st[8usize]).wrapping_add(st[12usize]); - let std0: u32 = st[4usize] ^ st[8usize]; - st[4usize] = std0.wrapping_shl(12u32) | std0.wrapping_shr(20u32); - st[0usize] = (st[0usize]).wrapping_add(st[4usize]); - let std1: u32 = st[12usize] ^ st[0usize]; - st[12usize] = std1.wrapping_shl(8u32) | std1.wrapping_shr(24u32); - st[8usize] = (st[8usize]).wrapping_add(st[12usize]); - let std2: u32 = st[4usize] ^ st[8usize]; - st[4usize] = std2.wrapping_shl(7u32) | std2.wrapping_shr(25u32); - st[1usize] = (st[1usize]).wrapping_add(st[5usize]); - let std3: u32 = st[13usize] ^ st[1usize]; - st[13usize] = std3.wrapping_shl(16u32) | std3.wrapping_shr(16u32); - st[9usize] = (st[9usize]).wrapping_add(st[13usize]); - let std4: u32 = st[5usize] ^ st[9usize]; - st[5usize] = std4.wrapping_shl(12u32) | std4.wrapping_shr(20u32); - st[1usize] = (st[1usize]).wrapping_add(st[5usize]); - let std5: u32 = st[13usize] ^ st[1usize]; - st[13usize] = std5.wrapping_shl(8u32) | std5.wrapping_shr(24u32); - st[9usize] = (st[9usize]).wrapping_add(st[13usize]); - let std6: u32 = st[5usize] ^ st[9usize]; - st[5usize] = std6.wrapping_shl(7u32) | std6.wrapping_shr(25u32); - st[2usize] = (st[2usize]).wrapping_add(st[6usize]); - let std7: u32 = st[14usize] ^ st[2usize]; - st[14usize] = std7.wrapping_shl(16u32) | std7.wrapping_shr(16u32); - st[10usize] = (st[10usize]).wrapping_add(st[14usize]); - let std8: u32 = st[6usize] ^ st[10usize]; - st[6usize] = std8.wrapping_shl(12u32) | std8.wrapping_shr(20u32); - st[2usize] = (st[2usize]).wrapping_add(st[6usize]); - let std9: u32 = st[14usize] ^ st[2usize]; - st[14usize] = std9.wrapping_shl(8u32) | std9.wrapping_shr(24u32); - st[10usize] = (st[10usize]).wrapping_add(st[14usize]); - let std10: u32 = st[6usize] ^ st[10usize]; - st[6usize] = std10.wrapping_shl(7u32) | std10.wrapping_shr(25u32); - st[3usize] = (st[3usize]).wrapping_add(st[7usize]); - let std11: u32 = st[15usize] ^ st[3usize]; - st[15usize] = std11.wrapping_shl(16u32) | std11.wrapping_shr(16u32); - st[11usize] = (st[11usize]).wrapping_add(st[15usize]); - let std12: u32 = st[7usize] ^ st[11usize]; - st[7usize] = std12.wrapping_shl(12u32) | std12.wrapping_shr(20u32); - st[3usize] = (st[3usize]).wrapping_add(st[7usize]); - let std13: u32 = st[15usize] ^ st[3usize]; - st[15usize] = std13.wrapping_shl(8u32) | std13.wrapping_shr(24u32); - st[11usize] = (st[11usize]).wrapping_add(st[15usize]); - let std14: u32 = st[7usize] ^ st[11usize]; - st[7usize] = std14.wrapping_shl(7u32) | std14.wrapping_shr(25u32); - st[0usize] = (st[0usize]).wrapping_add(st[5usize]); - let std15: u32 = st[15usize] ^ st[0usize]; - st[15usize] = std15.wrapping_shl(16u32) | std15.wrapping_shr(16u32); - st[10usize] = (st[10usize]).wrapping_add(st[15usize]); - let std16: u32 = st[5usize] ^ st[10usize]; - st[5usize] = std16.wrapping_shl(12u32) | std16.wrapping_shr(20u32); - st[0usize] = (st[0usize]).wrapping_add(st[5usize]); - let std17: u32 = st[15usize] ^ st[0usize]; - st[15usize] = std17.wrapping_shl(8u32) | std17.wrapping_shr(24u32); - st[10usize] = (st[10usize]).wrapping_add(st[15usize]); - let std18: u32 = st[5usize] ^ st[10usize]; - st[5usize] = std18.wrapping_shl(7u32) | std18.wrapping_shr(25u32); - st[1usize] = (st[1usize]).wrapping_add(st[6usize]); - let std19: u32 = st[12usize] ^ st[1usize]; - st[12usize] = std19.wrapping_shl(16u32) | std19.wrapping_shr(16u32); - st[11usize] = (st[11usize]).wrapping_add(st[12usize]); - let std20: u32 = st[6usize] ^ st[11usize]; - st[6usize] = std20.wrapping_shl(12u32) | std20.wrapping_shr(20u32); - st[1usize] = (st[1usize]).wrapping_add(st[6usize]); - let std21: u32 = st[12usize] ^ st[1usize]; - st[12usize] = std21.wrapping_shl(8u32) | std21.wrapping_shr(24u32); - st[11usize] = (st[11usize]).wrapping_add(st[12usize]); - let std22: u32 = st[6usize] ^ st[11usize]; - st[6usize] = std22.wrapping_shl(7u32) | std22.wrapping_shr(25u32); - st[2usize] = (st[2usize]).wrapping_add(st[7usize]); - let std23: u32 = st[13usize] ^ st[2usize]; - st[13usize] = std23.wrapping_shl(16u32) | std23.wrapping_shr(16u32); - st[8usize] = (st[8usize]).wrapping_add(st[13usize]); - let std24: u32 = st[7usize] ^ st[8usize]; - st[7usize] = std24.wrapping_shl(12u32) | std24.wrapping_shr(20u32); - st[2usize] = (st[2usize]).wrapping_add(st[7usize]); - let std25: u32 = st[13usize] ^ st[2usize]; - st[13usize] = std25.wrapping_shl(8u32) | std25.wrapping_shr(24u32); - st[8usize] = (st[8usize]).wrapping_add(st[13usize]); - let std26: u32 = st[7usize] ^ st[8usize]; - st[7usize] = std26.wrapping_shl(7u32) | std26.wrapping_shr(25u32); - st[3usize] = (st[3usize]).wrapping_add(st[4usize]); - let std27: u32 = st[14usize] ^ st[3usize]; - st[14usize] = std27.wrapping_shl(16u32) | std27.wrapping_shr(16u32); - st[9usize] = (st[9usize]).wrapping_add(st[14usize]); - let std28: u32 = st[4usize] ^ st[9usize]; - st[4usize] = std28.wrapping_shl(12u32) | std28.wrapping_shr(20u32); - st[3usize] = (st[3usize]).wrapping_add(st[4usize]); - let std29: u32 = st[14usize] ^ st[3usize]; - st[14usize] = std29.wrapping_shl(8u32) | std29.wrapping_shr(24u32); - st[9usize] = (st[9usize]).wrapping_add(st[14usize]); - let std30: u32 = st[4usize] ^ st[9usize]; - st[4usize] = std30.wrapping_shl(7u32) | std30.wrapping_shr(25u32) -} - -#[inline] -fn chacha20_core_32(k: &mut [u32], ctx: &[u32], ctr: u32) { - (k[0usize..16usize]).copy_from_slice(&ctx[0usize..16usize]); - let ctr_u32: u32 = 1u32.wrapping_mul(ctr); - let cv: u32 = ctr_u32; - k[12usize] = (k[12usize]).wrapping_add(cv); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - crate::hacl::chacha20_vec32::double_round_32(k); - krml::unroll_for!(16, "i", 0u32, 1u32, { - let x: u32 = (k[i as usize]).wrapping_add(ctx[i as usize]); - let os: (&mut [u32], &mut [u32]) = k.split_at_mut(0usize); - os.1[i as usize] = x - }); - k[12usize] = (k[12usize]).wrapping_add(cv) -} - -#[inline] -fn chacha20_init_32(ctx: &mut [u32], k: &[u8], n: &[u8], ctr: u32) { - let mut ctx1: [u32; 16] = [0u32; 16usize]; - krml::unroll_for!(4, "i", 0u32, 1u32, { - let x: u32 = (&crate::hacl::chacha20::chacha20_constants)[i as usize]; - let os: &mut [u32] = &mut (&mut (&mut ctx1)[0usize..])[0usize..]; - os[i as usize] = x - }); - let uu____0: (&mut [u32], &mut [u32]) = ctx1.split_at_mut(4usize); - krml::unroll_for!(8, "i", 0u32, 1u32, { - let bj: (&[u8], &[u8]) = k.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]) = uu____0.1.split_at_mut(0usize); - os.1[i as usize] = x - }); - (&mut ctx1)[12usize] = ctr; - let uu____1: (&mut [u32], &mut [u32]) = ctx1.split_at_mut(13usize); - krml::unroll_for!(3, "i", 0u32, 1u32, { - let bj: (&[u8], &[u8]) = n.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]) = uu____1.1.split_at_mut(0usize); - os.1[i as usize] = x - }); - krml::unroll_for!(16, "i", 0u32, 1u32, { - let x: u32 = (&ctx1)[i as usize]; - let os: (&mut [u32], &mut [u32]) = ctx.split_at_mut(0usize); - os.1[i as usize] = x - }); - let ctr1: u32 = 0u32; - let c12: u32 = ctx[12usize]; - ctx[12usize] = c12.wrapping_add(ctr1) -} - -pub fn chacha20_encrypt_32(len: u32, out: &mut [u8], text: &[u8], key: &[u8], n: &[u8], ctr: u32) { - let mut ctx: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_init_32(&mut ctx, key, n, ctr); - let rem: u32 = len.wrapping_rem(64u32); - let nb: u32 = len.wrapping_div(64u32); - let rem1: u32 = len.wrapping_rem(64u32); - for i in 0u32..nb { - let uu____0: (&mut [u8], &mut [u8]) = out.split_at_mut(i.wrapping_mul(64u32) as usize); - let uu____1: (&[u8], &[u8]) = text.split_at(i.wrapping_mul(64u32) as usize); - let mut k: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, i); - krml::unroll_for!(16, "i0", 0u32, 1u32, { - let u: u32 = - lowstar::endianness::load32_le(&uu____1.1[i0.wrapping_mul(4u32) as usize..]); - let x: u32 = u; - let y: u32 = x ^ (&k)[i0 as usize]; - lowstar::endianness::store32_le(&mut uu____0.1[i0.wrapping_mul(4u32) as usize..], y) - }) - } - if rem1 > 0u32 { - let uu____2: (&mut [u8], &mut [u8]) = out.split_at_mut(nb.wrapping_mul(64u32) as usize); - let mut plain: [u8; 64] = [0u8; 64usize]; - ((&mut plain)[0usize..rem as usize]) - .copy_from_slice(&(&text[nb.wrapping_mul(64u32) as usize..])[0usize..rem as usize]); - let mut k: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, nb); - krml::unroll_for!(16, "i", 0u32, 1u32, { - let u: u32 = lowstar::endianness::load32_le(&(&plain)[i.wrapping_mul(4u32) as usize..]); - let x: u32 = u; - let y: u32 = x ^ (&k)[i as usize]; - lowstar::endianness::store32_le(&mut (&mut plain)[i.wrapping_mul(4u32) as usize..], y) - }); - (uu____2.1[0usize..rem as usize]) - .copy_from_slice(&(&(&plain)[0usize..])[0usize..rem as usize]) - } -} - -pub fn chacha20_decrypt_32( - len: u32, - out: &mut [u8], - cipher: &[u8], - key: &[u8], - n: &[u8], - ctr: u32, -) { - let mut ctx: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_init_32(&mut ctx, key, n, ctr); - let rem: u32 = len.wrapping_rem(64u32); - let nb: u32 = len.wrapping_div(64u32); - let rem1: u32 = len.wrapping_rem(64u32); - for i in 0u32..nb { - let uu____0: (&mut [u8], &mut [u8]) = out.split_at_mut(i.wrapping_mul(64u32) as usize); - let uu____1: (&[u8], &[u8]) = cipher.split_at(i.wrapping_mul(64u32) as usize); - let mut k: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, i); - krml::unroll_for!(16, "i0", 0u32, 1u32, { - let u: u32 = - lowstar::endianness::load32_le(&uu____1.1[i0.wrapping_mul(4u32) as usize..]); - let x: u32 = u; - let y: u32 = x ^ (&k)[i0 as usize]; - lowstar::endianness::store32_le(&mut uu____0.1[i0.wrapping_mul(4u32) as usize..], y) - }) - } - if rem1 > 0u32 { - let uu____2: (&mut [u8], &mut [u8]) = out.split_at_mut(nb.wrapping_mul(64u32) as usize); - let mut plain: [u8; 64] = [0u8; 64usize]; - ((&mut plain)[0usize..rem as usize]) - .copy_from_slice(&(&cipher[nb.wrapping_mul(64u32) as usize..])[0usize..rem as usize]); - let mut k: [u32; 16] = [0u32; 16usize]; - crate::hacl::chacha20_vec32::chacha20_core_32(&mut k, &ctx, nb); - krml::unroll_for!(16, "i", 0u32, 1u32, { - let u: u32 = lowstar::endianness::load32_le(&(&plain)[i.wrapping_mul(4u32) as usize..]); - let x: u32 = u; - let y: u32 = x ^ (&k)[i as usize]; - lowstar::endianness::store32_le(&mut (&mut plain)[i.wrapping_mul(4u32) as usize..], y) - }); - (uu____2.1[0usize..rem as usize]) - .copy_from_slice(&(&(&plain)[0usize..])[0usize..rem as usize]) - } -} diff --git a/chacha20poly1305/src/impl_hacl.rs b/chacha20poly1305/src/impl_hacl.rs index 460377e0f..77139e615 100644 --- a/chacha20poly1305/src/impl_hacl.rs +++ b/chacha20poly1305/src/impl_hacl.rs @@ -19,8 +19,8 @@ pub fn encrypt<'a>( let aad_len: u32 = aad.len().try_into().map_err(|_| AeadError::AadTooLarge)?; - // we already knwo that ptxt.len() < u32::MAX, so we can safely add here. - if ctxt.len() < ptxt.len() + TAG_LEN { + // we already knwo that ptxt.len() < u32::MAX, so we can safely add if we use u64. + if (ctxt.len() as u64) < (ptxt.len() as u64) + (TAG_LEN as u64) { return Err(AeadError::CiphertextTooShort); } diff --git a/chacha20poly1305/src/lib.rs b/chacha20poly1305/src/lib.rs index 90852f83f..d5d17aabf 100644 --- a/chacha20poly1305/src/lib.rs +++ b/chacha20poly1305/src/lib.rs @@ -40,7 +40,6 @@ mod hacl { pub(crate) mod aead_chacha20poly1305; pub(crate) mod chacha20; - pub(crate) mod chacha20_vec32; } mod impl_hacl; diff --git a/rsa/src/lib.rs b/rsa/src/lib.rs index 2747273a6..cea603c40 100644 --- a/rsa/src/lib.rs +++ b/rsa/src/lib.rs @@ -21,8 +21,13 @@ pub mod hacl { /// The hash algorithm used for signing or verifying. #[derive(Clone, Copy, Debug)] pub enum DigestAlgorithm { + /// The SHA256 hash algorithm Sha2_256, + + /// The SHA384 hash algorithm Sha2_384, + + /// The SHA512 hash algorithm Sha2_512, } From a0130bf0f83a6b7f96e9ad39217241941e5c4e93 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 20 Dec 2024 12:41:35 +0100 Subject: [PATCH 12/13] chachapoly tests --- Cargo.lock | 2109 -------------------------- chacha20poly1305/Cargo.toml | 5 + chacha20poly1305/tests/chachapoly.rs | 141 ++ 3 files changed, 146 insertions(+), 2109 deletions(-) delete mode 100644 Cargo.lock create mode 100644 chacha20poly1305/tests/chachapoly.rs diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index c18135e0e..000000000 --- a/Cargo.lock +++ /dev/null @@ -1,2109 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" -dependencies = [ - "anstyle", - "windows-sys 0.59.0", -] - -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "benchmarks" -version = "0.0.2-beta.2" -dependencies = [ - "chacha20poly1305", - "criterion", - "curve25519-dalek", - "lib25519", - "libcrux", - "libcrux-kem", - "libcrux-ml-kem", - "libjade-sys", - "openssl", - "p256", - "pqcrypto-kyber", - "rand", - "rand_core", - "ring", - "sha2", - "sha3", - "x25519-dalek", - "x25519-dalek-ng", -] - -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.90", -] - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cavp" -version = "0.0.2-beta.2" -dependencies = [ - "hex", - "log", - "pretty_env_logger", -] - -[[package]] -name = "cc" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "classic-mceliece-rust" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ce62f72a15a9071f83c5084bdf0af4e8cbf31431e79eb4a5509a2f7fe7fe5d" -dependencies = [ - "rand", - "sha3", - "zeroize", -] - -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "curve25519-dalek-ng" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core", - "subtle-ng", - "zeroize", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "hax-lib" -version = "0.1.0-rc.1" -source = "git+https://github.com/hacspec/hax/#62f7bfabe31ac2dcdbda867e3879b49b080fd292" -dependencies = [ - "hax-lib-macros", - "num-bigint", - "num-traits", -] - -[[package]] -name = "hax-lib-macros" -version = "0.1.0-rc.1" -source = "git+https://github.com/hacspec/hax/#62f7bfabe31ac2dcdbda867e3879b49b080fd292" -dependencies = [ - "hax-lib-macros-types", - "paste", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "hax-lib-macros-types" -version = "0.1.0-rc.1" -source = "git+https://github.com/hacspec/hax/#62f7bfabe31ac2dcdbda867e3879b49b080fd292" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_json", - "uuid", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "is-terminal" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lib25519" -version = "0.0.2-beta.2" -dependencies = [ - "bindgen", - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "libc" -version = "0.2.168" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" - -[[package]] -name = "libcrux" -version = "0.0.2-beta.2" -dependencies = [ - "clap", - "getrandom", - "hax-lib", - "hex", - "libcrux", - "libcrux-ecdh", - "libcrux-ed25519", - "libcrux-hacl", - "libcrux-hacl-rs", - "libcrux-hkdf", - "libcrux-hmac", - "libcrux-kem", - "libcrux-ml-kem", - "libcrux-platform", - "libcrux-sha2", - "libcrux-traits", - "log", - "pretty_env_logger", - "quickcheck", - "quickcheck_macros", - "rand", - "rand_core", - "serde", - "serde_json", - "wasm-bindgen", - "wasm-bindgen-test", - "wycheproof", -] - -[[package]] -name = "libcrux-curve25519" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-hacl-rs", - "libcrux-macros", - "libcrux-sha2", -] - -[[package]] -name = "libcrux-ecdh" -version = "0.0.2-beta.2" -dependencies = [ - "hex", - "libcrux-curve25519", - "libcrux-hacl", - "pretty_env_logger", - "rand", - "rand_core", - "serde", - "serde_json", -] - -[[package]] -name = "libcrux-ed25519" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-hacl-rs", - "libcrux-macros", - "libcrux-sha2", -] - -[[package]] -name = "libcrux-fuzz" -version = "0.0.0" -dependencies = [ - "libcrux", - "libfuzzer-sys", - "rand", -] - -[[package]] -name = "libcrux-hacl" -version = "0.0.2-beta.2" -dependencies = [ - "bindgen", - "cc", - "hex", - "libcrux-platform", - "wasm-bindgen-test", -] - -[[package]] -name = "libcrux-hacl-rs" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-macros", -] - -[[package]] -name = "libcrux-hkdf" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-hacl-rs", - "libcrux-hmac", -] - -[[package]] -name = "libcrux-hmac" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-hacl-rs", - "libcrux-macros", - "libcrux-sha2", -] - -[[package]] -name = "libcrux-intrinsics" -version = "0.0.2-beta.2" -dependencies = [ - "hax-lib", -] - -[[package]] -name = "libcrux-kem" -version = "0.0.2-beta.2" -dependencies = [ - "hex", - "libcrux-ecdh", - "libcrux-kem", - "libcrux-ml-kem", - "libcrux-sha3", - "rand", -] - -[[package]] -name = "libcrux-macros" -version = "0.0.2-beta.2" - -[[package]] -name = "libcrux-ml-dsa" -version = "0.0.2-beta.2" -dependencies = [ - "criterion", - "hax-lib", - "hex", - "libcrux-intrinsics", - "libcrux-platform", - "libcrux-sha3", - "pqcrypto-dilithium", - "rand", - "serde", - "serde_json", -] - -[[package]] -name = "libcrux-ml-kem" -version = "0.0.2-beta.2" -dependencies = [ - "criterion", - "hax-lib", - "hex", - "libcrux-intrinsics", - "libcrux-platform", - "libcrux-sha3", - "rand", - "serde", - "serde_json", -] - -[[package]] -name = "libcrux-ml-kem-fuzz" -version = "0.0.0" -dependencies = [ - "libcrux-ml-kem", - "libfuzzer-sys", -] - -[[package]] -name = "libcrux-platform" -version = "0.0.2-beta.2" -dependencies = [ - "libc", -] - -[[package]] -name = "libcrux-pqclean" -version = "0.0.2-beta.2" -dependencies = [ - "bindgen", - "cc", - "fs_extra", -] - -[[package]] -name = "libcrux-psq" -version = "0.0.2-beta.2" -dependencies = [ - "classic-mceliece-rust", - "criterion", - "libcrux", - "libcrux-ecdh", - "libcrux-hkdf", - "libcrux-hmac", - "libcrux-kem", - "rand", -] - -[[package]] -name = "libcrux-sha2" -version = "0.0.2-beta.2" -dependencies = [ - "libcrux-hacl-rs", - "libcrux-macros", - "libcrux-traits", -] - -[[package]] -name = "libcrux-sha3" -version = "0.0.2-beta.2" -dependencies = [ - "cavp", - "criterion", - "hax-lib", - "hex", - "libcrux-intrinsics", - "libcrux-platform", - "pretty_env_logger", - "rand", -] - -[[package]] -name = "libcrux-traits" -version = "0.0.2-beta.2" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] -name = "libjade-sys" -version = "0.0.2-beta.2" -dependencies = [ - "bindgen", - "cc", - "libcrux-platform", - "pretty_env_logger", -] - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "minicov" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" -dependencies = [ - "cc", - "walkdir", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "oorandom" -version = "11.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl" -version = "0.10.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "openssl-sys" -version = "0.9.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "pqcrypto-dilithium" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685de0fa68c6786559d5fcdaa414f0cd68ef3f5d162f61823bd7424cd276726f" -dependencies = [ - "cc", - "glob", - "libc", - "pqcrypto-internals", - "pqcrypto-traits", -] - -[[package]] -name = "pqcrypto-internals" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62cd8ebf02b43967cda06e6a3f54d0bd9659459c3003d16aeedd07b44c6db06c" -dependencies = [ - "cc", - "dunce", - "getrandom", - "libc", -] - -[[package]] -name = "pqcrypto-kyber" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c00293cf898859d0c771455388054fd69ab712263c73fdc7f287a39b1ba000" -dependencies = [ - "cc", - "glob", - "libc", - "pqcrypto-internals", - "pqcrypto-traits", -] - -[[package]] -name = "pqcrypto-traits" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e851c7654eed9e68d7d27164c454961a616cf8c203d500607ef22c737b51bb" - -[[package]] -name = "pretty_env_logger" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" -dependencies = [ - "env_logger 0.10.2", - "log", -] - -[[package]] -name = "prettyplease" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" -dependencies = [ - "proc-macro2", - "syn 2.0.90", -] - -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quickcheck" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" -dependencies = [ - "env_logger 0.8.4", - "log", - "rand", -] - -[[package]] -name = "quickcheck_macros" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22a693222d716a9587786f37ac3f6b4faedb5b80c23914e7303ff5a1d8016e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-hash" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "semver" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" - -[[package]] -name = "serde" -version = "1.0.216" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.216" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "serde_json" -version = "1.0.133" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "subtle-ng" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" -dependencies = [ - "getrandom", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.90", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" - -[[package]] -name = "wasm-bindgen-test" -version = "0.3.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d44563646eb934577f2772656c7ad5e9c90fac78aa8013d776fcdaf24625d" -dependencies = [ - "js-sys", - "minicov", - "scoped-tls", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54171416ce73aa0b9c377b51cc3cb542becee1cd678204812e8392e5b0e4a031" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "web-sys" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "wycheproof" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb3be19abfb206c6adcbdf2007b09b0e8ca1f6530db40c03b42ce8ed4719894" -dependencies = [ - "data-encoding", - "serde", - "serde_json", -] - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", -] - -[[package]] -name = "x25519-dalek-ng" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7074de8999662970c3c4c8f7f30925028dd8f4ca31ad4c055efa9cdf2ec326" -dependencies = [ - "curve25519-dalek-ng", - "rand", - "rand_core", - "zeroize", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] diff --git a/chacha20poly1305/Cargo.toml b/chacha20poly1305/Cargo.toml index 94036cab5..8a76931d2 100644 --- a/chacha20poly1305/Cargo.toml +++ b/chacha20poly1305/Cargo.toml @@ -16,3 +16,8 @@ libcrux-poly1305 = { version = "=0.0.2-beta.2", path = "../poly1305/", features ] } libcrux-hacl-rs = { version = "=0.0.2-beta.2", path = "../hacl-rs/" } libcrux-macros = { version = "=0.0.2-beta.2", path = "../macros" } + +[dev-dependencies] +hex = { version = "0.4.3", features = ["serde"] } +serde = { version = "1.0.216", features = ["derive"] } +serde_json = "1.0.133" diff --git a/chacha20poly1305/tests/chachapoly.rs b/chacha20poly1305/tests/chachapoly.rs new file mode 100644 index 000000000..ead28b1b0 --- /dev/null +++ b/chacha20poly1305/tests/chachapoly.rs @@ -0,0 +1,141 @@ +use std::{fs::File, io::BufReader}; + +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_json::Value; + +pub(crate) trait ReadFromFile { + fn from_file(file_str: &'static str) -> T { + let file = match File::open(file_str) { + Ok(f) => f, + Err(_) => panic!("Couldn't open file {file_str}."), + }; + let reader = BufReader::new(file); + match serde_json::from_reader(reader) { + Ok(r) => r, + Err(e) => { + println!("{:?}", e); + panic!("Error reading file {file_str}.") + } + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(non_snake_case)] +struct AeadTestVector { + algorithm: String, + generatorVersion: String, + numberOfTests: usize, + notes: Option, // text notes (might not be present), keys correspond to flags + header: Vec, // not used + testGroups: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(non_snake_case)] +struct TestGroup { + ivSize: usize, + keySize: usize, + tagSize: usize, + r#type: String, + tests: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(non_snake_case)] +struct Test { + tcId: usize, + comment: String, + #[serde(with = "hex::serde")] + key: Vec, + #[serde(with = "hex::serde")] + iv: Vec, + #[serde(with = "hex::serde")] + aad: Vec, + #[serde(with = "hex::serde")] + msg: Vec, + #[serde(with = "hex::serde")] + ct: Vec, + #[serde(with = "hex::serde")] + tag: Vec, + result: String, + flags: Vec, +} + +impl ReadFromFile for AeadTestVector {} + +#[allow(non_snake_case)] +#[test] +fn wycheproof() { + let chacha_poly_tests: AeadTestVector = + AeadTestVector::from_file("../tests/wycheproof/chacha20_poly1305_test.json"); + + let num_tests = chacha_poly_tests.numberOfTests; + let mut skipped_tests = 0; + let mut tests_run = 0; + assert_eq!(chacha_poly_tests.algorithm, "CHACHA20-POLY1305"); + + test_group(chacha_poly_tests, &mut skipped_tests, &mut tests_run); + + fn test_group(test_vec: AeadTestVector, skipped_tests: &mut usize, tests_run: &mut usize) { + for testGroup in test_vec.testGroups.iter() { + assert_eq!(testGroup.r#type, "AeadTest"); + assert_eq!(testGroup.keySize, 256); + + let invalid_iv = if testGroup.ivSize != 96 { true } else { false }; + + for test in testGroup.tests.iter() { + let valid = test.result.eq("valid"); + if invalid_iv { + // AEAD requires input of a 12-byte nonce. + let nonce = &test.iv; + assert!(nonce.len() != 12); + *skipped_tests += 1; + continue; + } + println!("Test {:?}: {:?}", test.tcId, test.comment); + let nonce = <&[u8; 12]>::try_from(&test.iv[..]).unwrap(); + let msg = &test.msg; + let aad = &test.aad; + let exp_cipher = &test.ct; + let exp_tag = &test.tag; + let key = <&[u8; 32]>::try_from(&test.key[..]).unwrap(); + + let mut ctxt = msg.clone(); + let tag = match libcrux_chacha20poly1305::encrypt(key, &msg, &mut ctxt, &aad, nonce) + { + Ok((_v, t)) => t, + Err(_) => { + *tests_run += 1; + continue; + } + }; + if valid { + assert_eq!(tag, exp_tag.as_slice()); + } else { + assert_ne!(tag, exp_tag.as_slice()); + } + assert_eq!(ctxt, exp_cipher.as_slice()); + + let mut decrypted = vec![0; msg.len()]; + match libcrux_chacha20poly1305::decrypt(&key, &mut decrypted, &ctxt, &aad, nonce) { + Ok(m) => { + assert_eq!(m, msg); + assert_eq!(&decrypted, msg); + } + Err(_) => { + assert!(!valid); + } + }; + + *tests_run += 1; + } + } + } + // Check that we ran all tests. + println!( + "Ran {} out of {} tests and skipped {}.", + tests_run, num_tests, skipped_tests + ); + assert_eq!(num_tests - skipped_tests, tests_run); +} From f3b91435f66748a175131bfe343a653f8a470b3c Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 20 Dec 2024 12:57:40 +0100 Subject: [PATCH 13/13] RSA PSS tests --- rsa/src/impl_hacl.rs | 12 ++++ rsa/tests/rsa_pss.rs | 129 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 rsa/tests/rsa_pss.rs diff --git a/rsa/src/impl_hacl.rs b/rsa/src/impl_hacl.rs index 5faead7a9..94daf9e0e 100644 --- a/rsa/src/impl_hacl.rs +++ b/rsa/src/impl_hacl.rs @@ -4,6 +4,18 @@ use crate::Error; #[derive(Debug)] pub struct Signature([u8; LEN]); +impl Signature { + pub fn new() -> Self { + Self([0u8; LEN]) + } +} + +impl From<[u8; LEN]> for Signature { + fn from(value: [u8; LEN]) -> Self { + Self(value) + } +} + /// An RSA Public Key that is `LEN` bytes long. #[derive(Debug, Clone)] pub struct PublicKey { diff --git a/rsa/tests/rsa_pss.rs b/rsa/tests/rsa_pss.rs new file mode 100644 index 000000000..38764b48a --- /dev/null +++ b/rsa/tests/rsa_pss.rs @@ -0,0 +1,129 @@ +use libcrux_rsa::{sign_2048, verify_2048, DigestAlgorithm, PrivateKey, PublicKey, Signature}; + +const MODULUS: [u8; 256] = [ + 0xd2, 0x78, 0x16, 0xcb, 0x72, 0xbb, 0x6e, 0x27, 0xdb, 0x10, 0x1a, 0x6f, 0x3e, 0x64, 0x62, 0x93, + 0xd9, 0xec, 0xa7, 0xb3, 0x98, 0xe3, 0x36, 0x6c, 0x9e, 0x69, 0x31, 0xc4, 0x5d, 0xd7, 0x24, 0xd3, + 0xf8, 0x90, 0xb0, 0xd0, 0x57, 0x78, 0x3e, 0xdd, 0xee, 0xf0, 0xc9, 0x0e, 0x98, 0x6d, 0xad, 0xe9, + 0x46, 0x47, 0xc5, 0xcb, 0x4d, 0xa4, 0xc6, 0x9c, 0x83, 0x1a, 0x13, 0x9f, 0xb7, 0x8d, 0xe7, 0xe3, + 0x79, 0x97, 0xf2, 0x9e, 0x36, 0x5c, 0x96, 0xaa, 0xf6, 0x29, 0xfe, 0x6e, 0x3c, 0x0d, 0xb0, 0xcb, + 0x04, 0x7d, 0x35, 0xd3, 0xeb, 0xf7, 0xee, 0x36, 0x59, 0xda, 0xb5, 0xb2, 0x34, 0x08, 0x86, 0x87, + 0x27, 0x02, 0x4b, 0x49, 0xb3, 0x85, 0x33, 0x9b, 0x63, 0x8f, 0x28, 0x3b, 0x27, 0x83, 0x65, 0xf9, + 0x62, 0x23, 0xe0, 0x8b, 0x15, 0x1d, 0xd3, 0x00, 0xb1, 0xd6, 0x37, 0x3e, 0x7b, 0xa7, 0x1d, 0xc7, + 0x63, 0x79, 0xe2, 0xa2, 0xca, 0x2d, 0xa4, 0xb6, 0xcd, 0xef, 0x8d, 0x73, 0xec, 0x56, 0xfc, 0x0b, + 0xac, 0xcb, 0x80, 0x53, 0xcf, 0x34, 0x2f, 0x29, 0xb0, 0xe7, 0xf0, 0xb9, 0x24, 0xf4, 0xe4, 0x99, + 0xb2, 0x58, 0xc0, 0x9e, 0x1f, 0xf5, 0x43, 0x6e, 0xca, 0xc6, 0xeb, 0x65, 0xd0, 0x5f, 0xdb, 0x13, + 0x4c, 0x8c, 0xca, 0x82, 0xd9, 0xad, 0xc1, 0xfd, 0x7a, 0xd9, 0x78, 0xc7, 0xed, 0xdf, 0xc9, 0x70, + 0x54, 0xd3, 0x80, 0x5f, 0x06, 0x48, 0x11, 0x6e, 0xfb, 0x9b, 0x46, 0xfa, 0x02, 0x65, 0xde, 0xcc, + 0xe9, 0x6e, 0x91, 0x98, 0x93, 0x3d, 0x3d, 0x6d, 0xb1, 0x99, 0xa4, 0x73, 0xc1, 0x2c, 0xa2, 0x16, + 0x55, 0x97, 0xf3, 0x0f, 0x67, 0xf7, 0x9a, 0x78, 0x74, 0x15, 0x66, 0xb1, 0xd4, 0xdc, 0x98, 0x47, + 0x8a, 0x50, 0xb6, 0x2d, 0x63, 0xf9, 0xce, 0xa2, 0x76, 0x70, 0x91, 0xa8, 0x3b, 0x00, 0x28, 0x01, +]; + +const PRIVATE_EXPONENT: [u8; 256] = [ + 0x5a, 0x90, 0x21, 0xfe, 0xd9, 0x17, 0x9d, 0x86, 0xb8, 0xd4, 0x6d, 0x0b, 0x81, 0x25, 0x60, 0xe5, + 0x8d, 0xd8, 0x2f, 0x31, 0x30, 0x90, 0x54, 0x52, 0xd8, 0xb7, 0x1b, 0x1b, 0x0b, 0xe6, 0x0f, 0x8a, + 0xc6, 0x62, 0x3c, 0x32, 0xe9, 0xf0, 0x6b, 0xdc, 0xc3, 0x7c, 0x08, 0x87, 0xa7, 0x3f, 0x4a, 0x9e, + 0x1e, 0x07, 0xb4, 0x2c, 0x8e, 0xf4, 0x60, 0x21, 0xe8, 0xa7, 0xc7, 0xd9, 0xe9, 0xf9, 0xbd, 0xd6, + 0x3b, 0xf4, 0x0e, 0x09, 0xd6, 0x0a, 0x71, 0x2a, 0x8f, 0x51, 0xf2, 0x91, 0x2c, 0x76, 0x17, 0xa4, + 0xc4, 0x01, 0xbc, 0xaf, 0xbb, 0xd1, 0xab, 0x46, 0xe7, 0xd3, 0x1c, 0x6b, 0xd9, 0xc7, 0xf1, 0x5b, + 0x26, 0x85, 0xee, 0x2f, 0x80, 0x77, 0xc8, 0x85, 0x0c, 0x8a, 0x05, 0x1d, 0xaf, 0x1a, 0xf3, 0x3e, + 0x23, 0xe4, 0x9c, 0x32, 0x3c, 0x9b, 0xe0, 0xb7, 0x63, 0xce, 0x71, 0x67, 0x09, 0x7e, 0x17, 0x69, + 0x74, 0x9a, 0xec, 0x2a, 0x71, 0xf4, 0xeb, 0xe2, 0x84, 0x23, 0x8b, 0xa8, 0x27, 0x69, 0x19, 0x53, + 0x52, 0x8f, 0xc3, 0x62, 0xd5, 0x2a, 0x43, 0xb0, 0x78, 0x90, 0x54, 0x98, 0x22, 0x12, 0x2d, 0x32, + 0x28, 0xcf, 0xf9, 0x04, 0x1c, 0x4f, 0x28, 0xb7, 0xad, 0x98, 0x1a, 0xdf, 0x2e, 0xdb, 0x94, 0xd5, + 0x3d, 0xe2, 0xa9, 0x29, 0x3c, 0x3e, 0xaa, 0x81, 0x2a, 0x61, 0x8d, 0x4b, 0x41, 0x2f, 0xda, 0x99, + 0x8b, 0x78, 0x7a, 0xd5, 0xec, 0x93, 0x53, 0x5a, 0x84, 0x43, 0x47, 0x1a, 0xaf, 0x68, 0xa7, 0x5f, + 0x4e, 0x62, 0xe5, 0xcf, 0x07, 0xc9, 0x2b, 0x67, 0x34, 0x82, 0x27, 0xf6, 0xe0, 0x6d, 0x51, 0xca, + 0x21, 0xea, 0xfa, 0x32, 0xf0, 0x9f, 0x84, 0xb4, 0xfb, 0xaf, 0x25, 0x1e, 0x91, 0x08, 0x94, 0x5e, + 0x83, 0x7f, 0x0f, 0x6a, 0x86, 0x98, 0x77, 0xb8, 0xb0, 0xca, 0xd0, 0x34, 0x10, 0x69, 0x59, 0x21, +]; + +#[test] +fn self_test_rsa_pss() { + let pk = PublicKey::from(MODULUS); + let sk = PrivateKey::from_components(MODULUS, PRIVATE_EXPONENT); + let salt = [1, 2, 3, 4, 5]; + let msg = [7, 8, 9, 10]; + let mut signature = Signature::new(); + sign_2048(DigestAlgorithm::Sha2_256, &sk, &msg, &salt, &mut signature).unwrap(); + eprintln!("signature: {:x?}", signature); + verify_2048( + DigestAlgorithm::Sha2_256, + &pk, + &msg, + salt.len() as u32, + &signature, + ) + .expect("Error verifying signature"); +} + +const N: [u8; 256] = [ + 0xa2, 0xb4, 0x51, 0xa0, 0x7d, 0x0a, 0xa5, 0xf9, 0x6e, 0x45, 0x56, 0x71, 0x51, 0x35, 0x50, 0x51, + 0x4a, 0x8a, 0x5b, 0x46, 0x2e, 0xbe, 0xf7, 0x17, 0x09, 0x4f, 0xa1, 0xfe, 0xe8, 0x22, 0x24, 0xe6, + 0x37, 0xf9, 0x74, 0x6d, 0x3f, 0x7c, 0xaf, 0xd3, 0x18, 0x78, 0xd8, 0x03, 0x25, 0xb6, 0xef, 0x5a, + 0x17, 0x00, 0xf6, 0x59, 0x03, 0xb4, 0x69, 0x42, 0x9e, 0x89, 0xd6, 0xea, 0xc8, 0x84, 0x50, 0x97, + 0xb5, 0xab, 0x39, 0x31, 0x89, 0xdb, 0x92, 0x51, 0x2e, 0xd8, 0xa7, 0x71, 0x1a, 0x12, 0x53, 0xfa, + 0xcd, 0x20, 0xf7, 0x9c, 0x15, 0xe8, 0x24, 0x7f, 0x3d, 0x3e, 0x42, 0xe4, 0x6e, 0x48, 0xc9, 0x8e, + 0x25, 0x4a, 0x2f, 0xe9, 0x76, 0x53, 0x13, 0xa0, 0x3e, 0xff, 0x8f, 0x17, 0xe1, 0xa0, 0x29, 0x39, + 0x7a, 0x1f, 0xa2, 0x6a, 0x8d, 0xce, 0x26, 0xf4, 0x90, 0xed, 0x81, 0x29, 0x96, 0x15, 0xd9, 0x81, + 0x4c, 0x22, 0xda, 0x61, 0x04, 0x28, 0xe0, 0x9c, 0x7d, 0x96, 0x58, 0x59, 0x42, 0x66, 0xf5, 0xc0, + 0x21, 0xd0, 0xfc, 0xec, 0xa0, 0x8d, 0x94, 0x5a, 0x12, 0xbe, 0x82, 0xde, 0x4d, 0x1e, 0xce, 0x6b, + 0x4c, 0x03, 0x14, 0x5b, 0x5d, 0x34, 0x95, 0xd4, 0xed, 0x54, 0x11, 0xeb, 0x87, 0x8d, 0xaf, 0x05, + 0xfd, 0x7a, 0xfc, 0x3e, 0x09, 0xad, 0xa0, 0xf1, 0x12, 0x64, 0x22, 0xf5, 0x90, 0x97, 0x5a, 0x19, + 0x69, 0x81, 0x6f, 0x48, 0x69, 0x8b, 0xcb, 0xba, 0x1b, 0x4d, 0x9c, 0xae, 0x79, 0xd4, 0x60, 0xd8, + 0xf9, 0xf8, 0x5e, 0x79, 0x75, 0x00, 0x5d, 0x9b, 0xc2, 0x2c, 0x4e, 0x5a, 0xc0, 0xf7, 0xc1, 0xa4, + 0x5d, 0x12, 0x56, 0x9a, 0x62, 0x80, 0x7d, 0x3b, 0x9a, 0x02, 0xe5, 0xa5, 0x30, 0xe7, 0x73, 0x06, + 0x6f, 0x45, 0x3d, 0x1f, 0x5b, 0x4c, 0x2e, 0x9c, 0xf7, 0x82, 0x02, 0x83, 0xf7, 0x42, 0xb9, 0xd5, +]; + +#[test] +fn wycheproof_single_test() { + let pk = PublicKey::from(N); + let msg: [u8; 0] = []; + let signature: [u8; 256] = [ + 0x20, 0x08, 0x1f, 0x88, 0x94, 0xa1, 0x33, 0x0c, 0x4d, 0x50, 0x3f, 0x64, 0x28, 0x80, 0xe3, + 0xc3, 0x0e, 0x39, 0x8f, 0xc6, 0x23, 0x5c, 0x24, 0xf1, 0xbe, 0x75, 0x2e, 0x2d, 0x49, 0xcd, + 0x94, 0x93, 0xac, 0x0c, 0xf9, 0x99, 0xe2, 0x75, 0xc4, 0xf8, 0x9f, 0xf0, 0x8f, 0x0d, 0x9b, + 0xa4, 0xe2, 0x64, 0xa3, 0x32, 0x52, 0x5a, 0x61, 0x6d, 0x33, 0x6b, 0xd9, 0xe8, 0x22, 0xf4, + 0x1a, 0xb3, 0xf4, 0xfa, 0xe2, 0xf4, 0x8e, 0xc6, 0x6c, 0x2e, 0x52, 0x64, 0x2e, 0xd9, 0x3b, + 0x7c, 0xb9, 0x44, 0x39, 0x6f, 0xba, 0xa7, 0x27, 0xcb, 0xfd, 0xfc, 0x1f, 0x20, 0xaa, 0xce, + 0x99, 0xa6, 0xf2, 0xa7, 0x44, 0x75, 0xc3, 0x38, 0xf8, 0xd9, 0xf2, 0x2a, 0x38, 0xcb, 0x5b, + 0xc5, 0x17, 0x52, 0x07, 0x65, 0x03, 0xb3, 0xae, 0xf1, 0xe6, 0x5e, 0x5a, 0x8f, 0x85, 0x83, + 0xd9, 0xae, 0x73, 0x78, 0xde, 0xd0, 0x38, 0xcf, 0x51, 0x68, 0x98, 0xad, 0x06, 0xbe, 0xb9, + 0x0a, 0x42, 0xb8, 0x57, 0x64, 0x52, 0x6f, 0xce, 0xa4, 0x4f, 0x74, 0x25, 0x8f, 0xa4, 0xef, + 0xb1, 0xda, 0x25, 0x3d, 0x33, 0x7f, 0x65, 0x61, 0x91, 0x81, 0xce, 0xb8, 0x32, 0xdf, 0xe2, + 0x85, 0xce, 0x78, 0xae, 0x6b, 0x15, 0xf2, 0x04, 0xe2, 0x3b, 0xab, 0x27, 0x4e, 0x87, 0x44, + 0x5d, 0x9f, 0x5d, 0xf9, 0x7f, 0x41, 0xdc, 0x8e, 0x3a, 0x97, 0x73, 0x6b, 0x62, 0x59, 0x1d, + 0x07, 0x57, 0x44, 0xb2, 0x55, 0x2f, 0x90, 0xbc, 0xf1, 0xb1, 0x39, 0x3e, 0x1e, 0x76, 0x27, + 0xef, 0x1f, 0x98, 0x5f, 0x2b, 0xba, 0xbd, 0x52, 0xe4, 0x3a, 0x35, 0xd0, 0xdd, 0xf4, 0xc6, + 0x71, 0x26, 0xe3, 0x91, 0xf9, 0x22, 0xef, 0x7b, 0x1b, 0xb1, 0x91, 0x1c, 0xd6, 0xe1, 0xb3, + 0x03, 0xcb, 0x29, 0x10, 0xdd, 0x70, 0x67, 0x2b, 0xbf, 0xb6, 0x2e, 0xa4, 0xea, 0xad, 0x72, + 0x5c, + ]; + verify_2048(DigestAlgorithm::Sha2_256, &pk, &msg, 0, &signature.into()) + .expect("Error verifying signature"); + + let msg = [0x33, 0x32, 0x32, 0x32, 0x30, 0x34, 0x31, 0x30, 0x34, 0x36]; + let signature: [u8; 256] = [ + 0x6b, 0x9a, 0x45, 0xec, 0x51, 0x7b, 0xf8, 0x38, 0xa5, 0x35, 0xed, 0x93, 0xfb, 0x36, 0xbb, + 0x02, 0x74, 0x71, 0xb1, 0x1d, 0x20, 0xd0, 0xbf, 0x6b, 0x1e, 0xda, 0xae, 0xef, 0xa2, 0x5b, + 0xcc, 0xdf, 0x58, 0x81, 0xf3, 0x44, 0x09, 0xa0, 0x42, 0xda, 0xdb, 0xe4, 0xa7, 0xb3, 0xc4, + 0x1b, 0xf2, 0x4a, 0xbe, 0x66, 0xc1, 0xf7, 0xf3, 0x7b, 0x92, 0xb9, 0x65, 0x8f, 0x59, 0xc5, + 0x5f, 0xa8, 0x8a, 0xa1, 0x63, 0x24, 0x65, 0xba, 0x82, 0x45, 0xc5, 0xf0, 0xc9, 0x8d, 0x08, + 0x2f, 0xca, 0xbb, 0x5e, 0x9f, 0xb8, 0x34, 0xd7, 0x27, 0xa3, 0x54, 0xf8, 0xf8, 0xa7, 0xfc, + 0xdb, 0x8d, 0x32, 0x30, 0x72, 0x54, 0x72, 0xa6, 0xa4, 0xec, 0xb6, 0xf3, 0xd9, 0x75, 0x40, + 0x77, 0x3e, 0x53, 0xeb, 0x45, 0x38, 0x3a, 0xcb, 0xe4, 0xbc, 0x81, 0x16, 0x8e, 0x24, 0x4f, + 0xe7, 0x69, 0xb1, 0xa7, 0xd5, 0x22, 0x0d, 0xbc, 0xaf, 0x83, 0x1e, 0x46, 0xc9, 0x3f, 0x6e, + 0xa7, 0xca, 0x2e, 0xe3, 0x0c, 0xe9, 0x28, 0x1d, 0xd9, 0x67, 0x4f, 0xcc, 0xdc, 0x79, 0x6f, + 0xd6, 0x14, 0x7b, 0xe4, 0xbd, 0x99, 0xc5, 0x3a, 0x12, 0xea, 0xcf, 0xd4, 0xb9, 0xb0, 0x09, + 0x72, 0xb0, 0x53, 0x9e, 0x3d, 0x94, 0xb8, 0x59, 0x11, 0x69, 0x4e, 0xa9, 0x8f, 0x27, 0x49, + 0x6b, 0x56, 0x7a, 0x29, 0xfd, 0x30, 0x87, 0x84, 0x2b, 0xa0, 0x14, 0x02, 0x90, 0x1d, 0x1b, + 0xb1, 0xba, 0x6b, 0x3c, 0x79, 0x31, 0xf1, 0x32, 0x9f, 0xf5, 0x64, 0x49, 0x89, 0xbd, 0xc1, + 0xf7, 0x02, 0x50, 0x59, 0xd0, 0xd0, 0x69, 0x51, 0x7f, 0xbb, 0x68, 0x2c, 0x0b, 0xe0, 0x49, + 0xec, 0x7e, 0x38, 0xb6, 0x14, 0xaf, 0x1c, 0xf9, 0xcc, 0x37, 0xea, 0xb7, 0x4e, 0x20, 0xe6, + 0xbc, 0xa4, 0x68, 0xf9, 0x3d, 0x3f, 0x13, 0x74, 0x95, 0x57, 0xb7, 0x01, 0x29, 0xef, 0x95, + 0xe5, + ]; + verify_2048(DigestAlgorithm::Sha2_256, &pk, &msg, 32, &signature.into()) + .expect("Error verifying signature"); +}