Merge pull request #7330 from mpg/hashes-wrapup

Driver-only hashes: wrap-up
This commit is contained in:
Manuel Pégourié-Gonnard 2023-03-27 13:19:45 +02:00 committed by GitHub
commit 0048d15036
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 104 deletions

View file

@ -0,0 +1,10 @@
Features
* All modules that use hashes or HMAC can now take advantage of PSA Crypto
drivers when MBEDTLS_PSA_CRYPTO_C is enabled and psa_crypto_init() has
been called. Previously (in 3.3), this was restricted to a few modules,
and only in builds where MBEDTLS_MD_C was disabled; in particular the
entropy module was not covered which meant an external RNG had to be
provided - these limitations are lifted in this version. A new set of
feature macros, MBEDTLS_MD_CAN_xxx, has been introduced that can be used
to check for availability of hash algorithms, regardless of whether
they're provided by a built-in implementation, a driver or both.

View file

@ -11,11 +11,15 @@ is, of course, to actually do the migration work.
Limitations relevant for G1 (performing crypto operations)
==========================================================
Restartable ECC operations
--------------------------
Restartable (aka interruptible) ECC operations
----------------------------------------------
There is currently no support for that in PSA at all, but it will be added at
some point, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18816849>.
Support for interruptible ECDSA sign/verify was added to PSA in Mbed TLS 3.4.
However support for interruptible ECDH is not present yet. Also, PK, X.509 and
TLS have not yet been adapted to take advantage of the new PSA APIs. See:
- <https://github.com/Mbed-TLS/mbedtls/issues/7292>;
- <https://github.com/Mbed-TLS/mbedtls/issues/7293>;
- <https://github.com/Mbed-TLS/mbedtls/issues/7294>.
Currently, when `MBEDTLS_USE_PSA_CRYPTO` and `MBEDTLS_ECP_RESTARTABLE` are
both enabled, some operations that should be restartable are not (ECDH in TLS
@ -78,6 +82,10 @@ the one that requires the most work, but it would deliver value beyond PSA
migration by implementing RFC 7919. (Implementing RFC 7919 could be done any
time; making it mandatory can only be done in 4.0 or another major version.)
As of early 2023, the plan is to go with option 2 in Mbed TLS 4.0, which has
been announced on the mailing-list and got no push-back, see
<https://github.com/Mbed-TLS/mbedtls/issues/5278>.
RSA-PSS parameters
------------------
@ -321,6 +329,8 @@ probably not acceptable.
in the meantime. Such an extension seems inconvenient and not motivated by
strong security arguments, so it's unclear whether it would be accepted.
Since Mbed TLS 3.4, option 1 is implemented.
Limitations relevant for G2 (isolation of long-term secrets)
============================================================

View file

@ -18,13 +18,17 @@ needs to be changed to use new APIs. For a more detailed account of what's
implemented, see `docs/use-psa-crypto.md`, where new APIs are about (G2), and
internal changes implement (G1).
As of early 2023, work towards G5 is in progress: Mbed TLS 3.3 and 3.4 saw
some improvements in this area, and more will be coming in future releases.
Generally speaking, the numbering above doesn't mean that each goal requires
the preceding ones to be completed.
Compile-time options
====================
We currently have two compile-time options that are relevant to the migration:
We currently have a few compile-time options that are relevant to the migration:
- `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA
Crypto APIs.
@ -36,7 +40,9 @@ We currently have two compile-time options that are relevant to the migration:
The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default
are:
- it's incompatible with `MBEDTLS_ECP_RESTARTABLE`;
- it's not fully compatible with `MBEDTLS_ECP_RESTARTABLE`: you can enable
both, but then you won't get the full effect of RESTARTBLE (see the
documentation of this option in `mbedtls_config.h`);
- to avoid a hard/default dependency of TLS, X.509 and PK on
`MBEDTLS_PSA_CRYPTO_C`, for backward compatibility reasons:
- When `MBEDTLS_PSA_CRYPTO_C` is enabled and used, applications need to call
@ -71,10 +77,10 @@ Crypto does not support restartable operations, there's a clear conflict: the
TLS and X.509 layers can't both use only PSA APIs and get restartable
behaviour.
Supporting this in PSA is on our roadmap and currently planned for end of
2022, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18883250>.
Support for restartable (aka interruptible) ECDSA sign/verify operation was
added to PSA in Mbed TLS 3.4, but support for ECDH is not present yet.
It will then require follow-up work to make use of the new PSA API in
It will then require follow-up work to make use of the new PSA APIs in
PK/X.509/TLS in all places where we currently allow restartable operations.
### Backward compatibility issues with making `MBEDTLS_USE_PSA_CRYPTO` always on
@ -137,8 +143,11 @@ crypto API.
- Downside: tricky to implement if the PSA implementation is currently done on
top of that layer (dependency loop).
This strategy is currently (early 2022) used for all operations in the PK
layer.
This strategy is currently (early 2023) used for all operations in the PK
layer; the MD layer uses a variant where it dispatches to PSA if a driver is
available and the driver subsystem has been initialized, regardless of whether
`USE_PSA_CRYPTO` is enabled; see `md-cipher-dispatch.md` in the same directory
for details.
This strategy is not very well suited to the Cipher layer, as the PSA
implementation is currently done on top of that layer.
@ -161,8 +170,9 @@ Replace calls for each operation
code size.
- Downside: TLS/X.509 code has to be done for each operation.
This strategy is currently (early 2022) used for the MD layer and the Cipher
layer.
This strategy is currently (early 2023) used for the MD layer and the Cipher
layer in X.509 and TLS. Crypto modules however always call to MD which may
then dispatch to PSA, see `md-cipher-dispatch.md`.
Opt-in use of PSA from the abstraction layer
--------------------------------------------
@ -210,7 +220,10 @@ Strategies currently (early 2022) used with each abstraction layer:
- PK (for G1): silently call PSA
- PK (for G2): opt-in use of PSA (new key type)
- Cipher (G1): replace calls at each call site
- MD (G1): replace calls at each call site
- MD (G1, X.509 and TLS): replace calls at each call site (depending on
`USE_PSA_CRYPTO`)
- MD (G5): silently call PSA when a driver is available, see
`md-cipher-dispatch.md`.
Supporting builds with drivers without the software implementation
@ -219,10 +232,6 @@ Supporting builds with drivers without the software implementation
This section presents a plan towards G5: save code size by compiling out our
software implementation when a driver is available.
Additionally, we want to save code size by compiling out the
abstractions layers that we are not using when `MBEDTLS_USE_PSA_CRYPTO` is
enabled (see previous section): MD and Cipher.
Let's expand a bit on the definition of the goal: in such a configuration
(driver used, software implementation and abstraction layer compiled out),
we want:
@ -238,9 +247,10 @@ at feature parity with software-based builds.
We can roughly divide the work needed to get there in the following steps:
0. Have a working driver interface for the algorithms we want to replace.
1. Have users of these algorithms call to PSA, not the legacy API, for all
operations. (This is G1, and for PK, X.509 and TLS this is controlled by
`MBEDTLS_USE_PSA_CRYPTO`.) This needs to be done in the library and tests.
1. Have users of these algorithms call to PSA or an abstraction layer than can
dispatch to PSA, but not the low-level legacy API, for all operations.
(This is G1, and for PK, X.509 and TLS this is controlled by
`MBEDTLS_USE_PSA_CRYPTO`.) This needs to be done in the library and tests.
2. Have users of these algorithms not depend on the legacy API for information
management (getting a size for a given algorithm, etc.)
3. Adapt compile-time guards used to query availability of a given algorithm;
@ -262,50 +272,32 @@ not possible to achieve good test coverage at the end of step 1 or step 2, it
is preferable to group with the next step(s) in the same PR until good test
coverage can be reached.
**Status as of Mbed TLS 3.2:**
**Status as of end of March 2023 (shortly after 3.4):**
- Step 0 is achieved for most algorithms, with only a few gaps remaining.
- Step 1 is achieved for most of PK, X.509, and TLS when
`MBEDTLS_USE_PSA_CRYPTO` is enabled with only a few gaps remaining (see
docs/use-psa-crypto.md).
- Step 1 is not achieved for a lot of the crypto library including the PSA
core. For example, `entropy.c` calls the legacy API
`mbedtls_sha256` (or `mbedtls_sha512` optionally); `hmac_drbg.c` calls the
legacy API `mbedtls_md` and `ctr_drbg.c` calls the legacy API `mbedtls_aes`;
the PSA core depends on the entropy module and at least one of the DRBG
modules (unless `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is used). Further, several
crypto modules have similar issues, for example RSA PKCS#1 v2.1 calls
`mbedtls_md` directly.
- Step 1 is achieved for the crypto library regarding hashes: everything uses
MD (not low-level hash APIs), which then dispatches to PSA if applicable.
- Step 1 is not achieved for all of the crypto library when it come to
ciphers. For example,`ctr_drbg.c` calls the legacy API `mbedtls_aes`.
- Step 2 is achieved for most of X.509 and TLS (same gaps as step 1) when
`MBEDTLS_USE_PSA_CRYPTO` is enabled - this was tasks like #5795, #5796,
#5797. It is being done in PK and RSA PKCS#1 v1.5 by PR #6065.
- Step 3 was mostly not started at all before 3.2; it is being done for PK by
PR #6065.
`MBEDTLS_USE_PSA_CRYPTO` is enabled.
- Step 3 is done for hashes and top-level ECC modules (ECDSA, ECDH, ECJPAKE).
**Strategy for step 1:**
Regarding PK, X.509, and TLS, this is mostly achieved with only a few gaps.
(The strategy was outlined in the previous section.)
Regarding libmbedcrypto, outside of the RNG subsystem, for modules that
currently depend on other legacy crypto modules, this can be achieved without
backwards compatibility issues, by using the software implementation if
available, and "falling back" to PSA only if it's not. The compile-time
dependency changes from the current one (say, `MD_C` or `AES_C`) to "the
previous dependency OR PSA Crypto with needed algorithms". When building
without software implementation, users need to call `psa_crypto_init()` before
calling any function from these modules. This condition does not constitute a
break of backwards compatibility, as it was previously impossible to build in
those configurations, and in configurations were the build was possible,
application code keeps working unchanged. An work-in-progress example of
applying this strategy, for RSA PKCS#1 v2.1, is here:
<https://github.com/Mbed-TLS/mbedtls/pull/6141>
There is a problem with the modules used for the PSA RNG, as currently the RNG
is initialized before drivers and the key store. This part will need further
study, but in the meantime we can proceed with everything that's not the
entropy module of one of the DRBG modules, and that does not depend on one of
those modules.
Regarding libmbedcrypto:
- for hashes and ciphers, see `md-cipher-dispatch.md` in the same directory;
- for ECC, we have no internal uses of the top-level algorithms (ECDSA, ECDH,
ECJPAKE), however they all depend on `ECP_C` which in turn depends on
`BIGNUM_C`. So, direct calls from TLS, X.509 and PK to ECP and Bignum will
need to be replaced; see <https://github.com/Mbed-TLS/mbedtls/issues/6839> and
linked issues for a summary of intermediate steps and open points.
**Strategy for step 2:**
@ -315,14 +307,11 @@ convenient, for example in parts of the code that accept old-style identifiers
(such as `mbedtls_md_type_t`) in their API and can't assume PSA to be
compiled in (such as `rsa.c`).
It is suggested that, as a temporary solution until we clean this up
later when removing the legacy API including its identifiers (G4), we may
occasionally use ad-hoc internal functions, such as the ones introduced by PR
6065 in `library/hash_info.[ch]`.
An alternative would be to have two different code paths depending on whether
`MBEDTLS_PSA_CRYPTO_C` is defined or not. However this is not great for
readability or testability.
When using an existing abstraction layer such as MD, it can provide
information management functions. In other cases, information that was in a
low-level module but logically belongs in a higher-level module can be moved
to that module (for example, TLS identifiers of curves and there conversion
to/from PSA or legacy identifiers belongs in TLS, not `ecp.c`).
**Strategy for step 3:**
@ -338,35 +327,15 @@ dependencies above depending on whether `MBEDTLS_USE_PSA_CRYPTO` is defined:
if it is, the code want the algorithm available in PSA, otherwise, it wants it
available via the legacy API(s) is it using (MD and/or low-level).
The strategy for steps 1 and 2 above will introduce new situations: code that
currently compute hashes using MD (resp. a low-level hash module) will gain
the ability to "fall back" to using PSA if the legacy dependency isn't
available. Data related to a certain hash (OID, sizes, translations) should
only be included in the build if it is possible to use that hash in some way.
As much as possible, we're trying to create for each algorithm a single new
macro that can be used to express dependencies everywhere (except pure PSA
code that should always use `PSA_WANT`). For example, for hashes this is the
`MBEDTLS_MD_CAN_xxx` family. For ECC algorithms, we have similar
`MBEDTLS_PK_CAN_xxx` macros.
In order to cater to these new needs, new families of macros are introduced in
`legacy_or_psa.h`, see its documentation for details.
It should be noted that there are currently:
- too many different ways of computing a hash (low-level, MD, PSA);
- too many different ways to configure the library that influence which of
these ways is available and will be used (`MBEDTLS_USE_PSA_CRYPTO`,
`MBEDTLS_PSA_CRYPTO_CONFIG`, `mbedtls_config.h` + `psa/crypto_config.h`).
As a result, we need more families of dependency macros than we'd like to.
This is a temporary situation until we move to a place where everything is
based on PSA Crypto. In the meantime, long and explicit names where chosen for
the new macros in the hope of avoiding confusion.
Note: the new macros supplement but do not replace the existing macros:
- code that always uses PSA Crypto (for example, code specific to TLS 1.3)
should use `PSA_WANT_xxx`;
- code that always uses the legacy API (for example, crypto modules that have
not undergone step 1 yet) should use `MBEDTLS_xxx_C`;
- code that may use one of the two APIs, either based on
`MBEDTLS_USE_PSA_CRYPTO` (X.509, TLS 1.2, shared between TLS 1.2 and 1.3),
or based on availability (crypto modules after step 1), should use one of
the new macros from `legacy_or_psa.h`.
Note that in order to achieve that goal, even for code that obeys
`USE_PSA_CRYPTO`, it is useful to impose that all algorithms that are
available via the legacy APIs are also available via PSA.
Executing step 3 will mostly consist of using the right dependency macros in
the right places (once the previous steps are done).

