PK: try storing all private RSA keys in PSA #298

Closed
opened 2025-05-20 03:49:03 -05:00 by mpg · 3 comments
mpg commented 2025-05-20 03:49:03 -05:00 (Migrated from github.com)

As part of the investigation on RSA keys in PK, this issue is to gauge how hard it would be to make all private RSA keys stored in PSA right now. This is a move we know we want to make in 1.x, and delaying it makes the investigation harder (because we need to make sure we don't do anything that would prevent or complicate that move later). So, we want to have an idea how much work it would be to do it now, and if it's not too much, do it.

The general idea is to have something very similar to what we did for EC keys when MBEDTLS_USE_PSA_EC_DATA is enabled, with the following differences:

  1. Here we don't want to have a compile-time option (we're trying to remove it for EC keys anyway), just do the move unconditionally.
  2. As a first step we don't really care about how public keys are stored - depending on what seems more convenient we can either (a) keep them in an rsa_context or (b) move them to a more PSA-friendly format similarly to what was done for EC keys, or even (c) store them as a proper PSA key. The guiding principle here is to just do what's the most convenient in the moment (whether it's minimising changes, or making more changes to make things more consistent and simpler).

The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension. This maximises compatibility with the existing, hence likelihood that we can pass existing tests without too much hassle. We're likely to change that in a follow-up, but that's out of scope for this initial step.

Work should probably be based on https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/297 (removal of pk_decrypt()/pk_encrypt()).

As part of the investigation on RSA keys in PK, this issue is to gauge how hard it would be to make all private RSA keys stored in PSA right now. This is a move we know we want to make in 1.x, and delaying it makes the investigation harder (because we need to make sure we don't do anything that would prevent or complicate that move later). So, we want to have an idea how much work it would be to do it now, and if it's not too much, do it. The general idea is to have something very similar to what we did for EC keys when `MBEDTLS_USE_PSA_EC_DATA` is enabled, with the following differences: 1. Here we don't want to have a compile-time option (we're trying to remove it for EC keys anyway), just do the move unconditionally. 2. As a first step we don't really care about how public keys are stored - depending on what seems more convenient we can either (a) keep them in an `rsa_context` or (b) move them to a more PSA-friendly format similarly to what was done for EC keys, or even (c) store them as a proper PSA key. The guiding principle here is to just do what's the most convenient in the moment (whether it's minimising changes, or making more changes to make things more consistent and simpler). The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension. This maximises compatibility with the existing, hence likelihood that we can pass existing tests without too much hassle. We're likely to change that in a follow-up, but that's out of scope for this initial step. Work should probably be based on https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/297 (removal of `pk_decrypt()`/`pk_encrypt()`).
valeriosetti commented 2025-05-26 09:16:34 -05:00 (Migrated from github.com)

The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension

Quick note. The key enrollment algorithm is a vendor extension added by Mbed TLS which might not be present when another PSA server is used (ex: TF-M or any case where CRYPTO_CLIENT && !CRYPTO_C). Since PKCS1 v1.5 signature is weaker than PSS, I suggest setting the latter as default/main algorithm and the former as alternative/enrollment algorithm. In this way we can at least always support the most secure alternative. Wdyt?

> The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension Quick note. The key enrollment algorithm is a vendor extension added by Mbed TLS which might not be present when another PSA server is used (ex: TF-M or any case where `CRYPTO_CLIENT && !CRYPTO_C`). Since PKCS1 v1.5 signature is weaker than PSS, I suggest setting the latter as default/main algorithm and the former as alternative/enrollment algorithm. In this way we can at least always support the most secure alternative. Wdyt?
gilles-peskine-arm commented 2025-05-26 10:53:11 -05:00 (Migrated from github.com)

In Mbed TLS 3, the default for mbedtls_pk_parse_key and friends with an RSA key is to set it up for PKCS#1v1.5 encryption and PKCS#1v1.5 signature. We're making a new version so we can obviously change that, but changing the behavior is more disruptive than not changing it.

For encryption, security would be a major motivation to change, since PKCS#1v1.5 is dangerous even when it's implemented correctly. But we're removing the PK interface for encryption. There's still a default encryption algorithm for mbedtls_pk_import_into_psa when the usage is ENCRYPT or DECRYPT though.

For signature, security is not particularly relevant. There have been historical vulnerabilities in PKCS#1v1.5 verification implementations that PSS is intrinsically resistant to, but only really awful implementation still have those vulnerability. PSS has a better security proof, but that doesn't translate to practical attacks.

There is a technical obstacle to selecting OAEP or PSS instead of PKCS#1v1.5, however. OAEP and PSS both use a hash algorithm internally. In contrast, PKCS#1v1.5 encryption doesn't use a hash at all, and PKCS#1v1.5 signature needs to know what hash algorithm produced its input but doesn't run the hash itself. So if we just have a key and nobody to tell us to choose a particular hash algorithm, we can easily avoid choosing a hash with PKCS#1v1.5, but not with OAEP or PSS.

For mbedtls_pk_import_into_psa, annoyingly, all we need to do is to choose a policy, and that is possible with PSS because it supports PSA_ALG_ANY_HASH, but not possible with OAEP which needs to always have a specific hash in the policy.

In Mbed TLS 3, the default for `mbedtls_pk_parse_key` and friends with an RSA key is to set it up for PKCS#1v1.5 encryption and PKCS#1v1.5 signature. We're making a new version so we can obviously change that, but changing the behavior is more disruptive than not changing it. For encryption, security would be a major motivation to change, since PKCS#1v1.5 is dangerous even when it's implemented correctly. But we're removing the PK interface for encryption. There's still a default encryption algorithm for `mbedtls_pk_import_into_psa` when the usage is `ENCRYPT` or `DECRYPT` though. For signature, security is not particularly relevant. There have been historical vulnerabilities in PKCS#1v1.5 verification implementations that PSS is intrinsically resistant to, but only really awful implementation still have those vulnerability. PSS has a better security proof, but that doesn't translate to practical attacks. There is a technical obstacle to selecting OAEP or PSS instead of PKCS#1v1.5, however. OAEP and PSS both use a hash algorithm internally. In contrast, PKCS#1v1.5 encryption doesn't use a hash at all, and PKCS#1v1.5 signature needs to know what hash algorithm produced its input but doesn't run the hash itself. So if we just have a key and nobody to tell us to choose a particular hash algorithm, we can easily avoid choosing a hash with PKCS#1v1.5, but not with OAEP or PSS. For `mbedtls_pk_import_into_psa`, annoyingly, all we need to do is to choose a policy, and that is possible with PSS because it supports `PSA_ALG_ANY_HASH`, but not possible with OAEP which needs to always have a specific hash in the policy.
mpg commented 2025-05-27 02:12:31 -05:00 (Migrated from github.com)

The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension

Quick note. The key enrollment algorithm is a vendor extension added by Mbed TLS which might not be present when another PSA server is used (ex: TF-M or any case where CRYPTO_CLIENT && !CRYPTO_C). Since PKCS1 v1.5 signature is weaker than PSS, I suggest setting the latter as default/main algorithm and the former as alternative/enrollment algorithm. In this way we can at least always support the most secure alternative. Wdyt?

I agree that we may not want to rely on the key enrolment extension in the final version, but I like to proceed step by step:

  1. Change the internals while (mostly) preserving observable behaviour.
  2. Possibly change observable behaviour (while mostly not changing internals).

The present issue is step 1. There is an on-going design discussion about what to do at step 2, but it partially depends on how step 1 will go (and also on some testing that Gilles has been working on).

> > The ultimate goal of the investigation is to decide how we'll handle permissions on RSA keys, but for the present step, parsed RSA keys should allow both v1.5 and PSS signatures, by taking advantage of the "key enrolment algorithm" extension > > Quick note. The key enrollment algorithm is a vendor extension added by Mbed TLS which might not be present when another PSA server is used (ex: TF-M or any case where `CRYPTO_CLIENT && !CRYPTO_C`). Since PKCS1 v1.5 signature is weaker than PSS, I suggest setting the latter as default/main algorithm and the former as alternative/enrollment algorithm. In this way we can at least always support the most secure alternative. Wdyt? I agree that we may not want to rely on the key enrolment extension in the final version, but I like to proceed step by step: 1. Change the internals while (mostly) preserving observable behaviour. 2. Possibly change observable behaviour (while mostly not changing internals). The present issue is step 1. There is an on-going design discussion about what to do at step 2, but it partially depends on how step 1 will go (and also on some testing that Gilles has been working on).
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-Mbed-TLS/TF-PSA-Crypto#298
No description provided.