blob: d63ad70145019582cfb57aa600cef0ea1cb2157b [file] [log] [blame] [view]
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +02001This document explains the strategy that was used so far in starting the
2migration to PSA Crypto and mentions future perspectives and open questions.
3
4Goals
5=====
6
7Several benefits are expected from migrating to PSA Crypto:
8
Manuel Pégourié-Gonnard74979912021-10-27 14:00:08 +02009G1. Use PSA Crypto drivers when available.
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +020010G2. Allow isolation of long-term secrets (for example, private keys).
11G3. Allow isolation of short-term secrets (for example, TLS sesssion keys).
12G4. Have a clean, unified API for Crypto (retire the legacy API).
Manuel Pégourié-Gonnard74979912021-10-27 14:00:08 +020013G5. Code size: compile out our implementation when a driver is available.
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +020014
15Currently, some parts of (G1) and (G2) are implemented when
16`MBEDTLS_USE_PSA_CRYPTO` is enabled. For (G2) to take effect, the application
17needs to be changed to use new APIs.
18
19Generally speaking, the numbering above doesn't mean that each goal requires
Manuel Pégourié-Gonnard74979912021-10-27 14:00:08 +020020the preceding ones to be completed, for example G2-G5 could be done in any
21order; however they all either depend on G1 or are just much more convenient
22if G1 is done before (note that this is not a dependency on G1 being complete,
23it's more like each bit of G2-G5 is helped by some speficic bit in G1).
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +020024
25So, a solid intermediate goal would be to complete (G1) when
26`MBEDTLS_USA_PSA_CRYPTO` is enabled - that is, all crypto operations in X.509
27and TLS would be done via the PSA Crypto API.
28
29Compile-time options
30====================
31
32We currently have two compile-time options that are relevant to the migration:
33
34- `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA
35 Crypto APIs.
36- `MBEDTLS_USE_PSA_CRYPTO` - disabled by default (enabled in "full" config),
37 controls usage of PSA Crypto APIs to perform operations in X.509 and TLS
38(G1 above), as well as the availability of some new APIs (G2 above).
39
Manuel Pégourié-Gonnarda6c601c2021-10-27 14:12:44 +020040The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default
41are:
42- it's incompatible with `MBEDTLS_ECP_RESTARTABLE`, `MBEDTLS_PSA_CRYPTO_CONFIG` and `MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER`;
43- to avoid a hard/default dependency of X509 and TLS and
44 `MBEDTLS_PSA_CRYPTO_C`, mostly reasons of code size, and historically
45concerns about the maturity of the PSA code (which we might want to
46re-evaluate).
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +020047
48The downside of this approach is that until we feel ready to make
49`MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain
50two versions of some parts of the code: one using PSA, the other using the
51legacy APIs. However, see next section for strategies that can lower that
Manuel Pégourié-Gonnarda6c601c2021-10-27 14:12:44 +020052cost. The rest of this section explains the reasons for the
53incompatibilities mentioned above.
54
55### `MBEDTLS_ECP_RESTARTABLE`
56
57Currently this option controls not only the presence of restartable APIs in
58the crypto library, but also their use in the TLS and X.509 layers. Since PSA
59Crypto does not support restartable operations, there's a clear conflict: the
60TLS and X.509 layers can't both use only PSA APIs and get restartable
61behaviour.
62
63Supporting this in PSA is on our roadmap (it's been requested). But it's way
64below generalizing support for `MBEDTLS_USE_PSA_CRYPTO` for “mainstream” use
65cases on our priority list. So in the medium term `MBEDTLS_ECP_RESTARTABLE` is
66incompatible with `MBEDTLS_USE_PSA_CRYPTO`.
67
68Note: it is possible to make the options compatible at build time simply by
69deciding that when `USE_PSA_CRYPTO` is enabled, then `MBEDTLS_ECP_RESTARTABLE`
70cease to have any effect on X.509 and TLS: it simply controls the presence of
71the APIs in libmbedcrypto. (Or we could split `ECP_RESTARTABLE` into several
72options to achieve a similar effect.) This would allow people to use
73restartable ECC in non-TLS, non-X509 code (for example firmware verification)
74with a build that also uses PSA for TLS and X509), if there is an interest for
75that.
76
77### `MBEDTLS_PSA_CRYPTO_CONFIG`
78
79X509 and TLS code use `MBEDTLS_xxx` macros to decide whether an algorithm is
80supported. This doesn't make `MBEDTLS_USE_PSA_CRYPTO` incompatible with
81`MBEDTLS_PSA_CRYPTO_CONFIG` per se, but it makes it incompatible with most
82useful uses of `MBEDTLS_PSA_CRYPTO_CONFIG`. The point of
83`MBEDTLS_PSA_CRYPTO_CONFIG` is to be able to build a library with support for
84an algorithm through a PSA driver only, without building the software
85implementation of that algorithm. But then the TLS code would consider the
86algorithm unavailable.
87
88This is tracked in https://github.com/ARMmbed/mbedtls/issues/3674 and
89https://github.com/ARMmbed/mbedtls/issues/3677. But now that I look at it with
90fresh eyes, I don't think the approach we were planning to use would actually
91works. This needs more design effort.
92
93This is something we need to support eventually, and several partners want it.
94I don't know what the priority is for `MBEDTLS_USE_PSA_CRYPTO` between
95improving driver support and covering more of the protocol. It seems to me
96that it'll be less work overall to first implement a good architecture for
97`MBEDTLS_USE_PSA_CRYPTO + MBEDTLS_PSA_CRYPTO_CONFIG` and then extend to more
98protocol featues, because implementing that architecture will require changes
99to the existing code and the less code there is at this point the better,
100whereas extending to more procotol features will require the same amount of
101work either way.
102
103### `MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER`
104
105When `MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER` is enabled, the library is
106built for use with an RPC server that dispatches PSA crypto function calls
107from multiple clients. In such a build, all the `psa_xxx` functions that take
108would normally take a `psa_key_id_t` as argument instead take a structure
109containing both the key id and the client id. And so if e.g. a TLS function
110calls `psa_import_key`, it would have to pass this structure, not just the
111`psa_key_id_t` key id.
112
113A solution is to use `mbedtls_svc_key_id_t` throughout instead of
114`psa_key_id_t`, and use similar abstractions to define values. That's what we
115do in unit tests of PSA crypto itself to support both cases. That abstraction
116is more confusing to readers, so the less we use it the better.
117
118I don't think supporting TLS and an RPC interface in the same build is an
119important use case (I don't remember anyone requesting it). So I propose to
120ignore it in the design: we just don't intend to support it.
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +0200121
122Taking advantage of the existing abstractions layers - or not
123=============================================================
124
125The Crypto library in Mbed TLS currently has 3 abstraction layers that offer
126algorithm-agnostic APIs for a class of algorithms:
127
128- MD for messages digests aka hashes (including HMAC)
129- Cipher for symmetric ciphers (included AEAD)
130- PK for asymmetric (aka public-key) cryptography (excluding key exchange)
131
132Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer.
133
134These abstraction layers typically provide, in addition to the API for crypto
135operations, types and numerical identifiers for algorithms (for
136example `mbedtls_cipher_mode_t` and its values). The
137current strategy is to keep using those identifiers in most of the code, in
138particular in existing structures and public APIs, even when
139`MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3
140above, and is only potentially relevant for G4.)
141
142The are multiple strategies that can be used regarding the place of those
143layers in the migration to PSA.
144
145Silently call to PSA from the abstraction layer
146-----------------------------------------------
147
148- Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper
149 functions in the abstraction layer, that calls PSA instead of the legacy
150crypto API.
151- Upside: changes contained to a single place, no need to change TLS or X.509
152 code anywhere.
153- Downside: tricky to implement if the PSA implementation is currently done on
154 top of that layer (dependency loop).
155
156This strategy is currently used for ECDSA signature verification in the PK
157layer, and could be extended to all operations in the PK layer.
158
Manuel Pégourié-Gonnard09503592021-10-27 14:21:23 +0200159This strategy is not very well suited to the Cipher layer, as the PSA
160implementation is currently done on top of that layer.
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +0200161
162Replace calls for each operation
163--------------------------------
164
165- For every operation that's done through this layer in TLS or X.509, just
166 replace function call with calls to PSA (conditionally on `USE_PSA_CRYPTO`)
167- Upside: conceptually simple, and if the PSA implementation is currently done
168 on top of that layer, avoids concerns about dependency loops.
169- Downside: TLS/X.509 code has to be done for each operation.
170
171This strategy is currently used for the MD layer. (Currently only a subset of
172calling places, but could be extended to all of them.)
173
174Opt-in use of PSA from the abstraction layer
175--------------------------------------------
176
177- Provide a new way to set up a context that causes operations on that context
178 to be done via PSA.
179- Upside: changes mostly contained in one place, TLS/X.509 code only needs to
180 be changed when setting up the context, but not when using it. In
181 particular, no changes to/duplication of existing public APIs that expect a
182 key to be passed as a context of this layer (eg, `mbedtls_pk_context`).
183- Upside: avoids dependency loop when PSA implemented on top of that layer.
184- Downside: when the context is typically set up by the application, requires
185 changes in application code.
186
Manuel Pégourié-Gonnard09503592021-10-27 14:21:23 +0200187This strategy is not useful when no context is used, for example with the
188one-shot function `mbedtls_md()`.
189
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +0200190There are two variants of this strategy: one where using the new setup
191function also allows for key isolation (the key is only held by PSA,
192supporting both G1 and G2 in that area), and one without isolation (the key is
193still stored outsde of PSA most of the time, supporting only G1).
194
195This strategy, with support for key isolation, is currently used for ECDSA
196signature generation in the PK layer - see `mbedtls_pk_setup_opaque()`. This
197allows use of PSA-held private ECDSA keys in TLS and X.509 with no change to
198the TLS/X.509 code, but a contained change in the application. If could be
199extended to other private key operations in the PK layer.
200
201This strategy, without key isolation, is also currently used in the Cipher
202layer - see `mbedtls_cipher_setup_psa()`. This allows use of PSA for cipher
203operations in TLS with no change to the application code, and a
204contained change in TLS code. (It currently only supports a subset of ciphers,
205but could easily be extended to all of them.)
206
207Note: for private key operations in the PK layer, both the "silent" and the
208"opt-in" strategy can apply, and can complement each other, as one provides
209support for key isolation, but at the (unavoidable) code of change in
210application code, while the other requires no application change to get
211support for drivers, but fails to provide isolation support.
212
Manuel Pégourié-Gonnard09503592021-10-27 14:21:23 +0200213Summary
214-------
215
216Stategies currently used with each abstraction layer:
217
218- PK (for G1): silently call PSA
219- PK (for G2): opt-in use of PSA (new key type)
220- Cipher (G1): opt-in use of PSA (new setup function)
221- MD (G1): replace calls at each call site
222
Manuel Pégourié-Gonnardb89fd952021-09-30 11:52:04 +0200223Migrating away from the legacy API
224==================================
225
226This section briefly introduces questions and possible plans towards G4,
227mainly as they relate to choices in previous stages.
228
229The role of the PK/Cipher/MD APIs in user migration
230---------------------------------------------------
231
232We're currently taking advantage of the existing PK and Cipher layers in order
233to reduce the number of places where library code needs to be changed. It's
234only natural to consider using the same strategy (with the PK, MD and Cipher
235layers) for facilitating migration of application code.
236
237Note: a necessary first step for that would be to make sure PSA is no longer
238implemented of top of the concerned layers
239
240### Zero-cost compatibility layer?
241
242The most favourable case is if we can have a zero-cost abstraction (no
243runtime, RAM usage or code size penalty), for example just a bunch of
244`#define`s, essentialy mapping `mbedtls_` APIs to their `psa_` equivalent.
245
246Unfortunately that's unlikely fully work. For example, the MD layer uses the
247same context type for hashes and HMACs, while the PSA API (rightfully) has
248distinct operation types. Similarly, the Cipher layer uses the same context
249type for unauthenticated and AEAD ciphers, which again the PSA API
250distinguishes.
251
252It is unclear how much value, if any, a zero-cost compatibility layer that's
253incomplete (for example, for MD covering only hashes, or for Cipher covering
254only AEAD) or differs significantly from the existing API (for example,
255introducing new context types) would provide to users.
256
257### Low-cost compatibility layers?
258
259Another possibility is to keep most or all of the existing API for the PK, MD
260and Cipher layers, implemented on top of PSA, aiming for the lowest possible
261cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union
262of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()`
263would initialize the correct part, and the rest of the functions be simple
264wrappers around PSA functions. This would vastly reduce the complexity of the
265layers compared to the existing (no need to dispatch through function
266pointers, just call the corresponding PSA API).
267
268Since this would still represent a non-zero cost, not only in terms of code
269size, but also in terms of maintainance (testing, etc.) this would probably
270be a temporary solution: for example keep the compatibility layers in 4.0 (and
271make them optional), but remove them in 5.0.
272
273Again, this provides the most value to users if we can manage to keep the
274existing API unchanged. Their might be conflcits between this goal and that of
275reducing the cost, and judgment calls may need to be made.
276
277Note: when it comes to holding public keys in the PK layer, depending on how
278the rest of the code is structured, it may be worth holding the key data in
279memory controlled by the PK layer as opposed to a PSA key slot, moving it to a
280slot only when needed (see current `ecdsa_verify_wrap` when
281`MBEDTLS_USE_PSA_CRYPTO` is defined) For example, when parsing a large
282number, N, of X.509 certificates (for example the list of trusted roots), it
283might be undesirable to use N PSA key slots for their public keys as long as
284the certs are loaded. OTOH, this could also be addressed by merging the "X.509
285parsing on-demand" (#2478), and then the public key data would be held as
286bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot
287when it's actually used.
288
289Note: the PK layer actually consists of two relatively distinct parts: crypto
290operations, which will be covered by PSA, and parsing/writing (exporting)
291from/to various formats, which is currently not fully covered by the PSA
292Crypto API.
293
294### Algorithm identifiers and other identifiers
295
296It should be easy to provide the user with a bunch of `#define`s for algorithm
297identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of
298those would be in the MD, Cipher and PK compatibility layers mentioned above,
299but there might be some in other modules that may be worth considering, for
300example identifiers for elliptic curves.
301
302### Lower layers
303
304Generally speaking, we would retire all of the low-level, non-generic modules,
305such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing
306compatibility APIs for them. People would be encouraged to switch to the PSA
307API. (The compatiblity implementation of the existing PK, MD, Cipher APIs
308would mostly benefit people who already used those generic APis rather than
309the low-level, alg-specific ones.)
310
311### APIs in TLS and X.509
312
313Public APIs in TLS and X.509 may be affected by the migration in at least two
314ways:
315
3161. APIs that rely on a legacy `mbedtls_` crypto type: for example
317 `mbedtls_ssl_conf_own_cert()` to configure a (certificate and the
318associated) private key. Currently the private key is passed as a
319`mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`.
320Since some users would probably still be using the compatibility PK layer, it
321would need a way to easily extract the PSA key ID from the PK context.
322
3232. APIs the accept list of identifiers: for example
324 `mbedtls_ssl_conf_curves()` taking a list of `mbedtls_ecp_group_id`s. This
325could be changed to accept a list of pairs (`psa_ecc_familiy_t`, size) but we
326should probably take this opportunity to move to a identifier independant from
327the underlying crypto implementation and use TLS-specific identifiers instead
328(based on IANA values or custom enums), as is currently done in the new
329`mbedtls_ssl_conf_groups()` API, see #4859).
330
331Testing
332-------
333
334An question that needs careful consideration when we come around to removing
335the low-level crypto APIs and making PK, MD and Cipher optional compatibility
336layers is to be sure to preserve testing quality. A lot of the existing test
337cases use the low level crypto APIs; we would need to either keep using that
338API for tests, or manually migrated test to the PSA Crypto API. Perhaps a
339combination of both, perhaps evolving gradually over time.