capsules_extra/test/
hmac_sha256.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 Tock Contributors 2022.
4
5//! Test the software implementation of HMAC-SHA256 by performing a hash and
6//! checking it against the expected hash value.
7
8use crate::hmac_sha256::HmacSha256Software;
9use crate::sha256::Sha256Software;
10use capsules_core::test::capsule_test::{CapsuleTest, CapsuleTestClient, CapsuleTestError};
11use kernel::hil::digest;
12use kernel::hil::digest::HmacSha256;
13use kernel::hil::digest::{DigestData, DigestHash};
14use kernel::utilities::cells::OptionalCell;
15use kernel::utilities::cells::TakeCell;
16use kernel::utilities::leasable_buffer::SubSlice;
17use kernel::utilities::leasable_buffer::SubSliceMut;
18use kernel::ErrorCode;
19
20pub struct TestHmacSha256 {
21    hmac: &'static HmacSha256Software<'static, Sha256Software<'static>>,
22    key: TakeCell<'static, [u8]>,        // The key to use for HMAC
23    data: TakeCell<'static, [u8]>,       // The data to hash
24    digest: TakeCell<'static, [u8; 32]>, // The supplied hash
25    correct: &'static [u8; 32],          // The supplied hash
26    client: OptionalCell<&'static dyn CapsuleTestClient>,
27}
28
29impl TestHmacSha256 {
30    pub fn new(
31        hmac: &'static HmacSha256Software<'static, Sha256Software<'static>>,
32        key: &'static mut [u8],
33        data: &'static mut [u8],
34        digest: &'static mut [u8; 32],
35        correct: &'static [u8; 32],
36    ) -> Self {
37        TestHmacSha256 {
38            hmac,
39            key: TakeCell::new(key),
40            data: TakeCell::new(data),
41            digest: TakeCell::new(digest),
42            correct,
43            client: OptionalCell::empty(),
44        }
45    }
46
47    pub fn run(&'static self) {
48        kernel::hil::digest::Digest::set_client(self.hmac, self);
49
50        let key = self.key.take().unwrap();
51        let r = self.hmac.set_mode_hmacsha256(key);
52        if r.is_err() {
53            panic!("HmacSha256Test: failed to set key: {:?}", r);
54        }
55        let data = self.data.take().unwrap();
56        let buffer = SubSliceMut::new(data);
57        let r = self.hmac.add_mut_data(buffer);
58        if r.is_err() {
59            panic!("HmacSha256Test: failed to add data: {:?}", r);
60        }
61    }
62}
63
64impl digest::ClientData<32> for TestHmacSha256 {
65    fn add_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSlice<'static, u8>) {
66        unimplemented!()
67    }
68
69    fn add_mut_data_done(&self, result: Result<(), ErrorCode>, data: SubSliceMut<'static, u8>) {
70        self.data.replace(data.take());
71
72        match result {
73            Ok(()) => {}
74            Err(e) => {
75                kernel::debug!("HmacSha256Test: 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!("HmacSha256Test: 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 digest::ClientHash<32> for TestHmacSha256 {
99    fn hash_done(&self, _result: Result<(), ErrorCode>, digest: &'static mut [u8; 32]) {
100        let mut error = false;
101        for i in 0..32 {
102            if self.correct[i] != digest[i] {
103                error = true;
104            }
105        }
106        if !error {
107            kernel::debug!("HMAC-SHA256 matches!");
108            self.client.map(|client| {
109                client.done(Ok(()));
110            });
111        } else {
112            kernel::debug!("HmacSha256Test: incorrect HMAC output!");
113            self.client.map(|client| {
114                client.done(Err(CapsuleTestError::IncorrectResult));
115            });
116        }
117    }
118}
119
120impl digest::ClientVerify<32> for TestHmacSha256 {
121    fn verification_done(&self, _result: Result<bool, ErrorCode>, _compare: &'static mut [u8; 32]) {
122    }
123}
124
125impl CapsuleTest for TestHmacSha256 {
126    fn set_client(&self, client: &'static dyn CapsuleTestClient) {
127        self.client.set(client);
128    }
129}