| 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 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 21 | As of early 2023, work towards G5 is in progress: Mbed TLS 3.3 and 3.4 saw | 
|  | 22 | some improvements in this area, and more will be coming in future releases. | 
|  | 23 |  | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 24 | 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] | 25 | the preceding ones to be completed. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 26 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 27 |  | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 28 | Compile-time options | 
|  | 29 | ==================== | 
|  | 30 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 31 | We currently have a few compile-time options that are relevant to the migration: | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 32 |  | 
|  | 33 | - `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA | 
|  | 34 | Crypto APIs. | 
|  | 35 | - `MBEDTLS_USE_PSA_CRYPTO` - disabled by default (enabled in "full" config), | 
|  | 36 | controls usage of PSA Crypto APIs to perform operations in X.509 and TLS | 
|  | 37 | (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] | 38 | - `PSA_CRYPTO_CONFIG` - disabled by default, supports builds with drivers and | 
|  | 39 | without the corresponding software implementation (G5 above). | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 40 |  | 
| Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 41 | The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default | 
|  | 42 | are: | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 43 | - it's not fully compatible with `MBEDTLS_ECP_RESTARTABLE`: you can enable | 
|  | 44 | both, but then you won't get the full effect of RESTARTBLE (see the | 
|  | 45 | documentation of this option in `mbedtls_config.h`); | 
| Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 46 | - 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] | 47 | `MBEDTLS_PSA_CRYPTO_C`, for backward compatibility reasons: | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 48 | - When `MBEDTLS_PSA_CRYPTO_C` is enabled and used, applications need to call | 
|  | 49 | `psa_crypto_init()` before TLS/X.509 uses PSA functions. (This prevents us | 
|  | 50 | from even enabling the option by default.) | 
| Tom Cosgrove | 0b86ac1 | 2022-07-29 13:44:01 +0100 | [diff] [blame] | 51 | - `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] | 52 | MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` but it's | 
| Tom Cosgrove | 0b86ac1 | 2022-07-29 13:44:01 +0100 | [diff] [blame] | 53 | 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] | 54 | 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] | 55 | out of the box on all platforms, and even less | 
|  | 56 | `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` as it requires a user-provided RNG | 
|  | 57 | function. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 58 |  | 
| Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 59 | 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] | 60 | `MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain | 
|  | 61 | two versions of some parts of the code: one using PSA, the other using the | 
|  | 62 | 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] | 63 | cost. The rest of this section explains the reasons for the | 
|  | 64 | incompatibilities mentioned above. | 
|  | 65 |  | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 66 | At the time of writing (early 2022) it is unclear what could be done about the | 
|  | 67 | backward compatibility issues, and in particular if the cost of implementing | 
|  | 68 | solutions to these problems would be higher or lower than the cost of | 
|  | 69 | maintaining dual code paths until the next major version. (Note: these | 
|  | 70 | 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] | 71 |  | 
| Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 72 | ### `MBEDTLS_ECP_RESTARTABLE` | 
|  | 73 |  | 
|  | 74 | Currently this option controls not only the presence of restartable APIs in | 
|  | 75 | the crypto library, but also their use in the TLS and X.509 layers. Since PSA | 
|  | 76 | Crypto does not support restartable operations, there's a clear conflict: the | 
|  | 77 | TLS and X.509 layers can't both use only PSA APIs and get restartable | 
|  | 78 | behaviour. | 
|  | 79 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 80 | Support for restartable (aka interruptible) ECDSA sign/verify operation was | 
|  | 81 | added to PSA in Mbed TLS 3.4, but support for ECDH is not present yet. | 
| Manuel Pégourié-Gonnard | a6c601c | 2021-10-27 14:12:44 +0200 | [diff] [blame] | 82 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 83 | It will then require follow-up work to make use of the new PSA APIs in | 
| Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 84 | 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] | 85 |  | 
| Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 86 | ### 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] | 87 |  | 
|  | 88 | 1. Existing applications may not be calling `psa_crypto_init()` before using | 
|  | 89 | TLS, X.509 or PK. We can try to work around that by calling (the relevant | 
|  | 90 | part of) it ourselves under the hood as needed, but that would likely require | 
|  | 91 | 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] | 92 | <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] | 93 | 2. It's currently not possible to enable `MBEDTLS_PSA_CRYPTO_C` in | 
|  | 94 | configurations that don't have `MBEDTLS_ENTROPY_C`, and we can't just | 
|  | 95 | auto-enable the latter, as it won't build or work out of the box on all | 
|  | 96 | platforms. There are two kinds of things we'd need to do if we want to work | 
|  | 97 | around that: | 
|  | 98 | 1. Make it possible to enable the parts of PSA Crypto that don't require an | 
|  | 99 | RNG (typically, public key operations, symmetric crypto, some key | 
|  | 100 | management functions (destroy etc)) in configurations that don't have | 
|  | 101 | `ENTROPY_C`. This requires going through the PSA code base to adjust | 
|  | 102 | dependencies. Risk: there may be annoying dependencies, some of which may be | 
|  | 103 | surprising. | 
|  | 104 | 2. For operations that require an RNG, provide an alternative function | 
|  | 105 | accepting an explicit `f_rng` parameter (see #5238), that would be | 
|  | 106 | available in entropy-less builds. (Then code using those functions still needs | 
|  | 107 | to have one version using it, for entropy-less builds, and one version using | 
|  | 108 | the standard function, for driver support in build with entropy.) | 
|  | 109 |  | 
| Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 110 | See <https://github.com/Mbed-TLS/mbedtls/issues/5156>. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 111 |  | 
|  | 112 | Taking advantage of the existing abstractions layers - or not | 
|  | 113 | ============================================================= | 
|  | 114 |  | 
|  | 115 | The Crypto library in Mbed TLS currently has 3 abstraction layers that offer | 
|  | 116 | algorithm-agnostic APIs for a class of algorithms: | 
|  | 117 |  | 
|  | 118 | - MD for messages digests aka hashes (including HMAC) | 
|  | 119 | - Cipher for symmetric ciphers (included AEAD) | 
|  | 120 | - PK for asymmetric (aka public-key) cryptography (excluding key exchange) | 
|  | 121 |  | 
|  | 122 | Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer. | 
|  | 123 |  | 
|  | 124 | These abstraction layers typically provide, in addition to the API for crypto | 
|  | 125 | operations, types and numerical identifiers for algorithms (for | 
|  | 126 | example `mbedtls_cipher_mode_t` and its values). The | 
|  | 127 | current strategy is to keep using those identifiers in most of the code, in | 
|  | 128 | particular in existing structures and public APIs, even when | 
|  | 129 | `MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3 | 
|  | 130 | above, and is only potentially relevant for G4.) | 
|  | 131 |  | 
|  | 132 | The are multiple strategies that can be used regarding the place of those | 
|  | 133 | layers in the migration to PSA. | 
|  | 134 |  | 
|  | 135 | Silently call to PSA from the abstraction layer | 
|  | 136 | ----------------------------------------------- | 
|  | 137 |  | 
|  | 138 | - Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper | 
|  | 139 | functions in the abstraction layer, that calls PSA instead of the legacy | 
|  | 140 | crypto API. | 
|  | 141 | - Upside: changes contained to a single place, no need to change TLS or X.509 | 
|  | 142 | code anywhere. | 
|  | 143 | - Downside: tricky to implement if the PSA implementation is currently done on | 
|  | 144 | top of that layer (dependency loop). | 
|  | 145 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 146 | This strategy is currently (early 2023) used for all operations in the PK | 
|  | 147 | layer; the MD layer uses a variant where it dispatches to PSA if a driver is | 
|  | 148 | available and the driver subsystem has been initialized, regardless of whether | 
|  | 149 | `USE_PSA_CRYPTO` is enabled; see `md-cipher-dispatch.md` in the same directory | 
|  | 150 | for details. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 151 |  | 
| Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 152 | This strategy is not very well suited to the Cipher layer, as the PSA | 
|  | 153 | implementation is currently done on top of that layer. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 154 |  | 
| Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 155 | This strategy will probably be used for some time for the PK layer, while we | 
|  | 156 | figure out what the future of that layer is: parts of it (parse/write, ECDSA | 
|  | 157 | 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] | 158 | 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] | 159 | 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] | 160 | 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] | 161 |  | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 162 | Replace 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. | 
| Manuel Pégourié-Gonnard | ec3fd75 | 2022-01-17 11:29:18 +0100 | [diff] [blame] | 169 | - Upside: opens the door to building TLS/X.509 without that layer, saving some | 
|  | 170 | code size. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 171 | - Downside: TLS/X.509 code has to be done for each operation. | 
|  | 172 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 173 | This strategy is currently (early 2023) used for the MD layer and the Cipher | 
|  | 174 | layer in X.509 and TLS. Crypto modules however always call to MD which may | 
|  | 175 | then dispatch to PSA, see `md-cipher-dispatch.md`. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 176 |  | 
|  | 177 | Opt-in use of PSA from the abstraction layer | 
|  | 178 | -------------------------------------------- | 
|  | 179 |  | 
|  | 180 | - Provide a new way to set up a context that causes operations on that context | 
|  | 181 | to be done via PSA. | 
|  | 182 | - Upside: changes mostly contained in one place, TLS/X.509 code only needs to | 
|  | 183 | be changed when setting up the context, but not when using it. In | 
|  | 184 | particular, no changes to/duplication of existing public APIs that expect a | 
|  | 185 | key to be passed as a context of this layer (eg, `mbedtls_pk_context`). | 
|  | 186 | - Upside: avoids dependency loop when PSA implemented on top of that layer. | 
|  | 187 | - Downside: when the context is typically set up by the application, requires | 
|  | 188 | changes in application code. | 
|  | 189 |  | 
| Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 190 | This strategy is not useful when no context is used, for example with the | 
|  | 191 | one-shot function `mbedtls_md()`. | 
|  | 192 |  | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 193 | There are two variants of this strategy: one where using the new setup | 
|  | 194 | function also allows for key isolation (the key is only held by PSA, | 
|  | 195 | 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] | 196 | 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] | 197 |  | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 198 | This strategy, with support for key isolation, is currently (early 2022) used for | 
|  | 199 | 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] | 200 | 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] | 201 | 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] | 202 |  | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 203 | This strategy, without key isolation, was also previously used (until 3.1 | 
|  | 204 | included) in the Cipher layer - see `mbedtls_cipher_setup_psa()`. This allowed | 
|  | 205 | use of PSA for cipher operations in TLS with no change to the application | 
|  | 206 | code, and a contained change in TLS code. (It only supported a subset of | 
|  | 207 | ciphers.) | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 208 |  | 
|  | 209 | Note: for private key operations in the PK layer, both the "silent" and the | 
|  | 210 | "opt-in" strategy can apply, and can complement each other, as one provides | 
|  | 211 | support for key isolation, but at the (unavoidable) code of change in | 
|  | 212 | application code, while the other requires no application change to get | 
|  | 213 | support for drivers, but fails to provide isolation support. | 
|  | 214 |  | 
| Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 215 | Summary | 
|  | 216 | ------- | 
|  | 217 |  | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 218 | Strategies currently (early 2022) used with each abstraction layer: | 
| Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 219 |  | 
|  | 220 | - PK (for G1): silently call PSA | 
|  | 221 | - 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] | 222 | - Cipher (G1): replace calls at each call site | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 223 | - MD (G1, X.509 and TLS): replace calls at each call site (depending on | 
|  | 224 | `USE_PSA_CRYPTO`) | 
|  | 225 | - MD (G5): silently call PSA when a driver is available, see | 
|  | 226 | `md-cipher-dispatch.md`. | 
| Manuel Pégourié-Gonnard | 0950359 | 2021-10-27 14:21:23 +0200 | [diff] [blame] | 227 |  | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 228 |  | 
|  | 229 | Supporting builds with drivers without the software implementation | 
|  | 230 | ================================================================== | 
|  | 231 |  | 
|  | 232 | This section presents a plan towards G5: save code size by compiling out our | 
|  | 233 | software implementation when a driver is available. | 
|  | 234 |  | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 235 | Let's expand a bit on the definition of the goal: in such a configuration | 
|  | 236 | (driver used, software implementation and abstraction layer compiled out), | 
|  | 237 | we want: | 
|  | 238 |  | 
|  | 239 | a. the library to build in a reasonably-complete configuration, | 
|  | 240 | b. with all tests passing, | 
|  | 241 | c. and no more tests skipped than the same configuration with software | 
|  | 242 | implementation. | 
|  | 243 |  | 
|  | 244 | Criterion (c) ensures not only test coverage, but that driver-based builds are | 
|  | 245 | at feature parity with software-based builds. | 
|  | 246 |  | 
|  | 247 | We can roughly divide the work needed to get there in the following steps: | 
|  | 248 |  | 
|  | 249 | 0. Have a working driver interface for the algorithms we want to replace. | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 250 | 1. Have users of these algorithms call to PSA or an abstraction layer than can | 
|  | 251 | dispatch to PSA, but not the low-level legacy API, for all operations. | 
|  | 252 | (This is G1, and for PK, X.509 and TLS this is controlled by | 
|  | 253 | `MBEDTLS_USE_PSA_CRYPTO`.) This needs to be done in the library and tests. | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 254 | 2. Have users of these algorithms not depend on the legacy API for information | 
|  | 255 | management (getting a size for a given algorithm, etc.) | 
|  | 256 | 3. Adapt compile-time guards used to query availability of a given algorithm; | 
|  | 257 | this needs to be done in the library (for crypto operations and data) and | 
|  | 258 | tests. | 
|  | 259 |  | 
|  | 260 | Note: the first two steps enable use of drivers, but not by themselves removal | 
|  | 261 | of the software implementation. | 
|  | 262 |  | 
|  | 263 | Note: the fact that step 1 is not achieved for all of libmbedcrypto (see | 
|  | 264 | below) is the reason why criterion (a) has "a reasonably-complete | 
|  | 265 | configuration", to allow working around internal crypto dependencies when | 
|  | 266 | working on other parts such as X.509 and TLS - for example, a configuration | 
|  | 267 | without RSA PKCS#1 v2.1 still allows reasonable use of X.509 and TLS. | 
|  | 268 |  | 
| Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 269 | Note: this is a conceptual division that will sometimes translate to how the | 
|  | 270 | work is divided into PRs, sometimes not. For example, in situations where it's | 
|  | 271 | not possible to achieve good test coverage at the end of step 1 or step 2, it | 
|  | 272 | is preferable to group with the next step(s) in the same PR until good test | 
|  | 273 | coverage can be reached. | 
|  | 274 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 275 | **Status as of end of March 2023 (shortly after 3.4):** | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 276 |  | 
|  | 277 | - Step 0 is achieved for most algorithms, with only a few gaps remaining. | 
|  | 278 | - Step 1 is achieved for most of PK, X.509, and TLS when | 
|  | 279 | `MBEDTLS_USE_PSA_CRYPTO` is enabled with only a few gaps remaining (see | 
|  | 280 | docs/use-psa-crypto.md). | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 281 | - Step 1 is achieved for the crypto library regarding hashes: everything uses | 
|  | 282 | MD (not low-level hash APIs), which then dispatches to PSA if applicable. | 
|  | 283 | - Step 1 is not achieved for all of the crypto library when it come to | 
|  | 284 | ciphers. For example,`ctr_drbg.c` calls the legacy API `mbedtls_aes`. | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 285 | - Step 2 is achieved for most of X.509 and TLS (same gaps as step 1) when | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 286 | `MBEDTLS_USE_PSA_CRYPTO` is enabled. | 
|  | 287 | - Step 3 is done for hashes and top-level ECC modules (ECDSA, ECDH, ECJPAKE). | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 288 |  | 
|  | 289 | **Strategy for step 1:** | 
|  | 290 |  | 
|  | 291 | 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] | 292 | (The strategy was outlined in the previous section.) | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 293 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 294 | Regarding libmbedcrypto: | 
|  | 295 | - for hashes and ciphers, see `md-cipher-dispatch.md` in the same directory; | 
|  | 296 | - for ECC, we have no internal uses of the top-level algorithms (ECDSA, ECDH, | 
|  | 297 | ECJPAKE), however they all depend on `ECP_C` which in turn depends on | 
|  | 298 | `BIGNUM_C`. So, direct calls from TLS, X.509 and PK to ECP and Bignum will | 
|  | 299 | need to be replaced; see <https://github.com/Mbed-TLS/mbedtls/issues/6839> and | 
| Manuel Pégourié-Gonnard | b38c9c8 | 2023-03-24 10:43:28 +0100 | [diff] [blame] | 300 | linked issues for a summary of intermediate steps and open points. | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 301 |  | 
|  | 302 | **Strategy for step 2:** | 
|  | 303 |  | 
|  | 304 | The most satisfying situation here is when we can just use the PSA Crypto API | 
|  | 305 | 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] | 306 | 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] | 307 | (such as `mbedtls_md_type_t`) in their API and can't assume PSA to be | 
|  | 308 | compiled in (such as `rsa.c`). | 
|  | 309 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 310 | When using an existing abstraction layer such as MD, it can provide | 
|  | 311 | information management functions. In other cases, information that was in a | 
|  | 312 | low-level module but logically belongs in a higher-level module can be moved | 
|  | 313 | to that module (for example, TLS identifiers of curves and there conversion | 
|  | 314 | to/from PSA or legacy identifiers belongs in TLS, not `ecp.c`). | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 315 |  | 
|  | 316 | **Strategy for step 3:** | 
|  | 317 |  | 
| Manuel Pégourié-Gonnard | f88b1b5 | 2022-07-15 11:05:05 +0200 | [diff] [blame] | 318 | 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] | 319 | particular algorithm is supported: using `MBEDTLS_xxx` macros, and using | 
|  | 320 | `PSA_WANT_xxx` macros. For example, PSA-based code that want to use SHA-256 | 
|  | 321 | will check for `PSA_WANT_ALG_SHA_256`, while legacy-based code that wants to | 
|  | 322 | 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] | 323 | 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] | 324 |  | 
| Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 325 | Code that obeys `MBEDTLS_USE_PSA_CRYPTO` will want to use one of the two | 
|  | 326 | dependencies above depending on whether `MBEDTLS_USE_PSA_CRYPTO` is defined: | 
|  | 327 | if it is, the code want the algorithm available in PSA, otherwise, it wants it | 
|  | 328 | 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] | 329 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 330 | As much as possible, we're trying to create for each algorithm a single new | 
|  | 331 | macro that can be used to express dependencies everywhere (except pure PSA | 
|  | 332 | code that should always use `PSA_WANT`). For example, for hashes this is the | 
|  | 333 | `MBEDTLS_MD_CAN_xxx` family. For ECC algorithms, we have similar | 
|  | 334 | `MBEDTLS_PK_CAN_xxx` macros. | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 335 |  | 
| Manuel Pégourié-Gonnard | 52f7edb | 2023-03-22 15:56:01 +0100 | [diff] [blame] | 336 | Note that in order to achieve that goal, even for code that obeys | 
|  | 337 | `USE_PSA_CRYPTO`, it is useful to impose that all algorithms that are | 
|  | 338 | available via the legacy APIs are also available via PSA. | 
| Manuel Pégourié-Gonnard | c42c7e6 | 2022-09-15 11:11:00 +0200 | [diff] [blame] | 339 |  | 
| Manuel Pégourié-Gonnard | c8c352c | 2022-07-21 11:01:50 +0200 | [diff] [blame] | 340 | Executing step 3 will mostly consist of using the right dependency macros in | 
|  | 341 | the right places (once the previous steps are done). | 
| Manuel Pégourié-Gonnard | af8cf5c | 2022-07-12 11:05:53 +0200 | [diff] [blame] | 342 |  | 
| Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 343 | **Note on testing** | 
|  | 344 |  | 
| Manuel Pégourié-Gonnard | fca4dc6 | 2022-07-26 10:10:07 +0200 | [diff] [blame] | 345 | Since supporting driver-only builds is not about adding features, but about | 
|  | 346 | supporting existing features in new types of builds, testing will not involve | 
|  | 347 | adding cases to the test suites, but instead adding new components in `all.sh` | 
|  | 348 | that build and run tests in newly-supported configurations. For example, if | 
|  | 349 | we're making some part of the library work with hashes provided only by | 
|  | 350 | drivers when `MBEDTLS_USE_PSA_CRYPTO` is defined, there should be a place in | 
|  | 351 | `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] | 352 |  | 
|  | 353 | There is however a risk, especially in step 3 where we change how dependencies | 
|  | 354 | are expressed (sometimes in bulk), to get things wrong in a way that would | 
|  | 355 | result in more tests being skipped, which is easy to miss. Care must be | 
|  | 356 | taken to ensure this does not happen. The following criteria can be used: | 
|  | 357 |  | 
| Manuel Pégourié-Gonnard | 222bc85 | 2022-12-29 13:47:25 +0100 | [diff] [blame] | 358 | 1. The sets of tests skipped in the default config and the full config must be | 
|  | 359 | the same before and after the PR that implements step 3. This is tested | 
|  | 360 | manually for each PR that changes dependency declarations by using the script | 
|  | 361 | `outcome-analysis.sh` in the present directory. | 
|  | 362 | 2. The set of tests skipped in the driver-only build is the same as in an | 
|  | 363 | equivalent software-based configuration. This is tested automatically by the | 
|  | 364 | CI in the "Results analysis" stage, by running | 
| Manuel Pégourié-Gonnard | 5a2e026 | 2023-01-23 12:51:52 +0100 | [diff] [blame] | 365 | `tests/scripts/analyze_outcomes.py`. See the | 
| Manuel Pégourié-Gonnard | 222bc85 | 2022-12-29 13:47:25 +0100 | [diff] [blame] | 366 | `analyze_driver_vs_reference_xxx` actions in the script and the comments above | 
|  | 367 | their declaration for how to do that locally. | 
| Manuel Pégourié-Gonnard | fb2ed58 | 2022-07-21 11:04:52 +0200 | [diff] [blame] | 368 |  | 
|  | 369 |  | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 370 | Migrating away from the legacy API | 
|  | 371 | ================================== | 
|  | 372 |  | 
|  | 373 | This section briefly introduces questions and possible plans towards G4, | 
|  | 374 | mainly as they relate to choices in previous stages. | 
|  | 375 |  | 
|  | 376 | The role of the PK/Cipher/MD APIs in user migration | 
|  | 377 | --------------------------------------------------- | 
|  | 378 |  | 
| Manuel Pégourié-Gonnard | 481846c | 2022-07-12 09:27:39 +0200 | [diff] [blame] | 379 | 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] | 380 | to reduce the number of places where library code needs to be changed. It's | 
|  | 381 | only natural to consider using the same strategy (with the PK, MD and Cipher | 
|  | 382 | layers) for facilitating migration of application code. | 
|  | 383 |  | 
|  | 384 | Note: a necessary first step for that would be to make sure PSA is no longer | 
|  | 385 | implemented of top of the concerned layers | 
|  | 386 |  | 
|  | 387 | ### Zero-cost compatibility layer? | 
|  | 388 |  | 
|  | 389 | The most favourable case is if we can have a zero-cost abstraction (no | 
|  | 390 | 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] | 391 | `#define`s, essentially mapping `mbedtls_` APIs to their `psa_` equivalent. | 
| Manuel Pégourié-Gonnard | b89fd95 | 2021-09-30 11:52:04 +0200 | [diff] [blame] | 392 |  | 
| Manuel Pégourié-Gonnard | 2a47d23 | 2022-04-20 15:01:13 +0200 | [diff] [blame] | 393 | 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] | 394 | same context type for hashes and HMACs, while the PSA API (rightfully) has | 
|  | 395 | distinct operation types. Similarly, the Cipher layer uses the same context | 
|  | 396 | type for unauthenticated and AEAD ciphers, which again the PSA API | 
|  | 397 | distinguishes. | 
|  | 398 |  | 
|  | 399 | It is unclear how much value, if any, a zero-cost compatibility layer that's | 
|  | 400 | incomplete (for example, for MD covering only hashes, or for Cipher covering | 
|  | 401 | only AEAD) or differs significantly from the existing API (for example, | 
|  | 402 | introducing new context types) would provide to users. | 
|  | 403 |  | 
|  | 404 | ### Low-cost compatibility layers? | 
|  | 405 |  | 
|  | 406 | Another possibility is to keep most or all of the existing API for the PK, MD | 
|  | 407 | and Cipher layers, implemented on top of PSA, aiming for the lowest possible | 
|  | 408 | cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union | 
|  | 409 | of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()` | 
|  | 410 | would initialize the correct part, and the rest of the functions be simple | 
|  | 411 | wrappers around PSA functions. This would vastly reduce the complexity of the | 
|  | 412 | layers compared to the existing (no need to dispatch through function | 
|  | 413 | pointers, just call the corresponding PSA API). | 
|  | 414 |  | 
|  | 415 | 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] | 416 | 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] | 417 | be a temporary solution: for example keep the compatibility layers in 4.0 (and | 
|  | 418 | make them optional), but remove them in 5.0. | 
|  | 419 |  | 
|  | 420 | 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] | 421 | 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] | 422 | reducing the cost, and judgment calls may need to be made. | 
|  | 423 |  | 
|  | 424 | Note: when it comes to holding public keys in the PK layer, depending on how | 
|  | 425 | the rest of the code is structured, it may be worth holding the key data in | 
|  | 426 | memory controlled by the PK layer as opposed to a PSA key slot, moving it to a | 
|  | 427 | slot only when needed (see current `ecdsa_verify_wrap` when | 
|  | 428 | `MBEDTLS_USE_PSA_CRYPTO` is defined)  For example, when parsing a large | 
|  | 429 | number, N, of X.509 certificates (for example the list of trusted roots), it | 
|  | 430 | might be undesirable to use N PSA key slots for their public keys as long as | 
|  | 431 | the certs are loaded. OTOH, this could also be addressed by merging the "X.509 | 
|  | 432 | parsing on-demand" (#2478), and then the public key data would be held as | 
|  | 433 | bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot | 
|  | 434 | when it's actually used. | 
|  | 435 |  | 
|  | 436 | Note: the PK layer actually consists of two relatively distinct parts: crypto | 
|  | 437 | operations, which will be covered by PSA, and parsing/writing (exporting) | 
|  | 438 | from/to various formats, which is currently not fully covered by the PSA | 
|  | 439 | Crypto API. | 
|  | 440 |  | 
|  | 441 | ### Algorithm identifiers and other identifiers | 
|  | 442 |  | 
|  | 443 | It should be easy to provide the user with a bunch of `#define`s for algorithm | 
|  | 444 | identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of | 
|  | 445 | those would be in the MD, Cipher and PK compatibility layers mentioned above, | 
|  | 446 | but there might be some in other modules that may be worth considering, for | 
|  | 447 | example identifiers for elliptic curves. | 
|  | 448 |  | 
|  | 449 | ### Lower layers | 
|  | 450 |  | 
|  | 451 | Generally speaking, we would retire all of the low-level, non-generic modules, | 
|  | 452 | such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing | 
|  | 453 | 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] | 454 | 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] | 455 | would mostly benefit people who already used those generic APis rather than | 
|  | 456 | the low-level, alg-specific ones.) | 
|  | 457 |  | 
|  | 458 | ### APIs in TLS and X.509 | 
|  | 459 |  | 
|  | 460 | Public APIs in TLS and X.509 may be affected by the migration in at least two | 
|  | 461 | ways: | 
|  | 462 |  | 
|  | 463 | 1. APIs that rely on a legacy `mbedtls_` crypto type: for example | 
|  | 464 | `mbedtls_ssl_conf_own_cert()` to configure a (certificate and the | 
|  | 465 | associated) private key. Currently the private key is passed as a | 
|  | 466 | `mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`. | 
|  | 467 | Since some users would probably still be using the compatibility PK layer, it | 
|  | 468 | would need a way to easily extract the PSA key ID from the PK context. | 
|  | 469 |  | 
|  | 470 | 2. APIs the accept list of identifiers: for example | 
|  | 471 | `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] | 472 | 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] | 473 | 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] | 474 | the underlying crypto implementation and use TLS-specific identifiers instead | 
|  | 475 | (based on IANA values or custom enums), as is currently done in the new | 
|  | 476 | `mbedtls_ssl_conf_groups()` API, see #4859). | 
|  | 477 |  | 
|  | 478 | Testing | 
|  | 479 | ------- | 
|  | 480 |  | 
|  | 481 | An question that needs careful consideration when we come around to removing | 
|  | 482 | the low-level crypto APIs and making PK, MD and Cipher optional compatibility | 
|  | 483 | layers is to be sure to preserve testing quality. A lot of the existing test | 
|  | 484 | 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] | 485 | 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] | 486 | combination of both, perhaps evolving gradually over time. |