xref: /aosp_15_r20/external/mbedtls/docs/architecture/psa-migration/md-cipher-dispatch.md (revision 62c56f9862f102b96d72393aff6076c951fb8148)
1*62c56f98SSadaf EbrahimiPSA migration strategy for hashes and ciphers
2*62c56f98SSadaf Ebrahimi=============================================
3*62c56f98SSadaf Ebrahimi
4*62c56f98SSadaf Ebrahimi## Introduction
5*62c56f98SSadaf Ebrahimi
6*62c56f98SSadaf EbrahimiThis document discusses a migration strategy for code that is not subject to `MBEDTLS_USE_PSA_CRYPTO`, is currently using legacy cryptography APIs, and should transition to PSA, without a major version change.
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi### Relationship with the main strategy document
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf EbrahimiThis is complementary to the main [strategy document](strategy.html) and is intended as a refinement. However, at this stage, there may be contradictions between the strategy proposed here and some of the earlier strategy.
11*62c56f98SSadaf Ebrahimi
12*62c56f98SSadaf EbrahimiA difference between the original strategy and the current one is that in this work, we are not treating PSA as a black box. We can change experimental features, and we can call internal interfaces.
13*62c56f98SSadaf Ebrahimi
14*62c56f98SSadaf Ebrahimi## Requirements
15*62c56f98SSadaf Ebrahimi
16*62c56f98SSadaf Ebrahimi### User stories
17*62c56f98SSadaf Ebrahimi
18*62c56f98SSadaf Ebrahimi#### Backward compatibility user story
19*62c56f98SSadaf Ebrahimi
20*62c56f98SSadaf EbrahimiAs a developer of an application that uses Mbed TLS's interfaces (including legacy crypto),
21*62c56f98SSadaf EbrahimiI want Mbed TLS to preserve backward compatibility,
22*62c56f98SSadaf Ebrahimiso that my code keeps working in new minor versions of Mbed TLS.
23*62c56f98SSadaf Ebrahimi
24*62c56f98SSadaf Ebrahimi#### Interface design user story
25*62c56f98SSadaf Ebrahimi
26*62c56f98SSadaf EbrahimiAs a developer of library code that uses Mbed TLS to perform cryptographic operations,
27*62c56f98SSadaf EbrahimiI want to know which functions to call and which feature macros to check,
28*62c56f98SSadaf Ebrahimiso that my code works in all Mbed TLS configurations.
29*62c56f98SSadaf Ebrahimi
30*62c56f98SSadaf EbrahimiNote: this is the same problem we face in X.509 and TLS.
31*62c56f98SSadaf Ebrahimi
32*62c56f98SSadaf Ebrahimi#### Hardware accelerator vendor user stories
33*62c56f98SSadaf Ebrahimi
34*62c56f98SSadaf EbrahimiAs a vendor of a platform with hardware acceleration for some crypto,
35*62c56f98SSadaf EbrahimiI want to build Mbed TLS in a way that uses my hardware wherever relevant,
36*62c56f98SSadaf Ebrahimiso that my customers maximally benefit from my hardware.
37*62c56f98SSadaf Ebrahimi
38*62c56f98SSadaf EbrahimiAs a vendor of a platform with hardware acceleration for some crypto,
39*62c56f98SSadaf EbrahimiI want to build Mbed TLS without software that replicates what my hardware does,
40*62c56f98SSadaf Ebrahimito minimize the code size.
41*62c56f98SSadaf Ebrahimi
42*62c56f98SSadaf Ebrahimi#### Maintainer user stories
43*62c56f98SSadaf Ebrahimi
44*62c56f98SSadaf EbrahimiAs a maintainer of Mbed TLS,
45*62c56f98SSadaf EbrahimiI want to have clear rules for when to use which interface,
46*62c56f98SSadaf Ebrahimito avoid bugs in “unusual” configurations.
47*62c56f98SSadaf Ebrahimi
48*62c56f98SSadaf EbrahimiAs a maintainer of Mbed TLS,
49*62c56f98SSadaf EbrahimiI want to avoid duplicating code,
50*62c56f98SSadaf Ebrahimibecause this is inefficient and error-prone.
51*62c56f98SSadaf Ebrahimi
52*62c56f98SSadaf Ebrahimi### Use PSA more
53*62c56f98SSadaf Ebrahimi
54*62c56f98SSadaf EbrahimiIn the long term, all code using cryptography should use PSA interfaces, to benefit from PSA drivers, allow eliminating legacy interfaces (less code size, less maintenance). However, this can't be done without breaking [backward compatibility](#backward-compatibility).
55*62c56f98SSadaf Ebrahimi
56*62c56f98SSadaf EbrahimiThe goal of this work is to arrange for more non-PSA interfaces to use PSA interfaces under the hood, without breaking code in the cases where this doesn't work. Using PSA interfaces has two benefits:
57*62c56f98SSadaf Ebrahimi
58*62c56f98SSadaf Ebrahimi* Where a PSA driver is available, it likely has better performance, and sometimes better security, than the built-in software implementation.
59*62c56f98SSadaf Ebrahimi* In many scenarios, where a PSA driver is available, this allows removing the software implementation altogether.
60*62c56f98SSadaf Ebrahimi* We may be able to get rid of some redundancies, for example the duplication between the implementations of HMAC in `md.c` and in `psa_crypto_mac.c`, and HKDF in `hkdf.c` and `psa_crypto.c`.
61*62c56f98SSadaf Ebrahimi
62*62c56f98SSadaf Ebrahimi### Correct dependencies
63*62c56f98SSadaf Ebrahimi
64*62c56f98SSadaf EbrahimiTraditionally, to determine whether a cryptographic mechanism was available, you had to check whether the corresponding Mbed TLS module or submodule was present: `MBEDTLS_SHA256_C` for SHA256, `MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC` for AES-CBC, etc. In code that uses the PSA interfaces, this needs to change to `PSA_WANT_xxx` symbols.
65*62c56f98SSadaf Ebrahimi
66*62c56f98SSadaf Ebrahimi### Backward compatibility
67*62c56f98SSadaf Ebrahimi
68*62c56f98SSadaf EbrahimiAll documented behavior must be preserved, except for interfaces currently described as experimental or unstable. Those interfaces can change, but we should minimize disruption by providing a transition path for reasonable use cases.
69*62c56f98SSadaf Ebrahimi
70*62c56f98SSadaf Ebrahimi#### Changeable configuration options
71*62c56f98SSadaf Ebrahimi
72*62c56f98SSadaf EbrahimiThe following configuration options are described as experimental, and are likely to change at least marginally:
73*62c56f98SSadaf Ebrahimi
74*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_CLIENT`: “This interface is experimental and may change or be removed without notice.” In practice we don't want to remove this, but we may constrain how it's used.
75*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_DRIVERS`: “This interface is experimental. We intend to maintain backward compatibility with application code that relies on drivers, but the driver interfaces may change without notice.” In practice, this may mean constraints not only on how to write drivers, but also on how to integrate drivers into code that is platform code more than application code.
76*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_CONFIG`: “This feature is still experimental and is not ready for production since it is not completed.” We may want to change this, for example, to automatically enable more mechanisms (although this wouldn't be considered a backward compatibility break anyway, since we don't promise that you will not get a feature if you don't enable its `PSA_WANT_xxx`).
77*62c56f98SSadaf Ebrahimi
78*62c56f98SSadaf Ebrahimi### Non-goals
79*62c56f98SSadaf Ebrahimi
80*62c56f98SSadaf EbrahimiIt is not a goal at this stage to make more code directly call `psa_xxx` functions. Rather, the goal is to make more code call PSA drivers where available. How dispatch is done is secondary.
81*62c56f98SSadaf Ebrahimi
82*62c56f98SSadaf Ebrahimi## Problem analysis
83*62c56f98SSadaf Ebrahimi
84*62c56f98SSadaf Ebrahimi### Scope analysis
85*62c56f98SSadaf Ebrahimi
86*62c56f98SSadaf Ebrahimi#### Limitations of `MBEDTLS_USE_PSA_CRYPTO`
87*62c56f98SSadaf Ebrahimi
88*62c56f98SSadaf EbrahimiThe option `MBEDTLS_USE_PSA_CRYPTO` causes parts of the library to call the PSA API instead of legacy APIs for cryptographic calculations. `MBEDTLS_USE_PSA_CRYPTO` only applies to `pk.h`, X.509 and TLS. When this option is enabled, applications must call `psa_crypto_init()` before calling any of the functions in these modules.
89*62c56f98SSadaf Ebrahimi
90*62c56f98SSadaf EbrahimiIn this work, we want two things:
91*62c56f98SSadaf Ebrahimi
92*62c56f98SSadaf Ebrahimi* Make non-covered modules call PSA, but only [when this will actually work](#why-psa-is-not-always-possible). This effectively brings those modules to a partial use-PSA behavior (benefiting from PSA accelerators when they're usable) regardless of whether the option is enabled.
93*62c56f98SSadaf Ebrahimi* Call PSA when a covered module calls a non-covered module which calls another module, for example X.509 calling pk for PSS verification which calls RSA which calculates a hash ([see issue \#6497](https://github.com/Mbed-TLS/mbedtls/issues/6497)). This effectively extends the option to modules that aren't directly covered.
94*62c56f98SSadaf Ebrahimi
95*62c56f98SSadaf Ebrahimi#### Classification of callers
96*62c56f98SSadaf Ebrahimi
97*62c56f98SSadaf EbrahimiWe can classify code that implements or uses cryptographic mechanisms into several groups:
98*62c56f98SSadaf Ebrahimi
99*62c56f98SSadaf Ebrahimi* Software implementations of primitive cryptographic mechanisms. These are not expected to change.
100*62c56f98SSadaf Ebrahimi* Software implementations of constructed cryptographic mechanisms (e.g. HMAC, CTR_DRBG, RSA (calling a hash for PSS/OAEP, and needing to know the hash length in PKCS1v1.5 sign/verify), …). These need to keep working whenever a legacy implementation of the auxiliary mechanism is available, regardless of whether a PSA implementation is also available.
101*62c56f98SSadaf Ebrahimi* Code implementing the PSA crypto interface. This is not expected to change, except perhaps to expose some internal functionality to overhauled glue code.
102*62c56f98SSadaf Ebrahimi* Code that's subject to `MBEDTLS_USE_PSA_CRYPTO`: `pk.h`, X.509, TLS (excluding TLS 1.3).
103*62c56f98SSadaf Ebrahimi* Code that always uses PSA for crypto: TLS 1.3, LMS.
104*62c56f98SSadaf Ebrahimi
105*62c56f98SSadaf EbrahimiFor the purposes of this work, three domains emerge:
106*62c56f98SSadaf Ebrahimi
107*62c56f98SSadaf Ebrahimi* **Legacy domain**: does not interact with PSA. Implementations of hashes, of cipher primitives, of arithmetic.
108*62c56f98SSadaf Ebrahimi* **Mixed domain**: does not currently use PSA, but should [when possible](#why-psa-is-not-always-possible). This consists of the constructed cryptographic primitives (except LMS), as well as pk, X.509 and TLS when `MBEDTLS_USE_PSA_CRYPTO` is disabled.
109*62c56f98SSadaf Ebrahimi* **PSA domain**: includes pk, X.509 and TLS when `MBEDTLS_USE_PSA_CRYPTO` is enabled. Also TLS 1.3, LMS.
110*62c56f98SSadaf Ebrahimi
111*62c56f98SSadaf Ebrahimi#### Non-use-PSA modules
112*62c56f98SSadaf Ebrahimi
113*62c56f98SSadaf EbrahimiThe following modules in Mbed TLS call another module to perform cryptographic operations which, in the long term, will be provided through a PSA interface, but cannot make any PSA-related assumption:
114*62c56f98SSadaf Ebrahimi
115*62c56f98SSadaf Ebrahimi* CCM (block cipher in ECB mode; interdependent with cipher)
116*62c56f98SSadaf Ebrahimi* cipher (cipher and AEAD algorithms)
117*62c56f98SSadaf Ebrahimi* CMAC (AES-ECB and DES-ECB, but could be extended to the other block ciphers; interdependent with cipher)
118*62c56f98SSadaf Ebrahimi* CTR\_DRBG (AES-ECB, but could be extended to the other block ciphers)
119*62c56f98SSadaf Ebrahimi* entropy (hashes via low-level)
120*62c56f98SSadaf Ebrahimi* ECDSA (HMAC\_DRBG; `md.h` exposed through API)
121*62c56f98SSadaf Ebrahimi* ECJPAKE (hashes via md; `md.h` exposed through API)
122*62c56f98SSadaf Ebrahimi* GCM (block cipher in ECB mode; interdependent with cipher)
123*62c56f98SSadaf Ebrahimi* md (hashes and HMAC)
124*62c56f98SSadaf Ebrahimi* NIST\_KW (AES-ECB; interdependent with cipher)
125*62c56f98SSadaf Ebrahimi* HMAC\_DRBG (hashes and HMAC via `md.h`; `md.h` exposed through API)
126*62c56f98SSadaf Ebrahimi* PEM (AES and DES in CBC mode without padding; MD5 hash via low-level)
127*62c56f98SSadaf Ebrahimi* PKCS12 (cipher, generically, selected from ASN.1 or function parameters; hashes via md; `cipher.h` exposed through API)
128*62c56f98SSadaf Ebrahimi* PKCS5 (cipher, generically, selected from ASN.1; HMAC via `md.h`; `md.h` exposed through API)
129*62c56f98SSadaf Ebrahimi* RSA (hash via md for PSS and OAEP; `md.h` exposed through API)
130*62c56f98SSadaf Ebrahimi
131*62c56f98SSadaf Ebrahimi### Difficulties
132*62c56f98SSadaf Ebrahimi
133*62c56f98SSadaf Ebrahimi#### Why PSA is not always possible
134*62c56f98SSadaf Ebrahimi
135*62c56f98SSadaf EbrahimiHere are some reasons why calling `psa_xxx()` to perform a hash or cipher calculation might not be desirable in some circumstances, explaining why the application would arrange to call the legacy software implementation instead.
136*62c56f98SSadaf Ebrahimi
137*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_C` is disabled.
138*62c56f98SSadaf Ebrahimi* There is a PSA driver which has not been initialized (this happens in `psa_crypto_init()`).
139*62c56f98SSadaf Ebrahimi* For ciphers, the keystore is not initialized yet, and Mbed TLS uses a custom implementation of PSA ITS where the file system is not accessible yet (because something else needs to happen first, and the application takes care that it happens before it calls `psa_crypto_init()`). A possible workaround may be to dispatch to the internal functions that are called after the keystore lookup, rather than to the PSA API functions (but this is incompatible with `MBEDTLS_PSA_CRYPTO_CLIENT`).
140*62c56f98SSadaf Ebrahimi* The requested mechanism is enabled in the legacy interface but not in the PSA interface. This was not really intended, but is possible, for example, if you enable `MBEDTLS_MD5_C` for PEM decoding with PBKDF1 but don't want `PSA_ALG_WANT_MD5` because it isn't supported for `PSA_ALG_RSA_PSS` and `PSA_ALG_DETERMINISTIC_ECDSA`.
141*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_CLIENT` is enabled, and the client has not yet activated the connection to the server (this happens in `psa_crypto_init()`).
142*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_CLIENT` is enabled, but the operation is part of the implementation of an encrypted communication with the crypto service, or the local implementation is faster because it avoids a costly remote procedure call.
143*62c56f98SSadaf Ebrahimi
144*62c56f98SSadaf Ebrahimi#### Indirect knowledge
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf EbrahimiConsider for example the code in `rsa.c` to perform an RSA-PSS signature. It needs to calculate a hash. If `mbedtls_rsa_rsassa_pss_sign()` is called directly by application code, it is supposed to call the built-in implementation: calling a PSA accelerator would be a behavior change, acceptable only if this does not add a risk of failure or performance degradation ([PSA is impossible or undesirable in some circumstances](#why-psa-is-not-always-possible)). Note that this holds regardless of the state of `MBEDTLS_USE_PSA_CRYPTO`, since `rsa.h` is outside the scope of `MBEDTLS_USE_PSA_CRYPTO`. On the other hand, if `mbedtls_rsa_rsassa_pss_sign()` is called from X.509 code, it should use PSA to calculate hashes. It doesn't, currently, which is [bug \#6497](https://github.com/Mbed-TLS/mbedtls/issues/6497).
147*62c56f98SSadaf Ebrahimi
148*62c56f98SSadaf EbrahimiGenerally speaking, modules in the mixed domain:
149*62c56f98SSadaf Ebrahimi
150*62c56f98SSadaf Ebrahimi* must call PSA if called by a module in the PSA domain;
151*62c56f98SSadaf Ebrahimi* must not call PSA (or must have a fallback) if their caller is not in the PSA domain and the PSA call is not guaranteed to work.
152*62c56f98SSadaf Ebrahimi
153*62c56f98SSadaf Ebrahimi#### Non-support guarantees: requirements
154*62c56f98SSadaf Ebrahimi
155*62c56f98SSadaf EbrahimiGenerally speaking, just because some feature is not enabled in `mbedtls_config.h` or `psa_config.h` doesn't guarantee that it won't be enabled in the build. We can enable additional features through `build_info.h`.
156*62c56f98SSadaf Ebrahimi
157*62c56f98SSadaf EbrahimiIf `PSA_WANT_xxx` is disabled, this should guarantee that attempting xxx through the PSA API will fail. This is generally guaranteed by the test suite `test_suite_psa_crypto_not_supported` with automatically enumerated test cases, so it would be inconvenient to carve out an exception.
158*62c56f98SSadaf Ebrahimi
159*62c56f98SSadaf Ebrahimi### Technical requirements
160*62c56f98SSadaf Ebrahimi
161*62c56f98SSadaf EbrahimiBased on the preceding analysis, the core of the problem is: for code in the mixed domain (see [“Classification of callers”](#classification-of-callers)), how do we handle a cryptographic mechanism? This has several related subproblems:
162*62c56f98SSadaf Ebrahimi
163*62c56f98SSadaf Ebrahimi* How the mechanism is encoded (e.g. `mbedtls_md_type_t` vs `const *mbedtls_md_info_t` vs `psa_algorithm_t` for hashes).
164*62c56f98SSadaf Ebrahimi* How to decide whether a specific algorithm or key type is supported (eventually based on `MBEDTLS_xxx_C` vs `PSA_WANT_xxx`).
165*62c56f98SSadaf Ebrahimi* How to obtain metadata about algorithms (e.g. hash/MAC/tag size, key size).
166*62c56f98SSadaf Ebrahimi* How to perform the operation (context type, which functions to call).
167*62c56f98SSadaf Ebrahimi
168*62c56f98SSadaf EbrahimiWe need a way to decide this based on the available information:
169*62c56f98SSadaf Ebrahimi
170*62c56f98SSadaf Ebrahimi* Who's the ultimate caller — see [indirect knowledge](#indirect-knowledge) — which is not actually available.
171*62c56f98SSadaf Ebrahimi* Some parameter indicating which algorithm to use.
172*62c56f98SSadaf Ebrahimi* The available cryptographic implementations, based on preprocessor symbols (`MBEDTLS_xxx_C`, `PSA_WANT_xxx`, `MBEDTLS_PSA_ACCEL_xxx`, etc.).
173*62c56f98SSadaf Ebrahimi* Possibly additional runtime state (for example, we might check whether `psa_crypto_init` has been called).
174*62c56f98SSadaf Ebrahimi
175*62c56f98SSadaf EbrahimiAnd we need to take care of the [the cases where PSA is not possible](#why-psa-is-not-always-possible): either make sure the current behavior is preserved, or (where allowed by backward compatibility) document a behavior change and, preferably, a workaround.
176*62c56f98SSadaf Ebrahimi
177*62c56f98SSadaf Ebrahimi### Working through an example: RSA-PSS
178*62c56f98SSadaf Ebrahimi
179*62c56f98SSadaf EbrahimiLet us work through the example of RSA-PSS which calculates a hash, as in [see issue \#6497](https://github.com/Mbed-TLS/mbedtls/issues/6497).
180*62c56f98SSadaf Ebrahimi
181*62c56f98SSadaf EbrahimiRSA is in the [mixed domain](#classification-of-callers). So:
182*62c56f98SSadaf Ebrahimi
183*62c56f98SSadaf Ebrahimi* When called from `psa_sign_hash` and other PSA functions, it must call the PSA hash accelerator if there is one.
184*62c56f98SSadaf Ebrahimi* When called from user code, it must call the built-in hash implementation if PSA is not available (regardless of whether this is because `MBEDTLS_PSA_CRYPTO_C` is disabled, or because `PSA_WANT_ALG_xxx` is disabled for this hash, or because there is an accelerator driver which has not been initialized yet).
185*62c56f98SSadaf Ebrahimi
186*62c56f98SSadaf EbrahimiRSA knows which hash algorithm to use based on a parameter of type `mbedtls_md_type_t`. (More generally, all mixed-domain modules that take an algorithm specification as a parameter take it via a numerical type, except HMAC\_DRBG and HKDF which take a `const mbedtls_md_info_t*` instead, and CMAC which takes a `const mbedtls_cipher_info_t *`.)
187*62c56f98SSadaf Ebrahimi
188*62c56f98SSadaf Ebrahimi#### Double encoding solution
189*62c56f98SSadaf Ebrahimi
190*62c56f98SSadaf EbrahimiA natural solution is to double up the encoding of hashes in `mbedtls_md_type_t`. Pass `MBEDTLS_MD_SHA256` and `md` will dispatch to the legacy code, pass a new constant `MBEDTLS_MD_SHA256_USE_PSA` and `md` will dispatch through PSA.
191*62c56f98SSadaf Ebrahimi
192*62c56f98SSadaf EbrahimiThis maximally preserves backward compatibility, but then no non-PSA code benefits from PSA accelerators, and there's little potential for removing the software implementation.
193*62c56f98SSadaf Ebrahimi
194*62c56f98SSadaf Ebrahimi#### Availability of hashes in RSA-PSS
195*62c56f98SSadaf Ebrahimi
196*62c56f98SSadaf EbrahimiHere we try to answer the question: As a caller of RSA-PSS via `rsa.h`, how do I know whether it can use a certain hash?
197*62c56f98SSadaf Ebrahimi
198*62c56f98SSadaf Ebrahimi* For a caller in the legacy domain: if e.g. `MBEDTLS_SHA256_C` is enabled, then I want RSA-PSS to support SHA-256. I don't care about negative support. So `MBEDTLS_SHA256_C` must imply support for RSA-PSS-SHA-256. It must work at all times, regardless of the state of PSA (e.g. drivers not initialized).
199*62c56f98SSadaf Ebrahimi* For a caller in the PSA domain: if e.g. `PSA_WANT_ALG_SHA_256` is enabled, then I want RSA-PSS to support SHA-256, provided that `psa_crypto_init()` has been called. In some limited cases, such as `test_suite_psa_crypto_not_supported` when PSA implements RSA-PSS in software, we care about negative support: if `PSA_WANT_ALG_SHA_256` is disabled then `psa_verify_hash` must reject `PSA_WANT_ALG_SHA_256`. This can be done at the level of PSA before it calls the RSA module, though, so it doesn't have any implication on the RSA module. As far as `rsa.c` is concerned, what matters is that `PSA_WANT_ALG_SHA_256` implies that SHA-256 is supported after `psa_crypto_init()` has been called.
200*62c56f98SSadaf Ebrahimi* For a caller in the mixed domain: requirements depend on the caller. Whatever solution RSA has to determine the availability of algorithms will apply to its caller as well.
201*62c56f98SSadaf Ebrahimi
202*62c56f98SSadaf EbrahimiConclusion so far: RSA must be able to do SHA-256 if either `MBEDTLS_SHA256_C` or `PSA_WANT_ALG_SHA_256` is enabled. If only `PSA_WANT_ALG_SHA_256` and not `MBEDTLS_SHA256_C` is enabled (which implies that PSA's SHA-256 comes from an accelerator driver), then SHA-256 only needs to work if `psa_crypto_init()` has been called.
203*62c56f98SSadaf Ebrahimi
204*62c56f98SSadaf Ebrahimi#### More in-depth discussion of compile-time availability determination
205*62c56f98SSadaf Ebrahimi
206*62c56f98SSadaf EbrahimiThe following combinations of compile-time support are possible:
207*62c56f98SSadaf Ebrahimi
208*62c56f98SSadaf Ebrahimi* `MBEDTLS_PSA_CRYPTO_CLIENT`. Then calling PSA may or may not be desirable for performance. There are plausible use cases where only the server has access to an accelerator so it's best to call the server, and plausible use cases where calling the server has overhead that negates the savings from using acceleration, if there are savings at all. In any case, calling PSA only works if the connection to the server has been established, meaning `psa_crypto_init` has been called successfully. In the rest of this case enumeration, assume `MBEDTLS_PSA_CRYPTO_CLIENT` is disabled.
209*62c56f98SSadaf Ebrahimi* No PSA accelerator. Then just call `mbedtls_sha256`, it's all there is, and it doesn't matter (from an API perspective) exactly what call chain leads to it.
210*62c56f98SSadaf Ebrahimi* PSA accelerator, no software implementation. Then we might as well call the accelerator, unless it's important that the call fails. At the time of writing, I can't think of a case where we would want to guarantee that if `MBEDTLS_xxx_C` is not enabled, but xxx is enabled through PSA, then a request to use algorithm xxx through some legacy interface must fail.
211*62c56f98SSadaf Ebrahimi* Both PSA acceleration and the built-in implementation. In this case, we would prefer PSA for the acceleration, but we can only do this if the accelerator driver is working. For hashes, it's enough to assume the driver is initialized; we've [considered requiring hash drivers to work without initialization](https://github.com/Mbed-TLS/mbedtls/pull/6470). For ciphers, this is more complicated because the cipher functions require the keystore, and plausibly a cipher accelerator might want entropy (for side channel countermeasures) which might not be available at boot time.
212*62c56f98SSadaf Ebrahimi
213*62c56f98SSadaf EbrahimiNote that it's a bit tricky to determine which algorithms are available. In the case where there is a PSA accelerator but no software implementation, we don't want the preprocessor symbols to indicate that the algorithm is available through the legacy domain, only through the PSA domain. What does this mean for the interfaces in the mixed domain? They can't guarantee the availability of the algorithm, but they must try if requested.
214*62c56f98SSadaf Ebrahimi
215*62c56f98SSadaf Ebrahimi### Designing an interface for hashes
216*62c56f98SSadaf Ebrahimi
217*62c56f98SSadaf EbrahimiIn this section, we specify a hash metadata and calculation for the [mixed domain](#classification-of-callers), i.e. code that can be called both from legacy code and from PSA code.
218*62c56f98SSadaf Ebrahimi
219*62c56f98SSadaf Ebrahimi#### Availability of hashes
220*62c56f98SSadaf Ebrahimi
221*62c56f98SSadaf EbrahimiGeneralizing the analysis in [“Availability of hashes in RSA-PSS”](#availability-of-hashes-in-RSA-PSS):
222*62c56f98SSadaf Ebrahimi
223*62c56f98SSadaf EbrahimiA hash is available through the mixed-domain interface iff either of the following conditions is true:
224*62c56f98SSadaf Ebrahimi
225*62c56f98SSadaf Ebrahimi* A legacy hash interface is available and the hash algorithm is implemented in software.
226*62c56f98SSadaf Ebrahimi* PSA crypto is enabled and the hash algorithm is implemented via PSA.
227*62c56f98SSadaf Ebrahimi
228*62c56f98SSadaf EbrahimiWe could go further and make PSA accelerators available to legacy callers that call any legacy hash interface, e.g. `md.h` or `shaX.h`. There is little point in doing this, however: callers should just use the mixed-domain interface.
229*62c56f98SSadaf Ebrahimi
230*62c56f98SSadaf Ebrahimi#### Implications between legacy availability and PSA availability
231*62c56f98SSadaf Ebrahimi
232*62c56f98SSadaf Ebrahimi* When `MBEDTLS_PSA_CRYPTO_CONFIG` is disabled, all legacy mechanisms are automatically enabled through PSA. Users can manually enable PSA mechanisms that are available through accelerators but not through legacy, but this is not officially supported (users are not supposed to manually define PSA configuration symbols when `MBEDTLS_PSA_CRYPTO_CONFIG` is disabled).
233*62c56f98SSadaf Ebrahimi* When `MBEDTLS_PSA_CRYPTO_CONFIG` is enabled, there is no mandatory relationship between PSA support and legacy support for a mechanism. Users can configure legacy support and PSA support independently. Legacy support is automatically enabled if PSA support is requested, but only if there is no accelerator.
234*62c56f98SSadaf Ebrahimi
235*62c56f98SSadaf EbrahimiIt is strongly desirable to allow mechanisms available through PSA but not legacy: this allows saving code size when an accelerator is present.
236*62c56f98SSadaf Ebrahimi
237*62c56f98SSadaf EbrahimiThere is no strong reason to allow mechanisms available through legacy but not PSA when `MBEDTLS_PSA_CRYPTO_C` is enabled. This would only save at best a very small amount of code size in the PSA dispatch code. This may be more desirable when `MBEDTLS_PSA_CRYPTO_CLIENT` is enabled (having a mechanism available only locally and not in the crypto service), but we do not have an explicit request for this and it would be entirely reasonable to forbid it.
238*62c56f98SSadaf Ebrahimi
239*62c56f98SSadaf EbrahimiIn this analysis, we have not found a compelling reason to require all legacy mechanisms to also be available through PSA. However, this can simplify both the implementation and the use of dispatch code thanks to some simplifying properties:
240*62c56f98SSadaf Ebrahimi
241*62c56f98SSadaf Ebrahimi* Mixed-domain code can call PSA code if it knows that `psa_crypto_init()` has been called, without having to inspect the specifics of algorithm support.
242*62c56f98SSadaf Ebrahimi* Mixed-domain code can assume that PSA buffer calculations work correctly for all algorithms that it supports.
243*62c56f98SSadaf Ebrahimi
244*62c56f98SSadaf Ebrahimi#### Shape of the mixed-domain hash interface
245*62c56f98SSadaf Ebrahimi
246*62c56f98SSadaf EbrahimiWe now need to create an abstraction for mixed-domain hash calculation. (We could not create an abstraction, but that would require every piece of mixed-domain code to replicate the logic here. We went that route in Mbed TLS 3.3, but it made it effectively impossible to get something that works correctly.)
247*62c56f98SSadaf Ebrahimi
248*62c56f98SSadaf EbrahimiRequirements: given a hash algorithm,
249*62c56f98SSadaf Ebrahimi
250*62c56f98SSadaf Ebrahimi* Obtain some metadata about it (size, block size).
251*62c56f98SSadaf Ebrahimi* Calculate the hash.
252*62c56f98SSadaf Ebrahimi* Set up a multipart operation to calculate the hash. The operation must support update, finish, reset, abort, clone.
253*62c56f98SSadaf Ebrahimi
254*62c56f98SSadaf EbrahimiThe existing interface in `md.h` is close to what we want, but not perfect. What's wrong with it?
255*62c56f98SSadaf Ebrahimi
256*62c56f98SSadaf Ebrahimi* It has an extra step of converting from `mbedtls_md_type_t` to `const mbedtls_md_info_t *`.
257*62c56f98SSadaf Ebrahimi* It includes extra fluff such as names and HMAC. This costs code size.
258*62c56f98SSadaf Ebrahimi* The md module has some legacy baggage dating from when it was more open, which we don't care about anymore. This may cost code size.
259*62c56f98SSadaf Ebrahimi
260*62c56f98SSadaf EbrahimiThese problems are easily solvable.
261*62c56f98SSadaf Ebrahimi
262*62c56f98SSadaf Ebrahimi* `mbedtls_md_info_t` can become a very thin type. We can't remove the extra function call from the source code of callers, but we can make it a very thin abstraction that compilers can often optimize.
263*62c56f98SSadaf Ebrahimi* We can make names and HMAC optional. The mixed-domain hash interface won't be the full `MBEDTLS_MD_C` but a subset.
264*62c56f98SSadaf Ebrahimi* We can optimize `md.c` without making API changes to `md.h`.
265*62c56f98SSadaf Ebrahimi
266*62c56f98SSadaf Ebrahimi## Specification
267*62c56f98SSadaf Ebrahimi
268*62c56f98SSadaf Ebrahimi### MD light
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimihttps://github.com/Mbed-TLS/mbedtls/pull/6474 implements part of this specification, but it's based on Mbed TLS 3.2, so it needs to be rewritten for 3.3.
271*62c56f98SSadaf Ebrahimi
272*62c56f98SSadaf Ebrahimi#### Definition of MD light
273*62c56f98SSadaf Ebrahimi
274*62c56f98SSadaf EbrahimiMD light is a subset of `md.h` that implements the hash calculation interface described in ”[Designing an interface for hashes](#designing-an-interface-for-hashes)”. It is activated by `MBEDTLS_MD_LIGHT` in `mbedtls_config.h`.
275*62c56f98SSadaf Ebrahimi
276*62c56f98SSadaf EbrahimiThe following things enable MD light automatically in `build_info.h`:
277*62c56f98SSadaf Ebrahimi
278*62c56f98SSadaf Ebrahimi* A [mixed-domain](#classification-of-callers) module that needs to calculate hashes is enabled.
279*62c56f98SSadaf Ebrahimi* `MBEDTLS_MD_C` is enabled.
280*62c56f98SSadaf Ebrahimi
281*62c56f98SSadaf EbrahimiMD light includes the following types:
282*62c56f98SSadaf Ebrahimi
283*62c56f98SSadaf Ebrahimi* `mbedtls_md_type_t`
284*62c56f98SSadaf Ebrahimi* `mbedtls_md_info_t`
285*62c56f98SSadaf Ebrahimi* `mbedtls_md_context_t`
286*62c56f98SSadaf Ebrahimi
287*62c56f98SSadaf EbrahimiMD light includes the following functions:
288*62c56f98SSadaf Ebrahimi
289*62c56f98SSadaf Ebrahimi* `mbedtls_md_info_from_type`
290*62c56f98SSadaf Ebrahimi* `mbedtls_md_init`
291*62c56f98SSadaf Ebrahimi* `mbedtls_md_free`
292*62c56f98SSadaf Ebrahimi* `mbedtls_md_setup` — but `hmac` must be 0 if `MBEDTLS_MD_C` is disabled.
293*62c56f98SSadaf Ebrahimi* `mbedtls_md_clone`
294*62c56f98SSadaf Ebrahimi* `mbedtls_md_get_size`
295*62c56f98SSadaf Ebrahimi* `mbedtls_md_get_type`
296*62c56f98SSadaf Ebrahimi* `mbedtls_md_starts`
297*62c56f98SSadaf Ebrahimi* `mbedtls_md_update`
298*62c56f98SSadaf Ebrahimi* `mbedtls_md_finish`
299*62c56f98SSadaf Ebrahimi* `mbedtls_md`
300*62c56f98SSadaf Ebrahimi
301*62c56f98SSadaf EbrahimiUnlike the full MD, MD light does not support null pointers as `mbedtls_md_context_t *`. At least some functions still need to support null pointers as `const mbedtls_md_info_t *` because this arises when you try to use an unsupported algorithm (`mbedtls_md_info_from_type` returns `NULL`).
302*62c56f98SSadaf Ebrahimi
303*62c56f98SSadaf Ebrahimi#### MD algorithm support macros
304*62c56f98SSadaf Ebrahimi
305*62c56f98SSadaf EbrahimiFor each hash algorithm, `md.h` defines a macro `MBEDTLS_MD_CAN_xxx` whenever the corresponding hash is available through MD light. These macros are only defined when `MBEDTLS_MD_LIGHT` is enabled. Per “[Availability of hashes](#availability-of-hashes)”, `MBEDTLS_MD_CAN_xxx` is enabled if:
306*62c56f98SSadaf Ebrahimi
307*62c56f98SSadaf Ebrahimi* the corresponding `MBEDTLS_xxx_C` is defined; or
308*62c56f98SSadaf Ebrahimi* one of `MBEDTLS_PSA_CRYPTO_C` or `MBEDTLS_PSA_CRYPTO_CLIENT` is enabled, and the corresponding `PSA_WANT_ALG_xxx` is enabled.
309*62c56f98SSadaf Ebrahimi
310*62c56f98SSadaf EbrahimiNote that some algorithms have different spellings in legacy and PSA. Since MD is a legacy interface, we'll use the legacy names. Thus, for example:
311*62c56f98SSadaf Ebrahimi
312*62c56f98SSadaf Ebrahimi```
313*62c56f98SSadaf Ebrahimi#if defined(MBEDTLS_MD_LIGHT)
314*62c56f98SSadaf Ebrahimi#if defined(MBEDTLS_SHA256_C) || \
315*62c56f98SSadaf Ebrahimi    (defined(MBEDTLS_PSA_CRYPTO_C) && PSA_WANT_ALG_SHA_256)
316*62c56f98SSadaf Ebrahimi#define MBEDTLS_MD_CAN_SHA256
317*62c56f98SSadaf Ebrahimi#endif
318*62c56f98SSadaf Ebrahimi#endif
319*62c56f98SSadaf Ebrahimi```
320*62c56f98SSadaf Ebrahimi
321*62c56f98SSadaf EbrahimiNote: in the future, we may want to replace `defined(MBEDTLS_PSA_CRYPTO_C)`
322*62c56f98SSadaf Ebrahimiwith `defined(MBEDTLS_PSA_CRYTO_C) || defined(MBEDTLS_PSA_CRYPTO_CLIENT)` but
323*62c56f98SSadaf Ebrahimifor now this is out of scope.
324*62c56f98SSadaf Ebrahimi
325*62c56f98SSadaf Ebrahimi#### MD light internal support macros
326*62c56f98SSadaf Ebrahimi
327*62c56f98SSadaf Ebrahimi* If at least one hash has a PSA driver, define `MBEDTLS_MD_SOME_PSA`.
328*62c56f98SSadaf Ebrahimi* If at least one hash has a legacy implementation, defined `MBEDTLS_MD_SOME_LEGACY`.
329*62c56f98SSadaf Ebrahimi
330*62c56f98SSadaf Ebrahimi#### Support for PSA in the MD context
331*62c56f98SSadaf Ebrahimi
332*62c56f98SSadaf EbrahimiAn MD context needs to contain either a legacy module's context (or a pointer to one, as is the case now), or a PSA context (or a pointer to one).
333*62c56f98SSadaf Ebrahimi
334*62c56f98SSadaf EbrahimiI am inclined to remove the pointer indirection, but this means that an MD context would always be as large as the largest supported hash context. So for the time being, this specification keeps a pointer. For uniformity, PSA will also have a pointer (we may simplify this later).
335*62c56f98SSadaf Ebrahimi
336*62c56f98SSadaf Ebrahimi```
337*62c56f98SSadaf Ebrahimienum {
338*62c56f98SSadaf Ebrahimi    MBEDTLS_MD_ENGINE_LEGACY,
339*62c56f98SSadaf Ebrahimi    MBEDTLS_MD_ENGINE_PSA,
340*62c56f98SSadaf Ebrahimi} mbedtls_md_engine_t; // private type
341*62c56f98SSadaf Ebrahimi
342*62c56f98SSadaf Ebrahimitypedef struct mbedtls_md_context_t {
343*62c56f98SSadaf Ebrahimi    mbedtls_md_type_t type;
344*62c56f98SSadaf Ebrahimi#if defined(MBEDTLS_MD_SOME_PSA)
345*62c56f98SSadaf Ebrahimi    mbedtls_md_engine_t engine;
346*62c56f98SSadaf Ebrahimi#endif
347*62c56f98SSadaf Ebrahimi    void *md_ctx; // mbedtls_xxx_context or psa_hash_operation
348*62c56f98SSadaf Ebrahimi#if defined(MBEDTLS_MD_C)
349*62c56f98SSadaf Ebrahimi    void *hmac_ctx;
350*62c56f98SSadaf Ebrahimi#endif
351*62c56f98SSadaf Ebrahimi} mbedtls_md_context_t;
352*62c56f98SSadaf Ebrahimi```
353*62c56f98SSadaf Ebrahimi
354*62c56f98SSadaf EbrahimiAll fields are private.
355*62c56f98SSadaf Ebrahimi
356*62c56f98SSadaf EbrahimiThe `engine` field is almost redundant with knowledge about `type`. However, when an algorithm is available both via a legacy module and a PSA accelerator, we will choose based on the runtime availability of the accelerator when the context is set up. This choice needs to be recorded in the context structure.
357*62c56f98SSadaf Ebrahimi
358*62c56f98SSadaf Ebrahimi#### Inclusion of MD info structures
359*62c56f98SSadaf Ebrahimi
360*62c56f98SSadaf EbrahimiMD light needs to support hashes that are only enabled through PSA. Therefore the `mbedtls_md_info_t` structures must be included based on `MBEDTLS_MD_CAN_xxx` instead of just the legacy module.
361*62c56f98SSadaf Ebrahimi
362*62c56f98SSadaf EbrahimiThe same criterion applies in `mbedtls_md_info_from_type`.
363*62c56f98SSadaf Ebrahimi
364*62c56f98SSadaf Ebrahimi#### Conversion to PSA encoding
365*62c56f98SSadaf Ebrahimi
366*62c56f98SSadaf EbrahimiThe implementation needs to convert from a legacy type encoding to a PSA encoding.
367*62c56f98SSadaf Ebrahimi
368*62c56f98SSadaf Ebrahimi```
369*62c56f98SSadaf Ebrahimistatic inline psa_algorithm_t psa_alg_of_md_info(
370*62c56f98SSadaf Ebrahimi    const mbedtls_md_info_t *md_info );
371*62c56f98SSadaf Ebrahimi```
372*62c56f98SSadaf Ebrahimi
373*62c56f98SSadaf Ebrahimi#### Determination of PSA support at runtime
374*62c56f98SSadaf Ebrahimi
375*62c56f98SSadaf Ebrahimi```
376*62c56f98SSadaf Ebrahimiint psa_can_do_hash(psa_algorithm_t hash_alg);
377*62c56f98SSadaf Ebrahimi```
378*62c56f98SSadaf Ebrahimi
379*62c56f98SSadaf EbrahimiThe job of this private function is to return 1 if `hash_alg` can be performed through PSA now, and 0 otherwise. It is only defined on algorithms that are enabled via PSA.
380*62c56f98SSadaf Ebrahimi
381*62c56f98SSadaf EbrahimiAs a starting point, return 1 if PSA crypto has been initialized. This will be refined later (to return 1 if the [accelerator subsystem](https://github.com/Mbed-TLS/mbedtls/issues/6007) has been initialized).
382*62c56f98SSadaf Ebrahimi
383*62c56f98SSadaf EbrahimiUsage note: for algorithms that are not enabled via PSA, calling `psa_can_do_hash` is generally safe: whether it returns 0 or 1, you can call a PSA hash function on the algorithm and it will return `PSA_ERROR_NOT_SUPPORTED`.
384*62c56f98SSadaf Ebrahimi
385*62c56f98SSadaf Ebrahimi#### Support for PSA dispatch in hash operations
386*62c56f98SSadaf Ebrahimi
387*62c56f98SSadaf EbrahimiEach function that performs some hash operation or context management needs to know whether to dispatch via PSA or legacy.
388*62c56f98SSadaf Ebrahimi
389*62c56f98SSadaf EbrahimiIf given an established context, use its `engine` field.
390*62c56f98SSadaf Ebrahimi
391*62c56f98SSadaf EbrahimiIf given an algorithm as an `mbedtls_md_type_t type` (possibly being the `type` field of a `const mbedtls_md_info_t *`):
392*62c56f98SSadaf Ebrahimi
393*62c56f98SSadaf Ebrahimi* If there is a PSA accelerator for this hash and `psa_can_do_hash(alg)`, call the corresponding PSA function, and if applicable set the engine to `MBEDTLS_MD_ENGINE_PSA`. (Skip this is `MBEDTLS_MD_SOME_PSA` is not defined.)
394*62c56f98SSadaf Ebrahimi* Otherwise dispatch to the legacy module based on the type as currently done. (Skip this is `MBEDTLS_MD_SOME_LEGACY` is not defined.)
395*62c56f98SSadaf Ebrahimi* If no dispatch is possible, return `MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE`.
396*62c56f98SSadaf Ebrahimi
397*62c56f98SSadaf EbrahimiNote that this assumes that an operation that has been started via PSA can be completed. This implies that `mbedtls_psa_crypto_free` must not be called while an operation using PSA is in progress. Document this.
398*62c56f98SSadaf Ebrahimi
399*62c56f98SSadaf Ebrahimi#### Error code conversion
400*62c56f98SSadaf Ebrahimi
401*62c56f98SSadaf EbrahimiAfter calling a PSA function, call `mbedtls_md_error_from_psa` to convert its status code. This function is currently defined in `hash_info.c`.
402*62c56f98SSadaf Ebrahimi
403*62c56f98SSadaf Ebrahimi### Migration to MD light
404*62c56f98SSadaf Ebrahimi
405*62c56f98SSadaf Ebrahimi#### Migration of modules that used to call MD and now do the legacy-or-PSA dance
406*62c56f98SSadaf Ebrahimi
407*62c56f98SSadaf EbrahimiGet rid of the case where `MBEDTLS_MD_C` is undefined. Enable `MBEDTLS_MD_LIGHT` in `build_info.h`.
408*62c56f98SSadaf Ebrahimi
409*62c56f98SSadaf Ebrahimi#### Migration of modules that used to call a low-level hash module and now do the legacy-or-PSA dance
410*62c56f98SSadaf Ebrahimi
411*62c56f98SSadaf EbrahimiSwitch to calling MD (light) unconditionally. Enable `MBEDTLS_MD_LIGHT` in `build_info.h`.
412*62c56f98SSadaf Ebrahimi
413*62c56f98SSadaf Ebrahimi#### Migration of modules that call a low-level hash module
414*62c56f98SSadaf Ebrahimi
415*62c56f98SSadaf EbrahimiSwitch to calling MD (light). Enable `MBEDTLS_MD_LIGHT` in `build_info.h`.
416*62c56f98SSadaf Ebrahimi
417*62c56f98SSadaf Ebrahimi#### Migration of use-PSA mixed code
418*62c56f98SSadaf Ebrahimi
419*62c56f98SSadaf EbrahimiInstead of calling `hash_info.h` functions to obtain metadata, get it from `md.h`.
420*62c56f98SSadaf Ebrahimi
421*62c56f98SSadaf EbrahimiOptionally, code that currently tests on `MBEDTLS_USE_PSA_CRYPTO` just to determine whether to call MD or PSA to calculate hashes can switch to just having the MD variant.
422*62c56f98SSadaf Ebrahimi
423*62c56f98SSadaf Ebrahimi#### Remove `legacy_or_psa.h`
424*62c56f98SSadaf Ebrahimi
425*62c56f98SSadaf EbrahimiIt's no longer used.
426*62c56f98SSadaf Ebrahimi
427*62c56f98SSadaf Ebrahimi### Support all legacy algorithms in PSA
428*62c56f98SSadaf Ebrahimi
429*62c56f98SSadaf EbrahimiAs discussed in [“Implications between legacy availability and PSA availability”](#implications-between-legacy-availability-and-psa-availability), we require the following property:
430*62c56f98SSadaf Ebrahimi
431*62c56f98SSadaf Ebrahimi> If an algorithm has a legacy implementation, it is also available through PSA.
432*62c56f98SSadaf Ebrahimi
433*62c56f98SSadaf EbrahimiWhen `MBEDTLS_PSA_CRYPTO_CONFIG` is disabled, this is already the case. When is enabled, we will now make it so as well. Change `include/mbedtls/config_psa.h` accordingly.
434*62c56f98SSadaf Ebrahimi
435*62c56f98SSadaf Ebrahimi### MD light optimizations
436*62c56f98SSadaf Ebrahimi
437*62c56f98SSadaf EbrahimiThis section is not necessary to implement MD light, but will cut down its code size.
438*62c56f98SSadaf Ebrahimi
439*62c56f98SSadaf Ebrahimi#### Split names out of MD light
440*62c56f98SSadaf Ebrahimi
441*62c56f98SSadaf EbrahimiRemove hash names from `mbedtls_md_info_t`. Use a simple switch-case or a separate list to implement `mbedtls_md_info_from_string` and `mbedtls_md_get_name`.
442*62c56f98SSadaf Ebrahimi
443*62c56f98SSadaf Ebrahimi#### Remove metadata from the info structure
444*62c56f98SSadaf Ebrahimi
445*62c56f98SSadaf EbrahimiIn `mbedtls_md_get_size` and in modules that want a hash's block size, instead of looking up hash metadata in the info structure, call the PSA macros.
446*62c56f98SSadaf Ebrahimi
447*62c56f98SSadaf Ebrahimi#### Optimize type conversions
448*62c56f98SSadaf Ebrahimi
449*62c56f98SSadaf EbrahimiTo allow optimizing conversions between `mbedtls_md_type_t` and `psa_algorithm_t`, renumber the `mbedtls_md_type_t` enum so that the values are the 8 lower bits of the PSA encoding.
450*62c56f98SSadaf Ebrahimi
451*62c56f98SSadaf EbrahimiWith this optimization,
452*62c56f98SSadaf Ebrahimi```
453*62c56f98SSadaf Ebrahimistatic inline psa_algorithm_t psa_alg_of_md_info(
454*62c56f98SSadaf Ebrahimi    const mbedtls_md_info_t *md_info )
455*62c56f98SSadaf Ebrahimi{
456*62c56f98SSadaf Ebrahimi    if( md_info == NULL )
457*62c56f98SSadaf Ebrahimi        return( PSA_ALG_NONE );
458*62c56f98SSadaf Ebrahimi    return( PSA_ALG_CATEGORY_HASH | md_info->type );
459*62c56f98SSadaf Ebrahimi}
460*62c56f98SSadaf Ebrahimi```
461*62c56f98SSadaf Ebrahimi
462*62c56f98SSadaf EbrahimiWork in progress on this conversion is at https://github.com/gilles-peskine-arm/mbedtls/tree/hash-unify-ids-wip-1
463*62c56f98SSadaf Ebrahimi
464*62c56f98SSadaf Ebrahimi#### Get rid of the hash_info module
465*62c56f98SSadaf Ebrahimi
466*62c56f98SSadaf EbrahimiThe hash_info module is redundant with MD light. Move `mbedtls_md_error_from_psa` to `md.c`, defined only when `MBEDTLS_MD_SOME_PSA` is defined. The rest is no longer used.
467*62c56f98SSadaf Ebrahimi
468*62c56f98SSadaf Ebrahimi#### Unify HMAC with PSA
469*62c56f98SSadaf Ebrahimi
470*62c56f98SSadaf EbrahimiPSA has its own HMAC implementation. In builds with both `MBEDTLS_MD_C` and `PSA_WANT_ALG_HMAC` not fully provided by drivers, we should have a single implementation. Replace the one in `md.h` by calls to the PSA driver interface. This will also give mixed-domain modules access to HMAC accelerated directly by a PSA driver (eliminating the need to a HMAC interface in software if all supported hashes have an accelerator that includes HMAC support).
471*62c56f98SSadaf Ebrahimi
472*62c56f98SSadaf Ebrahimi### Improving support for `MBEDTLS_PSA_CRYPTO_CLIENT`
473*62c56f98SSadaf Ebrahimi
474*62c56f98SSadaf EbrahimiSo far, MD light only dispatches to PSA if an algorithm is available via `MBEDTLS_PSA_CRYPTO_C`, not if it's available via `MBEDTLS_PSA_CRYPTO_CLIENT`. This is acceptable because `MBEDTLS_USE_PSA_CRYPTO` requires `MBEDTLS_PSA_CRYPTO_C`, hence mixed-domain code never invokes PSA.
475*62c56f98SSadaf Ebrahimi
476*62c56f98SSadaf EbrahimiThe architecture can be extended to support `MBEDTLS_PSA_CRYPTO_CLIENT` with a little extra work. Here is an overview of the task breakdown, which should be fleshed up after we've done the first [migration](#migration-to-md-light):
477*62c56f98SSadaf Ebrahimi
478*62c56f98SSadaf Ebrahimi* Compile-time dependencies: instead of checking `defined(MBEDTLS_PSA_CRYPTO_C)`, check `defined(MBEDTLS_PSA_CRYPTO_C) || defined(MBEDTLS_PSA_CRYPTO_CLIENT)`.
479*62c56f98SSadaf Ebrahimi* Implementers of `MBEDTLS_PSA_CRYPTO_CLIENT` will need to provide `psa_can_do_hash()` (or a more general function `psa_can_do`) alongside `psa_crypto_init()`. Note that at this point, it will become a public interface, hence we won't be able to change it at a whim.
480