1use core::cell::Cell;
8use core::ops::Index;
9use kernel::hil;
10use kernel::hil::digest::{self, DigestData, DigestHash};
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::leasable_buffer::SubSlice;
13use kernel::utilities::leasable_buffer::SubSliceMut;
14use kernel::utilities::leasable_buffer::SubSliceMutImmut;
15use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
16use kernel::utilities::registers::{
17 register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
18};
19use kernel::utilities::StaticRef;
20use kernel::ErrorCode;
21
22register_structs! {
23 pub HmacRegisters {
24 (0x00 => intr_state: ReadWrite<u32, INTR_STATE::Register>),
25 (0x04 => intr_enable: ReadWrite<u32, INTR_ENABLE::Register>),
26 (0x08 => intr_test: ReadWrite<u32, INTR_TEST::Register>),
27 (0x0C => alert_test: ReadWrite<u32>),
28 (0x10 => cfg: ReadWrite<u32, CFG::Register>),
29 (0x14 => cmd: ReadWrite<u32, CMD::Register>),
30 (0x18 => status: ReadOnly<u32, STATUS::Register>),
31 (0x1C => err_code: ReadOnly<u32>),
32 (0x20 => wipe_secret: WriteOnly<u32>),
33 (0x24 => key: [WriteOnly<u32>; 8]),
34 (0x44 => digest: [ReadOnly<u32>; 8]),
35 (0x64 => msg_length_lower: ReadOnly<u32>),
36 (0x68 => msg_length_upper: ReadOnly<u32>),
37 (0x6C => _reserved0),
38 (0x800 => msg_fifo: WriteOnly<u32>),
39 (0x804 => msg_fifo_8: WriteOnly<u8>),
40 (0x805 => _reserved1),
41 (0x808 => @END),
42 }
43}
44
45register_bitfields![u32,
46 INTR_STATE [
47 HMAC_DONE OFFSET(0) NUMBITS(1) [],
48 FIFO_EMPTY OFFSET(1) NUMBITS(1) [],
49 HMAC_ERR OFFSET(2) NUMBITS(1) []
50 ],
51 INTR_ENABLE [
52 HMAC_DONE OFFSET(0) NUMBITS(1) [],
53 FIFO_EMPTY OFFSET(1) NUMBITS(1) [],
54 HMAC_ERR OFFSET(2) NUMBITS(1) []
55 ],
56 INTR_TEST [
57 HMAC_DONE OFFSET(0) NUMBITS(1) [],
58 FIFO_EMPTY OFFSET(1) NUMBITS(1) [],
59 HMAC_ERR OFFSET(2) NUMBITS(1) []
60 ],
61 CFG [
62 HMAC_EN OFFSET(0) NUMBITS(1) [],
63 SHA_EN OFFSET(1) NUMBITS(1) [],
64 ENDIAN_SWAP OFFSET(2) NUMBITS(1) [],
65 DIGEST_SWAP OFFSET(3) NUMBITS(1) []
66 ],
67 CMD [
68 START OFFSET(0) NUMBITS(1) [],
69 PROCESS OFFSET(1) NUMBITS(1) []
70 ],
71 STATUS [
72 FIFO_EMPTY OFFSET(0) NUMBITS(1) [],
73 FIFO_FULL OFFSET(1) NUMBITS(1) [],
74 FIFO_DEPTH OFFSET(4) NUMBITS(5) []
75 ]
76];
77
78pub struct Hmac<'a> {
79 registers: StaticRef<HmacRegisters>,
80 client: OptionalCell<&'a dyn hil::digest::Client<32>>,
81 data: Cell<Option<SubSliceMutImmut<'static, u8>>>,
82 verify: Cell<bool>,
83 digest: Cell<Option<&'static mut [u8; 32]>>,
84 cancelled: Cell<bool>,
85 busy: Cell<bool>,
86}
87
88impl Hmac<'_> {
89 pub fn new(base: StaticRef<HmacRegisters>) -> Self {
90 Hmac {
91 registers: base,
92 client: OptionalCell::empty(),
93 data: Cell::new(None),
94 verify: Cell::new(false),
95 digest: Cell::new(None),
96 cancelled: Cell::new(false),
97 busy: Cell::new(false),
98 }
99 }
100
101 fn process(&self, data: &dyn Index<usize, Output = u8>, count: usize) -> usize {
102 let regs = self.registers;
103 for i in 0..(count / 4) {
104 if regs.status.is_set(STATUS::FIFO_FULL) {
105 return i * 4;
106 }
107
108 let data_idx = i * 4;
109
110 let mut d = (data[data_idx + 3] as u32) << 0;
111 d |= (data[data_idx + 2] as u32) << 8;
112 d |= (data[data_idx + 1] as u32) << 16;
113 d |= (data[data_idx + 0] as u32) << 24;
114
115 regs.msg_fifo.set(d);
116 }
117
118 if (count % 4) != 0 {
119 for i in 0..(count % 4) {
120 let data_idx = (count - (count % 4)) + i;
121 regs.msg_fifo_8.set(data[data_idx]);
122 }
123 }
124 count
125 }
126
127 fn data_progress(&self) -> bool {
130 self.data.take().is_some_and(|buf| match buf {
131 SubSliceMutImmut::Immutable(mut b) => {
132 if b.len() == 0 {
133 self.data.set(Some(SubSliceMutImmut::Immutable(b)));
134 false
135 } else {
136 let count = self.process(&b, b.len());
137 b.slice(count..);
138 self.data.set(Some(SubSliceMutImmut::Immutable(b)));
139 true
140 }
141 }
142 SubSliceMutImmut::Mutable(mut b) => {
143 if b.len() == 0 {
144 self.data.set(Some(SubSliceMutImmut::Mutable(b)));
145 false
146 } else {
147 let count = self.process(&b, b.len());
148 b.slice(count..);
149 self.data.set(Some(SubSliceMutImmut::Mutable(b)));
150 true
151 }
152 }
153 })
154 }
155
156 pub fn handle_interrupt(&self) {
157 let regs = self.registers;
158 let intrs = regs.intr_state.extract();
159 regs.intr_enable.modify(
160 INTR_ENABLE::HMAC_DONE::CLEAR
161 + INTR_ENABLE::FIFO_EMPTY::CLEAR
162 + INTR_ENABLE::HMAC_ERR::CLEAR,
163 );
164 self.busy.set(false);
165 if intrs.is_set(INTR_STATE::HMAC_DONE) {
166 self.client.map(|client| {
167 let digest = self.digest.take().unwrap();
168
169 regs.intr_state.modify(INTR_STATE::HMAC_DONE::SET);
170
171 if self.verify.get() {
172 let mut equal = true;
173
174 for i in 0..8 {
175 let d = regs.digest[i].get().to_ne_bytes();
176
177 let idx = i * 4;
178
179 if digest[idx + 0] != d[0]
180 || digest[idx + 1] != d[1]
181 || digest[idx + 2] != d[2]
182 || digest[idx + 3] != d[3]
183 {
184 equal = false;
185 }
186 }
187
188 if self.cancelled.get() {
189 self.clear_data();
190 self.cancelled.set(false);
191 client.verification_done(Err(ErrorCode::CANCEL), digest);
192 } else {
193 self.clear_data();
194 self.cancelled.set(false);
195 client.verification_done(Ok(equal), digest);
196 }
197 } else {
198 for i in 0..8 {
199 let d = regs.digest[i].get().to_ne_bytes();
200
201 let idx = i * 4;
202
203 digest[idx + 0] = d[0];
204 digest[idx + 1] = d[1];
205 digest[idx + 2] = d[2];
206 digest[idx + 3] = d[3];
207 }
208 if self.cancelled.get() {
209 self.clear_data();
210 self.cancelled.set(false);
211 client.hash_done(Err(ErrorCode::CANCEL), digest);
212 } else {
213 self.clear_data();
214 self.cancelled.set(false);
215 client.hash_done(Ok(()), digest);
216 }
217 }
218 });
219 } else if intrs.is_set(INTR_STATE::FIFO_EMPTY) {
220 regs.intr_state.modify(INTR_STATE::FIFO_EMPTY::SET);
222 let rval = if self.cancelled.get() {
223 self.cancelled.set(false);
224 Err(ErrorCode::CANCEL)
225 } else {
226 Ok(())
227 };
228 if !self.data_progress() {
229 self.client.map(move |client| {
231 self.data.take().map(|buf| match buf {
232 SubSliceMutImmut::Mutable(b) => client.add_mut_data_done(rval, b),
233 SubSliceMutImmut::Immutable(b) => client.add_data_done(rval, b),
234 })
235 });
236 regs.intr_enable.modify(INTR_ENABLE::FIFO_EMPTY::CLEAR);
238 } else {
239 regs.intr_enable.modify(INTR_ENABLE::FIFO_EMPTY::SET);
242 }
243 } else if intrs.is_set(INTR_STATE::HMAC_ERR) {
244 regs.intr_state.modify(INTR_STATE::HMAC_ERR::SET);
245
246 self.client.map(|client| {
247 let errval = if self.cancelled.get() {
248 self.cancelled.set(false);
249 ErrorCode::CANCEL
250 } else {
251 ErrorCode::FAIL
252 };
253 if self.verify.get() {
254 client.hash_done(Err(errval), self.digest.take().unwrap());
255 } else {
256 client.hash_done(Err(errval), self.digest.take().unwrap());
257 }
258 });
259 }
260 }
261}
262
263impl<'a> hil::digest::DigestData<'a, 32> for Hmac<'a> {
264 fn add_data(
265 &self,
266 data: SubSlice<'static, u8>,
267 ) -> Result<(), (ErrorCode, SubSlice<'static, u8>)> {
268 if self.busy.get() {
269 Err((ErrorCode::BUSY, data))
270 } else {
271 self.busy.set(true);
272 self.data.set(Some(SubSliceMutImmut::Immutable(data)));
273
274 let regs = self.registers;
275 regs.cmd.modify(CMD::START::SET);
276 regs.intr_state.modify(INTR_STATE::FIFO_EMPTY::SET);
278 regs.intr_enable.modify(INTR_ENABLE::FIFO_EMPTY::SET);
280 let ret = self.data_progress();
281
282 if ret {
283 regs.intr_test.modify(INTR_TEST::FIFO_EMPTY::SET);
284 }
285
286 Ok(())
287 }
288 }
289
290 fn add_mut_data(
291 &self,
292 data: SubSliceMut<'static, u8>,
293 ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)> {
294 if self.busy.get() {
295 Err((ErrorCode::BUSY, data))
296 } else {
297 self.busy.set(true);
298 self.data.set(Some(SubSliceMutImmut::Mutable(data)));
299
300 let regs = self.registers;
301 regs.cmd.modify(CMD::START::SET);
302 regs.intr_state.modify(INTR_STATE::FIFO_EMPTY::SET);
304 regs.intr_enable.modify(INTR_ENABLE::FIFO_EMPTY::SET);
306 let ret = self.data_progress();
307
308 if ret {
309 regs.intr_test.modify(INTR_TEST::FIFO_EMPTY::SET);
310 }
311
312 Ok(())
313 }
314 }
315
316 fn clear_data(&self) {
317 let regs = self.registers;
318 regs.cmd.modify(CMD::START::CLEAR);
319 regs.wipe_secret.set(1_u32);
320 self.cancelled.set(true);
321 }
322
323 fn set_data_client(&'a self, _client: &'a (dyn digest::ClientData<32> + 'a)) {
324 unimplemented!()
325 }
326}
327
328impl<'a> hil::digest::DigestHash<'a, 32> for Hmac<'a> {
329 fn run(
330 &'a self,
331 digest: &'static mut [u8; 32],
332 ) -> Result<(), (ErrorCode, &'static mut [u8; 32])> {
333 let regs = self.registers;
334
335 regs.intr_state
337 .modify(INTR_STATE::HMAC_DONE::SET + INTR_STATE::HMAC_ERR::SET);
338 regs.intr_enable
339 .modify(INTR_ENABLE::HMAC_DONE::SET + INTR_ENABLE::HMAC_ERR::SET);
340
341 regs.cmd.modify(CMD::PROCESS::SET);
343 self.busy.set(true);
344 self.digest.set(Some(digest));
345
346 Ok(())
347 }
348
349 fn set_hash_client(&'a self, _client: &'a (dyn digest::ClientHash<32> + 'a)) {
350 unimplemented!()
351 }
352}
353
354impl<'a> hil::digest::DigestVerify<'a, 32> for Hmac<'a> {
355 fn verify(
356 &'a self,
357 compare: &'static mut [u8; 32],
358 ) -> Result<(), (ErrorCode, &'static mut [u8; 32])> {
359 self.verify.set(true);
360
361 self.run(compare)
362 }
363
364 fn set_verify_client(&'a self, _client: &'a (dyn digest::ClientVerify<32> + 'a)) {
365 unimplemented!()
366 }
367}
368
369impl<'a> hil::digest::Digest<'a, 32> for Hmac<'a> {
370 fn set_client(&'a self, client: &'a dyn digest::Client<32>) {
371 self.client.set(client);
372 }
373}
374
375impl hil::digest::HmacSha256 for Hmac<'_> {
376 fn set_mode_hmacsha256(&self, key: &[u8]) -> Result<(), ErrorCode> {
377 if self.busy.get() {
378 return Err(ErrorCode::BUSY);
379 }
380 let regs = self.registers;
381 let mut key_idx = 0;
382
383 if key.len() > 32 {
384 return Err(ErrorCode::NOSUPPORT);
385 }
386
387 regs.cfg.write(
389 CFG::HMAC_EN::SET + CFG::SHA_EN::SET + CFG::ENDIAN_SWAP::CLEAR + CFG::DIGEST_SWAP::SET,
390 );
391
392 for i in 0..(key.len() / 4) {
393 let idx = i * 4;
394
395 let mut k = *key.get(idx + 3).ok_or(ErrorCode::INVAL)? as u32;
396 k |= (*key.get(i * 4 + 2).ok_or(ErrorCode::INVAL)? as u32) << 8;
397 k |= (*key.get(i * 4 + 1).ok_or(ErrorCode::INVAL)? as u32) << 16;
398 k |= (*key.get(i * 4 + 0).ok_or(ErrorCode::INVAL)? as u32) << 24;
399
400 regs.key.get(i).ok_or(ErrorCode::INVAL)?.set(k);
401 key_idx = i + 1;
402 }
403
404 if (key.len() % 4) != 0 {
405 let mut k = 0;
406
407 for i in 0..(key.len() % 4) {
408 k |= (*key.get(key_idx * 4 + 1).ok_or(ErrorCode::INVAL)? as u32) << (8 * (3 - i));
409 }
410
411 regs.key.get(key_idx).ok_or(ErrorCode::INVAL)?.set(k);
412 key_idx += 1;
413 }
414
415 for i in key_idx..8 {
416 regs.key.get(i).ok_or(ErrorCode::INVAL)?.set(0);
417 }
418
419 Ok(())
420 }
421}
422
423impl hil::digest::HmacSha384 for Hmac<'_> {
424 fn set_mode_hmacsha384(&self, _key: &[u8]) -> Result<(), ErrorCode> {
425 Err(ErrorCode::NOSUPPORT)
426 }
427}
428
429impl hil::digest::HmacSha512 for Hmac<'_> {
430 fn set_mode_hmacsha512(&self, _key: &[u8]) -> Result<(), ErrorCode> {
431 Err(ErrorCode::NOSUPPORT)
432 }
433}
434
435impl hil::digest::Sha256 for Hmac<'_> {
436 fn set_mode_sha256(&self) -> Result<(), ErrorCode> {
437 if self.busy.get() {
438 return Err(ErrorCode::BUSY);
439 }
440 let regs = self.registers;
441
442 regs.cfg.write(
444 CFG::HMAC_EN::CLEAR
445 + CFG::SHA_EN::SET
446 + CFG::ENDIAN_SWAP::CLEAR
447 + CFG::DIGEST_SWAP::SET,
448 );
449
450 Ok(())
451 }
452}
453
454impl hil::digest::Sha384 for Hmac<'_> {
455 fn set_mode_sha384(&self) -> Result<(), ErrorCode> {
456 Err(ErrorCode::NOSUPPORT)
457 }
458}
459
460impl hil::digest::Sha512 for Hmac<'_> {
461 fn set_mode_sha512(&self) -> Result<(), ErrorCode> {
462 Err(ErrorCode::NOSUPPORT)
463 }
464}