Summary: I am soliciting feedback about builds of Mbed TLS where *there is both a PSA implementation and the built-in software implementation of the same algorithm, by design, *and the PSA implementation isn't just calling the built-in implementation because the two have different characteristics, each desirable in some context. Please read this message if you are doing this or considering it. Feel free to ignore otherwise.
For example, both MBEDTLS_SHA256_C and MBEDTLS_PSA_ACCEL_ALG_SHA_256 are enabled, so that calls to mbedtls_md_xxx() use the software implementation and calls to psa_hash_xxx() use the hardware accelerator via the PSA driver. And this is deliberate: there is a reason why mbedtls_md_xxx() must not call the PSA driver.
In most cases, this is not desirable: if there's an accelerator, why not use it? And we're working to allow getting rid of the software implementation in more and more cases. Ultimately, PSA will be the only crypto interface in Mbed TLS, so all interfaces to calculate SHA-256 will go through psa_hash_xxx() and therefore will dispatch the call to the driver if there is one. This will be an API break, since it will require calling psa_crypto_init() before performing any cryptography. Currently we are planning to introduce this requirement in Mbed TLS 4.0.
But it is currently possible to have dual algorithm support, and I can think of unusual cases where it might desirable.
Scenario 1, with accelerator drivers: there is a driver, but it can only be used after some initialization. The application needs to use the algorithm before calling psa_crypto_init(), so it calls the legacy interface. After psa_crypto_init() has been called, the application would like to use the driver as much as possible. A typical use case is a bootloader which wants to verify a signature before initializing the random generator, so it calls mbedtls_md_xxx() and mbedtls_rsa_xxx().
Scenario 1 is clearly desirable, and for that we have a planned solution, which is staged initialization. The bootloader will be able to (1) initialize drivers, (2) perform a hash calculation, (3) initialize the keystore, (4) verify a signature, all without initializing the RNG. We won't make psa_crypto_init() mandatory until this feature is implemented.
Scenario 2: with a cryptography service. This is a build of Mbed TLS with MBEDTLS_PSA_CRYPTO_CLIENT, so all psa_xxx() calls call the service. But, for some reason, there is also a local implementation of some cryptography algorithms. So you can call mbedtls_md() to calculate a hash even before the connection to the service has been established. Or maybe you want to call mbedtls_md() for short messages and psa_hash_compute() for long messages, because the crypto service has a faster implementation but the communication overhead offsets the gain for short messages.
We are currently working on improving support for PSA drivers, and in particular, saving code size by eliminating more unnecessary code when a driver is present, and increasing the set of APIs that benefit from drivers. The obvious way to do that is to make all cryptography calls (especially from X.509 and TLS) go via the PSA interface, but we can't do that yet due to the need to have initialized the keystore and RNG. We are considering routing /certain/ crypto calls via PSA, in a way that would break scenario 2, and would also break scenario 1 in some cases, but not for hashes or signature verification.
If, for example, in Mbed TLS 3.4, mbedtls_md() starts calling psa_hash_(), would this break your code? Are you in scenario 1, scenario 2, or some other variant I haven't thought of?
If so, *please reply to this message and let us know what your needs are*. Feel free to reply to me in private if you don't want to discuss this publicly (I won't share directly outside Arm, but the eventual design might leak information about the unusual scenario).
If we don't hear objections, there is a chance that a future Mbed TLS 3.x will break scenarios 1 and 2. If we do hear objections, we'll work to keep the current behavior or arrange a migration path.
I forgot to mention explicitly: the driver fallback mechanism is not affected. If you have a working application that's calling psa_xxx(), it will keep working, whether that ends up calling a driver, calling the built-in code, or calling a driver and then falling back to the built-in code. Applications may be affected only if they were calling an mbedtls_xxx() API which, as of Mbed TLS 3.2, do not dispatch through PSA at all.