View file

@ -1,8 +1,12 @@
This document describes the compile-time configuration option
`MBEDTLS_USE_PSA_CRYPTO` from a user's perspective.
This option makes the X.509 and TLS library use PSA for cryptographic
operations, and enables new APIs for using keys handled by PSA Crypto.
This option:
- makes the X.509 and TLS libraries use PSA for cryptographic operations as
much as possible, see "Internal changes" below;
- enables new APIs for using keys handled by PSA Crypto, such as
`mbedtls_pk_setup_opaque()` and `mbedtls_ssl_conf_psk_opaque()`, see
"New APIs / API extensions" below.
General considerations
----------------------
@ -11,9 +15,25 @@ General considerations
`psa_crypto_init()` before calling any function from the SSL/TLS, X.509 or PK
module.
**Scope:** `MBEDTLS_USE_PSA_CRYPTO` has no effect on the most of the TLS 1.3
code, which always uses PSA crypto. The parts of the TLS 1.3 code that will
use PSA Crypto or not depending on the value of this option are:
**Relationship with other options:** This option depends on
`MBEDTLS_PSA_CRYPTO_C`. These two options differ in the following way:
- `MBEDTLS_PSA_CRYPTO_C` enables the implementation of the PSA Crypto API.
When it is enabled, `psa_xxx()` APIs are available and you must call
`psa_crypto_init()` before you call any other `psa_xxx()` function. Other
modules in the library (non-PSA crypto APIs, X.509, TLS) may or may not use
PSA Crypto but you're not required to call `psa_crypto_init()` before calling
non-PSA functions, unless when explicitly documented (TLS 1.3).
- `MBEDTLS_USE_PSA_CRYPTO` means that X.509 and TLS will use PSA Crypto as
much as possible (that is, everywhere except for features that are not
supported by PSA Crypto, see "Internal Changes" below for a complete list of
exceptions). When it is enabled, you need to call `psa_crypto_init()` before
calling any function from PK, X.509 or TLS; however it doesn't change anything
for the rest of the library.
**Scope:** `MBEDTLS_USE_PSA_CRYPTO` has no effect on modules other than PK,
X.509 and TLS. It also has no effect on most of the TLS 1.3 code, which always
uses PSA crypto. The parts of the TLS 1.3 code that will use PSA Crypto or not
depending on this option being set or not are:
- record protection;
- running handshake hash;
- asymmetric signature verification & generation;
@ -21,6 +41,21 @@ use PSA Crypto or not depending on the value of this option are:
You need to enable `MBEDTLS_USE_PSA_CRYPTO` if you want TLS 1.3 to use PSA
everywhere.
**Historical note:** This option was introduced at a time when PSA Crypto was
still beta and not ready for production, so we made its use in X.509 and TLS
opt-in: by default, these modules would keep using the stable,
production-ready legacy (pre-PSA) crypto APIs. So, the scope of was X.509 and
TLS, as well as some of PK for technical reasons. Nowadays PSA Crypto is no
longer beta, and production quality, so there's no longer any reason to make
its use in other modules opt-in. However, PSA Crypto functions require that
`psa_crypto_init()` has been called before their use, and for backwards
compatibility reasons we can't impose this requirement on non-PSA functions
that didn't have such a requirement before. So, nowadays the main meaning of
`MBEDTLS_USE_PSA_CRYPTO` is that the user promises to call `psa_crypto_init()`
before calling any PK, X.509 or TLS functions. For the same compatibility
reasons, we can't extend its scope. However, new modules in the library, such
as TLS 1.3, can be introduced with a requirement to call `psa_crypto_init()`.
New APIs / API extensions
-------------------------
@ -63,6 +98,19 @@ register a PSA key for use with a PSK key exchange.
**Use in TLS:** opt-in. The application needs to register the key using one of
the new APIs to get the benefits.
### PSA-held (opaque) keys for TLS 1.2 EC J-PAKE key exchange
**New API function:** `mbedtls_ssl_set_hs_ecjpake_password_opaque()`.
Call this function from an application to register a PSA key for use with the
TLS 1.2 EC J-PAKE key exchange.
**Benefits:** isolation of long-term secrets.
**Limitations:** none.
**Use in TLS:** opt-in. The application needs to register the key using one of
the new APIs to get the benefits.
### PSA-based operations in the Cipher layer
There is a new API function `mbedtls_cipher_setup_psa()` to set up a context

