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
// SPDX-License-Identifier: MIT OR Apache-2.0
// SPDX-FileCopyrightText: Inria-AIO, Cryspen, and Christian Amsüss
//! embedded-cal is a family of interface traits around cryptography, primarily [`Cal`].
//!
//! *Users of the trait* can implement their high-level cryptographic protocol implementation
//! libraries or applications on top of the trait, and leverage hardware acceleration available on
//! some platforms, without being tied to a particular implementation of the algorithms or a
//! aprticular acceleration module.
//!
//! *Providers of the trait* can be software implementations, specific hardware platforms, or
//! embedded operating systems that provide whichever acceleration or algorithms are configured for
//! a givens build.
//!
//! Neither the users or nor the providers are generally implemented in this crate; however, being
//! the centerpiece of the embedded-cal ecosystem, this documentation points to some noteworthy
//! implementations outside the crate.
//!
//! ## How to use this crate
//!
//! ### … as a user
//!
//! When a library you use requires you to pass in an implementation of [`Cal`], their functions
//! are generic over implementations of [`Cal`].
//!
//! Depending on the system you use the library on, you can obtain a suitable instance to pass in
//! from:
//!
//! * Your operating system.
//! * On embedded systems, this can be provided explicitly by the RTOS (e.g. work in progress in
//! Ariel OS and RIOT OS).
//! * On `std` systems, you can use software based implementations, which (while fundamentally
//! composable) generally offer a feature for ready-to-use construction (e.g.
//! `embedded_cal_libcrux::Standalone::standalone()` or
//! `embedded_cal_rustcrypto::Standalone::standalone()`.
//! * When developing on bare metal, an implementation such as `embedded-cal-nrf54l15` can be
//! constructed from the underlying hardware registers, and later augmented with software layers.
//! An example of doing this can be found in FIXME.
//!
//! ### … as a high-level library author
//!
//! When writing a library, be generic over `Cal` implementations.
//!
//! Where possible, it is recommended to take short-lived references to a `Cal`, because this
//! enables users to go with a lock-free exclusive version where that is an advantage.
//!
//! ### … when wrapping hardware
//!
//! Most parts of the [`Cal`] trait are optional to implement, in the sense that supporting no
//! algorithms is easy. (This is the reason why rather than having a single trait, there is an
//! [`Cal::AeadProvider`] iand [`.aead()`][Cal::aead()] accessor: If your hardware can not do it,
//! just don't provide it.
//!
//! In particular, for many aspects (list growing), there are "plumbing" traits you can implement
//! instead. For example, for SHA2, implement
//! [`plumbing::hash::Sha2Short`] and set [`SUPPORTED =
//! true`][plumbing::hash::Sha2Short::SUPPORTED]. While this does not
//! immediately give the users access to the algorithms, a higher-up wrapper can pick up the parts
//! and fill in the gaps. This way, edge-case prone buffer handling can be done by more carefully
//! vetted components rather than being repetitively implemented.
//!
//! ### … as an embedded RTOS maintainer
//!
//! Provide an easy single type implementing [`Cal`]. Configuration should happen outside of the
//! RTOS, typically in system-wide build configuration. By default, it is recommended to build from
//! whichever accelerated type is available for the hardware, and use `embedded-cal-libcrux` to
//! fill gaps.
//!
//! On many systems, that type needs to be a singleton and can not be shared (e.g. because it needs
//! exclusive access to some registers).
//!
//! On systems where mutex-style access is widespread, provide a mutex based implementation that
//! can be shared / cloned easily, so that libraries that can not do everything in short-lived
//! operations can be given something to work with. This API can be enabled conditionally based on
//! whether any user in the current build requests it.
//!
//! It is recommended to also have an accessor for short-time access available unconditionally. If
//! the mutex based API is requested, this merely hands out another copy of the shared instance;
//! otherwise, it can use a simpler run-time (or even build-time) check.
//!
//! ## Distinguishing properties and related work
//!
//! The interfaces of this crate are geared towards *cryptographic agility*: An application should
//! not need to be changed in order to support a larger set of hash functions or elliptic curves.
//! This is aligned with how higher-level cryptographic systems such as COSE or TLS work:
//! algorithms are negotiated rather than built into the protocol. In this, embedded-cal is
//! distinct from many rustcrypto traits such as [`aead`](https://docs.rs/aead/latest/aead/) or
//! [`digest`](https://docs.rs/digest/latest/digest/), through which generic application code gets
//! monomorphized onto a concrete algorithm.
//!
//! The crates focus on the *Embedded Rust ecosystem*, which includes bare metal and RTOS
//! applications. It is `no_std`, and does not use dynamic allocation in general. In this,
//! embedded-cal is distinct from the otherwise similar [PSA Crypto
//! API](https://arm-software.github.io/psa-api/crypto/) (which uses C embedded idioms).
//!
//! Implementations of embedded-cal are *composable*: Rather than having to select a single
//! provider of cryptographic tools, it allows picking suitable parts. For example, a software
//! implementation can be composed from the OS's source of randomness and the [libcrux software
//! implementation](https://crates.io/crates/embedded-cal-libcrux); on embedded hardware, there is
//! typically one layer of what the hardware can do, augmented by a software layer that fills gaps
//! (e.g. when the hardware accelerates elliptic curves primitives, and the software then make a
//! full DH key establishment out of it). Also, different algorithms can be served by different
//! components.
//!
//! While currently no implementations use it, the library is designed *with resident secrets in
//! mind*: Keys are never required to be visible to the user, by virtue of using associated types
//! in many places. This way, implementations based on secure elements can use either encapsulated
//! keys or key slot handles.
// FIXME: Once we start API stability, this should be a dedicated crate.
pub use ;
pub use ;
pub use ImportError;
pub use ;
pub use ;
pub use ;
pub use test_tryrng;
/// Accessors to the deep associated types of a [`Cal`].
///
/// As associated types often need explicit naming of the trait (even when the trait is in scope),
/// and due to the various Provider traits being associated types, accessing eg. a Cal's AEAD
/// algorithm type is relatively cumbersome.
///
/// This module provides easy `{Interface}{Type}Of` style type aliases for various values of
/// `Interface` and `Type`.
///
/// For example, [`AeadAlgorithmOf<C>`][accessor::AeadAlgorithmOf] is a shorthand way of writing
/// `<<C as Cal>::AeadProvider as AeadProvider>::Algorithm`, which would often be required because
/// associated type trait requirements are not automatically made available.
/// Cryptographic abstraction provider that encompasses all features abstracted by the
/// embedded-cal.
///
/// To ease implementation and give better access to its aspects, this does not have a list of
/// supertraits, but rather various associated types and acccessors to them.
///
/// These allow passing on full portions of the feature set between implementations. Common choices
/// for the associated type and the corresponding accessor implementation are:
///
/// * `type XxxProvider = Self` / `self`, when an object does provide that functionality.
/// * `type XxxProvider = Self::Base` / `self.base.xxx()`, when an extender does not touch that
/// functionality at all and merely forwards it to whatever is being extended.
/// * `type XxxProvider = embedded_cal::empty::EmptyCal` / `&mut self.empty`, when a non-extender
/// (typically a hardware module) does not implement something at all.
///
/// Note that to keep the types reasonably simple, the accessors are `fn(&mut Self) -> &mut
/// Self::XxxProvider`, which requires an existing (albeit zero-sized) [`EmptyCal`][empty::EmptyCal],
/// which is most easily provided by adding one as a field to the `Self` struct. (The alternative
/// would be to go through `AsMut` indirections or use lifetime-generic associated types like
/// `type XxxProvider<'t> = &mut Self` / `= Empty`, and that is not only unergonomic, it also
/// hinders restraining them in `where` clauses).