Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 1 | This document explains the strategy that was used so far in starting the |
| 2 | migration to PSA Crypto and mentions future perspectives and open questions. |
| 3 | |
| 4 | Goals |
| 5 | ===== |
| 6 | |
| 7 | Several benefits are expected from migrating to PSA Crypto: |
| 8 | |
Manuel Pégourié-Gonnard | 7497991 | 2021-10-27 14:00:08 +0200 | [diff] [blame] | 9 | G1. Use PSA Crypto drivers when available. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 10 | G2. Allow isolation of long-term secrets (for example, private keys). |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 11 | G3. Allow isolation of short-term secrets (for example, TLS session keys). |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 12 | G4. Have a clean, unified API for Crypto (retire the legacy API). |
Manuel Pégourié-Gonnard | 7497991 | 2021-10-27 14:00:08 +0200 | [diff] [blame] | 13 | G5. Code size: compile out our implementation when a driver is available. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 14 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 15 | As of Mbed TLS 3.2, most of (G1) and all of (G2) is implemented when |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 16 | `MBEDTLS_USE_PSA_CRYPTO` is enabled. For (G2) to take effect, the application |
Manuel Pégourié-Gonnard | 8c7b81c | 2022-07-18 11:17:06 +0200 | [diff] [blame] | 17 | needs to be changed to use new APIs. For a more detailed account of what's |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 18 | implemented, see `docs/use-psa-crypto.md`, where new APIs are about (G2), and |
| 19 | internal changes implement (G1). |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 20 | |
| 21 | Generally speaking, the numbering above doesn't mean that each goal requires |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 22 | the preceding ones to be completed. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 23 | |
| 24 | Compile-time options |
| 25 | ==================== |
| 26 | |
| 27 | We currently have two compile-time options that are relevant to the migration: |
| 28 | |
| 29 | - `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA |
| 30 | Crypto APIs. |
| 31 | - `MBEDTLS_USE_PSA_CRYPTO` - disabled by default (enabled in "full" config), |
| 32 | controls usage of PSA Crypto APIs to perform operations in X.509 and TLS |
| 33 | (G1 above), as well as the availability of some new APIs (G2 above). |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 34 | - `PSA_CRYPTO_CONFIG` - disabled by default, supports builds with drivers and |
| 35 | without the corresponding software implementation (G5 above). |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 36 | |
Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 37 | The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default |
| 38 | are: |
Manuel Pégourié-Gonnard | ce6c087 | 2022-02-01 10:34:20 +0100 | [diff] [blame] | 39 | - it's incompatible with `MBEDTLS_ECP_RESTARTABLE`; |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 40 | - to avoid a hard/default dependency of TLS, X.509 and PK on |
Manuel Pégourié-Gonnard | 80759c4 | 2022-02-08 10:33:11 +0100 | [diff] [blame] | 41 | `MBEDTLS_PSA_CRYPTO_C`, for backward compatibility reasons: |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 42 | - When `MBEDTLS_PSA_CRYPTO_C` is enabled and used, applications need to call |
| 43 | `psa_crypto_init()` before TLS/X.509 uses PSA functions. (This prevents us |
| 44 | from even enabling the option by default.) |
Tom Cosgrove | 0b86ac1 | 2022-07-29 13:44:01 +0100 | [diff] [blame] | 45 | - `MBEDTLS_PSA_CRYPTO_C` has a hard dependency on `MBEDTLS_ENTROPY_C || |
Manuel Pégourié-Gonnard | ce6c087 | 2022-02-01 10:34:20 +0100 | [diff] [blame] | 46 | MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` but it's |
Tom Cosgrove | 0b86ac1 | 2022-07-29 13:44:01 +0100 | [diff] [blame] | 47 | currently possible to compile TLS and X.509 without any of the options. |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 48 | Also, we can't just auto-enable `MBEDTLS_ENTROPY_C` as it doesn't build |
Manuel Pégourié-Gonnard | ce6c087 | 2022-02-01 10:34:20 +0100 | [diff] [blame] | 49 | out of the box on all platforms, and even less |
| 50 | `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` as it requires a user-provided RNG |
| 51 | function. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 52 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 53 | The downside of this approach is that until we are able to make |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 54 | `MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain |
| 55 | two versions of some parts of the code: one using PSA, the other using the |
| 56 | legacy APIs. However, see next section for strategies that can lower that |
Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 57 | cost. The rest of this section explains the reasons for the |
| 58 | incompatibilities mentioned above. |
| 59 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 60 | At the time of writing (early 2022) it is unclear what could be done about the |
| 61 | backward compatibility issues, and in particular if the cost of implementing |
| 62 | solutions to these problems would be higher or lower than the cost of |
| 63 | maintaining dual code paths until the next major version. (Note: these |
| 64 | solutions would probably also solve other problems at the same time.) |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 65 | |
Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 66 | ### `MBEDTLS_ECP_RESTARTABLE` |
| 67 | |
| 68 | Currently this option controls not only the presence of restartable APIs in |
| 69 | the crypto library, but also their use in the TLS and X.509 layers. Since PSA |
| 70 | Crypto does not support restartable operations, there's a clear conflict: the |
| 71 | TLS and X.509 layers can't both use only PSA APIs and get restartable |
| 72 | behaviour. |
| 73 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 74 | Supporting this in PSA is on our roadmap and currently planned for end of |
| 75 | 2022, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18883250>. |
Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 76 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 77 | It will then require follow-up work to make use of the new PSA API in |
| 78 | PK/X.509/TLS in all places where we currently allow restartable operations. |
Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 79 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 80 | ### Backward compatibility issues with making `MBEDTLS_USE_PSA_CRYPTO` always on |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 81 | |
| 82 | 1. Existing applications may not be calling `psa_crypto_init()` before using |
| 83 | TLS, X.509 or PK. We can try to work around that by calling (the relevant |
| 84 | part of) it ourselves under the hood as needed, but that would likely require |
| 85 | splitting init between the parts that can fail and the parts that can't (see |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 86 | <https://github.com/ARM-software/psa-crypto-api/pull/536> for that). |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 87 | 2. It's currently not possible to enable `MBEDTLS_PSA_CRYPTO_C` in |
| 88 | configurations that don't have `MBEDTLS_ENTROPY_C`, and we can't just |
| 89 | auto-enable the latter, as it won't build or work out of the box on all |
| 90 | platforms. There are two kinds of things we'd need to do if we want to work |
| 91 | around that: |
| 92 | 1. Make it possible to enable the parts of PSA Crypto that don't require an |
| 93 | RNG (typically, public key operations, symmetric crypto, some key |
| 94 | management functions (destroy etc)) in configurations that don't have |
| 95 | `ENTROPY_C`. This requires going through the PSA code base to adjust |
| 96 | dependencies. Risk: there may be annoying dependencies, some of which may be |
| 97 | surprising. |
| 98 | 2. For operations that require an RNG, provide an alternative function |
| 99 | accepting an explicit `f_rng` parameter (see #5238), that would be |
| 100 | available in entropy-less builds. (Then code using those functions still needs |
| 101 | to have one version using it, for entropy-less builds, and one version using |
| 102 | the standard function, for driver support in build with entropy.) |
| 103 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 104 | See <https://github.com/Mbed-TLS/mbedtls/issues/5156>. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 105 | |
| 106 | Taking advantage of the existing abstractions layers - or not |
| 107 | ============================================================= |
| 108 | |
| 109 | The Crypto library in Mbed TLS currently has 3 abstraction layers that offer |
| 110 | algorithm-agnostic APIs for a class of algorithms: |
| 111 | |
| 112 | - MD for messages digests aka hashes (including HMAC) |
| 113 | - Cipher for symmetric ciphers (included AEAD) |
| 114 | - PK for asymmetric (aka public-key) cryptography (excluding key exchange) |
| 115 | |
| 116 | Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer. |
| 117 | |
| 118 | These abstraction layers typically provide, in addition to the API for crypto |
| 119 | operations, types and numerical identifiers for algorithms (for |
| 120 | example `mbedtls_cipher_mode_t` and its values). The |
| 121 | current strategy is to keep using those identifiers in most of the code, in |
| 122 | particular in existing structures and public APIs, even when |
| 123 | `MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3 |
| 124 | above, and is only potentially relevant for G4.) |
| 125 | |
| 126 | The are multiple strategies that can be used regarding the place of those |
| 127 | layers in the migration to PSA. |
| 128 | |
| 129 | Silently call to PSA from the abstraction layer |
| 130 | ----------------------------------------------- |
| 131 | |
| 132 | - Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper |
| 133 | functions in the abstraction layer, that calls PSA instead of the legacy |
| 134 | crypto API. |
| 135 | - Upside: changes contained to a single place, no need to change TLS or X.509 |
| 136 | code anywhere. |
| 137 | - Downside: tricky to implement if the PSA implementation is currently done on |
| 138 | top of that layer (dependency loop). |
| 139 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 140 | This strategy is currently (early 2022) used for all operations in the PK |
| 141 | layer. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 142 | |
Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 143 | This strategy is not very well suited to the Cipher layer, as the PSA |
| 144 | implementation is currently done on top of that layer. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 145 | |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 146 | This strategy will probably be used for some time for the PK layer, while we |
| 147 | figure out what the future of that layer is: parts of it (parse/write, ECDSA |
| 148 | signatures in the format that X.509 & TLS want) are not covered by PSA, so |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 149 | they will need to keep existing in some way. (Also, the PK layer is a good |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 150 | place for dispatching to either PSA or `mbedtls_xxx_restartable` while that |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 151 | part is not covered by PSA yet, if we decide to do that.) |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 152 | |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 153 | Replace calls for each operation |
| 154 | -------------------------------- |
| 155 | |
| 156 | - For every operation that's done through this layer in TLS or X.509, just |
| 157 | replace function call with calls to PSA (conditionally on `USE_PSA_CRYPTO`) |
| 158 | - Upside: conceptually simple, and if the PSA implementation is currently done |
| 159 | on top of that layer, avoids concerns about dependency loops. |
Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 160 | - Upside: opens the door to building TLS/X.509 without that layer, saving some |
| 161 | code size. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 162 | - Downside: TLS/X.509 code has to be done for each operation. |
| 163 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 164 | This strategy is currently (early 2022) used for the MD layer and the Cipher |
| 165 | layer. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 166 | |
| 167 | Opt-in use of PSA from the abstraction layer |
| 168 | -------------------------------------------- |
| 169 | |
| 170 | - Provide a new way to set up a context that causes operations on that context |
| 171 | to be done via PSA. |
| 172 | - Upside: changes mostly contained in one place, TLS/X.509 code only needs to |
| 173 | be changed when setting up the context, but not when using it. In |
| 174 | particular, no changes to/duplication of existing public APIs that expect a |
| 175 | key to be passed as a context of this layer (eg, `mbedtls_pk_context`). |
| 176 | - Upside: avoids dependency loop when PSA implemented on top of that layer. |
| 177 | - Downside: when the context is typically set up by the application, requires |
| 178 | changes in application code. |
| 179 | |
Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 180 | This strategy is not useful when no context is used, for example with the |
| 181 | one-shot function `mbedtls_md()`. |
| 182 | |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 183 | There are two variants of this strategy: one where using the new setup |
| 184 | function also allows for key isolation (the key is only held by PSA, |
| 185 | supporting both G1 and G2 in that area), and one without isolation (the key is |
Manuel Pégourié-Gonnard | 80759c4 | 2022-02-08 10:33:11 +0100 | [diff] [blame] | 186 | still stored outside of PSA most of the time, supporting only G1). |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 187 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 188 | This strategy, with support for key isolation, is currently (early 2022) used for |
| 189 | private-key operations in the PK layer - see `mbedtls_pk_setup_opaque()`. This |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 190 | allows use of PSA-held private ECDSA keys in TLS and X.509 with no change to |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 191 | the TLS/X.509 code, but a contained change in the application. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 192 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 193 | This strategy, without key isolation, was also previously used (until 3.1 |
| 194 | included) in the Cipher layer - see `mbedtls_cipher_setup_psa()`. This allowed |
| 195 | use of PSA for cipher operations in TLS with no change to the application |
| 196 | code, and a contained change in TLS code. (It only supported a subset of |
| 197 | ciphers.) |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 198 | |
| 199 | Note: for private key operations in the PK layer, both the "silent" and the |
| 200 | "opt-in" strategy can apply, and can complement each other, as one provides |
| 201 | support for key isolation, but at the (unavoidable) code of change in |
| 202 | application code, while the other requires no application change to get |
| 203 | support for drivers, but fails to provide isolation support. |
| 204 | |
Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 205 | Summary |
| 206 | ------- |
| 207 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 208 | Strategies currently (early 2022) used with each abstraction layer: |
Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 209 | |
| 210 | - PK (for G1): silently call PSA |
| 211 | - PK (for G2): opt-in use of PSA (new key type) |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 212 | - Cipher (G1): replace calls at each call site |
Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 213 | - MD (G1): replace calls at each call site |
| 214 | |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 215 | |
| 216 | Supporting builds with drivers without the software implementation |
| 217 | ================================================================== |
| 218 | |
| 219 | This section presents a plan towards G5: save code size by compiling out our |
| 220 | software implementation when a driver is available. |
| 221 | |
Manuel Pégourié-Gonnard | 8c7b81c | 2022-07-18 11:17:06 +0200 | [diff] [blame] | 222 | Additionally, we want to save code size by compiling out the |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 223 | abstractions layers that we are not using when `MBEDTLS_USE_PSA_CRYPTO` is |
| 224 | enabled (see previous section): MD and Cipher. |
| 225 | |
| 226 | Let's expand a bit on the definition of the goal: in such a configuration |
| 227 | (driver used, software implementation and abstraction layer compiled out), |
| 228 | we want: |
| 229 | |
| 230 | a. the library to build in a reasonably-complete configuration, |
| 231 | b. with all tests passing, |
| 232 | c. and no more tests skipped than the same configuration with software |
| 233 | implementation. |
| 234 | |
| 235 | Criterion (c) ensures not only test coverage, but that driver-based builds are |
| 236 | at feature parity with software-based builds. |
| 237 | |
| 238 | We can roughly divide the work needed to get there in the following steps: |
| 239 | |
| 240 | 0. Have a working driver interface for the algorithms we want to replace. |
| 241 | 1. Have users of these algorithms call to PSA, not the legacy API, for all |
| 242 | operations. (This is G1, and for PK, X.509 and TLS this is controlled by |
| 243 | `MBEDTLS_USE_PSA_CRYPTO`.) This needs to be done in the library and tests. |
| 244 | 2. Have users of these algorithms not depend on the legacy API for information |
| 245 | management (getting a size for a given algorithm, etc.) |
| 246 | 3. Adapt compile-time guards used to query availability of a given algorithm; |
| 247 | this needs to be done in the library (for crypto operations and data) and |
| 248 | tests. |
| 249 | |
| 250 | Note: the first two steps enable use of drivers, but not by themselves removal |
| 251 | of the software implementation. |
| 252 | |
| 253 | Note: the fact that step 1 is not achieved for all of libmbedcrypto (see |
| 254 | below) is the reason why criterion (a) has "a reasonably-complete |
| 255 | configuration", to allow working around internal crypto dependencies when |
| 256 | working on other parts such as X.509 and TLS - for example, a configuration |
| 257 | without RSA PKCS#1 v2.1 still allows reasonable use of X.509 and TLS. |
| 258 | |
Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 259 | Note: this is a conceptual division that will sometimes translate to how the |
| 260 | work is divided into PRs, sometimes not. For example, in situations where it's |
| 261 | not possible to achieve good test coverage at the end of step 1 or step 2, it |
| 262 | is preferable to group with the next step(s) in the same PR until good test |
| 263 | coverage can be reached. |
| 264 | |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 265 | **Status as of Mbed TLS 3.2:** |
| 266 | |
| 267 | - Step 0 is achieved for most algorithms, with only a few gaps remaining. |
| 268 | - Step 1 is achieved for most of PK, X.509, and TLS when |
| 269 | `MBEDTLS_USE_PSA_CRYPTO` is enabled with only a few gaps remaining (see |
| 270 | docs/use-psa-crypto.md). |
| 271 | - Step 1 is not achieved for a lot of the crypto library including the PSA |
| 272 | core. For example, `entropy.c` calls the legacy API |
Manuel Pégourié-Gonnard | fca4dc6 | 2022-07-26 10:10:07 +0200 | [diff] [blame] | 273 | `mbedtls_sha256` (or `mbedtls_sha512` optionally); `hmac_drbg.c` calls the |
| 274 | legacy API `mbedtls_md` and `ctr_drbg.c` calls the legacy API `mbedtls_aes`; |
| 275 | the PSA core depends on the entropy module and at least one of the DRBG |
| 276 | modules (unless `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is used). Further, several |
| 277 | crypto modules have similar issues, for example RSA PKCS#1 v2.1 calls |
| 278 | `mbedtls_md` directly. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 279 | - Step 2 is achieved for most of X.509 and TLS (same gaps as step 1) when |
| 280 | `MBEDTLS_USE_PSA_CRYPTO` is enabled - this was tasks like #5795, #5796, |
| 281 | #5797. It is being done in PK and RSA PKCS#1 v1.5 by PR #6065. |
| 282 | - Step 3 was mostly not started at all before 3.2; it is being done for PK by |
| 283 | PR #6065. |
| 284 | |
| 285 | **Strategy for step 1:** |
| 286 | |
| 287 | Regarding PK, X.509, and TLS, this is mostly achieved with only a few gaps. |
Manuel Pégourié-Gonnard | 8c7b81c | 2022-07-18 11:17:06 +0200 | [diff] [blame] | 288 | (The strategy was outlined in the previous section.) |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 289 | |
Manuel Pégourié-Gonnard | bdc8fd6 | 2022-07-20 11:46:49 +0200 | [diff] [blame] | 290 | Regarding libmbedcrypto, outside of the RNG subsystem, for modules that |
| 291 | currently depend on other legacy crypto modules, this can be achieved without |
| 292 | backwards compatibility issues, by using the software implementation if |
| 293 | available, and "falling back" to PSA only if it's not. The compile-time |
| 294 | dependency changes from the current one (say, `MD_C` or `AES_C`) to "the |
| 295 | previous dependency OR PSA Crypto with needed algorithms". When building |
| 296 | without software implementation, users need to call `psa_crypto_init()` before |
Manuel Pégourié-Gonnard | 68429fc | 2022-07-27 20:37:12 +0200 | [diff] [blame] | 297 | calling any function from these modules. This condition does not constitute a |
| 298 | break of backwards compatibility, as it was previously impossible to build in |
Manuel Pégourié-Gonnard | bdc8fd6 | 2022-07-20 11:46:49 +0200 | [diff] [blame] | 299 | those configurations, and in configurations were the build was possible, |
Manuel Pégourié-Gonnard | 68429fc | 2022-07-27 20:37:12 +0200 | [diff] [blame] | 300 | application code keeps working unchanged. An work-in-progress example of |
| 301 | applying this strategy, for RSA PKCS#1 v2.1, is here: |
| 302 | <https://github.com/Mbed-TLS/mbedtls/pull/6141> |
Manuel Pégourié-Gonnard | bdc8fd6 | 2022-07-20 11:46:49 +0200 | [diff] [blame] | 303 | |
| 304 | There is a problem with the modules used for the PSA RNG, as currently the RNG |
| 305 | is initialized before drivers and the key store. This part will need further |
| 306 | study, but in the meantime we can proceed with everything that's not the |
| 307 | entropy module of one of the DRBG modules, and that does not depend on one of |
| 308 | those modules. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 309 | |
| 310 | **Strategy for step 2:** |
| 311 | |
| 312 | The most satisfying situation here is when we can just use the PSA Crypto API |
| 313 | for information management as well. However sometimes it may not be |
Manuel Pégourié-Gonnard | 8c7b81c | 2022-07-18 11:17:06 +0200 | [diff] [blame] | 314 | convenient, for example in parts of the code that accept old-style identifiers |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 315 | (such as `mbedtls_md_type_t`) in their API and can't assume PSA to be |
| 316 | compiled in (such as `rsa.c`). |
| 317 | |
| 318 | It is suggested that, as a temporary solution until we clean this up |
| 319 | later when removing the legacy API including its identifiers (G4), we may |
Manuel Pégourié-Gonnard | bdc8fd6 | 2022-07-20 11:46:49 +0200 | [diff] [blame] | 320 | occasionally use ad-hoc internal functions, such as the ones introduced by PR |
| 321 | 6065 in `library/hash_info.[ch]`. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 322 | |
| 323 | An alternative would be to have two different code paths depending on whether |
| 324 | `MBEDTLS_PSA_CRYPTO_C` is defined or not. However this is not great for |
| 325 | readability or testability. |
| 326 | |
| 327 | **Strategy for step 3:** |
| 328 | |
Manuel Pégourié-Gonnard | f88b1b5 | 2022-07-15 11:05:05 +0200 | [diff] [blame] | 329 | There are currently two (complementary) ways for crypto-using code to check if a |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 330 | particular algorithm is supported: using `MBEDTLS_xxx` macros, and using |
| 331 | `PSA_WANT_xxx` macros. For example, PSA-based code that want to use SHA-256 |
| 332 | will check for `PSA_WANT_ALG_SHA_256`, while legacy-based code that wants to |
| 333 | use SHA-256 will check for `MBEDTLS_SHA256_C` if using the `mbedtls_sha256` |
Manuel Pégourié-Gonnard | 8c7b81c | 2022-07-18 11:17:06 +0200 | [diff] [blame] | 334 | API, or for `MBEDTLS_MD_C && MBEDTLS_SHA256_C` if using the `mbedtls_md` API. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 335 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 336 | Code that obeys `MBEDTLS_USE_PSA_CRYPTO` will want to use one of the two |
| 337 | dependencies above depending on whether `MBEDTLS_USE_PSA_CRYPTO` is defined: |
| 338 | if it is, the code want the algorithm available in PSA, otherwise, it wants it |
| 339 | available via the legacy API(s) is it using (MD and/or low-level). |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 340 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 341 | The strategy for steps 1 and 2 above will introduce new situations: code that |
| 342 | currently compute hashes using MD (resp. a low-level hash module) will gain |
| 343 | the ability to "fall back" to using PSA if the legacy dependency isn't |
| 344 | available. Data related to a certain hash (OID, sizes, translations) should |
| 345 | only be included in the build if it is possible to use that hash in some way. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 346 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 347 | In order to cater to these new needs, new families of macros are introduced in |
Manuel Pégourié-Gonnard | c42c7e6 | 2022-09-15 11:11:00 +0200 | [diff] [blame] | 348 | `legacy_or_psa.h`, see its documentation for details. |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 349 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 350 | It should be noted that there are currently: |
| 351 | - too many different ways of computing a hash (low-level, MD, PSA); |
| 352 | - too many different ways to configure the library that influence which of |
| 353 | these ways is available and will be used (`MBEDTLS_USE_PSA_CRYPTO`, |
Manuel Pégourié-Gonnard | 138387f | 2022-09-16 09:45:43 +0200 | [diff] [blame] | 354 | `MBEDTLS_PSA_CRYPTO_CONFIG`, `mbedtls_config.h` + `psa/crypto_config.h`). |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 355 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 356 | As a result, we need more families of dependency macros than we'd like to. |
Manuel Pégourié-Gonnard | 68429fc | 2022-07-27 20:37:12 +0200 | [diff] [blame] | 357 | This is a temporary situation until we move to a place where everything is |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 358 | based on PSA Crypto. In the meantime, long and explicit names where chosen for |
| 359 | the new macros in the hope of avoiding confusion. |
| 360 | |
Manuel Pégourié-Gonnard | c42c7e6 | 2022-09-15 11:11:00 +0200 | [diff] [blame] | 361 | Note: the new macros supplement but do not replace the existing macros: |
| 362 | - code that always uses PSA Crypto (for example, code specific to TLS 1.3) |
| 363 | should use `PSA_WANT_xxx`; |
Manuel Pégourié-Gonnard | 138387f | 2022-09-16 09:45:43 +0200 | [diff] [blame] | 364 | - code that always uses the legacy API (for example, crypto modules that have |
Manuel Pégourié-Gonnard | c42c7e6 | 2022-09-15 11:11:00 +0200 | [diff] [blame] | 365 | not undergone step 1 yet) should use `MBEDTLS_xxx_C`; |
| 366 | - code that may use one of the two APIs, either based on |
| 367 | `MBEDTLS_USE_PSA_CRYPTO` (X.509, TLS 1.2, shared between TLS 1.2 and 1.3), |
Manuel Pégourié-Gonnard | 138387f | 2022-09-16 09:45:43 +0200 | [diff] [blame] | 368 | or based on availability (crypto modules after step 1), should use one of |
| 369 | the new macros from `legacy_or_psa.h`. |
Manuel Pégourié-Gonnard | c42c7e6 | 2022-09-15 11:11:00 +0200 | [diff] [blame] | 370 | |
Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 371 | Executing step 3 will mostly consist of using the right dependency macros in |
| 372 | the right places (once the previous steps are done). |
Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 373 | |
Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 374 | **Note on testing** |
| 375 | |
Manuel Pégourié-Gonnard | fca4dc6 | 2022-07-26 10:10:07 +0200 | [diff] [blame] | 376 | Since supporting driver-only builds is not about adding features, but about |
| 377 | supporting existing features in new types of builds, testing will not involve |
| 378 | adding cases to the test suites, but instead adding new components in `all.sh` |
| 379 | that build and run tests in newly-supported configurations. For example, if |
| 380 | we're making some part of the library work with hashes provided only by |
| 381 | drivers when `MBEDTLS_USE_PSA_CRYPTO` is defined, there should be a place in |
| 382 | `all.sh` that builds and run tests in such a configuration. |
Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 383 | |
| 384 | There is however a risk, especially in step 3 where we change how dependencies |
| 385 | are expressed (sometimes in bulk), to get things wrong in a way that would |
| 386 | result in more tests being skipped, which is easy to miss. Care must be |
| 387 | taken to ensure this does not happen. The following criteria can be used: |
| 388 | |
| 389 | - the sets of tests skipped in the default config and the full config must be |
| 390 | the same before and after the PR that implements step 3; |
| 391 | - the set of tests skipped in the driver-only build is the same as in an |
| 392 | equivalent software-based configuration, or the difference is small enough, |
Manuel Pégourié-Gonnard | fca4dc6 | 2022-07-26 10:10:07 +0200 | [diff] [blame] | 393 | justified, and a github issue is created to track it. |
Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 394 | |
| 395 | Note that the favourable case is when the number of tests skipped is 0 in the |
| 396 | driver-only build. In other cases, analysis of the outcome files is needed, |
| 397 | see the example script `outcome-analysis.sh` in the same directory. |
| 398 | |
| 399 | |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 400 | Migrating away from the legacy API |
| 401 | ================================== |
| 402 | |
| 403 | This section briefly introduces questions and possible plans towards G4, |
| 404 | mainly as they relate to choices in previous stages. |
| 405 | |
| 406 | The role of the PK/Cipher/MD APIs in user migration |
| 407 | --------------------------------------------------- |
| 408 | |
Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 409 | We're currently taking advantage of the existing PK layer in order |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 410 | to reduce the number of places where library code needs to be changed. It's |
| 411 | only natural to consider using the same strategy (with the PK, MD and Cipher |
| 412 | layers) for facilitating migration of application code. |
| 413 | |
| 414 | Note: a necessary first step for that would be to make sure PSA is no longer |
| 415 | implemented of top of the concerned layers |
| 416 | |
| 417 | ### Zero-cost compatibility layer? |
| 418 | |
| 419 | The most favourable case is if we can have a zero-cost abstraction (no |
| 420 | runtime, RAM usage or code size penalty), for example just a bunch of |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 421 | `#define`s, essentially mapping `mbedtls_` APIs to their `psa_` equivalent. |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 422 | |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 423 | Unfortunately that's unlikely to fully work. For example, the MD layer uses the |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 424 | same context type for hashes and HMACs, while the PSA API (rightfully) has |
| 425 | distinct operation types. Similarly, the Cipher layer uses the same context |
| 426 | type for unauthenticated and AEAD ciphers, which again the PSA API |
| 427 | distinguishes. |
| 428 | |
| 429 | It is unclear how much value, if any, a zero-cost compatibility layer that's |
| 430 | incomplete (for example, for MD covering only hashes, or for Cipher covering |
| 431 | only AEAD) or differs significantly from the existing API (for example, |
| 432 | introducing new context types) would provide to users. |
| 433 | |
| 434 | ### Low-cost compatibility layers? |
| 435 | |
| 436 | Another possibility is to keep most or all of the existing API for the PK, MD |
| 437 | and Cipher layers, implemented on top of PSA, aiming for the lowest possible |
| 438 | cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union |
| 439 | of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()` |
| 440 | would initialize the correct part, and the rest of the functions be simple |
| 441 | wrappers around PSA functions. This would vastly reduce the complexity of the |
| 442 | layers compared to the existing (no need to dispatch through function |
| 443 | pointers, just call the corresponding PSA API). |
| 444 | |
| 445 | Since this would still represent a non-zero cost, not only in terms of code |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 446 | size, but also in terms of maintenance (testing, etc.) this would probably |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 447 | be a temporary solution: for example keep the compatibility layers in 4.0 (and |
| 448 | make them optional), but remove them in 5.0. |
| 449 | |
| 450 | Again, this provides the most value to users if we can manage to keep the |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 451 | existing API unchanged. Their might be conflicts between this goal and that of |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 452 | reducing the cost, and judgment calls may need to be made. |
| 453 | |
| 454 | Note: when it comes to holding public keys in the PK layer, depending on how |
| 455 | the rest of the code is structured, it may be worth holding the key data in |
| 456 | memory controlled by the PK layer as opposed to a PSA key slot, moving it to a |
| 457 | slot only when needed (see current `ecdsa_verify_wrap` when |
| 458 | `MBEDTLS_USE_PSA_CRYPTO` is defined) For example, when parsing a large |
| 459 | number, N, of X.509 certificates (for example the list of trusted roots), it |
| 460 | might be undesirable to use N PSA key slots for their public keys as long as |
| 461 | the certs are loaded. OTOH, this could also be addressed by merging the "X.509 |
| 462 | parsing on-demand" (#2478), and then the public key data would be held as |
| 463 | bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot |
| 464 | when it's actually used. |
| 465 | |
| 466 | Note: the PK layer actually consists of two relatively distinct parts: crypto |
| 467 | operations, which will be covered by PSA, and parsing/writing (exporting) |
| 468 | from/to various formats, which is currently not fully covered by the PSA |
| 469 | Crypto API. |
| 470 | |
| 471 | ### Algorithm identifiers and other identifiers |
| 472 | |
| 473 | It should be easy to provide the user with a bunch of `#define`s for algorithm |
| 474 | identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of |
| 475 | those would be in the MD, Cipher and PK compatibility layers mentioned above, |
| 476 | but there might be some in other modules that may be worth considering, for |
| 477 | example identifiers for elliptic curves. |
| 478 | |
| 479 | ### Lower layers |
| 480 | |
| 481 | Generally speaking, we would retire all of the low-level, non-generic modules, |
| 482 | such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing |
| 483 | compatibility APIs for them. People would be encouraged to switch to the PSA |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 484 | API. (The compatibility implementation of the existing PK, MD, Cipher APIs |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 485 | would mostly benefit people who already used those generic APis rather than |
| 486 | the low-level, alg-specific ones.) |
| 487 | |
| 488 | ### APIs in TLS and X.509 |
| 489 | |
| 490 | Public APIs in TLS and X.509 may be affected by the migration in at least two |
| 491 | ways: |
| 492 | |
| 493 | 1. APIs that rely on a legacy `mbedtls_` crypto type: for example |
| 494 | `mbedtls_ssl_conf_own_cert()` to configure a (certificate and the |
| 495 | associated) private key. Currently the private key is passed as a |
| 496 | `mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`. |
| 497 | Since some users would probably still be using the compatibility PK layer, it |
| 498 | would need a way to easily extract the PSA key ID from the PK context. |
| 499 | |
| 500 | 2. APIs the accept list of identifiers: for example |
| 501 | `mbedtls_ssl_conf_curves()` taking a list of `mbedtls_ecp_group_id`s. This |
bootstrap-prime | 6dbbf44 | 2022-05-17 19:30:44 -0400 | [diff] [blame] | 502 | could be changed to accept a list of pairs (`psa_ecc_family_t`, size) but we |
Manuel Pégourié-Gonnard | 8ebed21 | 2022-02-07 10:23:49 +0100 | [diff] [blame] | 503 | should probably take this opportunity to move to a identifier independent from |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 504 | the underlying crypto implementation and use TLS-specific identifiers instead |
| 505 | (based on IANA values or custom enums), as is currently done in the new |
| 506 | `mbedtls_ssl_conf_groups()` API, see #4859). |
| 507 | |
| 508 | Testing |
| 509 | ------- |
| 510 | |
| 511 | An question that needs careful consideration when we come around to removing |
| 512 | the low-level crypto APIs and making PK, MD and Cipher optional compatibility |
| 513 | layers is to be sure to preserve testing quality. A lot of the existing test |
| 514 | cases use the low level crypto APIs; we would need to either keep using that |
Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 515 | API for tests, or manually migrate tests to the PSA Crypto API. Perhaps a |
Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 516 | combination of both, perhaps evolving gradually over time. |