blob: 52819acb9ec20fcc2c3c0d2997bd590f6456a7f8 [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
9G1. Take advantage of the PSA Crypto driver interface.
10G2. 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).
13
14Currently, some parts of (G1) and (G2) are implemented when
15`MBEDTLS_USE_PSA_CRYPTO` is enabled. For (G2) to take effect, the application
16needs to be changed to use new APIs.
17
18Generally speaking, the numbering above doesn't mean that each goal requires
19the preceding ones to be completed - for example it would be possible to
20start or even complete (G4) before (G3) is even started. However, (G2) and (G3)
21require operations to be done via the PSA Crypto API, which is mostly what (G1)
22is about. Also, we can't retire the legacy API (G4) until we no longer rely on
23it, which again is mostly (G1).
24
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
40The reason why `MBEDTLS_USE_PSA_CRYPTO` is optional, and disabled by default,
41is mostly to avoid introducing a hard (or even default) dependency of X509 and
42TLS and `MBEDTLS_PSA_CRYPTO_C`. This is mostly reasons of code size, and
43historically concerns about the maturity of the PSA code (which we might want
44to re-evaluate).
45
46The downside of this approach is that until we feel ready to make
47`MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain
48two versions of some parts of the code: one using PSA, the other using the
49legacy APIs. However, see next section for strategies that can lower that
50cost.
51
52Taking advantage of the existing abstractions layers - or not
53=============================================================
54
55The Crypto library in Mbed TLS currently has 3 abstraction layers that offer
56algorithm-agnostic APIs for a class of algorithms:
57
58- MD for messages digests aka hashes (including HMAC)
59- Cipher for symmetric ciphers (included AEAD)
60- PK for asymmetric (aka public-key) cryptography (excluding key exchange)
61
62Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer.
63
64These abstraction layers typically provide, in addition to the API for crypto
65operations, types and numerical identifiers for algorithms (for
66example `mbedtls_cipher_mode_t` and its values). The
67current strategy is to keep using those identifiers in most of the code, in
68particular in existing structures and public APIs, even when
69`MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3
70above, and is only potentially relevant for G4.)
71
72The are multiple strategies that can be used regarding the place of those
73layers in the migration to PSA.
74
75Silently call to PSA from the abstraction layer
76-----------------------------------------------
77
78- Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper
79 functions in the abstraction layer, that calls PSA instead of the legacy
80crypto API.
81- Upside: changes contained to a single place, no need to change TLS or X.509
82 code anywhere.
83- Downside: tricky to implement if the PSA implementation is currently done on
84 top of that layer (dependency loop).
85
86This strategy is currently used for ECDSA signature verification in the PK
87layer, and could be extended to all operations in the PK layer.
88
89This strategy is not very well suited to the Cipher and MD layers, as the PSA
90implementation is currently done on top of those layers.
91
92Replace calls for each operation
93--------------------------------
94
95- For every operation that's done through this layer in TLS or X.509, just
96 replace function call with calls to PSA (conditionally on `USE_PSA_CRYPTO`)
97- Upside: conceptually simple, and if the PSA implementation is currently done
98 on top of that layer, avoids concerns about dependency loops.
99- Downside: TLS/X.509 code has to be done for each operation.
100
101This strategy is currently used for the MD layer. (Currently only a subset of
102calling places, but could be extended to all of them.)
103
104Opt-in use of PSA from the abstraction layer
105--------------------------------------------
106
107- Provide a new way to set up a context that causes operations on that context
108 to be done via PSA.
109- Upside: changes mostly contained in one place, TLS/X.509 code only needs to
110 be changed when setting up the context, but not when using it. In
111 particular, no changes to/duplication of existing public APIs that expect a
112 key to be passed as a context of this layer (eg, `mbedtls_pk_context`).
113- Upside: avoids dependency loop when PSA implemented on top of that layer.
114- Downside: when the context is typically set up by the application, requires
115 changes in application code.
116
117There are two variants of this strategy: one where using the new setup
118function also allows for key isolation (the key is only held by PSA,
119supporting both G1 and G2 in that area), and one without isolation (the key is
120still stored outsde of PSA most of the time, supporting only G1).
121
122This strategy, with support for key isolation, is currently used for ECDSA
123signature generation in the PK layer - see `mbedtls_pk_setup_opaque()`. This
124allows use of PSA-held private ECDSA keys in TLS and X.509 with no change to
125the TLS/X.509 code, but a contained change in the application. If could be
126extended to other private key operations in the PK layer.
127
128This strategy, without key isolation, is also currently used in the Cipher
129layer - see `mbedtls_cipher_setup_psa()`. This allows use of PSA for cipher
130operations in TLS with no change to the application code, and a
131contained change in TLS code. (It currently only supports a subset of ciphers,
132but could easily be extended to all of them.)
133
134Note: for private key operations in the PK layer, both the "silent" and the
135"opt-in" strategy can apply, and can complement each other, as one provides
136support for key isolation, but at the (unavoidable) code of change in
137application code, while the other requires no application change to get
138support for drivers, but fails to provide isolation support.
139
140Migrating away from the legacy API
141==================================
142
143This section briefly introduces questions and possible plans towards G4,
144mainly as they relate to choices in previous stages.
145
146The role of the PK/Cipher/MD APIs in user migration
147---------------------------------------------------
148
149We're currently taking advantage of the existing PK and Cipher layers in order
150to reduce the number of places where library code needs to be changed. It's
151only natural to consider using the same strategy (with the PK, MD and Cipher
152layers) for facilitating migration of application code.
153
154Note: a necessary first step for that would be to make sure PSA is no longer
155implemented of top of the concerned layers
156
157### Zero-cost compatibility layer?
158
159The most favourable case is if we can have a zero-cost abstraction (no
160runtime, RAM usage or code size penalty), for example just a bunch of
161`#define`s, essentialy mapping `mbedtls_` APIs to their `psa_` equivalent.
162
163Unfortunately that's unlikely fully work. For example, the MD layer uses the
164same context type for hashes and HMACs, while the PSA API (rightfully) has
165distinct operation types. Similarly, the Cipher layer uses the same context
166type for unauthenticated and AEAD ciphers, which again the PSA API
167distinguishes.
168
169It is unclear how much value, if any, a zero-cost compatibility layer that's
170incomplete (for example, for MD covering only hashes, or for Cipher covering
171only AEAD) or differs significantly from the existing API (for example,
172introducing new context types) would provide to users.
173
174### Low-cost compatibility layers?
175
176Another possibility is to keep most or all of the existing API for the PK, MD
177and Cipher layers, implemented on top of PSA, aiming for the lowest possible
178cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union
179of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()`
180would initialize the correct part, and the rest of the functions be simple
181wrappers around PSA functions. This would vastly reduce the complexity of the
182layers compared to the existing (no need to dispatch through function
183pointers, just call the corresponding PSA API).
184
185Since this would still represent a non-zero cost, not only in terms of code
186size, but also in terms of maintainance (testing, etc.) this would probably
187be a temporary solution: for example keep the compatibility layers in 4.0 (and
188make them optional), but remove them in 5.0.
189
190Again, this provides the most value to users if we can manage to keep the
191existing API unchanged. Their might be conflcits between this goal and that of
192reducing the cost, and judgment calls may need to be made.
193
194Note: when it comes to holding public keys in the PK layer, depending on how
195the rest of the code is structured, it may be worth holding the key data in
196memory controlled by the PK layer as opposed to a PSA key slot, moving it to a
197slot only when needed (see current `ecdsa_verify_wrap` when
198`MBEDTLS_USE_PSA_CRYPTO` is defined) For example, when parsing a large
199number, N, of X.509 certificates (for example the list of trusted roots), it
200might be undesirable to use N PSA key slots for their public keys as long as
201the certs are loaded. OTOH, this could also be addressed by merging the "X.509
202parsing on-demand" (#2478), and then the public key data would be held as
203bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot
204when it's actually used.
205
206Note: the PK layer actually consists of two relatively distinct parts: crypto
207operations, which will be covered by PSA, and parsing/writing (exporting)
208from/to various formats, which is currently not fully covered by the PSA
209Crypto API.
210
211### Algorithm identifiers and other identifiers
212
213It should be easy to provide the user with a bunch of `#define`s for algorithm
214identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of
215those would be in the MD, Cipher and PK compatibility layers mentioned above,
216but there might be some in other modules that may be worth considering, for
217example identifiers for elliptic curves.
218
219### Lower layers
220
221Generally speaking, we would retire all of the low-level, non-generic modules,
222such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing
223compatibility APIs for them. People would be encouraged to switch to the PSA
224API. (The compatiblity implementation of the existing PK, MD, Cipher APIs
225would mostly benefit people who already used those generic APis rather than
226the low-level, alg-specific ones.)
227
228### APIs in TLS and X.509
229
230Public APIs in TLS and X.509 may be affected by the migration in at least two
231ways:
232
2331. APIs that rely on a legacy `mbedtls_` crypto type: for example
234 `mbedtls_ssl_conf_own_cert()` to configure a (certificate and the
235associated) private key. Currently the private key is passed as a
236`mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`.
237Since some users would probably still be using the compatibility PK layer, it
238would need a way to easily extract the PSA key ID from the PK context.
239
2402. APIs the accept list of identifiers: for example
241 `mbedtls_ssl_conf_curves()` taking a list of `mbedtls_ecp_group_id`s. This
242could be changed to accept a list of pairs (`psa_ecc_familiy_t`, size) but we
243should probably take this opportunity to move to a identifier independant from
244the underlying crypto implementation and use TLS-specific identifiers instead
245(based on IANA values or custom enums), as is currently done in the new
246`mbedtls_ssl_conf_groups()` API, see #4859).
247
248Testing
249-------
250
251An question that needs careful consideration when we come around to removing
252the low-level crypto APIs and making PK, MD and Cipher optional compatibility
253layers is to be sure to preserve testing quality. A lot of the existing test
254cases use the low level crypto APIs; we would need to either keep using that
255API for tests, or manually migrated test to the PSA Crypto API. Perhaps a
256combination of both, perhaps evolving gradually over time.