#![allow(clippy::module_name_repetitions)]
use aws_lc::EVP_MD;
#[cfg(not(feature = "fips"))]
use aws_lc::{SSKDF_digest, SSKDF_hmac};
#[cfg(feature = "fips")]
use stubs::{SSKDF_digest, SSKDF_hmac};
use crate::{
digest::{match_digest_type, AlgorithmID},
error::Unspecified,
ptr::ConstPointer,
};
#[cfg(feature = "fips")]
mod stubs {
#[allow(non_snake_case)]
pub(super) unsafe fn SSKDF_digest(
_out_key: *mut u8,
_out_len: usize,
_digest: *const aws_lc::EVP_MD,
_secret: *const u8,
_secret_len: usize,
_info: *const u8,
_info_len: usize,
) -> std::os::raw::c_int {
0
}
#[allow(clippy::too_many_arguments, non_snake_case)]
pub(super) unsafe fn SSKDF_hmac(
_out_key: *mut u8,
_out_len: usize,
_digest: *const aws_lc::EVP_MD,
_secret: *const u8,
_secret_len: usize,
_info: *const u8,
_info_len: usize,
_salt: *const u8,
_salt_len: usize,
) -> std::os::raw::c_int {
0
}
}
#[allow(dead_code)]
const SSKDF_HMAC_SHA224: SskdfHmacAlgorithm = SskdfHmacAlgorithm {
id: SskdfHmacAlgorithmId::Sha224,
};
#[allow(dead_code)]
const SSKDF_HMAC_SHA256: SskdfHmacAlgorithm = SskdfHmacAlgorithm {
id: SskdfHmacAlgorithmId::Sha256,
};
#[allow(dead_code)]
const SSKDF_HMAC_SHA384: SskdfHmacAlgorithm = SskdfHmacAlgorithm {
id: SskdfHmacAlgorithmId::Sha384,
};
#[allow(dead_code)]
const SSKDF_HMAC_SHA512: SskdfHmacAlgorithm = SskdfHmacAlgorithm {
id: SskdfHmacAlgorithmId::Sha512,
};
#[allow(dead_code)]
const SSKDF_DIGEST_SHA224: SskdfDigestAlgorithm = SskdfDigestAlgorithm {
id: SskdfDigestAlgorithmId::Sha224,
};
#[allow(dead_code)]
const SSKDF_DIGEST_SHA256: SskdfDigestAlgorithm = SskdfDigestAlgorithm {
id: SskdfDigestAlgorithmId::Sha256,
};
#[allow(dead_code)]
const SSKDF_DIGEST_SHA384: SskdfDigestAlgorithm = SskdfDigestAlgorithm {
id: SskdfDigestAlgorithmId::Sha384,
};
#[allow(dead_code)]
const SSKDF_DIGEST_SHA512: SskdfDigestAlgorithm = SskdfDigestAlgorithm {
id: SskdfDigestAlgorithmId::Sha512,
};
#[must_use]
pub const fn get_sskdf_hmac_algorithm(
id: SskdfHmacAlgorithmId,
) -> Option<&'static SskdfHmacAlgorithm> {
#[cfg(feature = "fips")]
{
let _ = id;
None
}
#[cfg(not(feature = "fips"))]
{
match id {
SskdfHmacAlgorithmId::Sha224 => Some(&SSKDF_HMAC_SHA224),
SskdfHmacAlgorithmId::Sha256 => Some(&SSKDF_HMAC_SHA256),
SskdfHmacAlgorithmId::Sha384 => Some(&SSKDF_HMAC_SHA384),
SskdfHmacAlgorithmId::Sha512 => Some(&SSKDF_HMAC_SHA512),
}
}
}
#[must_use]
pub const fn get_sskdf_digest_algorithm(
id: SskdfDigestAlgorithmId,
) -> Option<&'static SskdfDigestAlgorithm> {
#[cfg(feature = "fips")]
{
let _ = id;
None
}
#[cfg(not(feature = "fips"))]
{
match id {
SskdfDigestAlgorithmId::Sha224 => Some(&SSKDF_DIGEST_SHA224),
SskdfDigestAlgorithmId::Sha256 => Some(&SSKDF_DIGEST_SHA256),
SskdfDigestAlgorithmId::Sha384 => Some(&SSKDF_DIGEST_SHA384),
SskdfDigestAlgorithmId::Sha512 => Some(&SSKDF_DIGEST_SHA512),
}
}
}
pub struct SskdfHmacAlgorithm {
id: SskdfHmacAlgorithmId,
}
impl SskdfHmacAlgorithm {
#[must_use]
pub fn id(&self) -> SskdfHmacAlgorithmId {
self.id
}
#[must_use]
fn get_evp_md(&self) -> ConstPointer<EVP_MD> {
match_digest_type(match self.id {
SskdfHmacAlgorithmId::Sha224 => &AlgorithmID::SHA224,
SskdfHmacAlgorithmId::Sha256 => &AlgorithmID::SHA256,
SskdfHmacAlgorithmId::Sha384 => &AlgorithmID::SHA384,
SskdfHmacAlgorithmId::Sha512 => &AlgorithmID::SHA512,
})
}
}
impl PartialEq for SskdfHmacAlgorithm {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for SskdfHmacAlgorithm {}
impl core::fmt::Debug for SskdfHmacAlgorithm {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.id, f)
}
}
pub struct SskdfDigestAlgorithm {
id: SskdfDigestAlgorithmId,
}
impl SskdfDigestAlgorithm {
#[must_use]
pub fn id(&self) -> SskdfDigestAlgorithmId {
self.id
}
#[must_use]
fn get_evp_md(&self) -> ConstPointer<EVP_MD> {
match_digest_type(match self.id {
SskdfDigestAlgorithmId::Sha224 => &AlgorithmID::SHA224,
SskdfDigestAlgorithmId::Sha256 => &AlgorithmID::SHA256,
SskdfDigestAlgorithmId::Sha384 => &AlgorithmID::SHA384,
SskdfDigestAlgorithmId::Sha512 => &AlgorithmID::SHA512,
})
}
}
impl PartialEq for SskdfDigestAlgorithm {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for SskdfDigestAlgorithm {}
impl core::fmt::Debug for SskdfDigestAlgorithm {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&self.id, f)
}
}
#[non_exhaustive]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum SskdfDigestAlgorithmId {
Sha224,
Sha256,
Sha384,
Sha512,
}
#[non_exhaustive]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum SskdfHmacAlgorithmId {
Sha224,
Sha256,
Sha384,
Sha512,
}
pub fn sskdf_hmac(
algorithm: &'static SskdfHmacAlgorithm,
secret: &[u8],
info: &[u8],
salt: &[u8],
output: &mut [u8],
) -> Result<(), Unspecified> {
let evp_md = algorithm.get_evp_md();
let out_len = output.len();
if 1 != unsafe {
SSKDF_hmac(
output.as_mut_ptr(),
out_len,
*evp_md,
secret.as_ptr(),
secret.len(),
info.as_ptr(),
info.len(),
salt.as_ptr(),
salt.len(),
)
} {
return Err(Unspecified);
}
Ok(())
}
pub fn sskdf_digest(
algorithm: &'static SskdfDigestAlgorithm,
secret: &[u8],
info: &[u8],
output: &mut [u8],
) -> Result<(), Unspecified> {
let evp_md = algorithm.get_evp_md();
let out_len = output.len();
if 1 != unsafe {
SSKDF_digest(
output.as_mut_ptr(),
out_len,
*evp_md,
secret.as_ptr(),
secret.len(),
info.as_ptr(),
info.len(),
)
} {
return Err(Unspecified);
}
Ok(())
}