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;