kernel/hil/
digest.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//! Interface for computing digests (hashes, cryptographic hashes, and
6//! HMACs) over data.
7
8use crate::utilities::leasable_buffer::SubSlice;
9use crate::utilities::leasable_buffer::SubSliceMut;
10use crate::ErrorCode;
11
12/// Implement this trait and use `set_client()` in order to receive callbacks
13/// when data has been added to a digest.
14///
15/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
16pub trait ClientData<const DIGEST_LEN: usize> {
17    /// Called when the data has been added to the digest. `data` is
18    /// the `SubSlice` passed in the call to `add_data`, whose
19    /// active slice contains the data that was not added. On `Ok`,
20    /// `data` has an active slice of size zero (all data was added).
21    /// Valid `ErrorCode` values are:
22    ///  - OFF: the underlying digest engine is powered down and
23    ///  cannot be used.
24    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
25    ///  `run`, or `verify` operation, so the digest engine is busy
26    ///  and cannot accept more data.
27    ///  - SIZE: the active slice of the SubSlice has zero size.
28    ///  - CANCEL: the operation was cancelled by a call to `clear_data`.
29    ///  - FAIL: an internal failure.
30    fn add_data_done(&self, result: Result<(), ErrorCode>, data: SubSlice<'static, u8>);
31
32    /// Called when the data has been added to the digest. `data` is
33    /// the `SubSliceMut` passed in the call to
34    /// `add_mut_data`, whose active slice contains the data that was
35    /// not added. On `Ok`, `data` has an active slice of size zero
36    /// (all data was added). Valid `ErrorCode` values are:
37    ///  - OFF: the underlying digest engine is powered down and
38    ///  cannot be used.
39    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
40    ///  `run`, or `verify` operation, so the digest engine is busy
41    ///  and cannot accept more data.
42    ///  - SIZE: the active slice of the SubSlice has zero size.
43    ///  - CANCEL: the operation was cancelled by a call to `clear_data`.
44    ///  - FAIL: an internal failure.
45    fn add_mut_data_done(&self, result: Result<(), ErrorCode>, data: SubSliceMut<'static, u8>);
46}
47
48/// Implement this trait and use `set_client()` in order to receive callbacks when
49/// a digest is completed.
50///
51/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
52pub trait ClientHash<const DIGEST_LEN: usize> {
53    /// Called when a digest is computed. `digest` is the same
54    /// reference passed to `run()` to store the hash value. If
55    /// `result` is `Ok`, `digest` stores the computed hash. If
56    /// `result` is `Err`, the data stored in `digest` is undefined
57    /// and may have any value. Valid `ErrorCode` values are:
58    ///  - OFF: the underlying digest engine is powered down and
59    ///  cannot be used.
60    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
61    ///  `run`, or `verify` operation, so the digest engine is busy
62    ///  and cannot perform a hash.
63    ///  - CANCEL: the operation was cancelled by a call to `clear_data`.
64    ///  - NOSUPPORT: the requested digest algorithm is not supported,
65    ///  or one was not requested.
66    ///  - FAIL: an internal failure.
67    fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; DIGEST_LEN]);
68}
69
70/// Implement this trait and use `set_client()` in order to receive callbacks when
71/// digest verification is complete.
72///
73/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
74pub trait ClientVerify<const DIGEST_LEN: usize> {
75    /// Called when a verification is computed.  `compare` is the
76    /// reference supplied to `verify()` and the data stored in
77    /// `compare` is unchanged.  On `Ok` the `bool` indicates if the
78    /// computed hash matches the value in `compare`. Valid
79    /// `ErrorCode` values are:
80    ///  - OFF: the underlying digest engine is powered down and
81    ///  cannot be used.
82    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
83    ///  `run`, or `verify` operation, so the digest engine is busy
84    ///  and cannot verify a hash.
85    ///  - CANCEL: the operation was cancelled by a call to `clear_data`.
86    ///  - NOSUPPORT: the requested digest algorithm is not supported,
87    ///  or one was not requested.
88    ///  - FAIL: an internal failure.
89    fn verification_done(
90        &self,
91        result: Result<bool, ErrorCode>,
92        compare: &'static mut [u8; DIGEST_LEN],
93    );
94}
95
96pub trait Client<const DIGEST_LEN: usize>:
97    ClientData<DIGEST_LEN> + ClientHash<DIGEST_LEN> + ClientVerify<DIGEST_LEN>
98{
99}
100
101impl<
102        T: ClientData<DIGEST_LEN> + ClientHash<DIGEST_LEN> + ClientVerify<DIGEST_LEN>,
103        const DIGEST_LEN: usize,
104    > Client<DIGEST_LEN> for T
105{
106}
107
108pub trait ClientDataHash<const DIGEST_LEN: usize>:
109    ClientData<DIGEST_LEN> + ClientHash<DIGEST_LEN>
110{
111}
112impl<T: ClientData<DIGEST_LEN> + ClientHash<DIGEST_LEN>, const DIGEST_LEN: usize>
113    ClientDataHash<DIGEST_LEN> for T
114{
115}
116
117pub trait ClientDataVerify<const DIGEST_LEN: usize>:
118    ClientData<DIGEST_LEN> + ClientVerify<DIGEST_LEN>
119{
120}
121impl<T: ClientData<DIGEST_LEN> + ClientVerify<DIGEST_LEN>, const DIGEST_LEN: usize>
122    ClientDataVerify<DIGEST_LEN> for T
123{
124}
125
126/// Adding data (mutable or immutable) to a digest.
127///
128/// There are two separate methods, `add_data` for immutable data
129/// (e.g., flash) and `add_mut_data` for mutable data (e.g.,
130/// RAM). Each has its own callback, but only one operation may be in
131/// flight at any time.
132///
133/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
134pub trait DigestData<'a, const DIGEST_LEN: usize> {
135    /// Set the client instance which will handle the `add_data_done`
136    /// and `add_mut_data_done` callbacks.
137    fn set_data_client(&'a self, client: &'a dyn ClientData<DIGEST_LEN>);
138
139    /// Add data to the input of the hash function/digest. `Ok`
140    /// indicates all of the active bytes in `data` will be added.
141    /// There is no guarantee the data has been added to the digest
142    /// until the `add_data_done()` callback is called.  On error the
143    /// cause of the error is returned along with the SubSlice
144    /// unchanged (it has the same range of active bytes as the call).
145    /// Valid `ErrorCode` values are:
146    ///  - OFF: the underlying digest engine is powered down and
147    ///  cannot be used.
148    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
149    ///  `run`, or `verify` operation, so the digest engine is busy
150    ///  and cannot accept more data.
151    ///  - SIZE: the active slice of the SubSlice has zero size.
152    fn add_data(
153        &self,
154        data: SubSlice<'static, u8>,
155    ) -> Result<(), (ErrorCode, SubSlice<'static, u8>)>;
156
157    /// Add data to the input of the hash function/digest. `Ok`
158    /// indicates all of the active bytes in `data` will be added.
159    /// There is no guarantee the data has been added to the digest
160    /// until the `add_mut_data_done()` callback is called.  On error
161    /// the cause of the error is returned along with the
162    /// SubSlice unchanged (it has the same range of active
163    /// bytes as the call).  Valid `ErrorCode` values are:
164    ///  - OFF: the underlying digest engine is powered down and
165    ///  cannot be used.
166    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
167    ///  `run`, or `verify` operation, so the digest engine is busy
168    ///  and cannot accept more data.
169    ///  - SIZE: the active slice of the SubSlice has zero size.
170    fn add_mut_data(
171        &self,
172        data: SubSliceMut<'static, u8>,
173    ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)>;
174
175    /// Clear the keys and any other internal state. Any pending
176    /// operations terminate and issue a callback with an
177    /// `ErrorCode::CANCEL`. This call does not clear buffers passed
178    /// through `add_mut_data`, those are up to the client clear.
179    fn clear_data(&self);
180}
181
182/// Computes a digest (cryptographic hash) over data provided through a
183/// separate trait.
184///
185/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
186pub trait DigestHash<'a, const DIGEST_LEN: usize> {
187    /// Set the client instance which will receive the `hash_done()`
188    /// callback.
189    fn set_hash_client(&'a self, client: &'a dyn ClientHash<DIGEST_LEN>);
190
191    /// Compute a digest of all of the data added with `add_data` and
192    /// `add_data_mut`, storing the computed value in `digest`.  The
193    /// computed value is returned in a `hash_done` callback.  On
194    /// error the return value will contain a return code and the
195    /// slice passed in `digest`. Valid `ErrorCode` values are:
196    ///  - OFF: the underlying digest engine is powered down and
197    ///  cannot be used.
198    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
199    ///  `run`, or `verify` operation, so the digest engine is busy
200    ///  and cannot accept more data.
201    ///  - SIZE: the active slice of the SubSlice has zero size.
202    ///  - NOSUPPORT: the currently selected digest algorithm is not
203    ///  supported.
204    ///
205    /// If an appropriate `set_mode*()` wasn't called before this function the
206    /// implementation should try to use a default option. In the case where
207    /// there is only one digest supported this should be used. If there is no
208    /// suitable or obvious default option, the implementation can return
209    /// `ErrorCode::NOSUPPORT`.
210    fn run(
211        &'a self,
212        digest: &'static mut [u8; DIGEST_LEN],
213    ) -> Result<(), (ErrorCode, &'static mut [u8; DIGEST_LEN])>;
214}
215
216/// Verifies a digest (cryptographic hash) over data provided through a
217/// separate trait
218///
219/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
220pub trait DigestVerify<'a, const DIGEST_LEN: usize> {
221    /// Set the client instance which will receive the `verification_done()`
222    /// callback.
223    fn set_verify_client(&'a self, client: &'a dyn ClientVerify<DIGEST_LEN>);
224
225    /// Compute a digest of all of the data added with `add_data` and
226    /// `add_data_mut` then compare it with value in `compare`.  The
227    /// compare value is returned in a `verification_done` callback, along with
228    /// a boolean indicating whether it matches the computed value. On
229    /// error the return value will contain a return code and the
230    /// slice passed in `compare`. Valid `ErrorCode` values are:
231    ///  - OFF: the underlying digest engine is powered down and
232    ///  cannot be used.
233    ///  - BUSY: there is an outstanding `add_data`, `add_data_mut`,
234    ///  `run`, or `verify` operation, so the digest engine is busy
235    ///  and cannot accept more data.
236    ///  - SIZE: the active slice of the SubSlice has zero size.
237    ///  - NOSUPPORT: the currently selected digest algorithm is not
238    ///  supported.
239    ///
240    /// If an appropriate `set_mode*()` wasn't called before this function the
241    /// implementation should try to use a default option. In the case where
242    /// there is only one digest supported this should be used. If there is no
243    /// suitable or obvious default option, the implementation can return
244    /// `ErrorCode::NOSUPPORT`.
245    fn verify(
246        &'a self,
247        compare: &'static mut [u8; DIGEST_LEN],
248    ) -> Result<(), (ErrorCode, &'static mut [u8; DIGEST_LEN])>;
249}
250
251/// Computes a digest (cryptographic hash) over data or performs verification.
252///
253/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
254pub trait Digest<'a, const DIGEST_LEN: usize>:
255    DigestData<'a, DIGEST_LEN> + DigestHash<'a, DIGEST_LEN> + DigestVerify<'a, DIGEST_LEN>
256{
257    /// Set the client instance which will receive `hash_done()`,
258    /// `add_data_done()` and `verification_done()` callbacks.
259    fn set_client(&'a self, client: &'a dyn Client<DIGEST_LEN>);
260}
261
262/// Computes a digest (cryptographic hash) over data.
263///
264/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
265pub trait DigestDataHash<'a, const DIGEST_LEN: usize>:
266    DigestData<'a, DIGEST_LEN> + DigestHash<'a, DIGEST_LEN>
267{
268    /// Set the client instance which will receive `hash_done()` and
269    /// `add_data_done()` callbacks.
270    fn set_client(&'a self, client: &'a dyn ClientDataHash<DIGEST_LEN>);
271}
272
273/// Verify a digest (cryptographic hash) over data.
274///
275/// 'DIGEST_LEN' is the length of the 'u8' array to store the digest output.
276pub trait DigestDataVerify<'a, const DIGEST_LEN: usize>:
277    DigestData<'a, DIGEST_LEN> + DigestVerify<'a, DIGEST_LEN>
278{
279    /// Set the client instance which will receive `verify_done()` and
280    /// `add_data_done()` callbacks.
281    fn set_client(&'a self, client: &'a dyn ClientDataVerify<DIGEST_LEN>);
282}
283
284pub trait Sha224 {
285    /// Call before adding data to perform Sha224
286    fn set_mode_sha224(&self) -> Result<(), ErrorCode>;
287}
288
289pub trait Sha256 {
290    /// Call before adding data to perform Sha256
291    fn set_mode_sha256(&self) -> Result<(), ErrorCode>;
292}
293
294pub trait Sha384 {
295    /// Call before adding data to perform Sha384
296    fn set_mode_sha384(&self) -> Result<(), ErrorCode>;
297}
298
299pub trait Sha512 {
300    /// Call before adding data to perform Sha512
301    fn set_mode_sha512(&self) -> Result<(), ErrorCode>;
302}
303
304pub trait HmacSha256 {
305    /// Call before adding data to perform HMACSha256
306    ///
307    /// The key used for the HMAC is passed to this function.
308    fn set_mode_hmacsha256(&self, key: &[u8]) -> Result<(), ErrorCode>;
309}
310
311pub trait HmacSha384 {
312    /// Call before adding data to perform HMACSha384
313    ///
314    /// The key used for the HMAC is passed to this function.
315    fn set_mode_hmacsha384(&self, key: &[u8]) -> Result<(), ErrorCode>;
316}
317
318pub trait HmacSha512 {
319    /// Call before adding data to perform HMACSha512
320    ///
321    /// The key used for the HMAC is passed to this function.
322    fn set_mode_hmacsha512(&self, key: &[u8]) -> Result<(), ErrorCode>;
323}