diff --git a/src/hace_controller.rs b/src/hace_controller.rs
new file mode 100644
index 0000000..bac32ab
--- /dev/null
+++ b/src/hace_controller.rs
@@ -0,0 +1,412 @@
+use ast1060_pac::Hace;
+use core::convert::Infallible;
+use proposed_traits::digest::ErrorType as DigestErrorType;
+use proposed_traits::mac::ErrorType as MacErrorType;
+
+#[link_section = ".ram_nc"]
+static mut HMAC_CTX: AspeedHashContext = AspeedHashContext::new();
+
+const SHA1_IV: [u32; 8] = [
+ 0x0123_4567,
+ 0x89ab_cdef,
+ 0xfedc_ba98,
+ 0x7654_3210,
+ 0xf0e1_d2c3,
+ 0,
+ 0,
+ 0,
+];
+
+const SHA224_IV: [u32; 8] = [
+ 0xd89e_05c1,
+ 0x07d5_7c36,
+ 0x17dd_7030,
+ 0x3959_0ef7,
+ 0x310b_c0ff,
+ 0x1115_5868,
+ 0xa78f_f964,
+ 0xa44f_fabe,
+];
+
+const SHA256_IV: [u32; 8] = [
+ 0x67e6_096a,
+ 0x85ae_67bb,
+ 0x72f3_6e3c,
+ 0x3af5_4fa5,
+ 0x7f52_0e51,
+ 0x8c68_059b,
+ 0xabd9_831f,
+ 0x19cd_e05b,
+];
+
+const SHA384_IV: [u32; 16] = [
+ 0x5d9d_bbcb,
+ 0xd89e_05c1,
+ 0x2a29_9a62,
+ 0x07d5_7c36,
+ 0x5a01_5991,
+ 0x17dd_7030,
+ 0xd8ec_2f15,
+ 0x3959_0ef7,
+ 0x6726_3367,
+ 0x310b_c0ff,
+ 0x874a_b48e,
+ 0x1115_5868,
+ 0x0d2e_0cdb,
+ 0xa78f_f964,
+ 0x1d48_b547,
+ 0xa44f_fabe,
+];
+
+const SHA512_IV: [u32; 16] = [
+ 0x67e6_096a,
+ 0x08c9_bcf3,
+ 0x85ae_67bb,
+ 0x3ba7_ca84,
+ 0x72f3_6e3c,
+ 0x2bf8_94fe,
+ 0x3af5_4fa5,
+ 0xf136_1d5f,
+ 0x7f52_0e51,
+ 0xd182_e6ad,
+ 0x8c68_059b,
+ 0x1f6c_3e2b,
+ 0xabd9_831f,
+ 0x6bbd_41fb,
+ 0x19cd_e05b,
+ 0x7921_7e13,
+];
+
+const SHA512_224_IV: [u32; 16] = [
+ 0xC837_3D8C,
+ 0xA24D_5419,
+ 0x6699_E173,
+ 0xD6D4_DC89,
+ 0xAEB7_FA1D,
+ 0x829C_FF32,
+ 0x14D5_9D67,
+ 0xCF9F_2F58,
+ 0x692B_6D0F,
+ 0xA84D_D47B,
+ 0x736F_E377,
+ 0x4289_C404,
+ 0xA885_9D3F,
+ 0xC836_1D6A,
+ 0xADE6_1211,
+ 0xA192_D691,
+];
+
+const SHA512_256_IV: [u32; 16] = [
+ 0x9421_3122,
+ 0x2CF7_2BFC,
+ 0xA35F_559F,
+ 0xC264_4CC8,
+ 0x6BB8_9323,
+ 0x51B1_536F,
+ 0x1977_3896,
+ 0xBDEA_4059,
+ 0xE23E_2896,
+ 0xE3FF_8EA8,
+ 0x251E_5EBE,
+ 0x9239_8653,
+ 0xFC99_012B,
+ 0xAAB8_852C,
+ 0xDC2D_B70E,
+ 0xA22C_C581,
+];
+
+const HACE_SHA_BE_EN: u32 = 1 << 3;
+const HACE_CMD_ACC_MODE: u32 = 1 << 8;
+pub const HACE_SG_EN: u32 = 1 << 18;
+pub const HACE_SG_LAST: u32 = 1 << 31;
+
+const HACE_ALGO_SHA1: u32 = 1 << 5;
+const HACE_ALGO_SHA224: u32 = 1 << 6;
+const HACE_ALGO_SHA256: u32 = (1 << 4) | (1 << 6);
+const HACE_ALGO_SHA512: u32 = (1 << 5) | (1 << 6);
+const HACE_ALGO_SHA384: u32 = (1 << 5) | (1 << 6) | (1 << 10);
+const HACE_ALGO_SHA512_224: u32 = (1 << 5) | (1 << 6) | (1 << 10) | (1 << 11);
+const HACE_ALGO_SHA512_256: u32 = (1 << 5) | (1 << 6) | (1 << 11);
+
+/// Common context cleanup functionality
+pub trait ContextCleanup {
+ fn cleanup_context(&mut self);
+}
+
+impl ContextCleanup for crate::hace_controller::HaceController<'_> {
+ fn cleanup_context(&mut self) {
+ let ctx = self.ctx_mut();
+ ctx.bufcnt = 0;
+ ctx.buffer.fill(0);
+ ctx.digest.fill(0);
+ ctx.digcnt = [0; 2];
+
+ unsafe {
+ self.hace.hace30().write(|w| w.bits(0));
+ }
+ }
+}
+
+#[derive(Default, Copy, Clone)]
+pub struct AspeedSg {
+ pub len: u32,
+ pub addr: u32,
+}
+
+impl AspeedSg {
+ pub const fn new() -> Self {
+ Self { len: 0, addr: 0 }
+ }
+}
+
+#[repr(C)]
+#[repr(align(64))]
+pub struct AspeedHashContext {
+ pub sg: [AspeedSg; 2],
+ pub digest: [u8; 64],
+ pub method: u32,
+ pub block_size: u32,
+ pub key: [u8; 128],
+ pub key_len: u32,
+ pub ipad: [u8; 128],
+ pub opad: [u8; 128],
+ pub digcnt: [u64; 2],
+ pub bufcnt: u32,
+ pub buffer: [u8; 256],
+ pub iv_size: u8,
+}
+
+impl Default for AspeedHashContext {
+ fn default() -> Self {
+ Self {
+ sg: [AspeedSg::default(); 2],
+ digest: [0; 64],
+ method: 0,
+ block_size: 0,
+ key: [0; 128],
+ key_len: 0,
+ ipad: [0; 128],
+ opad: [0; 128],
+ digcnt: [0; 2],
+ bufcnt: 0,
+ buffer: [0; 256],
+ iv_size: 0,
+ }
+ }
+}
+
+impl AspeedHashContext {
+ pub const fn new() -> Self {
+ Self {
+ sg: [AspeedSg::new(), AspeedSg::new()],
+ digest: [0; 64],
+ method: 0,
+ block_size: 0,
+ digcnt: [0; 2],
+ key: [0; 128],
+ key_len: 0,
+ ipad: [0; 128],
+ opad: [0; 128],
+ bufcnt: 0,
+ buffer: [0; 256],
+ iv_size: 0,
+ }
+ }
+}
+
+#[derive(Copy, Clone)]
+pub enum HashAlgo {
+ SHA1,
+ SHA224,
+ SHA256,
+ SHA384,
+ SHA512,
+ SHA512_224,
+ SHA512_256,
+}
+
+impl HashAlgo {
+ pub const fn digest_size(&self) -> usize {
+ match self {
+ HashAlgo::SHA1 => 20,
+ HashAlgo::SHA224 | HashAlgo::SHA512_224 => 28,
+ HashAlgo::SHA256 | HashAlgo::SHA512_256 => 32,
+ HashAlgo::SHA384 => 48,
+ HashAlgo::SHA512 => 64,
+ }
+ }
+
+ pub const fn block_size(&self) -> usize {
+ match self {
+ HashAlgo::SHA1 | HashAlgo::SHA224 | HashAlgo::SHA256 => 64,
+ HashAlgo::SHA384 | HashAlgo::SHA512 | HashAlgo::SHA512_224 | HashAlgo::SHA512_256 => {
+ 128
+ }
+ }
+ }
+
+ pub const fn bitmask(&self) -> u32 {
+ match self {
+ HashAlgo::SHA1 => HACE_ALGO_SHA1,
+ HashAlgo::SHA224 => HACE_ALGO_SHA224,
+ HashAlgo::SHA256 => HACE_ALGO_SHA256,
+ HashAlgo::SHA512 => HACE_ALGO_SHA512,
+ HashAlgo::SHA384 => HACE_ALGO_SHA384,
+ HashAlgo::SHA512_224 => HACE_ALGO_SHA512_224,
+ HashAlgo::SHA512_256 => HACE_ALGO_SHA512_256,
+ }
+ }
+
+ pub const fn iv(&self) -> &'static [u32] {
+ match self {
+ HashAlgo::SHA1 => &SHA1_IV,
+ HashAlgo::SHA224 => &SHA224_IV,
+ HashAlgo::SHA256 => &SHA256_IV,
+ HashAlgo::SHA384 => &SHA384_IV,
+ HashAlgo::SHA512 => &SHA512_IV,
+ HashAlgo::SHA512_224 => &SHA512_224_IV,
+ HashAlgo::SHA512_256 => &SHA512_256_IV,
+ }
+ }
+
+ pub const fn iv_size(&self) -> usize {
+ match self {
+ HashAlgo::SHA1 => SHA1_IV.len(),
+ HashAlgo::SHA224 => SHA224_IV.len(),
+ HashAlgo::SHA256 => SHA256_IV.len(),
+ HashAlgo::SHA384 => SHA384_IV.len(),
+ HashAlgo::SHA512 => SHA512_IV.len(),
+ HashAlgo::SHA512_224 => SHA512_224_IV.len(),
+ HashAlgo::SHA512_256 => SHA512_256_IV.len(),
+ }
+ }
+
+ pub fn hash_cmd(&self) -> u32 {
+ const COMMON_FLAGS: u32 = HACE_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
+ COMMON_FLAGS | self.bitmask()
+ }
+}
+
+pub struct HaceController<'ctrl> {
+ pub hace: &'ctrl Hace,
+ pub algo: HashAlgo,
+ pub aspeed_hash_ctx: *mut AspeedHashContext,
+}
+
+impl<'ctrl> HaceController<'ctrl> {
+ pub fn new(hace: &'ctrl Hace) -> Self {
+ Self {
+ hace,
+ algo: HashAlgo::SHA256,
+ aspeed_hash_ctx: core::ptr::addr_of_mut!(HMAC_CTX),
+ }
+ }
+}
+
+impl DigestErrorType for HaceController<'_> {
+ type Error = Infallible;
+}
+
+impl MacErrorType for HaceController<'_> {
+ type Error = Infallible;
+}
+
+impl HaceController<'_> {
+ pub fn ctx_mut(&mut self) -> &mut AspeedHashContext {
+ unsafe { &mut *self.aspeed_hash_ctx }
+ }
+
+ pub fn start_hash_operation(&mut self, len: u32) {
+ let ctx = self.ctx_mut();
+
+ let src_addr = if (ctx.method & HACE_SG_EN) != 0 {
+ ctx.sg.as_ptr() as u32
+ } else {
+ ctx.buffer.as_ptr() as u32
+ };
+
+ let digest_addr = ctx.digest.as_ptr() as u32;
+ let method = ctx.method;
+
+ unsafe {
+ self.hace.hace1c().write(|w| w.hash_intflag().set_bit());
+ self.hace.hace20().write(|w| w.bits(src_addr));
+ self.hace.hace24().write(|w| w.bits(digest_addr));
+ self.hace.hace28().write(|w| w.bits(digest_addr));
+ self.hace.hace2c().write(|w| w.bits(len));
+ self.hace.hace30().write(|w| w.bits(method));
+ // blocking wait until hash engine ready
+ while self.hace.hace1c().read().hash_intflag().bit_is_clear() {
+ // wait for the hash operation to complete
+ cortex_m::asm::nop();
+ }
+ }
+ }
+
+ pub fn copy_iv_to_digest(&mut self) {
+ let iv = self.algo.iv();
+ let iv_bytes =
+ unsafe { core::slice::from_raw_parts(iv.as_ptr() as *const u8, iv.len() * 4) };
+
+ self.ctx_mut().digest[..iv_bytes.len()].copy_from_slice(iv_bytes);
+ }
+
+ pub fn hash_key(&mut self, key: &impl AsRef<[u8]>) {
+ let key_bytes = key.as_ref();
+ let key_len = key_bytes.len();
+ let digest_len = self.algo.digest_size();
+
+ self.ctx_mut().digcnt[0] = key_len as u64;
+ self.ctx_mut().bufcnt = key_len as u32;
+ self.ctx_mut().buffer[..key_len].copy_from_slice(key_bytes);
+ self.ctx_mut().method &= !HACE_SG_EN; // Disable SG mode for key hashing
+ self.copy_iv_to_digest();
+ self.fill_padding(0);
+ let bufcnt = self.ctx_mut().bufcnt;
+ self.start_hash_operation(bufcnt);
+
+ let slice =
+ unsafe { core::slice::from_raw_parts(self.ctx_mut().digest.as_ptr(), digest_len) };
+
+ self.ctx_mut().key[..digest_len].copy_from_slice(slice);
+ self.ctx_mut().ipad[..digest_len].copy_from_slice(slice);
+ self.ctx_mut().opad[..digest_len].copy_from_slice(slice);
+ self.ctx_mut().key_len = digest_len as u32;
+ }
+
+ pub fn fill_padding(&mut self, remaining: usize) {
+ let ctx = &mut self.ctx_mut();
+ let block_size = ctx.block_size as usize;
+ let bufcnt = ctx.bufcnt as usize;
+
+ let index = (bufcnt + remaining) & (block_size - 1);
+ let padlen = if block_size == 64 {
+ if index < 56 {
+ 56 - index
+ } else {
+ 64 + 56 - index
+ }
+ } else if index < 112 {
+ 112 - index
+ } else {
+ 128 + 112 - index
+ };
+
+ ctx.buffer[bufcnt] = 0x80;
+ ctx.buffer[bufcnt + 1..bufcnt + padlen].fill(0);
+
+ if block_size == 64 {
+ let bits = (ctx.digcnt[0] << 3).to_be_bytes();
+ ctx.buffer[bufcnt + padlen..bufcnt + padlen + 8].copy_from_slice(&bits);
+ ctx.bufcnt += (padlen + 8) as u32;
+ } else {
+ let low = (ctx.digcnt[0] << 3).to_be_bytes();
+ let high = ((ctx.digcnt[1] << 3) | (ctx.digcnt[0] >> 61)).to_be_bytes();
+
+ ctx.buffer[bufcnt + padlen..bufcnt + padlen + 8].copy_from_slice(&high);
+ ctx.buffer[bufcnt + padlen + 8..bufcnt + padlen + 16].copy_from_slice(&low);
+
+ ctx.bufcnt += (padlen + 16) as u32;
+ }
+ }
+}
diff --git a/src/hash.rs b/src/hash.rs
index 2c94a49..328dae2 100644
--- a/src/hash.rs
+++ b/src/hash.rs
@@ -1,261 +1,6 @@
-use ast1060_pac::Hace;
-use proposed_traits::digest::*;
+use crate::hace_controller::{ContextCleanup, HaceController, HashAlgo, HACE_SG_LAST};
use core::convert::Infallible;
-
-#[link_section = ".ram_nc"]
-static mut HASH_CTX: AspeedHashContext = AspeedHashContext::new();
-
-
-const SHA1_IV: [u32; 8] = [
- 0x0123_4567,
- 0x89ab_cdef,
- 0xfedc_ba98,
- 0x7654_3210,
- 0xf0e1_d2c3,
- 0,
- 0,
- 0,
-];
-
-const SHA224_IV: [u32; 8] = [
- 0xd89e_05c1,
- 0x07d5_7c36,
- 0x17dd_7030,
- 0x3959_0ef7,
- 0x310b_c0ff,
- 0x1115_5868,
- 0xa78f_f964,
- 0xa44f_fabe,
-];
-
-const SHA256_IV: [u32; 8] = [
- 0x67e6_096a,
- 0x85ae_67bb,
- 0x72f3_6e3c,
- 0x3af5_4fa5,
- 0x7f52_0e51,
- 0x8c68_059b,
- 0xabd9_831f,
- 0x19cd_e05b,
-];
-
-const SHA384_IV: [u32; 16] = [
- 0x5d9d_bbcb,
- 0xd89e_05c1,
- 0x2a29_9a62,
- 0x07d5_7c36,
- 0x5a01_5991,
- 0x17dd_7030,
- 0xd8ec_2f15,
- 0x3959_0ef7,
- 0x6726_3367,
- 0x310b_c0ff,
- 0x874a_b48e,
- 0x1115_5868,
- 0x0d2e_0cdb,
- 0xa78f_f964,
- 0x1d48_b547,
- 0xa44f_fabe,
-];
-
-const SHA512_IV: [u32; 16] = [
- 0x67e6_096a,
- 0x08c9_bcf3,
- 0x85ae_67bb,
- 0x3ba7_ca84,
- 0x72f3_6e3c,
- 0x2bf8_94fe,
- 0x3af5_4fa5,
- 0xf136_1d5f,
- 0x7f52_0e51,
- 0xd182_e6ad,
- 0x8c68_059b,
- 0x1f6c_3e2b,
- 0xabd9_831f,
- 0x6bbd_41fb,
- 0x19cd_e05b,
- 0x7921_7e13,
-];
-
-const SHA512_224_IV: [u32; 16] = [
- 0xC837_3D8C,
- 0xA24D_5419,
- 0x6699_E173,
- 0xD6D4_DC89,
- 0xAEB7_FA1D,
- 0x829C_FF32,
- 0x14D5_9D67,
- 0xCF9F_2F58,
- 0x692B_6D0F,
- 0xA84D_D47B,
- 0x736F_E377,
- 0x4289_C404,
- 0xA885_9D3F,
- 0xC836_1D6A,
- 0xADE6_1211,
- 0xA192_D691,
-];
-
-const SHA512_256_IV: [u32; 16] = [
- 0x9421_3122,
- 0x2CF7_2BFC,
- 0xA35F_559F,
- 0xC264_4CC8,
- 0x6BB8_9323,
- 0x51B1_536F,
- 0x1977_3896,
- 0xBDEA_4059,
- 0xE23E_2896,
- 0xE3FF_8EA8,
- 0x251E_5EBE,
- 0x9239_8653,
- 0xFC99_012B,
- 0xAAB8_852C,
- 0xDC2D_B70E,
- 0xA22C_C581,
-];
-
-const HACE_SHA_BE_EN: u32 = 1 << 3;
-const HACE_SG_EN: u32 = 1 << 18;
-const HACE_CMD_ACC_MODE: u32 = 1 << 8;
-
-const HACE_ALGO_SHA1: u32 = 1 << 5;
-const HACE_ALGO_SHA224: u32 = 1 << 6;
-const HACE_ALGO_SHA256: u32 = (1 << 4) | (1 << 6);
-const HACE_ALGO_SHA512: u32 = (1 << 5) | (1 << 6);
-const HACE_ALGO_SHA384: u32 = (1 << 5) | (1 << 6) | (1 << 10);
-const HACE_ALGO_SHA512_224: u32 = (1 << 5) | (1 << 6) | (1 << 10) | (1 << 11);
-const HACE_ALGO_SHA512_256: u32 = (1 << 5) | (1 << 6) | (1 << 11);
-
-const HACE_SG_LAST: u32 = 1 << 31;
-#[derive(Default, Copy, Clone)]
-pub struct AspeedSg {
- pub len: u32,
- pub addr: u32,
-}
-
-impl AspeedSg {
- pub const fn new() -> Self {
- Self { len: 0, addr: 0 }
- }
-}
-
-
-#[repr(C)]
-#[repr(align(64))]
-pub struct AspeedHashContext {
- pub sg: [AspeedSg; 2],
- pub digest: [u8; 64],
- pub method: u32,
- pub block_size: u32,
- pub digcnt: [u64; 2],
- pub bufcnt: u32,
- pub buffer: [u8; 256],
- pub iv_size: u8,
-}
-
-impl Default for AspeedHashContext {
- fn default() -> Self {
- Self {
- sg: [AspeedSg::default(); 2],
- digest: [0; 64],
- method: 0,
- block_size: 0,
- digcnt: [0; 2],
- bufcnt: 0,
- buffer: [0; 256],
- iv_size: 0,
- }
- }
-}
-
-impl AspeedHashContext {
- pub const fn new() -> Self {
- Self {
- sg: [AspeedSg::new(), AspeedSg::new()],
- digest: [0; 64],
- method: 0,
- block_size: 0,
- digcnt: [0; 2],
- bufcnt: 0,
- buffer: [0; 256],
- iv_size: 0,
- }
- }
-}
-
-#[derive(Copy, Clone)]
-pub enum HashAlgo {
- SHA1,
- SHA224,
- SHA256,
- SHA384,
- SHA512,
- SHA512_224,
- SHA512_256,
-}
-
-impl HashAlgo {
- pub fn digest_size(&self) -> usize {
- match self {
- HashAlgo::SHA1 => 20,
- HashAlgo::SHA224 | HashAlgo::SHA512_224 => 28,
- HashAlgo::SHA256 | HashAlgo::SHA512_256 => 32,
- HashAlgo::SHA384 => 48,
- HashAlgo::SHA512 => 64,
- }
- }
-
- pub fn block_size(&self) -> usize {
- match self {
- HashAlgo::SHA1 | HashAlgo::SHA224 | HashAlgo::SHA256 => 64,
- HashAlgo::SHA384 | HashAlgo::SHA512 | HashAlgo::SHA512_224 | HashAlgo::SHA512_256 => {
- 128
- }
- }
- }
-
- pub fn bitmask(&self) -> u32 {
- match self {
- HashAlgo::SHA1 => HACE_ALGO_SHA1,
- HashAlgo::SHA224 => HACE_ALGO_SHA224,
- HashAlgo::SHA256 => HACE_ALGO_SHA256,
- HashAlgo::SHA512 => HACE_ALGO_SHA512,
- HashAlgo::SHA384 => HACE_ALGO_SHA384,
- HashAlgo::SHA512_224 => HACE_ALGO_SHA512_224,
- HashAlgo::SHA512_256 => HACE_ALGO_SHA512_256,
- }
- }
-
- pub fn iv(&self) -> &'static [u32] {
- match self {
- HashAlgo::SHA1 => &SHA1_IV,
- HashAlgo::SHA224 => &SHA224_IV,
- HashAlgo::SHA256 => &SHA256_IV,
- HashAlgo::SHA384 => &SHA384_IV,
- HashAlgo::SHA512 => &SHA512_IV,
- HashAlgo::SHA512_224 => &SHA512_224_IV,
- HashAlgo::SHA512_256 => &SHA512_256_IV,
- }
- }
-
- pub fn iv_size(&self) -> usize {
- match self {
- HashAlgo::SHA1 => SHA1_IV.len(),
- HashAlgo::SHA224 => SHA224_IV.len(),
- HashAlgo::SHA256 => SHA256_IV.len(),
- HashAlgo::SHA384 => SHA384_IV.len(),
- HashAlgo::SHA512 => SHA512_IV.len(),
- HashAlgo::SHA512_224 => SHA512_224_IV.len(),
- HashAlgo::SHA512_256 => SHA512_256_IV.len(),
- }
- }
-
- pub fn hash_cmd(&self) -> u32 {
- const COMMON_FLAGS: u32 = HACE_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
- COMMON_FLAGS | self.bitmask()
- }
-}
+use proposed_traits::digest::*;
// DigestAlgorithm implementation for HashAlgo
impl DigestAlgorithm for HashAlgo {
@@ -338,18 +83,23 @@ impl DigestAlgorithm for Sha512 {
}
impl Default for Sha256 {
- fn default() -> Self { Sha256 }
+ fn default() -> Self {
+ Sha256
+ }
}
impl Default for Sha384 {
- fn default() -> Self { Sha384 }
+ fn default() -> Self {
+ Sha384
+ }
}
impl Default for Sha512 {
- fn default() -> Self { Sha512 }
+ fn default() -> Self {
+ Sha512
+ }
}
-
impl IntoHashAlgo for Sha256 {
fn to_hash_algo() -> HashAlgo {
HashAlgo::SHA256
@@ -368,116 +118,17 @@ impl IntoHashAlgo for Sha512 {
}
}
-pub struct Controller {
- hace: Hace,
- algo: HashAlgo,
- aspeed_hash_ctx: *mut AspeedHashContext,
-}
-
-impl Controller {
- pub fn new(hace: Hace) -> Self {
- Self {
- hace,
- algo: HashAlgo::SHA256,
- aspeed_hash_ctx: core::ptr::addr_of_mut!(HASH_CTX),
- }
- }
-}
-
-
-impl<'a> proposed_traits::digest::ErrorType for Controller {
- type Error = Infallible;
-}
-
-impl Controller {
- pub fn ctx_mut(&mut self) -> &mut AspeedHashContext {
- unsafe { &mut *self.aspeed_hash_ctx }
- }
-
- fn start_hash_operation(&mut self, _len: u32) {
- self.hace.hace1c().write(|w| w.hash_intflag().set_bit());
- let ctx = self.ctx_mut();
-
- let src_addr = if (ctx.method & HACE_SG_EN) != 0 {
- ctx.sg.as_ptr() as u32
- } else {
- ctx.buffer.as_ptr() as u32
- };
-
- let digest_addr = ctx.digest.as_ptr() as u32;
- let method = ctx.method;
-
- unsafe {
- self.hace.hace1c().write(|w| w.hash_intflag().set_bit());
- self.hace.hace20().write(|w| w.bits(src_addr));
- self.hace.hace24().write(|w| w.bits(digest_addr));
- self.hace.hace28().write(|w| w.bits(digest_addr));
- self.hace.hace2c().write(|w| w.bits(_len));
- self.hace.hace30().write(|w| w.bits(method));
- // blocking wait until hash engine ready
- while self.hace.hace1c().read().hash_intflag().bit_is_clear() {
- // wait for the hash operation to complete
- cortex_m::asm::nop();
- }
- }
- }
-
- fn copy_iv_to_digest(&mut self) {
- let iv = self.algo.iv();
- let iv_bytes =
- unsafe { core::slice::from_raw_parts(iv.as_ptr() as *const u8, iv.len() * 4) };
-
- self.ctx_mut().digest[..iv_bytes.len()].copy_from_slice(iv_bytes);
- }
-
- fn fill_padding(&mut self, remaining: usize) {
- let ctx = &mut self.ctx_mut();
- let block_size = ctx.block_size as usize;
- let bufcnt = ctx.bufcnt as usize;
-
- let index = (bufcnt + remaining) & (block_size - 1);
- let padlen = if block_size == 64 {
- if index < 56 {
- 56 - index
- } else {
- 64 + 56 - index
- }
- } else {
- if index < 112 {
- 112 - index
- } else {
- 128 + 112 - index
- }
- };
-
- ctx.buffer[bufcnt] = 0x80;
- ctx.buffer[bufcnt + 1..bufcnt + padlen].fill(0);
-
- if block_size == 64 {
- let bits = (ctx.digcnt[0] << 3).to_be_bytes();
- ctx.buffer[bufcnt + padlen..bufcnt + padlen + 8].copy_from_slice(&bits);
- ctx.bufcnt += (padlen + 8) as u32;
- } else {
- let low = (ctx.digcnt[0] << 3).to_be_bytes();
- let high = ((ctx.digcnt[1] << 3) | (ctx.digcnt[0] >> 61)).to_be_bytes();
-
- ctx.buffer[bufcnt + padlen..bufcnt + padlen + 8].copy_from_slice(&high);
- ctx.buffer[bufcnt + padlen + 8..bufcnt + padlen + 16].copy_from_slice(&low);
-
- ctx.bufcnt += (padlen + 16) as u32;
- }
- }
-}
-
-
-impl DigestInit for Controller
+impl<'ctrl, A> DigestInit for HaceController<'ctrl>
where
A: DigestAlgorithm + IntoHashAlgo,
A::DigestOutput: Default + AsMut<[u8]>,
{
- type OpContext<'a> = OpContextImpl<'a, A> where Self: 'a; // Define your OpContext type here
+ type OpContext<'a>
+ = OpContextImpl<'a, 'ctrl, A>
+ where
+ Self: 'a; // Define your OpContext type here
- fn init<'a>(&'a mut self, _algo: A) -> Result, Self::Error> {
+ fn init(&mut self, _algo: A) -> Result, Self::Error> {
self.algo = A::to_hash_algo();
self.ctx_mut().method = self.algo.hash_cmd();
self.copy_iv_to_digest();
@@ -485,7 +136,6 @@ where
self.ctx_mut().bufcnt = 0;
self.ctx_mut().digcnt = [0; 2];
-
Ok(OpContextImpl {
controller: self,
_phantom: core::marker::PhantomData,
@@ -493,28 +143,29 @@ where
}
}
-pub struct OpContextImpl<'a, A: DigestAlgorithm + IntoHashAlgo> {
- pub controller: &'a mut Controller,
+pub struct OpContextImpl<'a, 'ctrl, A: DigestAlgorithm + IntoHashAlgo> {
+ pub controller: &'a mut HaceController<'ctrl>,
_phantom: core::marker::PhantomData,
}
-impl<'a, A> proposed_traits::digest::ErrorType for OpContextImpl<'a, A>
+impl proposed_traits::digest::ErrorType for OpContextImpl<'_, '_, A>
where
A: DigestAlgorithm + IntoHashAlgo,
{
type Error = Infallible;
}
-impl<'a, A> DigestOp for OpContextImpl<'a, A>
+impl DigestOp for OpContextImpl<'_, '_, A>
where
A: DigestAlgorithm + IntoHashAlgo,
- A::DigestOutput: Default + AsMut<[u8]>
+ A::DigestOutput: Default + AsMut<[u8]>,
{
type Output = A::DigestOutput;
fn update(&mut self, _input: &[u8]) -> Result<(), Self::Error> {
let input_len = _input.len() as u32;
- let (new_len, carry) = self.controller.ctx_mut().digcnt[0].overflowing_add(input_len as u64);
+ let (new_len, carry) =
+ self.controller.ctx_mut().digcnt[0].overflowing_add(input_len as u64);
self.controller.ctx_mut().digcnt[0] = new_len;
if carry {
@@ -529,7 +180,8 @@ where
return Ok(());
}
- let remaining = (input_len + self.controller.ctx_mut().bufcnt) % self.controller.ctx_mut().block_size;
+ let remaining =
+ (input_len + self.controller.ctx_mut().bufcnt) % self.controller.ctx_mut().block_size;
let total_len = (input_len + self.controller.ctx_mut().bufcnt) - remaining;
let mut i = 0;
@@ -545,7 +197,8 @@ where
if total_len != self.controller.ctx_mut().bufcnt {
self.controller.ctx_mut().sg[i].addr = _input.as_ptr() as u32;
- self.controller.ctx_mut().sg[i].len = (total_len - self.controller.ctx_mut().bufcnt) | HACE_SG_LAST;
+ self.controller.ctx_mut().sg[i].len =
+ (total_len - self.controller.ctx_mut().bufcnt) | HACE_SG_LAST;
}
self.controller.start_hash_operation(total_len);
@@ -556,12 +209,11 @@ where
self.controller.ctx_mut().buffer[..(remaining as usize)]
.copy_from_slice(&_input[src_start..src_end]);
- self.controller.ctx_mut().bufcnt = remaining as u32;
+ self.controller.ctx_mut().bufcnt = remaining;
}
Ok(())
}
-
fn finalize(self) -> Result {
self.controller.fill_padding(0);
let digest_len = self.controller.algo.digest_size();
@@ -577,22 +229,12 @@ where
self.controller.start_hash_operation(bufcnt);
- let slice = unsafe {
- core::slice::from_raw_parts(digest_ptr, digest_len)
- };
+ let slice = unsafe { core::slice::from_raw_parts(digest_ptr, digest_len) };
- let mut output = A::DigestOutput::default();
- output.as_mut()[..digest_len].copy_from_slice(slice);
+ let mut output = A::DigestOutput::default();
+ output.as_mut()[..digest_len].copy_from_slice(slice);
- let ctx = self.controller.ctx_mut();
- ctx.bufcnt = 0;
- ctx.buffer.fill(0);
- ctx.digest.fill(0);
- ctx.digcnt = [0; 2];
-
- unsafe {
- self.controller.hace.hace30().write(|w| w.bits(0));
- }
+ self.controller.cleanup_context();
Ok(output) // Return the final output
}
diff --git a/src/hmac.rs b/src/hmac.rs
new file mode 100644
index 0000000..551a469
--- /dev/null
+++ b/src/hmac.rs
@@ -0,0 +1,249 @@
+use crate::hace_controller::{ContextCleanup, HaceController, HashAlgo, HACE_SG_EN};
+use core::convert::Infallible;
+use proposed_traits::mac::*;
+
+// MacAlgorithm implementation for HashAlgo
+impl MacAlgorithm for HashAlgo {
+ const OUTPUT_BITS: usize = 512; // Maximum size for all variants
+ type MacOutput = [u8; 64]; // Use the maximum size for all variants
+ type Key = [u8; 64]; // Use the maximum size for all variants
+}
+
+pub trait IntoHashAlgo {
+ fn to_hash_algo() -> HashAlgo;
+}
+
+pub struct Digest48(pub [u8; 48]);
+
+impl Default for Digest48 {
+ fn default() -> Self {
+ Digest48([0u8; 48])
+ }
+}
+
+impl AsRef<[u8]> for Digest48 {
+ fn as_ref(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl AsMut<[u8]> for Digest48 {
+ fn as_mut(&mut self) -> &mut [u8] {
+ &mut self.0
+ }
+}
+
+pub struct Digest64(pub [u8; 64]);
+impl Default for Digest64 {
+ fn default() -> Self {
+ Digest64([0u8; 64])
+ }
+}
+
+impl AsRef<[u8]> for Digest64 {
+ fn as_ref(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+impl AsMut<[u8]> for Digest64 {
+ fn as_mut(&mut self) -> &mut [u8] {
+ &mut self.0
+ }
+}
+
+pub struct Sha1;
+pub struct Sha224;
+pub struct Sha256;
+pub struct Sha384;
+pub struct Sha512;
+
+impl MacAlgorithm for Sha1 {
+ const OUTPUT_BITS: usize = 160;
+ type MacOutput = [u8; 20];
+ type Key = [u8; 64];
+}
+
+impl MacAlgorithm for Sha224 {
+ const OUTPUT_BITS: usize = 224;
+ type MacOutput = [u8; 28];
+ type Key = [u8; 64];
+}
+
+impl MacAlgorithm for Sha256 {
+ const OUTPUT_BITS: usize = 256;
+ type MacOutput = [u8; 32];
+ type Key = [u8; 32];
+}
+
+impl MacAlgorithm for Sha384 {
+ const OUTPUT_BITS: usize = 384;
+ type MacOutput = Digest48; // Use Digest48 for 384 bits
+ type Key = [u8; 48];
+}
+
+impl MacAlgorithm for Sha512 {
+ const OUTPUT_BITS: usize = 512;
+ type MacOutput = Digest64; // Use Digest64 for 512 bits
+ type Key = [u8; 64];
+}
+
+impl Default for Sha256 {
+ fn default() -> Self {
+ Sha256
+ }
+}
+
+impl Default for Sha384 {
+ fn default() -> Self {
+ Sha384
+ }
+}
+
+impl Default for Sha512 {
+ fn default() -> Self {
+ Sha512
+ }
+}
+
+impl IntoHashAlgo for Sha256 {
+ fn to_hash_algo() -> HashAlgo {
+ HashAlgo::SHA256
+ }
+}
+
+impl IntoHashAlgo for Sha384 {
+ fn to_hash_algo() -> HashAlgo {
+ HashAlgo::SHA384
+ }
+}
+
+impl IntoHashAlgo for Sha512 {
+ fn to_hash_algo() -> HashAlgo {
+ HashAlgo::SHA512
+ }
+}
+
+impl<'ctrl, A> MacInit for HaceController<'ctrl>
+where
+ A: MacAlgorithm + IntoHashAlgo,
+ A::MacOutput: Default + AsMut<[u8]>,
+ A::Key: AsRef<[u8]>,
+{
+ type OpContext<'a>
+ = OpContextImpl<'a, 'ctrl, A>
+ where
+ Self: 'a; // Define your OpContext type here
+
+ fn init<'a>(&'a mut self, _algo: A, key: &A::Key) -> Result, Self::Error> {
+ self.algo = A::to_hash_algo();
+ self.ctx_mut().method = self.algo.hash_cmd();
+ self.copy_iv_to_digest();
+ self.ctx_mut().block_size = self.algo.block_size() as u32;
+ self.ctx_mut().bufcnt = 0;
+ self.ctx_mut().digcnt = [0; 2];
+ self.ctx_mut().buffer.fill(0);
+ self.ctx_mut().digest.fill(0);
+ self.ctx_mut().ipad.fill(0);
+ self.ctx_mut().opad.fill(0);
+ self.ctx_mut().key.fill(0);
+
+ if key.as_ref().len() > self.ctx_mut().key.len() {
+ // hash key if it is too long
+ self.hash_key(key);
+ } else {
+ self.ctx_mut().key[..key.as_ref().len()].copy_from_slice(key.as_ref());
+ self.ctx_mut().ipad[..key.as_ref().len()].copy_from_slice(key.as_ref());
+ self.ctx_mut().opad[..key.as_ref().len()].copy_from_slice(key.as_ref());
+ self.ctx_mut().key_len = key.as_ref().len() as u32;
+ }
+
+ for i in 0..self.ctx_mut().block_size as usize {
+ self.ctx_mut().ipad[i] ^= 0x36;
+ self.ctx_mut().opad[i] ^= 0x5c;
+ }
+
+ Ok(OpContextImpl {
+ controller: self,
+ _phantom: core::marker::PhantomData,
+ })
+ }
+}
+
+pub struct OpContextImpl<'a, 'ctrl, A: MacAlgorithm + IntoHashAlgo> {
+ pub controller: &'a mut HaceController<'ctrl>,
+ _phantom: core::marker::PhantomData,
+}
+
+impl ErrorType for OpContextImpl<'_, '_, A>
+where
+ A: MacAlgorithm + IntoHashAlgo,
+{
+ type Error = Infallible;
+}
+
+impl MacOp for OpContextImpl<'_, '_, A>
+where
+ A: MacAlgorithm + IntoHashAlgo,
+ A::MacOutput: Default + AsMut<[u8]>,
+{
+ type Output = A::MacOutput;
+
+ fn update(&mut self, input: &[u8]) -> Result<(), Self::Error> {
+ let ctrl = &mut self.controller;
+ let algo = ctrl.algo;
+ let block_size = algo.block_size();
+ let digest_size = algo.digest_size();
+ let mut bufcnt: u32;
+
+ {
+ let ctx = ctrl.ctx_mut();
+ ctx.digcnt[0] = block_size as u64;
+ ctx.bufcnt = block_size as u32;
+
+ // H(ipad + input)
+ let ipad = &ctx.ipad[..block_size];
+ ctx.buffer[..algo.block_size()].copy_from_slice(ipad);
+ ctx.buffer[algo.block_size()..(algo.block_size() + input.len())].copy_from_slice(input);
+ ctx.digcnt[0] += input.len() as u64;
+ ctx.bufcnt += input.len() as u32;
+ ctx.method &= !HACE_SG_EN; // Disable SG mode for key hashing
+ }
+
+ ctrl.fill_padding(0);
+ bufcnt = ctrl.ctx_mut().bufcnt;
+ ctrl.copy_iv_to_digest();
+ ctrl.start_hash_operation(bufcnt);
+ let slice =
+ unsafe { core::slice::from_raw_parts(ctrl.ctx_mut().digest.as_ptr(), digest_size) };
+
+ // H(opad + H(opad + hash sum))
+ {
+ let ctx = ctrl.ctx_mut();
+ ctx.digcnt[0] = block_size as u64 + digest_size as u64;
+ ctx.bufcnt = block_size as u32 + digest_size as u32;
+ ctx.buffer[..block_size].copy_from_slice(&ctx.opad[..block_size]);
+ ctx.buffer[block_size..(block_size + digest_size)].copy_from_slice(slice);
+ }
+ ctrl.fill_padding(0);
+ bufcnt = ctrl.ctx_mut().bufcnt;
+ ctrl.copy_iv_to_digest();
+ ctrl.start_hash_operation(bufcnt);
+
+ Ok(())
+ }
+
+ fn finalize(self) -> Result {
+ let digest_size = self.controller.algo.digest_size();
+ let ctx = self.controller.ctx_mut();
+
+ let slice = unsafe { core::slice::from_raw_parts(ctx.digest.as_ptr(), digest_size) };
+
+ let mut output = A::MacOutput::default();
+ output.as_mut()[..digest_size].copy_from_slice(slice);
+
+ self.controller.cleanup_context();
+
+ Ok(output) // Return the final output
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8e5f1cc..a569022 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,9 @@
#![no_std]
pub mod uart;
pub mod watchdog;
+pub mod hace_controller;
pub mod hash;
+pub mod hmac;
pub mod ecdsa;
pub mod rsa;
pub mod tests;
diff --git a/src/main.rs b/src/main.rs
index 3c255f2..ebdd1dc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,12 +9,13 @@ use ast1060_pac::{Wdt, Wdt1};
use aspeed_ddk::watchdog::WdtController;
use fugit::MillisDurationU32 as MilliSeconds;
-use aspeed_ddk::hash::Controller;
+use aspeed_ddk::hace_controller::HaceController;
use aspeed_ddk::syscon::SysCon;
use aspeed_ddk::ecdsa::AspeedEcdsa;
use aspeed_ddk::rsa::AspeedRsa;
use aspeed_ddk::tests::functional::hash_test::run_hash_tests;
+use aspeed_ddk::tests::functional::hmac_test::run_hmac_tests;
use aspeed_ddk::tests::functional::ecdsa_test::run_ecdsa_tests;
use aspeed_ddk::tests::functional::rsa_test::run_rsa_tests;
use panic_halt as _;
@@ -135,9 +136,9 @@ fn main() -> ! {
let mut syscon = SysCon::new(delay.clone(), scu);
syscon.enable_hace();
- let mut hace_controller = Controller::new(hace);
-
+ let mut hace_controller = HaceController::new(&hace);
run_hash_tests(&mut uart_controller, &mut hace_controller);
+ run_hmac_tests(&mut uart_controller, &mut hace_controller);
// Enable RSA and ECC
syscon.enable_rsa_ecc();
diff --git a/src/tests/functional/hash_test.rs b/src/tests/functional/hash_test.rs
index f72ba5c..17f6c27 100644
--- a/src/tests/functional/hash_test.rs
+++ b/src/tests/functional/hash_test.rs
@@ -1,9 +1,9 @@
+use crate::hace_controller::HaceController;
+use crate::hash::{IntoHashAlgo, Sha256, Sha384, Sha512};
use crate::uart::UartController;
-use crate::hash::{Sha256, Sha384, Sha512, Controller, IntoHashAlgo};
-use proposed_traits::digest::{DigestInit, DigestOp, DigestAlgorithm};
+use core::any::TypeId;
use embedded_io::Write;
-
-
+use proposed_traits::digest::{DigestAlgorithm, DigestInit, DigestOp};
fn print_hex_array(uart: &mut UartController, data: &[u8], bytes_per_line: usize) {
for (i, b) in data.iter().enumerate() {
@@ -36,7 +36,7 @@ fn print_input(uart: &mut UartController, algo: &str, input: &[u8]) {
writeln!(uart, "]:").unwrap();
}
-pub fn run_hash_tests(uart: &mut UartController, hace: &mut Controller) {
+pub fn run_hash_tests(uart: &mut UartController, hace: &mut HaceController) {
let input = *b"hello_world";
run_hash::(uart, hace, &input);
@@ -44,9 +44,9 @@ pub fn run_hash_tests(uart: &mut UartController, hace: &mut Controller) {
run_hash::(uart, hace, &input);
}
-fn run_hash(uart: &mut UartController, ctrl: &mut Controller, input: &[u8])
+fn run_hash(uart: &mut UartController, ctrl: &mut HaceController, input: &[u8])
where
- A: DigestAlgorithm + IntoHashAlgo + Default,
+ A: DigestAlgorithm + IntoHashAlgo + Default + 'static,
A::DigestOutput: Default + AsRef<[u8]> + AsMut<[u8]>,
{
let mut ctx = ctrl.init(A::default()).unwrap();
@@ -54,5 +54,57 @@ where
let output = ctx.finalize().unwrap();
print_input(uart, core::any::type_name::(), input);
+ writeln!(uart, "\r\nOutput:").unwrap();
print_hex_array(uart, output.as_ref(), 16);
+
+ let expected = if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ // Expected SHA-256 hash of "hello_world"
+ 0x35, 0x07, 0x2c, 0x1a, 0xe5, 0x46, 0x35, 0x0e, 0x0b, 0xfa, 0x7a, 0xb1, 0x1d, 0x49,
+ 0xdc, 0x6f, 0x12, 0x9e, 0x72, 0xcc, 0xd5, 0x7e, 0xc7, 0xeb, 0x67, 0x12, 0x25, 0xbb,
+ 0xd1, 0x97, 0xc8, 0xf1,
+ ][..],
+ )
+ } else if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ 0x7f, 0x25, 0x1a, 0x65, 0xac, 0xbe, 0x92, 0xaf, 0x4c, 0x6a, 0x6d, 0x62, 0x4c, 0x08,
+ 0x60, 0xd9, 0xbe, 0x77, 0x32, 0x9e, 0x10, 0xe5, 0xbe, 0xb3, 0xb9, 0x59, 0x4f, 0x79,
+ 0x16, 0x12, 0x8c, 0xd9, 0x56, 0x10, 0xa4, 0xd8, 0x4e, 0x3a, 0x83, 0xa2, 0x4a, 0x72,
+ 0x36, 0x2f, 0x6c, 0x8f, 0x9c, 0x46,
+ ][..],
+ )
+ } else if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ 0x94, 0xf4, 0x27, 0xef, 0xef, 0xa7, 0x4c, 0x12, 0x30, 0xc3, 0xe9, 0x3c, 0x35, 0x10,
+ 0x4d, 0xcb, 0xaa, 0x8f, 0xf7, 0x1b, 0xa4, 0x53, 0x75, 0x83, 0xed, 0x83, 0xc0, 0x44,
+ 0x9d, 0x60, 0x7c, 0x4e, 0x61, 0xb3, 0x9c, 0x4c, 0x5e, 0xea, 0x55, 0x43, 0xe0, 0x1d,
+ 0x76, 0xa6, 0x8e, 0x22, 0x3d, 0xa0, 0x2b, 0x50, 0x05, 0x30, 0xa8, 0x21, 0x56, 0x62,
+ 0x5c, 0xb9, 0x6e, 0xe8, 0xc8, 0xc8, 0x0a, 0x85,
+ ][..],
+ )
+ } else {
+ None
+ };
+
+ if let Some(expected) = expected {
+ if output.as_ref() == expected {
+ writeln!(uart, "\r\n{}: Test passed!", core::any::type_name::()).unwrap();
+ } else {
+ writeln!(uart, "\r\n{}: Test failed!", core::any::type_name::()).unwrap();
+ writeln!(uart, "Expected:").unwrap();
+ print_hex_array(uart, expected, 16);
+ writeln!(uart, "Got:").unwrap();
+ print_hex_array(uart, output.as_ref(), 16);
+ }
+ } else {
+ writeln!(
+ uart,
+ "\r\n{}: No expected value defined.",
+ core::any::type_name::()
+ )
+ .unwrap();
+ }
}
diff --git a/src/tests/functional/hmac_test.rs b/src/tests/functional/hmac_test.rs
new file mode 100644
index 0000000..ecb51e0
--- /dev/null
+++ b/src/tests/functional/hmac_test.rs
@@ -0,0 +1,116 @@
+use crate::hace_controller::HaceController;
+use crate::hmac::{IntoHashAlgo, Sha256, Sha384, Sha512};
+use crate::uart::UartController;
+use core::any::TypeId;
+use embedded_io::Write;
+use proposed_traits::mac::{MacAlgorithm, MacInit, MacOp};
+
+fn print_hex_array(uart: &mut UartController, data: &[u8], bytes_per_line: usize) {
+ for (i, b) in data.iter().enumerate() {
+ if i % bytes_per_line == 0 {
+ writeln!(uart, "\r").unwrap();
+ } else {
+ write!(uart, " ").unwrap();
+ }
+ write!(uart, "{:02x}", b).unwrap();
+ }
+ writeln!(uart).unwrap();
+}
+
+fn print_input(uart: &mut UartController, algo: &str, input: &[u8]) {
+ match core::str::from_utf8(input) {
+ Ok(ascii) => {
+ write!(uart, "\r\n{} of \"{}\" [", algo, ascii).unwrap();
+ }
+ Err(_) => {
+ write!(uart, "\r\n{} of [", algo).unwrap();
+ }
+ }
+
+ for (i, b) in input.iter().enumerate() {
+ if i > 0 {
+ write!(uart, ", ").unwrap();
+ }
+ write!(uart, "0x{:02x}", b).unwrap();
+ }
+ writeln!(uart, "]:").unwrap();
+}
+
+pub fn run_hmac_tests(uart: &mut UartController, hace: &mut HaceController) {
+ let key256 = [0xb; 32];
+ let key384 = [0xb; 48];
+ let key512 = [0xb; 64];
+ let message = *b"The quick brown fox jumps over the lazy dog";
+
+ writeln!(uart, "\r\nRunning HMAC tests...").unwrap();
+ run_hmac::(uart, hace, &key256, &message);
+ run_hmac::(uart, hace, &key384, &message);
+ run_hmac::(uart, hace, &key512, &message);
+}
+
+fn run_hmac(uart: &mut UartController, ctrl: &mut HaceController, key: &A::Key, input: &[u8])
+where
+ A: MacAlgorithm + IntoHashAlgo + Default + 'static,
+ A::MacOutput: Default + AsRef<[u8]> + AsMut<[u8]>,
+ A::Key: AsRef<[u8]>,
+{
+ let mut ctx = ctrl.init(A::default(), key).unwrap();
+ ctx.update(input).unwrap();
+ let output = ctx.finalize().unwrap();
+
+ print_input(uart, core::any::type_name::(), input);
+ write!(uart, "\r\nKey: ").unwrap();
+ print_hex_array(uart, key.as_ref(), 16);
+ write!(uart, "\r\nOutput: ").unwrap();
+ print_hex_array(uart, output.as_ref(), 16);
+
+ let expected = if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ 0xde, 0x60, 0xb1, 0xd4, 0x83, 0xd2, 0x00, 0x11, 0xf1, 0xb4, 0x2f, 0x33, 0x70, 0x0c,
+ 0xb4, 0x4f, 0xa3, 0x16, 0xc4, 0x43, 0xce, 0x43, 0x03, 0x78, 0xcb, 0x5d, 0x65, 0x42,
+ 0x7f, 0x64, 0x34, 0x8d,
+ ][..],
+ )
+ } else if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ 0xCC, 0xD7, 0xCA, 0xE4, 0x59, 0xE4, 0x23, 0xB9, 0x94, 0x06, 0x9A, 0xC1, 0xD3, 0xF8,
+ 0x26, 0x41, 0x60, 0x88, 0x85, 0xAF, 0x04, 0x3A, 0x33, 0xAD, 0x51, 0x3E, 0x8E, 0x87,
+ 0x47, 0x19, 0x66, 0x6C, 0x24, 0xD1, 0xC0, 0xDC, 0x54, 0xAE, 0xBB, 0xB9, 0x3B, 0x84,
+ 0x34, 0xA1, 0xA9, 0x70, 0x83, 0x6D,
+ ][..],
+ )
+ } else if TypeId::of::() == TypeId::of::() {
+ Some(
+ &[
+ 0xf1, 0x10, 0x1d, 0xe2, 0xb4, 0xfa, 0x09, 0xe6, 0xfb, 0x04, 0x9d, 0x2e, 0x12, 0x68,
+ 0xdb, 0xe7, 0x65, 0x09, 0x22, 0x01, 0x75, 0x1a, 0x42, 0x1c, 0xbc, 0x80, 0x61, 0x09,
+ 0x36, 0x14, 0x35, 0x81, 0x22, 0x0f, 0x3a, 0x77, 0x1f, 0xff, 0x10, 0xd8, 0xd8, 0x16,
+ 0x63, 0x19, 0xb6, 0x0d, 0xf0, 0x98, 0xb3, 0x70, 0xdc, 0x5d, 0x1b, 0x01, 0x71, 0x4d,
+ 0x97, 0x87, 0x12, 0x72, 0x24, 0x60, 0x67, 0x4f,
+ ][..],
+ )
+ } else {
+ None
+ };
+
+ if let Some(expected) = expected {
+ if output.as_ref() == expected {
+ writeln!(uart, "\r\n{}: Test passed!", core::any::type_name::()).unwrap();
+ } else {
+ writeln!(uart, "\r\n{}: Test failed!", core::any::type_name::()).unwrap();
+ writeln!(uart, "Expected:").unwrap();
+ print_hex_array(uart, expected, 16);
+ writeln!(uart, "Got:").unwrap();
+ print_hex_array(uart, output.as_ref(), 16);
+ }
+ } else {
+ writeln!(
+ uart,
+ "\r\n{}: No expected value defined.",
+ core::any::type_name::()
+ )
+ .unwrap();
+ }
+}
diff --git a/src/tests/functional/mod.rs b/src/tests/functional/mod.rs
index 5797d29..0d52514 100644
--- a/src/tests/functional/mod.rs
+++ b/src/tests/functional/mod.rs
@@ -1,4 +1,5 @@
pub mod hash_test;
+pub mod hmac_test;
pub mod ecdsa_test;
pub mod rsa_test;
pub mod rsa_test_vec;