use super::cpu::HaveCryptoExt;
pub(crate) fn sha256_compress_blocks(state: &mut [u32; 8], blocks: &[u8]) {
debug_assert!(blocks.len().is_multiple_of(64));
if blocks.is_empty() {
return;
}
let (data, num) = (blocks.as_ptr(), blocks.len() / 64);
match HaveCryptoExt::check() {
Some(_) => unsafe { sha256_block_data_order_hw(state, data, num) },
None => unsafe { sha256_block_data_order_nohw(state, data, num) },
}
}
#[repr(C, align(64))]
struct Table([u32; 65]);
static K256: Table = Table(include!("aws_lc/sha256-armv8.K256.rs"));
#[unsafe(naked)]
unsafe extern "C" fn sha256_block_data_order_nohw(
state: *mut [u32; 8],
data: *const u8,
blocks: usize,
) {
#[cfg(not(target_vendor = "apple"))]
core::arch::naked_asm!(
include_str!("aws_lc/sha256_block_data_order_nohw.linux.s"),
K256 = sym K256,
);
#[cfg(target_vendor = "apple")]
core::arch::naked_asm!(
include_str!("aws_lc/sha256_block_data_order_nohw.apple.s"),
K256 = sym K256,
);
}
#[unsafe(naked)]
unsafe extern "C" fn sha256_block_data_order_hw(
state: *mut [u32; 8],
data: *const u8,
blocks: usize,
) {
#[cfg(not(target_vendor = "apple"))]
core::arch::naked_asm!(
include_str!("aws_lc/sha256_block_data_order_hw.linux.s"),
K256 = sym K256,
);
#[cfg(target_vendor = "apple")]
core::arch::naked_asm!(
include_str!("aws_lc/sha256_block_data_order_hw.apple.s"),
K256 = sym K256,
);
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn hw_matches_nohw() {
if HaveCryptoExt::check().is_none() {
return;
}
let blocks: Vec<u8> = (0..5 * 64u32)
.map(|i| (i.wrapping_mul(0x9e3779b9) >> 24) as u8)
.collect();
for n in 1..=5 {
let mut want = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
0x5be0cd19,
];
let mut got = want;
unsafe {
sha256_block_data_order_nohw(&mut want, blocks.as_ptr(), n);
sha256_block_data_order_hw(&mut got, blocks.as_ptr(), n);
}
assert_eq!(got, want, "{n} blocks");
}
}
}