blob: dda65f15a2cf7a0b81b2490884fd9967a123da96 [file] [log] [blame] [view]
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +02001This document explains feature guards macros to be used during the transition
2from legacy to PSA in order to determine whether a given cryptographic
3mechanism is available in the current build.
4
5We currently (as of Mbed TLS 3.6) have three sets of feature macros:
6- `PSA_WANT` macros;
7- legacy `MBEDTLS_xxx` macros;
8- transitional `MBEDTLS_xxx` macros that stem from the desire to be able to
9 use crypto mechanisms that are only provided by a driver (G5 in
10`strategy.md`).
11
12This document's goal is to shed some light on when to use which. It is mostly
13intended for maintainers.
14
15Since most transition macros come from driver-only work, it can be useful to
16check `docs/driver-only-builds.md` as well for background. (Note: as
17maintainers, for the best precision about what's supported of not with
18drivers, check the relevant `component_test_psa_crypto_config_accel_xxx`'s
19configuration, as well as the corresponding exclude list in
20`analyze_outcomes.py`.)
21
22General considerations
23======================
24
25This document only applies to Mbed TLS 3.6 TLS. By contrast:
26- in 2.28 we have no driver-only support, so the legacy guards `MBEDTLS_XXX`
27 should be used everywhere;
28- in 4.0 configuration will be purely based on PSA, so `PSA_WANT` macros
29 should be used everywhere.
30
31It is useful to consider the following domains:
32- The PSA domain: things declared in `include/psa/*.h`, implemented in
33 `library/psa_*.c` and tested in `tests/suites/test_suite_psa*`.
34- The pure TLS 1.3 domain: the parts of TLS 1.3 that are not in the `USE_PSA`
35 domain (see below). Those use PSA APIs unconditionally.
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +020036- The `USE_PSA` domain (that is, code that calls PSA crypto APIs when
37 `USE_PSA` is enabled, and legacy crypto APIs otherwise): that's PK, X.509,
38most of TLS 1.2 and the parts of TLS 1.3 that are common with TLS 1.2 or are
39about public/private keys (see `docs/use-psa-crypto.md` for details).
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020040- The legacy crypto domain: a number of modules there will use crypto from
41 other modules, for example RSA and entropy will use hashes, PEM will use
42hashes and ciphers (from encrypted PEM), etc.
43
44The first two categories (PSA domain, pure TLS 1.3 domain) are simple: as a
45general rule, use `PSA_WANT` macros. (With very few exceptions, see
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +020046`component_check_test_dependencies` in `all.sh`.) In the rare instances where it is necessary to
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020047check whether a mechanism is built-in or provided by a driver,
48`MBEDTLS_PSA_BUILTIN_xxx` and `MBEDTLS_PSA_ACCEL_xxx` macros should be used
49(but not legacy `MBEDTLS_xxx` macros).
50
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +020051For the `USE_PSA` domain, it should always be correct to use expressions like
52`(!USE_PSA && MBEDTLS_xxx) || (USE_PSA && PSA_WANT_xxx)`. Sometimes, macros
53are defined in order to avoid using long expressions everywhere; they will be
54mentioned in the following sections.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020055
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +020056The remaining category, the legacy domain, tends to be more complex. There are
57different rules for different families of mechanisms, as detailed in the
58following sections.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020059
60Symmetric crypto
61================
62
63Hashes
64------
65
66**Hash vs HMAC:** Historically (since 2.0) we've had the generic hash
67interface, and the implementation of HMAC, in the same file controlled by a
Manuel Pégourié-Gonnard3342e802024-07-23 09:57:57 +020068single feature macro: `MBEDTLS_MD_C`. This has now been split in two:
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020069- `MBEDTLS_MD_LIGHT` is about the generic hash interface; we could think of it
70 as `MBEDTLS_HASH_C`.
Manuel Pégourié-Gonnard3342e802024-07-23 09:57:57 +020071- `MBEDTLS_MD_C` is about the HMAC implementation; we could think of it as
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020072 `MBEDTLS_HMAC_C` (auto-enabling `MBEDTLS_HASH_C`).
Manuel Pégourié-Gonnard3342e802024-07-23 09:57:57 +020073
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020074(In fact, this is not the whole story: `MD_LIGHT` is the _core_ of the generic
75hash interface, excluding functions such as `mbedtls_md_list()` and
76`mbedtls_md_info_from_string()`, `mbedtls_md_file()`, etc. But I think the
77above should still provide a good intuition as first approximation.)
78
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +020079Note that all users of hashes in the library use either the PSA Crypto API or the `md.h` API.
80That is, no user in the library, even in the legacy domain, uses the low-level hash APIs
81(`mbedtls_sha256` etc). (That's not true of all example programs, though.)
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020082
83**Helper macros:** in `config_adjust_legacy_crypto.h` we define a family of
84macro `MBEDTLS_MD_CAN_xxx`. These macros are defined (for available hashes) as
85soon as `MBEDTLS_MD_LIGHT` is enabled. This subset of `MD` is automatically
86enabled as soon as something from the legacy domain, or from the `USE_PSA`
Manuel Pégourié-Gonnard3342e802024-07-23 09:57:57 +020087domain, needs a hash. (Note that this includes `ENTROPY_C`, so in practice
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020088`MD_LIGHT` is enabled in most builds.)
89
90Note that there is a rule, enforced by `config_adjust_psa_superset_legacy.h`,
Manuel Pégourié-Gonnard60769762024-09-26 09:54:30 +020091that as soon as `PSA_CRYPTO_C` is enabled, all hashes that are enabled on the
92legacy side are also enabled on the PSA side (the converse is not true: a hash
93that's provided by a driver will typically be available only on the PSA side). So, in
94practice, when `PSA_CRYPTO_C` and `MD_LIGHT` are both enabled,
95`PSA_WANT_ALG_xxx` and `MBEDTLS_MD_CAN_xxx` are equivalent.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +020096
97**Legacy and `USE_PSA` domains:** for hashes, `MBEDTLS_MD_CAN_xxx` (where
98`xxx` is the legacy name of the hash) can be used everywhere (except in the
99PSA domain which should use `PSA_WANT` as usual). No special include is
100required, `build_info.h` or `common.h` is enough.
101
102**Pure TLS 1.3 domain:** it is not easy to know which uses of hashes fall in
Manuel Pégourié-Gonnard83f62ff2024-09-26 10:14:55 +0200103this domain as opposed to the `USE_PSA` domain whithout looking at the code.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200104Fortunately, `MD_CAN` and `PSA_WANT` macros can be used interchangeably, as
105per the note above.
106
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200107HMAC
108----
109
110**Legacy domain:** the code is using the `md.h` API. For this domain,
111availability of HMAC-xxx is determined by `MBEDTLS_MD_C && MBEDTLS_MD_CAN_xxx`
112(see previous subsection about `MD_CAN`). Modules in this domain that may use
113HMAC are PKCS5, PKCS7, HKDF, HMAC-DRBG and ECDSA deterministic.
114
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +0200115**`USE_PSA` domain:** code will use the `md.h` API when `USE_PSA` is disabled,
116and the `psa_mac` API when `USE_PSA` is enabled. It should check for the
117availability of HMAC-xxx with either:
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200118```
119((!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_MD_C) ||
120 (MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ALG_HMAC)) &&
121MBEDTLS_MD_CAN_xxx
122```
123or
124```
125(!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_MD_C && MBEDTLS_xxx_C) ||
126(MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ALG_HMAC && PSA_WANT_ALG_xxx)
127```
128or any equivalent condition (see note at the end of the previous section).
129The only module in this case is TLS, which currently depends on
130`USE_PSA_CRYPTO || MD_C`.
131
132Note: while writing this, it occurs to me that TLS 1.2 does not seem to be
133checking for `PSA_WANT_ALG_HMAC` before enabling CBC ciphersuites when
134`USE_PSA` is enabled, which I think it should. Builds with `USE_PSA` enabled,
135`PSA_WANT_ALG_HMAC` disabled and other requirements for CBC ciphersuites
136enabled, are probably broken (perhaps only at runtime when a CBC ciphersuite
137is negotiated).
138
139**Pure TLS 1.3 domain:** HMAC is used for the Finished message via PSA Crypto
140APIs. So, TLS 1.3 should depend on `PSA_WANT_ALG_HMAC` - doesn't seem to be
Manuel Pégourié-Gonnard49752322024-07-23 12:58:35 +0200141enforced by `check_config.h`, or documented in `mbedtls_config.h`, at the
142moment.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200143
144Ciphers (AEAD and unauthenticated)
145----------------------------------
146
Manuel Pégourié-Gonnard9fc3b7d2024-09-26 11:00:02 +0200147**Overview of existing (internal) APIs:** we currently have 5 (families of)
148APIs for ciphers (and associated constructs) in the library:
149- Low-level API for primitives: `mbedtls_aes_xxx` etc. - used by `cipher.c`
150 and some other modules in the legacy domain.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200151- Internal abstraction layer `block_cipher` for AES, ARIA and Camellia
152 primitives - used only by `gcm.c` and `ccm.c`, only when `CIPHER_C` is not
153enabled (for compatibility reasons).
Manuel Pégourié-Gonnard9fc3b7d2024-09-26 11:00:02 +0200154- Block cipher modes / derivatives:
155 - `mbedtls_gcm_xxx` and `mbedtls_ccm_xxx`, used by `cipher.c` and
156 the built-in PSA implementation;
157 - `mbedtls_nist_kw_xxx`, used by `cipher.c`;
158 - `mbedtls_cipher_cmac_xxx`, used by the built-in PSA implementation;
159 - `mbedtls_ctr_drbg_xxx`, used by PSA crypto's RNG subsystem.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200160- Cipher: used by some modules in the legacy domain, and by the built-in PSA
161 implementation.
162- PSA: used by the `USE_PSA` domain when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
163
164**Legacy domain:** most code here is using either `cipher.h` or low-level APIs
165like `aes.h`, and should use legacy macros like `MBEDTLS_AES_C` and
Manuel Pégourié-Gonnard3342e802024-07-23 09:57:57 +0200166`MBEDTLS_CIPHER_MODE_CBC`. This includes NIST-KW, CMAC, PKCS5/PKCS12 en/decryption
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200167functions, PEM decryption, PK parsing of encrypted keys. The only exceptions
Manuel Pégourié-Gonnard9fc3b7d2024-09-26 11:00:02 +0200168are:
1691. `GCM` and `CCM` use the internal abstraction layer `block_cipher` and check
170 for availability of block ciphers using `MBEDTLS_CCM_GCM_CAN_xxx` macros
171defined in `config_adjut_legacy_crypto.h`. As a user, to check if AES-GCM is
172available through the `mbedtls_gcm` API, you want to check for `MBEDTLS_GCM_C`
173and `MBDTLS_CCM_GCM_CAN_AES`.
1742. `CTR_DRBG` uses the low-level `mbedtls_aes_` API if it's available,
175 otherwise it uses the PSA API. There is no need for users of `CTR_DRBG` to
176check if AES is available: `check_config.h` is already taking care of that, so
177from a user's perspective as soon as `MBEDTLS_CTR_DRBG_C` is enabled, you can
178use it without worrying about AES.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200179
180**`USE_PSA` domain:** here we should use conditions like the following in
181order to test for availability of ciphers and associated modes.
182```
183// is AES available?
184(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \
185(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES))
186// is CBC available?
187(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \
188(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING))
189// is GCM available?
190(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \
191(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))
192```
193Note: TLS is the only user of ciphers in the `USE_PSA` domain, and it defines
194`MBEDTLS_SSL_HAVE_xxx` macros in `config_adjust_legacy_crypto.h` for the
195ciphers and modes it needs to know about.
196
197**Pure TLS 1.3 domain:** none. All from TLS 1.3 are in the `USE_PSA` domain
198(common to TLS 1.2).
199
200Key derivation
201--------------
202
Manuel Pégourié-Gonnard83f62ff2024-09-26 10:14:55 +0200203**Legacy domain:** the modules PKCS5 and PKCS12 both provide
204key derivation (respectively PBKDF2-HMAC and PKCS12 derivation), and use it
205for password-based encryption. (Note: PEM has an implementation of PBKDF1 but
206it's internal.)
207
208**`USE_PSA` domain:** PK (parse) will use PKCS5 and PKCS12 encryption (hence
209indirectly key derivation) if present in the build. The macros are
210`MBEDTLS_PKCS5_C` and `MBEDTLS_PKCS12_C`. Note that even when `USE_PSA` is
211enabled, PK parse will _not_ use PSA for the PBKDF2 part of PKCS5 decryption.
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200212
213**Pure TLS 1.3 domain:** TLS 1.3 is using HKDF via PSA Crypto APIs. We already
214enforce in `check_config.h` that TLS 1.3 depends on the appropriate `PSA_WANT`
215macros.
216
217Asymmetric crypto
218=================
219
220RSA
221---
222
223**Legacy domain and `USE_PSA` domain:** use `RSA_C` everywhere. (Note: there's
224no user of RSA in the legacy domain, and the only direct user in the `USE_PSA`
225domain is PK - both X.509 and TLS will only RSA via PK.)
226
227**Pure TLS 1.3 domain:** no use of RSA in this domain. All TLS 1.3 uses of RSA
228go through PK, hence are in the `USE_PSA` domain.
229
230FFDH
231----
232
233**Legacy domain and `USE_PSA` domain:** use `DHM_C`. The only user is TLS 1.2
234which is actually in the legacy domain - this is an exception where `USE_PSA`
235has no effect, because PSA doesn't cover the needs of TLS 1.2 here.
236
237**Pure TLS 1.3 domain:** use `PSA_WANT`. The TLS 1.3 code for Diffie-Hellman
238is common to ECDH and FFDH thanks to PSA Crypto APIs being generic enough. The
239parts about FFDH are guarded with `PSA_WANT_ALG_FFDH` (with the reasoning that
240this implies support for the corresponding key type).
241
242ECC
243---
244
Manuel Pégourié-Gonnard60769762024-09-26 09:54:30 +0200245**Curves:** in `config_adjut_psa_superset_legacy.h` we ensure that, as soon as
246`PSA_CRYPTO_C` is enabled, all
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200247curves that are supported on the legacy side (`MBEDTLS_ECP_DP_xxx_ENABLED`)
Manuel Pégourié-Gonnard60769762024-09-26 09:54:30 +0200248are also supported on the PSA side (`PSA_WANT_ECC_xxx`). (The converse is not
249true as a curve provided by a driver will typically only be available on the
250PSA side).
Manuel Pégourié-Gonnard06adca42024-05-23 09:12:24 +0200251
252In `config_adjust_legacy_crypto.h` we define macros `MBEDTLS_ECP_HAVE_xxx`.
253These macros are useful for data and functions that have users in several
254domains, such as `mbedtls_ecc_group_to_psa()`, or that have users only in the
255`USE_PSA` domain but want a simpler (if sub-optimal) condition, such as
256`mbedtls_oid_get_ec_grp()`.
257
258Strictly speaking, code in the `USE_PSA` domain should not use the above
259`MBEDTLS_ECP_HAVE_xxx` macros but conditions like
260```
261(!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_ECP_DP_xxx_ENABLED) ||
262(MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ECC_xxx)
263```
264Note while writing: a lot of tests for things in the `USE_PSA` domain appear
265to be using `MBEDTLS_ECP_HAVE_xxx`. IMO this is incorrect, but not caught by
266the CI because I guess we don't run tests in configurations that have both
267`USE_PSA_CRYPTO` disabled, and some curves enabled only on the PSA side. My
268initial feeling is we don't care about such configurations as this point, and
269can leave the dependencies as they are until they're replaced with `PSA_WANT`
270macros in 4.0 anyway.
271
272**Legacy domain:** use the legacy macros `ECP_C`, `ECDH_C`, `ECDSA_C`,
273`ECJPAKE_C`, `MBEDTLS_ECP_DP_xxx_ENABLED`. (This is mostly just ECDH, ECDSA
274and EC J-PAKE using ECP.)
275
276**Key management, `USE_PSA` domain:** `MBEDTLS_PK_HAVE_ECC_KEYS` means that PK
277supports ECC key parsing and writing (and storage). It does not imply support
278for doing crypto operation with such keys - see `MBEDTLS_PK_CAN_ECDSA_xxx`
279above for that.
280
281**ECDH, `USE_PSA` domain:** this is just TLS 1.2. It's using the helper macro
282`MBEDTLS_CAN_ECDH` defined in `config_adjust_legacy_crypto.h` (which should
283probably be called `MBEDTLS_SSL_TLS1_2_CAN_ECDH` as it's only for TLS 1.2).
284(Note: the macro is not used directly in the code, it's only used as a
285dependency for relevant TLS 1.2 key exchanges. Then the code uses the guards
286for the key exchanges.)
287
288**ECDH, pure TLS 1.3 domain:** using `PSA_WANT_ALG_ECDH`.
289
290**ECDSA, `USE_PSA` domain:** should use the macros
291`MBEDTLS_PK_CAN_ECDSA_{SIGN,VERIFY,SOME}` that indicate support for signature
292generation, verification, or at least one of those, respectively. To check for
293support for signatures with a specific hash, combine
294`MBEDTLS_PK_CAN_ECDSA_xxx` with `MBEDTLS_MD_CAN_xxx`.
295
296**ECDSA, pure TLS 1.3 domain:** none - everything goes through PK.
297
298**EC J-PAKE, `USE_PSA` domain:** only used by TLS 1.2. The code is guarded by
299the corresponding `KEY_EXCHANGE` macro, which in `check_config.h` depends on
300the appropriate macros depending on whether `USE_PSA` is on or off.
301
302**EC J-PAKE, pure TLS 1.3 domain:** none - EC J-PAKE is TLS 1.2 (so far).
303
304**Related internal macros:**
305- `MBEDTLS_PK_USE_PSA_EC_DATA` is an internal switch of the PK module. When
306 it's not defined, PK stores ECC keys as a `struct mbedtls_ecxxx_keypair`;
307when it's defined, PK stores in a PSA -friendly format instead (PSA key slot
308for private keys, metadata + array of bytes with the PSA import/export format
309for the public part). This macro is only defined when `ECP_C` is not and
310`USE_PSA` is, see comments above its definition in `pk.h` for details.
311- `MBEDTLS_ECP_LIGHT` enables only a subset of `ecp.c`. This subset is pretty
312 much ad hoc: it's basically everything that doesn't depend on scalar
313multiplication (_the_ complex expensive operation in ECC arithmetic).
314Basically, this subset gives access to curve data (constants), key storage,
315basic parsing and writing. It is auto-enabled in some driver-only
316configurations where the user has disabled `ECP_C` because they have drivers
317for the crypto operations they use, but they've also asked for some things
318that are not supported by drivers yet, such as deterministic key derivation,
319or parsing of compressed keys - on those cases, `ECP_LIGHT` will support this
320needs without bringing back the full `ECP_C`.