quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

transition-guards.md (15677B)


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