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 an 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 an 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 an asymmetric 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 an asymmetric 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 asymmetric 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 SelectKeyClient {
289 /// Called when the number of keys available is known.
290 fn get_key_count_done(&self, count: usize);
291
292 /// Called when the specified key is active and ready to use for the next
293 /// cryptographic operation.
294 ///
295 /// ### `error`:
296 ///
297 /// - `Ok(())`: The key was selected successfully.
298 /// - `Err(())`: The key was selected set successfully.
299 /// - `ErrorCode::INVAL`: The index was not valid.
300 /// - `ErrorCode::FAIL`: The key could not be set.
301 fn select_key_done(&self, index: usize, error: Result<(), ErrorCode>);
302}
303
304/// Interface for selecting an active key among the number of available keys.
305///
306/// This interface allows for the implementer to maintain an opaque internal
307/// representation of keys. They may be stored in memory, flash, or in secure
308/// element (where the actual key may not be accessible). Users of this
309/// interface can select which key is active for cryptographic operations. There
310/// is no assumption for implementers of this interface that keys can be added
311/// or changed or that keys can be specified by their actual bytes in a slice.
312///
313/// Selecting a key is asynchronous as it may require communication over a bus
314/// or waiting for an interrupt.
315///
316/// Keys are specified by an index starting at zero and going to
317/// `get_key_count()-1`, without gaps. Selecting a key between `0` and
318/// `get_key_count()-1` must not fail with `ErrorCode::INVAL`.
319///
320/// The stored keys can be public or private keys.
321pub trait SelectKey<'a> {
322 /// Return the number of keys that the device can switch among.
323 ///
324 /// Each key must be identifiable by a consistent index.
325 ///
326 /// This operation is asynchronous and its completion is signaled by
327 /// `get_key_count_done()`.
328 ///
329 /// ## Return
330 ///
331 /// `Ok()` if getting the count has started. Otherwise:
332 /// - `Err(ErrorCode::FAIL)` if the key count could not be started and there
333 /// will be no callback.
334 fn get_key_count(&self) -> Result<(), ErrorCode>;
335
336 /// Set the key identified by its index as the active key.
337 ///
338 /// Indices start at 0 and go to `get_key_count() - 1`.
339 ///
340 /// This operation is asynchronous and its completion is signaled by
341 /// `select_key_done()`.
342 ///
343 /// ## Return
344 ///
345 /// `Ok()` if the key select operation was accepted. Otherwise:
346 /// - `Err(ErrorCode::INVAL)` if the index is not valid.
347 fn select_key(&self, index: usize) -> Result<(), ErrorCode>;
348
349 fn set_client(&self, client: &'a dyn SelectKeyClient);
350}
351
352/// Client for setting keys.
353pub trait SetKeyBySliceClient<const KL: usize> {
354 /// Called when the key has been set.
355 ///
356 /// Returns the key that was set.
357 ///
358 /// ### `error`:
359 ///
360 /// - `Ok(())`: The key was set successfully.
361 /// - `Err(())`: The key was not set successfully.
362 /// - `ErrorCode::FAIL`: The key could not be set.
363 fn set_key_done(&self, previous_key: &'static mut [u8; KL], error: Result<(), ErrorCode>);
364}
365
366/// Interface for setting keys by a slice.
367///
368/// `KL` is the length of the keys.
369///
370/// Implementers must be able to store keys from a slice. This is most commonly
371/// used for implementations that hold keys in memory. However, this interface
372/// is asynchronous as keys may be stored in external storage or an external
373/// chip and require an asynchronous operations.
374///
375/// Implementors cannot hold the slice of the key being set. Instead, they must
376/// make an internal copy of the key and return the slice in
377/// [`SetKeyBySliceClient::set_key_done()`].
378pub trait SetKeyBySlice<'a, const KL: usize> {
379 /// Set the current key.
380 ///
381 /// This is asynchronous. The key slice will be returned in
382 /// [`SetKeyBySliceClient::set_key_done()`], or immediately if there is an
383 /// error.
384 ///
385 /// ### Return
386 ///
387 /// `Ok()` if the key setting operation was accepted. Otherwise:
388 /// - `Err(ErrorCode::FAIL)` if the key cannot be set.
389 fn set_key(&self, key: &'static mut [u8; KL])
390 -> Result<(), (ErrorCode, &'static mut [u8; KL])>;
391
392 fn set_client(&self, client: &'a dyn SetKeyBySliceClient<KL>);
393}