wasefire_board_api/
crypto.rs1#[cfg(feature = "internal-crypto-rng")]
18use core::marker::PhantomData;
19
20#[cfg(feature = "internal-api-crypto-hash")]
21use crypto_common::BlockSizeUser;
22#[cfg(any(feature = "internal-api-crypto-hash", feature = "internal-api-crypto-hmac"))]
23use crypto_common::Output;
24#[cfg(feature = "internal-api-crypto-hmac")]
25use crypto_common::{InvalidLength, KeyInit};
26#[cfg(feature = "internal-api-crypto-hash")]
27use digest::HashMarker;
28#[cfg(feature = "internal-api-crypto-hmac")]
29use digest::MacMarker;
30#[cfg(any(feature = "internal-api-crypto-hash", feature = "internal-api-crypto-hmac"))]
31use digest::{FixedOutput, Update};
32#[cfg(feature = "internal-crypto-rng")]
33use signature::rand_core;
34#[cfg(feature = "internal-api-crypto-hmac")]
35use wasefire_error::Code;
36#[cfg(feature = "internal-with-error")]
37use wasefire_sync::TakeCell;
38
39#[cfg(feature = "internal-with-error")]
40use crate::Error;
41#[cfg(any(feature = "internal-api-crypto-hash", feature = "internal-api-crypto-hmac"))]
42use crate::Support;
43
44#[cfg(feature = "internal-api-crypto-aead")]
45pub mod aead;
46#[cfg(feature = "internal-api-crypto-cbc")]
47pub mod cbc;
48#[cfg(feature = "internal-api-crypto-ecc")]
49pub mod ecc;
50#[cfg(feature = "internal-api-crypto-ecdh")]
51pub mod ecdh;
52#[cfg(feature = "internal-api-crypto-ecdsa")]
53pub mod ecdsa;
54#[cfg(feature = "api-crypto-ed25519")]
55pub mod ed25519;
56
57pub trait Api: Send {
59 #[cfg(feature = "api-crypto-aes128-ccm")]
61 type Aes128Ccm: aead::Api<typenum::U16, typenum::U13, Tag = typenum::U4>;
62
63 #[cfg(feature = "api-crypto-aes256-cbc")]
65 type Aes256Cbc: cbc::Api<typenum::U32, typenum::U16>;
66
67 #[cfg(feature = "api-crypto-aes256-gcm")]
69 type Aes256Gcm: aead::Api<typenum::U32, typenum::U12>;
70
71 #[cfg(feature = "api-crypto-ed25519")]
73 type Ed25519: ed25519::Api;
74
75 #[cfg(feature = "api-crypto-hmac-sha256")]
77 type HmacSha256: Hmac<KeySize = typenum::U64, OutputSize = typenum::U32>;
78
79 #[cfg(feature = "api-crypto-hmac-sha384")]
81 type HmacSha384: Hmac<KeySize = typenum::U128, OutputSize = typenum::U48>;
82
83 #[cfg(feature = "api-crypto-p256")]
85 type P256: ecc::Api<typenum::U32>;
86
87 #[cfg(feature = "api-crypto-p256-ecdh")]
89 type P256Ecdh: ecdh::Api<32>;
90
91 #[cfg(feature = "api-crypto-p256-ecdsa")]
93 type P256Ecdsa: ecdsa::Api<32>;
94
95 #[cfg(feature = "api-crypto-p384")]
97 type P384: ecc::Api<typenum::U48>;
98
99 #[cfg(feature = "api-crypto-p384-ecdh")]
101 type P384Ecdh: ecdh::Api<48>;
102
103 #[cfg(feature = "api-crypto-p384-ecdsa")]
105 type P384Ecdsa: ecdsa::Api<48>;
106
107 #[cfg(feature = "api-crypto-sha256")]
109 type Sha256: Hash<BlockSize = typenum::U64, OutputSize = typenum::U32>;
110
111 #[cfg(feature = "api-crypto-sha384")]
113 type Sha384: Hash<BlockSize = typenum::U128, OutputSize = typenum::U48>;
114}
115
116#[cfg(feature = "internal-api-crypto-hash")]
118pub trait Hash:
119 Support<bool> + Send + Default + BlockSizeUser + Update + FixedOutput + HashMarker + WithError
120{
121}
122#[cfg(feature = "internal-api-crypto-hmac")]
124pub trait Hmac:
125 Support<bool> + Send + KeyInit + Update + FixedOutput + MacMarker + WithError
126{
127}
128
129#[cfg(feature = "internal-api-crypto-hash")]
130impl<T> Hash for T where T: Support<bool>
131 + Send
132 + Default
133 + BlockSizeUser
134 + Update
135 + FixedOutput
136 + HashMarker
137 + WithError
138{
139}
140#[cfg(feature = "internal-api-crypto-hmac")]
141impl<T> Hmac for T where T: Support<bool> + Send + KeyInit + Update + FixedOutput + MacMarker + WithError
142{}
143
144#[cfg(feature = "internal-with-error")]
146pub trait WithError {
147 fn with_error<T>(operation: impl FnOnce() -> T) -> Result<T, Error>;
153}
154
155#[cfg(feature = "internal-with-error")]
157pub trait NoError {}
158
159#[cfg(feature = "internal-with-error")]
160impl<T: NoError> WithError for T {
161 fn with_error<R>(operation: impl FnOnce() -> R) -> Result<R, Error> {
162 Ok(operation())
163 }
164}
165
166#[cfg(feature = "internal-with-error")]
168pub struct GlobalError(TakeCell<Result<(), Error>>);
169
170#[cfg(feature = "internal-with-error")]
171impl GlobalError {
172 #[allow(clippy::new_without_default)]
174 pub const fn new() -> Self {
175 GlobalError(TakeCell::new(None))
176 }
177
178 pub fn with<T>(&self, operation: impl FnOnce() -> T) -> Result<T, Error> {
182 self.0.put(Ok(()));
183 let result = operation();
184 self.0.take().map(|()| result)
185 }
186
187 pub fn record<T>(&self, x: Result<T, Error>) -> Option<T> {
191 x.inspect_err(|e| self.0.with(|x| *x = Err(*e))).ok()
192 }
193}
194
195#[cfg(feature = "internal-crypto-rng")]
197pub struct CryptoRng<T: crate::Api> {
198 rng: PhantomData<crate::Rng<T>>,
199}
200
201#[cfg(feature = "internal-crypto-rng")]
202impl<T: crate::Api> Default for CryptoRng<T> {
203 fn default() -> Self {
204 CryptoRng { rng: PhantomData }
205 }
206}
207
208#[cfg(feature = "internal-crypto-rng")]
209impl<T: crate::Api> rand_core::RngCore for CryptoRng<T> {
210 fn next_u32(&mut self) -> u32 {
211 rand_core::impls::next_u32_via_fill(self)
212 }
213
214 fn next_u64(&mut self) -> u64 {
215 rand_core::impls::next_u64_via_fill(self)
216 }
217
218 fn fill_bytes(&mut self, dest: &mut [u8]) {
219 self.try_fill_bytes(dest).unwrap()
220 }
221
222 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
223 ERROR
224 .record(<crate::Rng<T> as crate::rng::Api>::fill_bytes(dest))
225 .ok_or_else(|| core::num::NonZeroU32::new(1).unwrap().into())
226 }
227}
228
229#[cfg(feature = "internal-crypto-rng")]
230static ERROR: GlobalError = GlobalError::new();
231
232#[cfg(feature = "internal-crypto-rng")]
233impl<T: crate::Api> rand_core::CryptoRng for CryptoRng<T> {}
234
235#[cfg(feature = "internal-crypto-rng")]
236impl<T: crate::Api> WithError for CryptoRng<T> {
237 fn with_error<R>(operation: impl FnOnce() -> R) -> Result<R, Error> {
238 ERROR.with(operation)
239 }
240}
241
242#[cfg(feature = "api-crypto-aes128-ccm")]
244pub type Aes128Ccm<B> = <super::Crypto<B> as Api>::Aes128Ccm;
245
246#[cfg(feature = "api-crypto-aes256-cbc")]
248pub type Aes256Cbc<B> = <super::Crypto<B> as Api>::Aes256Cbc;
249
250#[cfg(feature = "api-crypto-aes256-gcm")]
252pub type Aes256Gcm<B> = <super::Crypto<B> as Api>::Aes256Gcm;
253
254#[cfg(feature = "api-crypto-ed25519")]
256pub type Ed25519<B> = <super::Crypto<B> as Api>::Ed25519;
257
258#[cfg(feature = "api-crypto-hmac-sha256")]
260pub type HmacSha256<B> = <super::Crypto<B> as Api>::HmacSha256;
261
262#[cfg(feature = "api-crypto-hmac-sha384")]
264pub type HmacSha384<B> = <super::Crypto<B> as Api>::HmacSha384;
265
266#[cfg(feature = "api-crypto-p256")]
268pub type P256<B> = <super::Crypto<B> as Api>::P256;
269
270#[cfg(feature = "api-crypto-p256-ecdh")]
272pub type P256Ecdh<B> = <super::Crypto<B> as Api>::P256Ecdh;
273
274#[cfg(feature = "api-crypto-p256-ecdsa")]
276pub type P256Ecdsa<B> = <super::Crypto<B> as Api>::P256Ecdsa;
277
278#[cfg(feature = "api-crypto-p384")]
280pub type P384<B> = <super::Crypto<B> as Api>::P384;
281
282#[cfg(feature = "api-crypto-p384-ecdh")]
284pub type P384Ecdh<B> = <super::Crypto<B> as Api>::P384Ecdh;
285
286#[cfg(feature = "api-crypto-p384-ecdsa")]
288pub type P384Ecdsa<B> = <super::Crypto<B> as Api>::P384Ecdsa;
289
290#[cfg(feature = "api-crypto-sha256")]
292pub type Sha256<B> = <super::Crypto<B> as Api>::Sha256;
293
294#[cfg(feature = "api-crypto-sha384")]
296pub type Sha384<B> = <super::Crypto<B> as Api>::Sha384;
297
298#[cfg(feature = "software-crypto-aes128-ccm")]
300pub type SoftwareAes128Ccm = ccm::Ccm<aes::Aes128, typenum::U4, typenum::U13>;
301
302#[cfg(feature = "software-crypto-aes256-cbc")]
304pub type SoftwareAes256Cbc = cbc::Software<aes::Aes256>;
305
306#[cfg(feature = "software-crypto-aes256-gcm")]
308pub type SoftwareAes256Gcm = aes_gcm::Aes256Gcm;
309
310#[cfg(feature = "software-crypto-ed25519")]
312pub type SoftwareEd25519<R> = ed25519::Software<R>;
313
314#[cfg(feature = "software-crypto-hmac-sha256")]
316pub type SoftwareHmacSha256<T> = hmac::SimpleHmac<<T as Api>::Sha256>;
317
318#[cfg(feature = "software-crypto-hmac-sha384")]
320pub type SoftwareHmacSha384<T> = hmac::SimpleHmac<<T as Api>::Sha384>;
321
322#[cfg(feature = "software-crypto-p256")]
324pub type SoftwareP256<T> = ecc::Software<p256::NistP256, <T as Api>::Sha256>;
325
326#[cfg(feature = "software-crypto-p256-ecdh")]
328pub type SoftwareP256Ecdh<R> = ecdh::Software<p256::NistP256, R, 32>;
329
330#[cfg(feature = "software-crypto-p256-ecdsa")]
332pub type SoftwareP256Ecdsa<T, R> = ecdsa::Software<p256::NistP256, <T as Api>::Sha256, R, 32>;
333
334#[cfg(feature = "software-crypto-p384")]
336pub type SoftwareP384<T> = ecc::Software<p384::NistP384, <T as Api>::Sha384>;
337
338#[cfg(feature = "software-crypto-p384-ecdh")]
340pub type SoftwareP384Ecdh<R> = ecdh::Software<p384::NistP384, R, 48>;
341
342#[cfg(feature = "software-crypto-p384-ecdsa")]
344pub type SoftwareP384Ecdsa<T, R> = ecdsa::Software<p384::NistP384, <T as Api>::Sha384, R, 48>;
345
346#[cfg(feature = "software-crypto-sha256")]
348pub type SoftwareSha256 = sha2::Sha256;
349
350#[cfg(feature = "software-crypto-sha384")]
352pub type SoftwareSha384 = sha2::Sha384;
353
354#[cfg(feature = "internal-test-software-crypto")]
355mod _test_software_crypto {
356 use super::*;
357
358 macro_rules! test {
359 ($Type:ident $($Param:ident)* $([$($where:tt)*])?; $Final:path) => {
360 #[allow(dead_code, non_snake_case)]
361 fn $Type<$($Param),*>() $(where $($where)*)? {
362 fn assert<T: $Final>() {}
363 assert::<$Type<$($Param),*>>();
364 }
365 };
366 }
367
368 #[cfg(feature = "software-crypto-aes128-ccm")]
369 test!(SoftwareAes128Ccm; aead::Api<typenum::U16, typenum::U13, Tag = typenum::U4>);
370 #[cfg(feature = "software-crypto-aes256-cbc")]
371 test!(SoftwareAes256Cbc; cbc::Api<typenum::U32, typenum::U16>);
372 #[cfg(feature = "software-crypto-aes256-gcm")]
373 test!(SoftwareAes256Gcm; aead::Api<typenum::U32, typenum::U12>);
374 #[cfg(feature = "software-crypto-ed25519")]
375 test!(SoftwareEd25519 R [R: Default + rand_core::CryptoRngCore + WithError + Send];
376 ed25519::Api);
377 #[cfg(feature = "software-crypto-hmac-sha256")]
378 test!(SoftwareHmacSha256 T [T: Api]; Hmac<KeySize = typenum::U64, OutputSize = typenum::U32>);
379 #[cfg(feature = "software-crypto-hmac-sha384")]
380 test!(SoftwareHmacSha384 T [T: Api]; Hmac<KeySize = typenum::U128, OutputSize = typenum::U48>);
381 #[cfg(feature = "software-crypto-p256")]
382 test!(SoftwareP256 T [T: Api, T::Sha256: digest::FixedOutputReset]; ecc::Api<typenum::U32>);
383 #[cfg(feature = "software-crypto-p256-ecdh")]
384 test!(SoftwareP256Ecdh R [R: Default + rand_core::CryptoRngCore + WithError + Send];
385 ecdh::Api<32>);
386 #[cfg(feature = "software-crypto-p256-ecdsa")]
387 test!(SoftwareP256Ecdsa T R [T: Api, T::Sha256: digest::FixedOutputReset,
388 R: Default + rand_core::CryptoRngCore + WithError + Send];
389 ecdsa::Api<32>);
390 #[cfg(feature = "software-crypto-p384")]
391 test!(SoftwareP384 T [T: Api, T::Sha384: digest::FixedOutputReset]; ecc::Api<typenum::U48>);
392 #[cfg(feature = "software-crypto-p384-ecdh")]
393 test!(SoftwareP384Ecdh R [R: Default + rand_core::CryptoRngCore + WithError + Send];
394 ecdh::Api<48>);
395 #[cfg(feature = "software-crypto-p384-ecdsa")]
396 test!(SoftwareP384Ecdsa T R [T: Api, T::Sha384: digest::FixedOutputReset,
397 R: Default + rand_core::CryptoRngCore + WithError + Send];
398 ecdsa::Api<48>);
399 #[cfg(feature = "software-crypto-sha256")]
400 test!(SoftwareSha256[]; Hash<BlockSize = typenum::U64, OutputSize = typenum::U32>);
401 #[cfg(feature = "software-crypto-sha384")]
402 test!(SoftwareSha384[]; Hash<BlockSize = typenum::U128, OutputSize = typenum::U48>);
403}
404
405#[cfg(feature = "software-crypto-sha256")]
406impl crate::Supported for sha2::Sha256 {}
407
408#[cfg(feature = "software-crypto-sha384")]
409impl crate::Supported for sha2::Sha384 {}
410
411#[cfg(feature = "internal-software-crypto-hmac")]
412impl<D> Support<bool> for hmac::SimpleHmac<D>
413where D: Support<bool> + Default + BlockSizeUser + Update + FixedOutput + HashMarker + WithError
414{
415 const SUPPORT: bool = D::SUPPORT;
416}
417
418#[cfg(feature = "software-crypto-sha256")]
419impl NoError for sha2::Sha256 {}
420
421#[cfg(feature = "software-crypto-sha384")]
422impl NoError for sha2::Sha384 {}
423
424#[cfg(feature = "internal-software-crypto-hmac")]
425impl<D> WithError for hmac::SimpleHmac<D>
426where D: Support<bool> + Default + BlockSizeUser + Update + FixedOutput + HashMarker + WithError
427{
428 fn with_error<T>(operation: impl FnOnce() -> T) -> Result<T, Error> {
429 D::with_error(operation)
430 }
431}
432
433#[cfg(feature = "internal-api-crypto-hash")]
435pub struct HashApi<T: Hash>(T);
436
437#[cfg(feature = "internal-api-crypto-hmac")]
439pub struct HmacApi<T: Hmac>(T);
440
441#[cfg(feature = "internal-api-crypto-hash")]
442impl<T: Hash> HashApi<T> {
443 pub fn new() -> Result<Self, Error> {
445 T::with_error(|| T::default()).map(HashApi)
446 }
447
448 pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
450 T::with_error(|| self.0.update(data))
451 }
452
453 pub fn finalize_into(self, out: &mut Output<T>) -> Result<(), Error> {
455 T::with_error(|| self.0.finalize_into(out))
456 }
457}
458
459#[cfg(feature = "internal-api-crypto-hmac")]
460impl<T: Hmac> HmacApi<T> {
461 pub fn new(key: &[u8]) -> Result<Self, Error> {
463 match T::with_error(|| T::new_from_slice(key)) {
464 Ok(Ok(x)) => Ok(HmacApi(x)),
465 Ok(Err(InvalidLength)) => Err(Error::user(Code::InvalidLength)),
466 Err(e) => Err(e),
467 }
468 }
469
470 pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
472 T::with_error(|| self.0.update(data))
473 }
474
475 pub fn finalize_into(self, out: &mut Output<T>) -> Result<(), Error> {
477 T::with_error(|| self.0.finalize_into(out))
478 }
479}