use crate::internal_alloc::Vec;
use noxtls_core::{Error, Result};
use noxtls_crypto::{
hkdf_expand_sha256, hkdf_expand_sha384, hkdf_extract_sha256, hkdf_extract_sha384, hmac_sha256,
hmac_sha384, sha256, sha384,
};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum HashAlgorithm {
Sha256,
Sha384,
}
impl HashAlgorithm {
#[must_use]
pub fn output_len(self) -> usize {
match self {
Self::Sha256 => 32,
Self::Sha384 => 48,
}
}
}
#[must_use]
pub fn hkdf_extract_for_hash(hash_algorithm: HashAlgorithm, ikm: &[u8]) -> Vec<u8> {
match hash_algorithm {
HashAlgorithm::Sha256 => hkdf_extract_sha256(&[0_u8; 32], ikm).to_vec(),
HashAlgorithm::Sha384 => hkdf_extract_sha384(&[0_u8; 48], ikm).to_vec(),
}
}
#[must_use]
pub fn hkdf_extract_with_salt_for_hash(
hash_algorithm: HashAlgorithm,
salt: &[u8],
ikm: &[u8],
) -> Vec<u8> {
match hash_algorithm {
HashAlgorithm::Sha256 => hkdf_extract_sha256(salt, ikm).to_vec(),
HashAlgorithm::Sha384 => hkdf_extract_sha384(salt, ikm).to_vec(),
}
}
pub fn hkdf_expand_for_hash(
hash_algorithm: HashAlgorithm,
prk: &[u8],
info: &[u8],
len: usize,
) -> Result<Vec<u8>> {
match hash_algorithm {
HashAlgorithm::Sha256 => hkdf_expand_sha256(prk, info, len),
HashAlgorithm::Sha384 => hkdf_expand_sha384(prk, info, len),
}
}
pub fn tls13_expand_label_for_hash(
hash_algorithm: HashAlgorithm,
secret: &[u8],
label: &[u8],
context: &[u8],
len: usize,
) -> Result<Vec<u8>> {
let mut hkdf_label = Vec::with_capacity(2 + 1 + 6 + label.len() + 1 + context.len());
hkdf_label.extend_from_slice(&(len as u16).to_be_bytes());
let mut full_label = b"tls13 ".to_vec();
full_label.extend_from_slice(label);
if full_label.len() > u8::MAX as usize || context.len() > u8::MAX as usize {
return Err(Error::InvalidLength("tls13 hkdf label/context too long"));
}
hkdf_label.push(full_label.len() as u8);
hkdf_label.extend_from_slice(&full_label);
hkdf_label.push(context.len() as u8);
hkdf_label.extend_from_slice(context);
hkdf_expand_for_hash(hash_algorithm, secret, &hkdf_label, len)
}
#[must_use]
pub fn finished_hmac_for_hash(
hash_algorithm: HashAlgorithm,
key: &[u8],
transcript_hash: &[u8],
) -> Vec<u8> {
match hash_algorithm {
HashAlgorithm::Sha256 => hmac_sha256(key, transcript_hash).to_vec(),
HashAlgorithm::Sha384 => hmac_sha384(key, transcript_hash).to_vec(),
}
}
#[must_use]
pub fn hash_bytes_for_algorithm(hash_algorithm: HashAlgorithm, input: &[u8]) -> Vec<u8> {
match hash_algorithm {
HashAlgorithm::Sha256 => sha256(input).to_vec(),
HashAlgorithm::Sha384 => sha384(input).to_vec(),
}
}