View file

@ -1567,13 +1567,14 @@
* Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
*
* Requires: Without MBEDTLS_USE_PSA_CRYPTO: MBEDTLS_MD_C and
* (MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C)
* (MBEDTLS_SHA256_C or MBEDTLS_SHA384_C or
* SHA-256 or SHA-512 provided by a PSA driver)
* With MBEDTLS_USE_PSA_CRYPTO:
* PSA_WANT_ALG_SHA_1 or PSA_WANT_ALG_SHA_256 or
* PSA_WANT_ALG_SHA_512
* PSA_WANT_ALG_SHA_256 or PSA_WANT_ALG_SHA_384
*
* \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call
* psa_crypto_init() before doing any TLS operations.
* \warning If building with MBEDTLS_USE_PSA_CRYPTO, or if the hash(es) used
* are only provided by PSA drivers, you must call psa_crypto_init() before
* doing any TLS operations.
*
* Comment this macro to disable support for TLS 1.2 / DTLS 1.2
*/
@ -1921,20 +1922,23 @@
/**
* \def MBEDTLS_USE_PSA_CRYPTO
*
* Make the X.509 and TLS library use PSA for cryptographic operations, and
* enable new APIs for using keys handled by PSA Crypto.
* Make the X.509 and TLS libraries use PSA for cryptographic operations as
* much as possible, and enable new APIs for using keys handled by PSA Crypto.
*
* \note Development of this option is currently in progress, and parts of Mbed
* TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts
* will still continue to work as usual, so enabling this option should not
* break backwards compatibility.
*
* \note See docs/use-psa-crypto.md for a complete description of what this
* option currently does, and of parts that are not affected by it so far.
*
* \warning If you enable this option, you need to call `psa_crypto_init()`
* before calling any function from the SSL/TLS, X.509 or PK modules.
*
* \note Even with this option disabled, some code in PK, X.509, TLS or the
* crypto library might still use PSA drivers, if it can determine it's safe
* to do so.
*
* \note See docs/use-psa-crypto.md for a complete description this option.
*
* Requires: MBEDTLS_PSA_CRYPTO_C.
*
* Uncomment this to enable internal use of PSA Crypto and new associated APIs.