diff --git a/Cargo.toml b/Cargo.toml index 4505f7d1..30e7e1f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ members = [ "libcrux-sha3", "libcrux-ml-dsa", "libcrux-intrinsics", + "libcrux-hmac", + "libcrux-hkdf", ] [workspace.package] @@ -45,6 +47,8 @@ libcrux-platform = { version = "=0.0.2-pre.2", path = "sys/platform" } [dependencies] libcrux-hacl = { version = "=0.0.2-pre.2", path = "sys/hacl" } libcrux-platform = { version = "=0.0.2-pre.2", path = "sys/platform" } +libcrux-hkdf = { version = "=0.0.2-pre.2", path = "libcrux-hkdf" } +libcrux-hmac = { version = "=0.0.2-pre.2", path = "libcrux-hmac" } rand = { version = "0.8" } log = { version = "0.4", optional = true } # WASM API diff --git a/libcrux-hkdf/Cargo.toml b/libcrux-hkdf/Cargo.toml new file mode 100644 index 00000000..65de2d0c --- /dev/null +++ b/libcrux-hkdf/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "libcrux-hkdf" +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[lib] +path = "src/hkdf.rs" + +[dependencies] +libcrux-hacl = { version = "=0.0.2-pre.2", path = "../sys/hacl" } + diff --git a/src/hacl/hkdf.rs b/libcrux-hkdf/src/hacl_hkdf.rs similarity index 100% rename from src/hacl/hkdf.rs rename to libcrux-hkdf/src/hacl_hkdf.rs diff --git a/libcrux-hkdf/src/hkdf.rs b/libcrux-hkdf/src/hkdf.rs new file mode 100644 index 00000000..c3a9036f --- /dev/null +++ b/libcrux-hkdf/src/hkdf.rs @@ -0,0 +1,75 @@ +//! HKDF +//! +//! This crate implements HKDF on SHA 1 and SHA 2 (except for SHA 224). + +pub(crate) mod hacl_hkdf; + +/// The HKDF algorithm defining the used hash function. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Algorithm { + Sha256, + Sha384, + Sha512, +} + +/// HKDF Errors +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Error { + OkmLengthTooLarge, +} + +/// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`. +/// Returns the pre-key material in a vector of tag length. +pub fn extract(alg: Algorithm, salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> Vec { + match alg { + Algorithm::Sha256 => { + crate::hacl_hkdf::sha2_256::extract(salt.as_ref(), ikm.as_ref()).into() + } + Algorithm::Sha384 => { + crate::hacl_hkdf::sha2_384::extract(salt.as_ref(), ikm.as_ref()).into() + } + Algorithm::Sha512 => { + crate::hacl_hkdf::sha2_512::extract(salt.as_ref(), ikm.as_ref()).into() + } + } +} + +/// 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. +pub fn expand( + alg: Algorithm, + prk: impl AsRef<[u8]>, + info: impl AsRef<[u8]>, + okm_len: usize, +) -> Result, Error> { + match alg { + Algorithm::Sha256 => { + crate::hacl_hkdf::sha2_256::vec::expand(prk.as_ref(), info.as_ref(), okm_len) + .map_err(|_| Error::OkmLengthTooLarge) + } + Algorithm::Sha384 => { + crate::hacl_hkdf::sha2_384::vec::expand(prk.as_ref(), info.as_ref(), okm_len) + .map_err(|_| Error::OkmLengthTooLarge) + } + Algorithm::Sha512 => { + crate::hacl_hkdf::sha2_512::vec::expand(prk.as_ref(), info.as_ref(), okm_len) + .map_err(|_| Error::OkmLengthTooLarge) + } + } +} + +/// HKDF using hash function `mode`, `salt`, input key material `ikm`, `info`, and output length `okm_len`. +/// 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. +pub fn hkdf( + mode: Algorithm, + salt: &[u8], + ikm: &[u8], + info: &[u8], + okm_len: usize, +) -> Result, Error> { + let prk = extract(mode, salt, ikm); + expand(mode, prk, info, okm_len) +} diff --git a/libcrux-hmac/Cargo.toml b/libcrux-hmac/Cargo.toml new file mode 100644 index 00000000..3e86f6e4 --- /dev/null +++ b/libcrux-hmac/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "libcrux-hmac" +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true + +[lib] +path = "src/hmac.rs" + +[dependencies] +libcrux-hkdf = { version = "=0.0.2-pre.2", path = "../libcrux-hkdf" } +libcrux-hacl = { version = "=0.0.2-pre.2", path = "../sys/hacl" } diff --git a/src/hacl/hmac.rs b/libcrux-hmac/src/hacl_hmac.rs similarity index 100% rename from src/hacl/hmac.rs rename to libcrux-hmac/src/hacl_hmac.rs diff --git a/libcrux-hmac/src/hmac.rs b/libcrux-hmac/src/hmac.rs new file mode 100644 index 00000000..3eea90a2 --- /dev/null +++ b/libcrux-hmac/src/hmac.rs @@ -0,0 +1,56 @@ +//! HMAC +//! +//! This crate implements HMAC on SHA 1 and SHA 2 (except for SHA 224). + +use libcrux_hkdf as hkdf; +pub(crate) mod hacl_hmac; + +/// The HMAC algorithm defining the used hash function. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Algorithm { + Sha1, + // Not implemented + // Sha224 + Sha256, + Sha384, + Sha512, +} + +impl From for Algorithm { + fn from(value: hkdf::Algorithm) -> Self { + match value { + hkdf::Algorithm::Sha256 => Self::Sha256, + hkdf::Algorithm::Sha384 => Self::Sha384, + hkdf::Algorithm::Sha512 => Self::Sha512, + } + } +} + +/// Get the tag size for a given algorithm. +pub const fn tag_size(alg: Algorithm) -> usize { + match alg { + Algorithm::Sha1 => 20, + Algorithm::Sha256 => 32, + Algorithm::Sha384 => 48, + Algorithm::Sha512 => 64, + } +} + +/// Compute the HMAC value with the given `alg` and `key` on `data` with an +/// output tag length of `tag_length`. +/// Returns a vector of length `tag_length`. +pub fn hmac(alg: Algorithm, key: &[u8], data: &[u8], tag_length: Option) -> Vec { + let native_tag_length = tag_size(alg); + let tag_length = match tag_length { + Some(v) => v, + None => native_tag_length, + }; + let mut dst: Vec<_> = match alg { + Algorithm::Sha1 => crate::hacl_hmac::sha1(key, data).into(), + Algorithm::Sha256 => crate::hacl_hmac::sha2_256(key, data).into(), + Algorithm::Sha384 => crate::hacl_hmac::sha2_384(key, data).into(), + Algorithm::Sha512 => crate::hacl_hmac::sha2_512(key, data).into(), + }; + dst.truncate(tag_length); + dst +} diff --git a/src/hacl.rs b/src/hacl.rs index c3f31568..e0091f25 100644 --- a/src/hacl.rs +++ b/src/hacl.rs @@ -16,8 +16,6 @@ pub(crate) mod curve25519; #[cfg(not(target_arch = "wasm32"))] pub(crate) mod drbg; pub(crate) mod ed25519; -pub(crate) mod hkdf; -pub(crate) mod hmac; pub(crate) mod p256; pub(crate) mod sha2; pub(crate) mod sha3; @@ -29,7 +27,7 @@ pub enum Error { Curve25519(curve25519::Error), P256(p256::Error), Ed25519(ed25519::Error), - Hkdf(hkdf::Error), + Hkdf(libcrux_hkdf::Error), } impl From for Error { @@ -50,8 +48,8 @@ impl From for Error { } } -impl From for Error { - fn from(val: hkdf::Error) -> Self { +impl From for Error { + fn from(val: libcrux_hkdf::Error) -> Self { Error::Hkdf(val) } } diff --git a/src/hkdf.rs b/src/hkdf.rs index 7093bf19..c23d89cd 100644 --- a/src/hkdf.rs +++ b/src/hkdf.rs @@ -2,72 +2,8 @@ //! //! This module implements HKDF on SHA 1 and SHA 2 (except for SHA 224). -/// The HKDF algorithm defining the used hash function. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Algorithm { - Sha256, - Sha384, - Sha512, -} - -/// HKDF Errors -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Error { - OkmLengthTooLarge, -} - -/// HKDF extract using hash function `mode`, `salt`, and the input key material `ikm`. -/// Returns the pre-key material in a vector of tag length. -pub fn extract(alg: Algorithm, salt: impl AsRef<[u8]>, ikm: impl AsRef<[u8]>) -> Vec { - match alg { - Algorithm::Sha256 => { - crate::hacl::hkdf::sha2_256::extract(salt.as_ref(), ikm.as_ref()).into() - } - Algorithm::Sha384 => { - crate::hacl::hkdf::sha2_384::extract(salt.as_ref(), ikm.as_ref()).into() - } - Algorithm::Sha512 => { - crate::hacl::hkdf::sha2_512::extract(salt.as_ref(), ikm.as_ref()).into() - } - } -} - -/// 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. -pub fn expand( - alg: Algorithm, - prk: impl AsRef<[u8]>, - info: impl AsRef<[u8]>, - okm_len: usize, -) -> Result, Error> { - match alg { - Algorithm::Sha256 => { - crate::hacl::hkdf::sha2_256::vec::expand(prk.as_ref(), info.as_ref(), okm_len) - .map_err(|_| Error::OkmLengthTooLarge) - } - Algorithm::Sha384 => { - crate::hacl::hkdf::sha2_384::vec::expand(prk.as_ref(), info.as_ref(), okm_len) - .map_err(|_| Error::OkmLengthTooLarge) - } - Algorithm::Sha512 => { - crate::hacl::hkdf::sha2_512::vec::expand(prk.as_ref(), info.as_ref(), okm_len) - .map_err(|_| Error::OkmLengthTooLarge) - } - } -} - -/// HKDF using hash function `mode`, `salt`, input key material `ikm`, `info`, and output length `okm_len`. -/// 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. -pub fn hkdf( - mode: Algorithm, - salt: &[u8], - ikm: &[u8], - info: &[u8], - okm_len: usize, -) -> Result, Error> { - let prk = extract(mode, salt, ikm); - expand(mode, prk, info, okm_len) -} +pub use libcrux_hkdf::expand; +pub use libcrux_hkdf::extract; +pub use libcrux_hkdf::hkdf; +pub use libcrux_hkdf::Algorithm; +pub use libcrux_hkdf::Error; diff --git a/src/hmac.rs b/src/hmac.rs index 8461f687..5734662f 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -2,54 +2,6 @@ //! //! This module implements HMAC on SHA 1 and SHA 2 (except for SHA 224). -use crate::hkdf; - -/// The HMAC algorithm defining the used hash function. -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum Algorithm { - Sha1, - // Not implemented - // Sha224 - Sha256, - Sha384, - Sha512, -} - -impl From for Algorithm { - fn from(value: hkdf::Algorithm) -> Self { - match value { - hkdf::Algorithm::Sha256 => Self::Sha256, - hkdf::Algorithm::Sha384 => Self::Sha384, - hkdf::Algorithm::Sha512 => Self::Sha512, - } - } -} - -/// Get the tag size for a given algorithm. -pub const fn tag_size(alg: Algorithm) -> usize { - match alg { - Algorithm::Sha1 => 20, - Algorithm::Sha256 => 32, - Algorithm::Sha384 => 48, - Algorithm::Sha512 => 64, - } -} - -/// Compute the HMAC value with the given `alg` and `key` on `data` with an -/// output tag length of `tag_length`. -/// Returns a vector of length `tag_length`. -pub fn hmac(alg: Algorithm, key: &[u8], data: &[u8], tag_length: Option) -> Vec { - let native_tag_length = tag_size(alg); - let tag_length = match tag_length { - Some(v) => v, - None => native_tag_length, - }; - let mut dst: Vec<_> = match alg { - Algorithm::Sha1 => crate::hacl::hmac::sha1(key, data).into(), - Algorithm::Sha256 => crate::hacl::hmac::sha2_256(key, data).into(), - Algorithm::Sha384 => crate::hacl::hmac::sha2_384(key, data).into(), - Algorithm::Sha512 => crate::hacl::hmac::sha2_512(key, data).into(), - }; - dst.truncate(tag_length); - dst -} +pub use libcrux_hmac::hmac; +pub use libcrux_hmac::tag_size; +pub use libcrux_hmac::Algorithm;