1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Key interface for Public/Private key encryption

use crate::hil::entropy;
use crate::ErrorCode;

/// Upcall from the `PubPrivKeyGenerate` trait.
pub trait PubPrivKeyGenerateClient<'a> {
    /// The `generate()` command has been completed.
    fn generation_complete(
        &'a self,
        result: Result<(), (ErrorCode, &'static mut [u8], &'static mut [u8])>,
    );
}

/// An internal representation of a asymetric Public key.
///
/// This trait is useful for managing keys internally in Tock.
///
/// PubKey is designed for fixed length keys. That is an implementation should
/// support only a single key length, for example RSA 2048.
/// Note that we don't use const generics here though. That is because even
/// within a single key length implementation, there can be different length
/// inputs, for examples compressed or uncompressed keys.
pub trait PubKey {
    /// Import an existing public key.
    ///
    /// The reference to the `public_key` is stored internally and can be
    /// retrieved with the `pub_key()` function.
    /// The `public_key` can be either a mutable static or an immutable static,
    /// depending on where the key is stored (flash or memory).
    ///
    /// The possible ErrorCodes are:
    ///     - `BUSY`: A key is already imported or in the process of being
    ///               generated.
    ///     - `INVAL`: An invalid key was supplied.
    ///     - `SIZE`: An invalid key size was supplied.
    fn import_public_key(
        &self,
        public_key: &'static [u8],
    ) -> Result<(), (ErrorCode, &'static [u8])>;

    /// Return the public key supplied by `import_public_key()` or
    /// `generate()`.
    ///
    /// On success the return value is `Ok(())` with the buffer that was
    /// originally passed in to hold the key.
    ///
    /// On failure the possible ErrorCodes are:
    ///     - `NODEVICE`: The key does not exist
    fn pub_key(&self) -> Result<&'static [u8], ErrorCode>;

    /// Report the length of the public key in bytes, as returned from `pub_key()`.
    /// A value of 0 indicates that the key does not exist.
    fn len(&self) -> usize;
}

/// An internal representation of a asymetric Public key.
///
/// This trait is useful for managing keys internally in Tock.
///
/// PubKey is designed for fixed length keys. That is an implementation should
/// support only a single key length, for example RSA 2048.
/// Note that we don't use const generics here though. That is because even
/// within a single key length implementation, there can be different length
/// inputs, for examples compressed or uncompressed keys.
pub trait PubKeyMut {
    /// Import an existing public key.
    ///
    /// The reference to the `public_key` is stored internally and can be
    /// retrieved with the `pub_key()` function.
    /// The `public_key` can be either a mutable static or an immutable static,
    /// depending on where the key is stored (flash or memory).
    ///
    /// The possible ErrorCodes are:
    ///     - `BUSY`: A key is already imported or in the process of being
    ///                  generated.
    ///     - `INVAL`: An invalid key was supplied.
    ///     - `SIZE`: An invalid key size was supplied.
    fn import_public_key(
        &self,
        public_key: &'static mut [u8],
    ) -> Result<(), (ErrorCode, &'static mut [u8])>;

    /// Return the public key supplied by `import_public_key()` or
    /// `generate()`.
    ///
    /// On success the return value is `Ok(())` with the buffer that was
    /// originally passed in to hold the key.
    ///
    /// On failure the possible ErrorCodes are:
    ///     - `NODEVICE`: The key does not exist
    fn pub_key(&self) -> Result<&'static mut [u8], ErrorCode>;

    /// Report the length of the public key in bytes, as returned from `pub_key()`.
    /// A value of 0 indicates that the key does not exist.
    fn len(&self) -> usize;
}

/// An internal representation of a asymetric Public and Private key.
///
/// This trait is useful for managing keys internally in Tock.
///
/// PubPrivKey is designed for fixed length keys. That is an implementation
/// should support only a single key length, for example RSA 2048.
/// Note that we don't use const generics here though. That is because even
/// within a single key length implementation, there can be different length
/// inputs, for examples compressed or uncompressed keys.
pub trait PubPrivKey: PubKey {
    /// Import an existing private key.
    ///
    /// The reference to the `private_key` is stored internally and can be
    /// retrieved with the `priv_key()` function.
    /// The `private_key` can be either a mutable static or an immutable static,
    /// depending on where the key is stored (flash or memory).
    ///
    /// The possible ErrorCodes are:
    ///     - `BUSY`: A key is already imported or in the process of being
    ///               generated.
    ///     - `INVAL`: An invalid key was supplied.
    ///     - `SIZE`: An invalid key size was supplied.
    fn import_private_key(
        &self,
        private_key: &'static [u8],
    ) -> Result<(), (ErrorCode, &'static [u8])>;

    /// Return the private key supplied by `import_private_key()` or
    /// `generate()`.
    ///
    /// On success the return value is `Ok(())` with the buffer that was
    /// originally passed in to hold the key.
    ///
    /// On failure the possible ErrorCodes are:
    ///     - `NODEVICE`: The key does not exist
    fn priv_key(&self) -> Result<&'static [u8], ErrorCode>;

    /// Report the length of the private key in bytes, as returned from `priv_key()`.
    /// A value of 0 indicates that the key does not exist.
    fn len(&self) -> usize;
}

/// An internal representation of a asymetric Public and Private key.
///
/// This trait is useful for managing keys internally in Tock.
///
/// PubPrivKey is designed for fixed length keys. That is an implementation
/// should support only a single key length, for example RSA 2048.
/// Note that we don't use const generics here though. That is because even
/// within a single key length implementation, there can be different length
/// inputs, for examples compressed or uncompressed keys.
pub trait PubPrivKeyMut: PubKeyMut {
    /// Import an existing private key.
    ///
    /// The reference to the `private_key` is stored internally and can be
    /// retrieved with the `priv_key()` function.
    /// The `private_key` can be either a mutable static or an immutable static,
    /// depending on where the key is stored (flash or memory).
    ///
    /// The possible ErrorCodes are:
    ///     - `BUSY`: A key is already imported or in the process of being
    ///                  generated.
    ///     - `INVAL`: An invalid key was supplied.
    ///     - `SIZE`: An invalid key size was supplied.
    fn import_private_key(
        &self,
        private_key: &'static mut [u8],
    ) -> Result<(), (ErrorCode, &'static mut [u8])>;

    /// Return the private key supplied by `import_private_key()` or
    /// `generate()`.
    ///
    /// On success the return value is `Ok(())` with the buffer that was
    /// originally passed in to hold the key.
    ///
    /// On failure the possible ErrorCodes are:
    ///     - `NODEVICE`: The key does not exist
    fn priv_key(&self) -> Result<&'static mut [u8], ErrorCode>;

    /// Report the length of the private key in bytes, as returned from `priv_key()`.
    /// A value of 0 indicates that the key does not exist.
    fn len(&self) -> usize;
}

/// An internal representation of generating asymetric Public/Private key
/// pairs.
///
/// This trait is useful for managing keys internally in Tock.
pub trait PubPrivKeyGenerate<'a>: PubPrivKey {
    /// Set the client. This client will be called when the `generate()`
    /// function is complete. If using an existing key this doesn't need to be
    /// used.
    fn set_client(&'a self, client: &'a dyn PubPrivKeyGenerateClient<'a>);

    /// This generates a new private/public key pair. The length will be
    /// hard coded by the implementation, for example RSA 2048 will create a
    /// 2048 bit key.
    /// This will call the `generation_complete()` on completion. They keys
    /// cannot be used and will return `None` until the upcall has been called.
    ///
    /// The keys generated by `generate()` will depend on the implementation.
    ///
    /// The original key buffers can be retrieve usind the `pub_key()` and
    /// `priv_key()` functions.
    ///
    /// The possible ErrorCodes are:
    ///     - `BUSY`: A key is already imported or in the process of being
    ///               generated.
    ///     - `OFF`: The underlying `trng` is powered down.
    ///     - `SIZE`: An invalid buffer size was supplied.
    fn generate(
        &'a self,
        trng: &'a dyn entropy::Entropy32,
        public_key_buffer: &'static mut [u8],
        private_key_buffer: &'static mut [u8],
    ) -> Result<(), (ErrorCode, &'static mut [u8], &'static mut [u8])>;
}

pub trait RsaKey: PubKey {
    /// Run the specified closure over the modulus, if it exists
    /// The modulus is returned MSB (big endian)
    /// Returns `Some()` if the key exists and the closure was called,
    /// otherwise returns `None`.
    fn map_modulus(&self, closure: &dyn Fn(&[u8])) -> Option<()>;

