blob: 5ed7041671f8f4a320c9f4b4e22db1e5f02cf7f3 [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.
36- The `USE_PSA` domain: that's PK, X.509, most of TLS 1.2 and the parts of TLS
37 1.3 that are common with TLS 1.2 or are about public/private keys (see
38`docs/use-psa-crypto.md` for details).
39- The legacy crypto domain: a number of modules there will use crypto from
40 other modules, for example RSA and entropy will use hashes, PEM will use
41hashes and ciphers (from encrypted PEM), etc.
42
43The first two categories (PSA domain, pure TLS 1.3 domain) are simple: as a
44general rule, use `PSA_WANT` macros. (With very few exceptions, see
45`component_check_test_dependencies` in `all.sh`.) When it is necessary to
46check whether a mechanism is built-in or provided by a driver,
47`MBEDTLS_PSA_BUILTIN_xxx` and `MBEDTLS_PSA_ACCEL_xxx` macros should be used
48(but not legacy `MBEDTLS_xxx` macros).
49
50The other two categories (legacy and `USE_PSA` domains) tend to be more
51complex. There are different rules for different families of mechanisms, as
52detailed in the following sections.
53
54However as a general rule, it should always be correct for code in the
55`USE_PSA` domain to use expressions like `(!USE_PSA && MBEDTLS_xxx) ||
56(USE_PSA && PSA_WANT_xxx)`.
57
58Symmetric crypto
59================
60
61Hashes
62------
63
64**Hash vs HMAC:** Historically (since 2.0) we've had the generic hash
65interface, and the implementation of HMAC, in the same file controlled by a
66single feature macro: `MBEDTLS_MD_C`. This has now be split in two:
67- `MBEDTLS_MD_LIGHT` is about the generic hash interface; we could think of it
68 as `MBEDTLS_HASH_C`.
69- `MBEDTLS_MC_C` is about the HMAC implementation; we could think of it as
70 `MBEDTLS_HMAC_C` (auto-enabling `MBEDTLS_HASH_C`).
71(In fact, this is not the whole story: `MD_LIGHT` is the _core_ of the generic
72hash interface, excluding functions such as `mbedtls_md_list()` and
73`mbedtls_md_info_from_string()`, `mbedtls_md_file()`, etc. But I think the
74above should still provide a good intuition as first approximation.)
75
76Note that all users of hashes use either the PSA Crypto API or the `md.h` API.
77That is, no user, even in the legacy domain, uses the low-level hash APIs
78(`mbedtls_sha256` etc).
79
80**Helper macros:** in `config_adjust_legacy_crypto.h` we define a family of
81macro `MBEDTLS_MD_CAN_xxx`. These macros are defined (for available hashes) as
82soon as `MBEDTLS_MD_LIGHT` is enabled. This subset of `MD` is automatically
83enabled as soon as something from the legacy domain, or from the `USE_PSA`
84domain, needs a hash. (Note that this include `ENTROPY_C`, so in practice
85`MD_LIGHT` is enabled in most builds.)
86
87Note that there is a rule, enforced by `config_adjust_psa_superset_legacy.h`,
88that all hashes that are enabled on the legacy side are also enabled on the
89PSA side. So, in practice, when `MD_LIGHT` is enabled, `PSA_WANT_ALG_xxx` and
90`MBEDTLS_MD_CAN_xxx` are equivalent.
91
92**Legacy and `USE_PSA` domains:** for hashes, `MBEDTLS_MD_CAN_xxx` (where
93`xxx` is the legacy name of the hash) can be used everywhere (except in the
94PSA domain which should use `PSA_WANT` as usual). No special include is
95required, `build_info.h` or `common.h` is enough.
96
97**Pure TLS 1.3 domain:** it is not easy to know which uses of hashes fall in
98this domain as opposed to the `USE_PSA` domain which looking at the code.
99Fortunately, `MD_CAN` and `PSA_WANT` macros can be used interchangeably, as
100per the note above.
101
102
103
104HMAC
105----
106
107**Legacy domain:** the code is using the `md.h` API. For this domain,
108availability of HMAC-xxx is determined by `MBEDTLS_MD_C && MBEDTLS_MD_CAN_xxx`
109(see previous subsection about `MD_CAN`). Modules in this domain that may use
110HMAC are PKCS5, PKCS7, HKDF, HMAC-DRBG and ECDSA deterministic.
111
112**`USE_PSA` domain:** code will use either the `md.h` API or the `psa_mac`
113API. It should check for the availability of HMAC-xxx with either:
114```
115((!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_MD_C) ||
116 (MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ALG_HMAC)) &&
117MBEDTLS_MD_CAN_xxx
118```
119or
120```
121(!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_MD_C && MBEDTLS_xxx_C) ||
122(MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ALG_HMAC && PSA_WANT_ALG_xxx)
123```
124or any equivalent condition (see note at the end of the previous section).
125The only module in this case is TLS, which currently depends on
126`USE_PSA_CRYPTO || MD_C`.
127
128Note: while writing this, it occurs to me that TLS 1.2 does not seem to be
129checking for `PSA_WANT_ALG_HMAC` before enabling CBC ciphersuites when
130`USE_PSA` is enabled, which I think it should. Builds with `USE_PSA` enabled,
131`PSA_WANT_ALG_HMAC` disabled and other requirements for CBC ciphersuites
132enabled, are probably broken (perhaps only at runtime when a CBC ciphersuite
133is negotiated).
134
135**Pure TLS 1.3 domain:** HMAC is used for the Finished message via PSA Crypto
136APIs. So, TLS 1.3 should depend on `PSA_WANT_ALG_HMAC` - doesn't seem to be
137enforced by `check_config.h` at the moment.
138
139Ciphers (AEAD and unauthenticated)
140----------------------------------
141
142**Overview of existing (internal) APIs:** we currently have 4 (families of)
143APIs for ciphers in the library:
144- Low-level API: `mbedtls_aes_xxx` etc. - used by `cipher.c` and some other
145 modules in the legacy domain.
146- Internal abstraction layer `block_cipher` for AES, ARIA and Camellia
147 primitives - used only by `gcm.c` and `ccm.c`, only when `CIPHER_C` is not
148enabled (for compatibility reasons).
149- Cipher: used by some modules in the legacy domain, and by the built-in PSA
150 implementation.
151- PSA: used by the `USE_PSA` domain when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
152
153**Legacy domain:** most code here is using either `cipher.h` or low-level APIs
154like `aes.h`, and should use legacy macros like `MBEDTLS_AES_C` and
155`MBEDTLS_CIPHER_MOD_CBC`. This includes NIST-KW, CMAC, PKCS5 en/decryption
156functions, PEM decryption, PK parsing of encrypted keys. The only exceptions
157are `GCM` and `CCM` which use the internal abstraction layer `block_cipher`
158and check for availability of block ciphers using `MBEDTLS_CCM_GCM_CAN_xxx`
159macros defined in `config_adjut_legacy_crypto.h`.
160
161**`USE_PSA` domain:** here we should use conditions like the following in
162order to test for availability of ciphers and associated modes.
163```
164// is AES available?
165(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \
166(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES))
167// is CBC available?
168(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \
169(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING))
170// is GCM available?
171(!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \
172(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))
173```
174Note: TLS is the only user of ciphers in the `USE_PSA` domain, and it defines
175`MBEDTLS_SSL_HAVE_xxx` macros in `config_adjust_legacy_crypto.h` for the
176ciphers and modes it needs to know about.
177
178**Pure TLS 1.3 domain:** none. All from TLS 1.3 are in the `USE_PSA` domain
179(common to TLS 1.2).
180
181Key derivation
182--------------
183
184**Legacy and `USE_PSA` domains:** no users here.
185
186**Pure TLS 1.3 domain:** TLS 1.3 is using HKDF via PSA Crypto APIs. We already
187enforce in `check_config.h` that TLS 1.3 depends on the appropriate `PSA_WANT`
188macros.
189
190Asymmetric crypto
191=================
192
193RSA
194---
195
196**Legacy domain and `USE_PSA` domain:** use `RSA_C` everywhere. (Note: there's
197no user of RSA in the legacy domain, and the only direct user in the `USE_PSA`
198domain is PK - both X.509 and TLS will only RSA via PK.)
199
200**Pure TLS 1.3 domain:** no use of RSA in this domain. All TLS 1.3 uses of RSA
201go through PK, hence are in the `USE_PSA` domain.
202
203FFDH
204----
205
206**Legacy domain and `USE_PSA` domain:** use `DHM_C`. The only user is TLS 1.2
207which is actually in the legacy domain - this is an exception where `USE_PSA`
208has no effect, because PSA doesn't cover the needs of TLS 1.2 here.
209
210**Pure TLS 1.3 domain:** use `PSA_WANT`. The TLS 1.3 code for Diffie-Hellman
211is common to ECDH and FFDH thanks to PSA Crypto APIs being generic enough. The
212parts about FFDH are guarded with `PSA_WANT_ALG_FFDH` (with the reasoning that
213this implies support for the corresponding key type).
214
215ECC
216---
217
218**Curves:** in `config_adjut_psa_superset_legacy.h` we ensure that all
219curves that are supported on the legacy side (`MBEDTLS_ECP_DP_xxx_ENABLED`)
220are also supported on the PSA side (`PSA_WANT_ECC_xxx`).
221
222In `config_adjust_legacy_crypto.h` we define macros `MBEDTLS_ECP_HAVE_xxx`.
223These macros are useful for data and functions that have users in several
224domains, such as `mbedtls_ecc_group_to_psa()`, or that have users only in the
225`USE_PSA` domain but want a simpler (if sub-optimal) condition, such as
226`mbedtls_oid_get_ec_grp()`.
227
228Strictly speaking, code in the `USE_PSA` domain should not use the above
229`MBEDTLS_ECP_HAVE_xxx` macros but conditions like
230```
231(!MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_ECP_DP_xxx_ENABLED) ||
232(MBEDTLS_USE_PSA_CRYPTO && PSA_WANT_ECC_xxx)
233```
234Note while writing: a lot of tests for things in the `USE_PSA` domain appear
235to be using `MBEDTLS_ECP_HAVE_xxx`. IMO this is incorrect, but not caught by
236the CI because I guess we don't run tests in configurations that have both
237`USE_PSA_CRYPTO` disabled, and some curves enabled only on the PSA side. My
238initial feeling is we don't care about such configurations as this point, and
239can leave the dependencies as they are until they're replaced with `PSA_WANT`
240macros in 4.0 anyway.
241
242**Legacy domain:** use the legacy macros `ECP_C`, `ECDH_C`, `ECDSA_C`,
243`ECJPAKE_C`, `MBEDTLS_ECP_DP_xxx_ENABLED`. (This is mostly just ECDH, ECDSA
244and EC J-PAKE using ECP.)
245
246**Key management, `USE_PSA` domain:** `MBEDTLS_PK_HAVE_ECC_KEYS` means that PK
247supports ECC key parsing and writing (and storage). It does not imply support
248for doing crypto operation with such keys - see `MBEDTLS_PK_CAN_ECDSA_xxx`
249above for that.
250
251**ECDH, `USE_PSA` domain:** this is just TLS 1.2. It's using the helper macro
252`MBEDTLS_CAN_ECDH` defined in `config_adjust_legacy_crypto.h` (which should
253probably be called `MBEDTLS_SSL_TLS1_2_CAN_ECDH` as it's only for TLS 1.2).
254(Note: the macro is not used directly in the code, it's only used as a
255dependency for relevant TLS 1.2 key exchanges. Then the code uses the guards
256for the key exchanges.)
257
258**ECDH, pure TLS 1.3 domain:** using `PSA_WANT_ALG_ECDH`.
259
260**ECDSA, `USE_PSA` domain:** should use the macros
261`MBEDTLS_PK_CAN_ECDSA_{SIGN,VERIFY,SOME}` that indicate support for signature
262generation, verification, or at least one of those, respectively. To check for
263support for signatures with a specific hash, combine
264`MBEDTLS_PK_CAN_ECDSA_xxx` with `MBEDTLS_MD_CAN_xxx`.
265
266**ECDSA, pure TLS 1.3 domain:** none - everything goes through PK.
267
268**EC J-PAKE, `USE_PSA` domain:** only used by TLS 1.2. The code is guarded by
269the corresponding `KEY_EXCHANGE` macro, which in `check_config.h` depends on
270the appropriate macros depending on whether `USE_PSA` is on or off.
271
272**EC J-PAKE, pure TLS 1.3 domain:** none - EC J-PAKE is TLS 1.2 (so far).
273
274**Related internal macros:**
275- `MBEDTLS_PK_USE_PSA_EC_DATA` is an internal switch of the PK module. When
276 it's not defined, PK stores ECC keys as a `struct mbedtls_ecxxx_keypair`;
277when it's defined, PK stores in a PSA -friendly format instead (PSA key slot
278for private keys, metadata + array of bytes with the PSA import/export format
279for the public part). This macro is only defined when `ECP_C` is not and
280`USE_PSA` is, see comments above its definition in `pk.h` for details.
281- `MBEDTLS_ECP_LIGHT` enables only a subset of `ecp.c`. This subset is pretty
282 much ad hoc: it's basically everything that doesn't depend on scalar
283multiplication (_the_ complex expensive operation in ECC arithmetic).
284Basically, this subset gives access to curve data (constants), key storage,
285basic parsing and writing. It is auto-enabled in some driver-only
286configurations where the user has disabled `ECP_C` because they have drivers
287for the crypto operations they use, but they've also asked for some things
288that are not supported by drivers yet, such as deterministic key derivation,
289or parsing of compressed keys - on those cases, `ECP_LIGHT` will support this
290needs without bringing back the full `ECP_C`.