Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull out hkdf and hmac modules as standalone crates #305

Merged
merged 6 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ members = [
"libcrux-sha3",
"libcrux-ml-dsa",
"libcrux-intrinsics",
"libcrux-hmac",
"libcrux-hkdf",
]

[workspace.package]
Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions libcrux-hkdf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }

File renamed without changes.
75 changes: 75 additions & 0 deletions libcrux-hkdf/src/hkdf.rs
Original file line number Diff line number Diff line change
@@ -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<u8> {
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<Vec<u8>, 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<Vec<u8>, Error> {
let prk = extract(mode, salt, ikm);
expand(mode, prk, info, okm_len)
}
16 changes: 16 additions & 0 deletions libcrux-hmac/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
File renamed without changes.
56 changes: 56 additions & 0 deletions libcrux-hmac/src/hmac.rs
Original file line number Diff line number Diff line change
@@ -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<hkdf::Algorithm> 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<usize>) -> Vec<u8> {
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
}
8 changes: 3 additions & 5 deletions src/hacl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<chacha20_poly1305::Error> for Error {
Expand All @@ -50,8 +48,8 @@ impl From<p256::Error> for Error {
}
}

impl From<hkdf::Error> for Error {
fn from(val: hkdf::Error) -> Self {
impl From<libcrux_hkdf::Error> for Error {
fn from(val: libcrux_hkdf::Error) -> Self {
Error::Hkdf(val)
}
}
Expand Down
74 changes: 5 additions & 69 deletions src/hkdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8> {
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<Vec<u8>, 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<Vec<u8>, 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;
54 changes: 3 additions & 51 deletions src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<hkdf::Algorithm> 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<usize>) -> Vec<u8> {
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;
Loading