Skip to content

Commit

Permalink
Merge pull request #305 from cryspen/jonas/hmac-hkdf-crates
Browse files Browse the repository at this point in the history
Pull out `hkdf` and `hmac` modules as standalone crates
  • Loading branch information
jschneider-bensch committed Jun 11, 2024
2 parents 1202ef2 + 42a37b5 commit 76c25c4
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 125 deletions.
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;

0 comments on commit 76c25c4

Please sign in to comment.