    /// The the modulus if it exists.
    /// The modulus is returned MSB (big endian)
    /// Returns `Some()` if the key exists otherwise returns `None`.
    /// The modulus can be returned by calling `import_public_key()` with
    /// the output of this function.
    fn take_modulus(&self) -> Option<&'static [u8]>;

    /// Returns the public exponent of the key pair if it exists
    fn public_exponent(&self) -> Option<u32>;
}

pub trait RsaPrivKey: PubPrivKey + RsaKey {
    /// Returns the specified closure over the private exponent, if it exists
    /// The exponent is returned MSB (big endian)
    /// Returns `Some()` if the key exists and the closure was called,
    /// otherwise returns `None`.
    fn map_exponent(&self, closure: &dyn Fn(&[u8])) -> Option<()>;

    /// The the private exponent if it exists.
    /// The exponent is returned MSB (big endian)
    /// Returns `Some()` if the key exists otherwise returns `None`.
    /// The exponent can be returned by calling `import_private_key()` with
    /// the output of this function.
    fn take_exponent(&self) -> Option<&'static [u8]>;
}

pub trait RsaKeyMut: PubKeyMut {
    /// Run the specified closure over the modulus, if it exists
    /// The modulus is returned MSB (big endian)
    /// Returns `Some()` if the key exists and the closure was called,
    /// otherwise returns `None`.
    fn map_modulus(&self, closure: &dyn Fn(&mut [u8])) -> Option<()>;

    /// The the modulus if it exists.
    /// The modulus is returned MSB (big endian)
    /// Returns `Some()` if the key exists otherwise returns `None`.
    /// The modulus can be returned by calling `import_public_key()` with
    /// the output of this function.
    fn take_modulus(&self) -> Option<&'static mut [u8]>;

    /// Returns the public exponent of the key pair if it exists
    fn public_exponent(&self) -> Option<u32>;
}

pub trait RsaPrivKeyMut: PubPrivKeyMut + RsaKeyMut {
    /// Returns the specified closure over the private exponent, if it exists
    /// The exponent is returned MSB (big endian)
    /// Returns `Some()` if the key exists and the closure was called,
    /// otherwise returns `None`.
    fn map_exponent(&self, closure: &dyn Fn(&mut [u8])) -> Option<()>;

    /// The the private exponent if it exists.
    /// The exponent is returned MSB (big endian)
    /// Returns `Some()` if the key exists otherwise returns `None`.
    /// The exponent can be returned by calling `import_private_key()` with
    /// the output of this function.
    fn take_exponent(&self) -> Option<&'static mut [u8]>;
}