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