Skip to content

Commit 40eb74a

Browse files
Merge pull request #18 from stevenlee7189/hmac_impl
hmac: introduce hmac driver
2 parents 2f67ae5 + 9e4f526 commit 40eb74a

File tree

8 files changed

+876
-401
lines changed

8 files changed

+876
-401
lines changed

src/hace_controller.rs

Lines changed: 412 additions & 0 deletions
Large diffs are not rendered by default.

src/hash.rs

Lines changed: 33 additions & 391 deletions
Large diffs are not rendered by default.

src/hmac.rs

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
use crate::hace_controller::{ContextCleanup, HaceController, HashAlgo, HACE_SG_EN};
2+
use core::convert::Infallible;
3+
use proposed_traits::mac::*;
4+
5+
// MacAlgorithm implementation for HashAlgo
6+
impl MacAlgorithm for HashAlgo {
7+
const OUTPUT_BITS: usize = 512; // Maximum size for all variants
8+
type MacOutput = [u8; 64]; // Use the maximum size for all variants
9+
type Key = [u8; 64]; // Use the maximum size for all variants
10+
}
11+
12+
pub trait IntoHashAlgo {
13+
fn to_hash_algo() -> HashAlgo;
14+
}
15+
16+
pub struct Digest48(pub [u8; 48]);
17+
18+
impl Default for Digest48 {
19+
fn default() -> Self {
20+
Digest48([0u8; 48])
21+
}
22+
}
23+
24+
impl AsRef<[u8]> for Digest48 {
25+
fn as_ref(&self) -> &[u8] {
26+
&self.0
27+
}
28+
}
29+
30+
impl AsMut<[u8]> for Digest48 {
31+
fn as_mut(&mut self) -> &mut [u8] {
32+
&mut self.0
33+
}
34+
}
35+
36+
pub struct Digest64(pub [u8; 64]);
37+
impl Default for Digest64 {
38+
fn default() -> Self {
39+
Digest64([0u8; 64])
40+
}
41+
}
42+
43+
impl AsRef<[u8]> for Digest64 {
44+
fn as_ref(&self) -> &[u8] {
45+
&self.0
46+
}
47+
}
48+
49+
impl AsMut<[u8]> for Digest64 {
50+
fn as_mut(&mut self) -> &mut [u8] {
51+
&mut self.0
52+
}
53+
}
54+
55+
pub struct Sha1;
56+
pub struct Sha224;
57+
pub struct Sha256;
58+
pub struct Sha384;
59+
pub struct Sha512;
60+
61+
impl MacAlgorithm for Sha1 {
62+
const OUTPUT_BITS: usize = 160;
63+
type MacOutput = [u8; 20];
64+
type Key = [u8; 64];
65+
}
66+
67+
impl MacAlgorithm for Sha224 {
68+
const OUTPUT_BITS: usize = 224;
69+
type MacOutput = [u8; 28];
70+
type Key = [u8; 64];
71+
}
72+
73+
impl MacAlgorithm for Sha256 {
74+
const OUTPUT_BITS: usize = 256;
75+
type MacOutput = [u8; 32];
76+
type Key = [u8; 32];
77+
}
78+
79+
impl MacAlgorithm for Sha384 {
80+
const OUTPUT_BITS: usize = 384;
81+
type MacOutput = Digest48; // Use Digest48 for 384 bits
82+
type Key = [u8; 48];
83+
}
84+
85+
impl MacAlgorithm for Sha512 {
86+
const OUTPUT_BITS: usize = 512;
87+
type MacOutput = Digest64; // Use Digest64 for 512 bits
88+
type Key = [u8; 64];
89+
}
90+
91+
impl Default for Sha256 {
92+
fn default() -> Self {
93+
Sha256
94+
}
95+
}
96+
97+
impl Default for Sha384 {
98+
fn default() -> Self {
99+
Sha384
100+
}
101+
}
102+
103+
impl Default for Sha512 {
104+
fn default() -> Self {
105+
Sha512
106+
}
107+
}
108+
109+
impl IntoHashAlgo for Sha256 {
110+
fn to_hash_algo() -> HashAlgo {
111+
HashAlgo::SHA256
112+
}
113+
}
114+
115+
impl IntoHashAlgo for Sha384 {
116+
fn to_hash_algo() -> HashAlgo {
117+
HashAlgo::SHA384
118+
}
119+
}
120+
121+
impl IntoHashAlgo for Sha512 {
122+
fn to_hash_algo() -> HashAlgo {
123+
HashAlgo::SHA512
124+
}
125+
}
126+
127+
impl<'ctrl, A> MacInit<A> for HaceController<'ctrl>
128+
where
129+
A: MacAlgorithm + IntoHashAlgo,
130+
A::MacOutput: Default + AsMut<[u8]>,
131+
A::Key: AsRef<[u8]>,
132+
{
133+
type OpContext<'a>
134+
= OpContextImpl<'a, 'ctrl, A>
135+
where
136+
Self: 'a; // Define your OpContext type here
137+
138+
fn init<'a>(&'a mut self, _algo: A, key: &A::Key) -> Result<Self::OpContext<'a>, Self::Error> {
139+
self.algo = A::to_hash_algo();
140+
self.ctx_mut().method = self.algo.hash_cmd();
141+
self.copy_iv_to_digest();
142+
self.ctx_mut().block_size = self.algo.block_size() as u32;
143+
self.ctx_mut().bufcnt = 0;
144+
self.ctx_mut().digcnt = [0; 2];
145+
self.ctx_mut().buffer.fill(0);
146+
self.ctx_mut().digest.fill(0);
147+
self.ctx_mut().ipad.fill(0);
148+
self.ctx_mut().opad.fill(0);
149+
self.ctx_mut().key.fill(0);
150+
151+
if key.as_ref().len() > self.ctx_mut().key.len() {
152+
// hash key if it is too long
153+
self.hash_key(key);
154+
} else {
155+
self.ctx_mut().key[..key.as_ref().len()].copy_from_slice(key.as_ref());
156+
self.ctx_mut().ipad[..key.as_ref().len()].copy_from_slice(key.as_ref());
157+
self.ctx_mut().opad[..key.as_ref().len()].copy_from_slice(key.as_ref());
158+
self.ctx_mut().key_len = key.as_ref().len() as u32;
159+
}
160+
161+
for i in 0..self.ctx_mut().block_size as usize {
162+
self.ctx_mut().ipad[i] ^= 0x36;
163+
self.ctx_mut().opad[i] ^= 0x5c;
164+
}
165+
166+
Ok(OpContextImpl {
167+
controller: self,
168+
_phantom: core::marker::PhantomData,
169+
})
170+
}
171+
}
172+
173+
pub struct OpContextImpl<'a, 'ctrl, A: MacAlgorithm + IntoHashAlgo> {
174+
pub controller: &'a mut HaceController<'ctrl>,
175+
_phantom: core::marker::PhantomData<A>,
176+
}
177+
178+
impl<A> ErrorType for OpContextImpl<'_, '_, A>
179+
where
180+
A: MacAlgorithm + IntoHashAlgo,
181+
{
182+
type Error = Infallible;
183+
}
184+
185+
impl<A> MacOp for OpContextImpl<'_, '_, A>
186+
where
187+
A: MacAlgorithm + IntoHashAlgo,
188+
A::MacOutput: Default + AsMut<[u8]>,
189+
{
190+
type Output = A::MacOutput;
191+
192+
fn update(&mut self, input: &[u8]) -> Result<(), Self::Error> {
193+
let ctrl = &mut self.controller;
194+
let algo = ctrl.algo;
195+
let block_size = algo.block_size();
196+
let digest_size = algo.digest_size();
197+
let mut bufcnt: u32;
198+
199+
{
200+
let ctx = ctrl.ctx_mut();
201+
ctx.digcnt[0] = block_size as u64;
202+
ctx.bufcnt = block_size as u32;
203+
204+
// H(ipad + input)
205+
let ipad = &ctx.ipad[..block_size];
206+
ctx.buffer[..algo.block_size()].copy_from_slice(ipad);
207+
ctx.buffer[algo.block_size()..(algo.block_size() + input.len())].copy_from_slice(input);
208+
ctx.digcnt[0] += input.len() as u64;
209+
ctx.bufcnt += input.len() as u32;
210+
ctx.method &= !HACE_SG_EN; // Disable SG mode for key hashing
211+
}
212+
213+
ctrl.fill_padding(0);
214+
bufcnt = ctrl.ctx_mut().bufcnt;
215+
ctrl.copy_iv_to_digest();
216+
ctrl.start_hash_operation(bufcnt);
217+
let slice =
218+
unsafe { core::slice::from_raw_parts(ctrl.ctx_mut().digest.as_ptr(), digest_size) };
219+
220+
// H(opad + H(opad + hash sum))
221+
{
222+
let ctx = ctrl.ctx_mut();
223+
ctx.digcnt[0] = block_size as u64 + digest_size as u64;
224+
ctx.bufcnt = block_size as u32 + digest_size as u32;
225+
ctx.buffer[..block_size].copy_from_slice(&ctx.opad[..block_size]);
226+
ctx.buffer[block_size..(block_size + digest_size)].copy_from_slice(slice);
227+
}
228+
ctrl.fill_padding(0);
229+
bufcnt = ctrl.ctx_mut().bufcnt;
230+
ctrl.copy_iv_to_digest();
231+
ctrl.start_hash_operation(bufcnt);
232+
233+
Ok(())
234+
}
235+
236+
fn finalize(self) -> Result<Self::Output, Self::Error> {
237+
let digest_size = self.controller.algo.digest_size();
238+
let ctx = self.controller.ctx_mut();
239+
240+
let slice = unsafe { core::slice::from_raw_parts(ctx.digest.as_ptr(), digest_size) };
241+
242+
let mut output = A::MacOutput::default();
243+
output.as_mut()[..digest_size].copy_from_slice(slice);
244+
245+
self.controller.cleanup_context();
246+
247+
Ok(output) // Return the final output
248+
}
249+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![no_std]
22
pub mod uart;
33
pub mod watchdog;
4+
pub mod hace_controller;
45
pub mod hash;
6+
pub mod hmac;
57
pub mod ecdsa;
68
pub mod rsa;
79
pub mod tests;

src/main.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ use ast1060_pac::{Wdt, Wdt1};
99
use aspeed_ddk::watchdog::WdtController;
1010

1111
use fugit::MillisDurationU32 as MilliSeconds;
12-
use aspeed_ddk::hash::Controller;
12+
use aspeed_ddk::hace_controller::HaceController;
1313
use aspeed_ddk::syscon::SysCon;
1414
use aspeed_ddk::ecdsa::AspeedEcdsa;
1515
use aspeed_ddk::rsa::AspeedRsa;
1616

1717
use aspeed_ddk::tests::functional::hash_test::run_hash_tests;
18+
use aspeed_ddk::tests::functional::hmac_test::run_hmac_tests;
1819
use aspeed_ddk::tests::functional::ecdsa_test::run_ecdsa_tests;
1920
use aspeed_ddk::tests::functional::rsa_test::run_rsa_tests;
2021
use panic_halt as _;
@@ -135,9 +136,9 @@ fn main() -> ! {
135136
let mut syscon = SysCon::new(delay.clone(), scu);
136137
syscon.enable_hace();
137138

138-
let mut hace_controller = Controller::new(hace);
139-
139+
let mut hace_controller = HaceController::new(&hace);
140140
run_hash_tests(&mut uart_controller, &mut hace_controller);
141+
run_hmac_tests(&mut uart_controller, &mut hace_controller);
141142

142143
// Enable RSA and ECC
143144
syscon.enable_rsa_ecc();

src/tests/functional/hash_test.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
use crate::hace_controller::HaceController;
2+
use crate::hash::{IntoHashAlgo, Sha256, Sha384, Sha512};
13
use crate::uart::UartController;
2-
use crate::hash::{Sha256, Sha384, Sha512, Controller, IntoHashAlgo};
3-
use proposed_traits::digest::{DigestInit, DigestOp, DigestAlgorithm};
4+
use core::any::TypeId;
45
use embedded_io::Write;
5-
6-
6+
use proposed_traits::digest::{DigestAlgorithm, DigestInit, DigestOp};
77

88
fn print_hex_array(uart: &mut UartController, data: &[u8], bytes_per_line: usize) {
99
for (i, b) in data.iter().enumerate() {
@@ -36,23 +36,75 @@ fn print_input(uart: &mut UartController, algo: &str, input: &[u8]) {
3636
writeln!(uart, "]:").unwrap();
3737
}
3838

39-
pub fn run_hash_tests(uart: &mut UartController, hace: &mut Controller) {
39+
pub fn run_hash_tests(uart: &mut UartController, hace: &mut HaceController) {
4040
let input = *b"hello_world";
4141

4242
run_hash::<Sha256>(uart, hace, &input);
4343
run_hash::<Sha384>(uart, hace, &input);
4444
run_hash::<Sha512>(uart, hace, &input);
4545
}
4646

47-
fn run_hash<A>(uart: &mut UartController, ctrl: &mut Controller, input: &[u8])
47+
fn run_hash<A>(uart: &mut UartController, ctrl: &mut HaceController, input: &[u8])
4848
where
49-
A: DigestAlgorithm + IntoHashAlgo + Default,
49+
A: DigestAlgorithm + IntoHashAlgo + Default + 'static,
5050
A::DigestOutput: Default + AsRef<[u8]> + AsMut<[u8]>,
5151
{
5252
let mut ctx = ctrl.init(A::default()).unwrap();
5353
ctx.update(input).unwrap();
5454
let output = ctx.finalize().unwrap();
5555

5656
print_input(uart, core::any::type_name::<A>(), input);
57+
writeln!(uart, "\r\nOutput:").unwrap();
5758
print_hex_array(uart, output.as_ref(), 16);
59+
60+
let expected = if TypeId::of::<A>() == TypeId::of::<Sha256>() {
61+
Some(
62+
&[
63+
// Expected SHA-256 hash of "hello_world"
64+
0x35, 0x07, 0x2c, 0x1a, 0xe5, 0x46, 0x35, 0x0e, 0x0b, 0xfa, 0x7a, 0xb1, 0x1d, 0x49,
65+
0xdc, 0x6f, 0x12, 0x9e, 0x72, 0xcc, 0xd5, 0x7e, 0xc7, 0xeb, 0x67, 0x12, 0x25, 0xbb,
66+
0xd1, 0x97, 0xc8, 0xf1,
67+
][..],
68+
)
69+
} else if TypeId::of::<A>() == TypeId::of::<Sha384>() {
70+
Some(
71+
&[
72+
0x7f, 0x25, 0x1a, 0x65, 0xac, 0xbe, 0x92, 0xaf, 0x4c, 0x6a, 0x6d, 0x62, 0x4c, 0x08,
73+
0x60, 0xd9, 0xbe, 0x77, 0x32, 0x9e, 0x10, 0xe5, 0xbe, 0xb3, 0xb9, 0x59, 0x4f, 0x79,
74+
0x16, 0x12, 0x8c, 0xd9, 0x56, 0x10, 0xa4, 0xd8, 0x4e, 0x3a, 0x83, 0xa2, 0x4a, 0x72,
75+
0x36, 0x2f, 0x6c, 0x8f, 0x9c, 0x46,
76+
][..],
77+
)
78+
} else if TypeId::of::<A>() == TypeId::of::<Sha512>() {
79+
Some(
80+
&[
81+
0x94, 0xf4, 0x27, 0xef, 0xef, 0xa7, 0x4c, 0x12, 0x30, 0xc3, 0xe9, 0x3c, 0x35, 0x10,
82+
0x4d, 0xcb, 0xaa, 0x8f, 0xf7, 0x1b, 0xa4, 0x53, 0x75, 0x83, 0xed, 0x83, 0xc0, 0x44,
83+
0x9d, 0x60, 0x7c, 0x4e, 0x61, 0xb3, 0x9c, 0x4c, 0x5e, 0xea, 0x55, 0x43, 0xe0, 0x1d,
84+
0x76, 0xa6, 0x8e, 0x22, 0x3d, 0xa0, 0x2b, 0x50, 0x05, 0x30, 0xa8, 0x21, 0x56, 0x62,
85+
0x5c, 0xb9, 0x6e, 0xe8, 0xc8, 0xc8, 0x0a, 0x85,
86+
][..],
87+
)
88+
} else {
89+
None
90+
};
91+
92+
if let Some(expected) = expected {
93+
if output.as_ref() == expected {
94+
writeln!(uart, "\r\n{}: Test passed!", core::any::type_name::<A>()).unwrap();
95+
} else {
96+
writeln!(uart, "\r\n{}: Test failed!", core::any::type_name::<A>()).unwrap();
97+
writeln!(uart, "Expected:").unwrap();
98+
print_hex_array(uart, expected, 16);
99+
writeln!(uart, "Got:").unwrap();
100+
print_hex_array(uart, output.as_ref(), 16);
101+
}
102+
} else {
103+
writeln!(
104+
uart,
105+
"\r\n{}: No expected value defined.",
106+
core::any::type_name::<A>()
107+
)
108+
.unwrap();
109+
}
58110
}

0 commit comments

Comments
 (0)