use crate::ir::DataType;
use crate::ops::Backend;
use crate::ops::{IntrinsicDescriptor, OpSpec};
pub const WGSL: &str = concat!(
include_str!("wgsl_shaders/words.wgsl"),
"\n",
include_str!("wgsl_shaders/sha256.wgsl"),
);
pub const BLOCK_BYTES: usize = 64;
#[must_use]
pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> [u32; 8] {
let mut key_block = [0u8; BLOCK_BYTES];
if key.len() > BLOCK_BYTES {
let key_hash = crate::ops::hash::reference::sha256::sha256_words(key);
for (chunk, word) in key_block.chunks_exact_mut(4).zip(key_hash) {
chunk.copy_from_slice(&word.to_be_bytes());
}
} else {
key_block[..key.len()].copy_from_slice(key);
}
let mut inner = Vec::with_capacity(BLOCK_BYTES + msg.len());
inner.extend(key_block.iter().map(|byte| byte ^ 0x36));
inner.extend_from_slice(msg);
let inner_hash = crate::ops::hash::reference::sha256::sha256_words(&inner);
let mut outer = Vec::with_capacity(BLOCK_BYTES + 32);
outer.extend(key_block.iter().map(|byte| byte ^ 0x5c));
for word in inner_hash {
outer.extend_from_slice(&word.to_be_bytes());
}
crate::ops::hash::reference::sha256::sha256_words(&outer)
}
pub const INPUTS: &[DataType] = &[DataType::Bytes, DataType::Bytes];
pub const LAWS: &[crate::ops::AlgebraicLaw] = &[];
pub const OUTPUTS: &[DataType] = &[const { DataType::U32 }; 8];
pub const SPEC: OpSpec = OpSpec::intrinsic(
"hash.hmac_sha256",
INPUTS,
OUTPUTS,
LAWS,
wgsl_only,
IntrinsicDescriptor::new(
"hash.hmac_sha256.wgsl",
"wgsl-hmac-sha256",
crate::ops::hash::cpu_refs::hmac_sha256,
),
);
pub fn wgsl_only(backend: &Backend) -> bool {
matches!(backend, Backend::Wgsl)
}