Skip to main content

capsules_extra/test/
hmac_sha224.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright OxidOS Automotive 2026.
4
5//! Test the implementation of HMAC-SHA224 by performing a hash and
6//! checking it against the expected hash value.
7
8use capsules_core::test::capsule_test::{CapsuleTest, CapsuleTestClient, CapsuleTestError};
9use kernel::ErrorCode;
10use kernel::hil::digest;
11use kernel::hil::digest::HmacSha224;
12use kernel::utilities::cells::OptionalCell;
13use kernel::utilities::cells::TakeCell;
14use kernel::utilities::leasable_buffer::SubSlice;
15use kernel::utilities::leasable_buffer::SubSliceMut;
16
17const HMAC_SHA224_DIGEST_LEN: usize = 28;
18
19pub struct TestHmacSha224<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN>> {
20    hmac: &'a H,
21    key: TakeCell<'static, [u8]>,  // The key to use for HMAC
22    data: TakeCell<'static, [u8]>, // The data to hash
23    digest: TakeCell<'static, [u8; HMAC_SHA224_DIGEST_LEN]>, // The supplied hash
24    correct: &'static [u8; HMAC_SHA224_DIGEST_LEN], // The supplied hash
25    client: OptionalCell<&'static dyn CapsuleTestClient>,
26}
27
28impl<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN> + HmacSha224> TestHmacSha224<'a, H> {
29    pub fn new(
30        hmac: &'a H,
31        key: &'static mut [u8],
32        data: &'static mut [u8],
33        digest: &'static mut [u8; HMAC_SHA224_DIGEST_LEN],
34        correct: &'static [u8; HMAC_SHA224_DIGEST_LEN],
35    ) -> Self {
36        TestHmacSha224 {
37            hmac,
38            key: TakeCell::new(key),
39            data: TakeCell::new(data),
40            digest: TakeCell::new(digest),
41            correct,
42            client: OptionalCell::empty(),
43        }
44    }
45
46    pub fn run(&'static self) {
47        kernel::hil::digest::Digest::set_client(self.hmac, self);
48
49        let key = self.key.take().unwrap();
50        let r = self.hmac.set_mode_hmacsha224(key);
51        if r.is_err() {
52            panic!("HmacSha224Test: failed to set key: {:?}", r);
53        }
54        let data = self.data.take().unwrap();
55        let buffer = SubSliceMut::new(data);
56        let r = self.hmac.add_mut_data(buffer);
57        if r.is_err() {
58            panic!("HmacSha224Test: failed to add data: {:?}", r);
59        }
60    }
61}
62
63impl<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN>> digest::ClientData<HMAC_SHA224_DIGEST_LEN>
64    for TestHmacSha224<'a, H>
65{
66    fn add_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSlice<'static, u8>) {
67        unimplemented!()
68    }
69
70    fn add_mut_data_done(&self, result: Result<(), ErrorCode>, data: SubSliceMut<'static, u8>) {
71        self.data.replace(data.take());
72        match result {
73            Ok(()) => {}
74            Err(e) => {
75                kernel::debug!("HmacSha224Test: failed to add data: {:?}", e);
76                self.client.map(|client| {
77                    client.done(Err(CapsuleTestError::ErrorCode(e)));
78                });
79                return;
80            }
81        }
82
83        let r = self.hmac.run(self.digest.take().unwrap());
84        match r {
85            Ok(()) => {}
86            Err((e, d)) => {
87                kernel::debug!("HmacSha224Test: failed to run HMAC: {:?}", e);
88
89                self.digest.replace(d);
90                self.client.map(|client| {
91                    client.done(Err(CapsuleTestError::ErrorCode(e)));
92                });
93            }
94        }
95    }
96}
97
98impl<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN>> digest::ClientHash<HMAC_SHA224_DIGEST_LEN>
99    for TestHmacSha224<'a, H>
100{
101    fn hash_done(
102        &self,
103        _result: Result<(), ErrorCode>,
104        digest: &'static mut [u8; HMAC_SHA224_DIGEST_LEN],
105    ) {
106        let mut error = false;
107        for i in 0..HMAC_SHA224_DIGEST_LEN {
108            if self.correct[i] != digest[i] {
109                error = true;
110                break;
111            }
112        }
113        if !error {
114            kernel::debug!("HMAC-SHA224 matches!");
115            self.client.map(|client| {
116                client.done(Ok(()));
117            });
118        } else {
119            kernel::debug!("HmacSha224Test: incorrect HMAC output!");
120            self.client.map(|client| {
121                client.done(Err(CapsuleTestError::IncorrectResult));
122            });
123        }
124    }
125}
126
127impl<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN>> digest::ClientVerify<HMAC_SHA224_DIGEST_LEN>
128    for TestHmacSha224<'a, H>
129{
130    fn verification_done(
131        &self,
132        _result: Result<bool, ErrorCode>,
133        _compare: &'static mut [u8; HMAC_SHA224_DIGEST_LEN],
134    ) {
135    }
136}
137
138impl<'a, H: digest::Digest<'a, HMAC_SHA224_DIGEST_LEN>> CapsuleTest for TestHmacSha224<'a, H> {
139    fn set_client(&self, client: &'static dyn CapsuleTestClient) {
140        self.client.set(client);
141    }
142}