kernel/hil/public_key_crypto/
keys.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//! Key interface for Public/Private key encryption
6
7use crate::hil::entropy;
8use crate::ErrorCode;
9
10/// Upcall from the `PubPrivKeyGenerate` trait.
11pub trait PubPrivKeyGenerateClient<'a> {
12    /// The `generate()` command has been completed.
13    fn generation_complete(
14        &'a self,
15        result: Result<(), (ErrorCode, &'static mut [u8], &'static mut [u8])>,
16    );
17}
18
19/// An internal representation of a asymmetric Public key.
20///
21/// This trait is useful for managing keys internally in Tock.
22///
23/// PubKey is designed for fixed length keys. That is an implementation should
24/// support only a single key length, for example RSA 2048.
25/// Note that we don't use const generics here though. That is because even
26/// within a single key length implementation, there can be different length
27/// inputs, for examples compressed or uncompressed keys.
28pub trait PubKey {
29    /// Import an existing public key.
30    ///
31    /// The reference to the `public_key` is stored internally and can be
32    /// retrieved with the `pub_key()` function.
33    /// The `public_key` can be either a mutable static or an immutable static,
34    /// depending on where the key is stored (flash or memory).
35    ///
36    /// The possible ErrorCodes are:
37    ///     - `BUSY`: A key is already imported or in the process of being
38    ///               generated.
39    ///     - `INVAL`: An invalid key was supplied.
40    ///     - `SIZE`: An invalid key size was supplied.
41    fn import_public_key(
42        &self,
43        public_key: &'static [u8],
44    ) -> Result<(), (ErrorCode, &'static [u8])>;
45
46    /// Return the public key supplied by `import_public_key()` or
47    /// `generate()`.
48    ///
49    /// On success the return value is `Ok(())` with the buffer that was
50    /// originally passed in to hold the key.
51    ///
52    /// On failure the possible ErrorCodes are:
53    ///     - `NODEVICE`: The key does not exist
54    fn pub_key(&self) -> Result<&'static [u8], ErrorCode>;
55
56    /// Report the length of the public key in bytes, as returned from `pub_key()`.
57    /// A value of 0 indicates that the key does not exist.
58    fn len(&self) -> usize;
59}
60
61/// An internal representation of a asymmetric Public key.
62///
63/// This trait is useful for managing keys internally in Tock.
64///
65/// PubKey is designed for fixed length keys. That is an implementation should
66/// support only a single key length, for example RSA 2048.
67/// Note that we don't use const generics here though. That is because even
68/// within a single key length implementation, there can be different length
69/// inputs, for examples compressed or uncompressed keys.
70pub trait PubKeyMut {
71    /// Import an existing public key.
72    ///
73    /// The reference to the `public_key` is stored internally and can be
74    /// retrieved with the `pub_key()` function.
75    /// The `public_key` can be either a mutable static or an immutable static,
76    /// depending on where the key is stored (flash or memory).
77    ///
78    /// The possible ErrorCodes are:
79    ///     - `BUSY`: A key is already imported or in the process of being
80    ///                  generated.
81    ///     - `INVAL`: An invalid key was supplied.
82    ///     - `SIZE`: An invalid key size was supplied.
83    fn import_public_key(
84        &self,
85        public_key: &'static mut [u8],
86    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
87
88    /// Return the public key supplied by `import_public_key()` or
89    /// `generate()`.
90    ///
91    /// On success the return value is `Ok(())` with the buffer that was
92    /// originally passed in to hold the key.
93    ///
94    /// On failure the possible ErrorCodes are:
95    ///     - `NODEVICE`: The key does not exist
96    fn pub_key(&self) -> Result<&'static mut [u8], ErrorCode>;
97
98    /// Report the length of the public key in bytes, as returned from `pub_key()`.
99    /// A value of 0 indicates that the key does not exist.
100    fn len(&self) -> usize;
101}
102
103/// An internal representation of a asymetric Public and Private key.
104///
105/// This trait is useful for managing keys internally in Tock.
106///
107/// PubPrivKey is designed for fixed length keys. That is an implementation
108/// should support only a single key length, for example RSA 2048.
109/// Note that we don't use const generics here though. That is because even
110/// within a single key length implementation, there can be different length
111/// inputs, for examples compressed or uncompressed keys.
112pub trait PubPrivKey: PubKey {
113    /// Import an existing private key.
114    ///
115    /// The reference to the `private_key` is stored internally and can be
116    /// retrieved with the `priv_key()` function.
117    /// The `private_key` can be either a mutable static or an immutable static,
118    /// depending on where the key is stored (flash or memory).
119    ///
120    /// The possible ErrorCodes are:
121    ///     - `BUSY`: A key is already imported or in the process of being
122    ///               generated.
123    ///     - `INVAL`: An invalid key was supplied.
124    ///     - `SIZE`: An invalid key size was supplied.
125    fn import_private_key(
126        &self,
127        private_key: &'static [u8],
128    ) -> Result<(), (ErrorCode, &'static [u8])>;
129
130    /// Return the private key supplied by `import_private_key()` or
131    /// `generate()`.
132    ///
133    /// On success the return value is `Ok(())` with the buffer that was
134    /// originally passed in to hold the key.
135    ///
136    /// On failure the possible ErrorCodes are:
137    ///     - `NODEVICE`: The key does not exist
138    fn priv_key(&self) -> Result<&'static [u8], ErrorCode>;
139
140    /// Report the length of the private key in bytes, as returned from `priv_key()`.
141    /// A value of 0 indicates that the key does not exist.
142    fn len(&self) -> usize;
143}
144
145/// An internal representation of a asymetric Public and Private key.
146///
147/// This trait is useful for managing keys internally in Tock.
148///
149/// PubPrivKey is designed for fixed length keys. That is an implementation
150/// should support only a single key length, for example RSA 2048.
151/// Note that we don't use const generics here though. That is because even
152/// within a single key length implementation, there can be different length
153/// inputs, for examples compressed or uncompressed keys.
154pub trait PubPrivKeyMut: PubKeyMut {
155    /// Import an existing private key.
156    ///
157    /// The reference to the `private_key` is stored internally and can be
158    /// retrieved with the `priv_key()` function.
159    /// The `private_key` can be either a mutable static or an immutable static,
160    /// depending on where the key is stored (flash or memory).
161    ///
162    /// The possible ErrorCodes are:
163    ///     - `BUSY`: A key is already imported or in the process of being
164    ///                  generated.
165    ///     - `INVAL`: An invalid key was supplied.
166    ///     - `SIZE`: An invalid key size was supplied.
167    fn import_private_key(
168        &self,
169        private_key: &'static mut [u8],
170    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
171
172    /// Return the private key supplied by `import_private_key()` or
173    /// `generate()`.
174    ///
175    /// On success the return value is `Ok(())` with the buffer that was
176    /// originally passed in to hold the key.
177    ///
178    /// On failure the possible ErrorCodes are:
179    ///     - `NODEVICE`: The key does not exist
180    fn priv_key(&self) -> Result<&'static mut [u8], ErrorCode>;
181
182    /// Report the length of the private key in bytes, as returned from `priv_key()`.
183    /// A value of 0 indicates that the key does not exist.
184    fn len(&self) -> usize;
185}
186
187/// An internal representation of generating asymetric Public/Private key
188/// pairs.
189///
190/// This trait is useful for managing keys internally in Tock.
191pub trait PubPrivKeyGenerate<'a>: PubPrivKey {
192    /// Set the client. This client will be called when the `generate()`
193    /// function is complete. If using an existing key this doesn't need to be
194    /// used.
195    fn set_client(&'a self, client: &'a dyn PubPrivKeyGenerateClient<'a>);
196
197    /// This generates a new private/public key pair. The length will be
198    /// hard coded by the implementation, for example RSA 2048 will create a
199    /// 2048 bit key.
200    /// This will call the `generation_complete()` on completion. They keys
201    /// cannot be used and will return `None` until the upcall has been called.
202    ///
203    /// The keys generated by `generate()` will depend on the implementation.
204    ///
205    /// The original key buffers can be retrieve usind the `pub_key()` and
206    /// `priv_key()` functions.
207    ///
208    /// The possible ErrorCodes are:
209    ///     - `BUSY`: A key is already imported or in the process of being
210    ///               generated.
211    ///     - `OFF`: The underlying `trng` is powered down.
212    ///     - `SIZE`: An invalid buffer size was supplied.
213    fn generate(
214        &'a self,
215        trng: &'a dyn entropy::Entropy32,
216        public_key_buffer: &'static mut [u8],
217        private_key_buffer: &'static mut [u8],
218    ) -> Result<(), (ErrorCode, &'static mut [u8], &'static mut [u8])>;
219}
220
221pub trait RsaKey: PubKey {
222    /// Run the specified closure over the modulus, if it exists
223    /// The modulus is returned MSB (big endian)
224    /// Returns `Some()` if the key exists and the closure was called,
225    /// otherwise returns `None`.
226    fn map_modulus(&self, closure: &dyn Fn(&[u8])) -> Option<()>;
227
228    /// The the modulus if it exists.
229    /// The modulus is returned MSB (big endian)
230    /// Returns `Some()` if the key exists otherwise returns `None`.
231    /// The modulus can be returned by calling `import_public_key()` with
232    /// the output of this function.
233    fn take_modulus(&self) -> Option<&'static [u8]>;
234
235    /// Returns the public exponent of the key pair if it exists
236    fn public_exponent(&self) -> Option<u32>;
237}
238
239pub trait RsaPrivKey: PubPrivKey + RsaKey {
240    /// Returns the specified closure over the private exponent, if it exists
241    /// The exponent is returned MSB (big endian)
242    /// Returns `Some()` if the key exists and the closure was called,
243    /// otherwise returns `None`.
244    fn map_exponent(&self, closure: &dyn Fn(&[u8])) -> Option<()>;
245
246    /// The the private exponent if it exists.
247    /// The exponent is returned MSB (big endian)
248    /// Returns `Some()` if the key exists otherwise returns `None`.
249    /// The exponent can be returned by calling `import_private_key()` with
250    /// the output of this function.
251    fn take_exponent(&self) -> Option<&'static [u8]>;
252}
253
254pub trait RsaKeyMut: PubKeyMut {
255    /// Run the specified closure over the modulus, if it exists
256    /// The modulus is returned MSB (big endian)
257    /// Returns `Some()` if the key exists and the closure was called,
258    /// otherwise returns `None`.
259    fn map_modulus(&self, closure: &dyn Fn(&mut [u8])) -> Option<()>;
260
261    /// The the modulus if it exists.
262    /// The modulus is returned MSB (big endian)
263    /// Returns `Some()` if the key exists otherwise returns `None`.
264    /// The modulus can be returned by calling `import_public_key()` with
265    /// the output of this function.
266    fn take_modulus(&self) -> Option<&'static mut [u8]>;
267
268    /// Returns the public exponent of the key pair if it exists
269    fn public_exponent(&self) -> Option<u32>;
270}
271
272pub trait RsaPrivKeyMut: PubPrivKeyMut + RsaKeyMut {
273    /// Returns the specified closure over the private exponent, if it exists
274    /// The exponent is returned MSB (big endian)
275    /// Returns `Some()` if the key exists and the closure was called,
276    /// otherwise returns `None`.
277    fn map_exponent(&self, closure: &dyn Fn(&mut [u8])) -> Option<()>;
278
279    /// The the private exponent if it exists.
280    /// The exponent is returned MSB (big endian)
281    /// Returns `Some()` if the key exists otherwise returns `None`.
282    /// The exponent can be returned by calling `import_private_key()` with
283    /// the output of this function.
284    fn take_exponent(&self) -> Option<&'static mut [u8]>;
285}
286
287/// Client for selecting keys.
288pub trait KeySelectClient {
289    /// Called when the specified key is active and ready to use for the next
290    /// cryptographic operation.
291    ///
292    /// ### `error`:
293    ///
294    /// - `Ok(())`: The key was selected successfully.
295    /// - `Err(())`: The key was selected set successfully.
296    ///   - `ErrorCode::INVAL`: The index was not valid.
297    ///   - `ErrorCode::FAIL`: The key could not be set.
298    fn select_key_done(&self, index: usize, error: Result<(), ErrorCode>);
299}
300
301/// Interface for selecting an active key among the number of available keys.
302///
303/// This interface allows for the implementer to maintain an opaque internal
304/// representation of keys. They may be stored in memory, flash, or in secure
305/// element (where the actual key may not be accessible). Users of this
306/// interface can select which key is active for cryptographic operations. There
307/// is no assumption for implementers of this interface that keys can be added
308/// or changed or that keys can be specified by their actual bytes in a slice.
309///
310/// Selecting a key is asynchronous as it may require communication over a bus
311/// or waiting for an interrupt.
312///
313/// Keys are specified by an index starting at zero and going to
314/// `get_key_count()-1`.
315///
316/// The stored keys can be public or private keys.
317pub trait KeySelect<'a> {
318    /// Return the number of keys that the device can switch among.
319    ///
320    /// Each key must be identifiable by a consistent index.
321    fn get_key_count(&self) -> usize;
322
323    /// Set the key identified by its index as the active key.
324    ///
325    /// Indices start at 0 and go to `get_key_count() - 1`.
326    ///
327    /// This operation is asynchronous and its completion is signaled by
328    /// `select_key_done()`.
329    ///
330    /// ## Return
331    ///
332    /// `Ok()` if the key select operation was accepted. Otherwise:
333    /// - `Err(ErrorCode::INVAL)` if the index is not valid.
334    /// - `Err(ErrorCode::ALREADY)` if the key is already selected.
335    fn select_key(&self, index: usize) -> Result<(), ErrorCode>;
336
337    fn set_client(&self, client: &'a dyn KeySelectClient);
338}
339
340/// Client for setting keys.
341pub trait KeySetClient<const KL: usize> {
342    /// Called when the key has been set.
343    ///
344    /// Returns the previous key if one was set.
345    ///
346    /// ### `error`:
347    ///
348    /// - `Ok(())`: The key was set successfully.
349    /// - `Err(())`: The key was not set successfully.
350    ///   - `ErrorCode::FAIL`: The key could not be set.
351    fn set_key_done(
352        &self,
353        previous_key: Option<&'static mut [u8; KL]>,
354        error: Result<(), ErrorCode>,
355    );
356}
357
358/// Interface for setting keys by a slice.
359///
360/// `KL` is the length of the keys.
361///
362/// Implementers must be able to store keys from a slice. This is most commonly
363/// used for implementations that hold keys in memory. However, this interface
364/// is asynchronous as keys may be stored in external storage or an external
365/// chip and require an asynchronous operations.
366pub trait KeySet<'a, const KL: usize> {
367    /// Set the current key.
368    ///
369    /// This is asynchronous. If there is an existing key that key will be
370    /// returned in the `set_key_done()` callback.
371    ///
372    /// ### Return
373    ///
374    /// `Ok()` if the key setting operation was accepted. Otherwise:
375    /// - `Err(ErrorCode::FAIL)` if the key cannot be set.
376    fn set_key(&self, key: &'static mut [u8; KL])
377        -> Result<(), (ErrorCode, &'static mut [u8; KL])>;
378
379    fn set_client(&self, client: &'a dyn KeySetClient<KL>);
380}