Complete discussion of RSASSA-PSS
Update to latest draft of PSA Crypto 1.1.0: back to strict verification
by default, but ANY_SALT introduced.
Commands used to observe default values of saltlen:
openssl genpkey -algorithm rsa-pss -out o.key
openssl req -x509 -new -key o.key -subj "/CN=CA" -sha256 -out o.crt
certtool --generate-privkey --key-type rsa-pss --outfile g.key
certtool --generate-self-signed --load-privkey g.key --outfile g.crt
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
diff --git a/docs/architecture/psa-migration/psa-limitations.md b/docs/architecture/psa-migration/psa-limitations.md
index d5d7d07..85ad28e 100644
--- a/docs/architecture/psa-migration/psa-limitations.md
+++ b/docs/architecture/psa-migration/psa-limitations.md
@@ -63,14 +63,16 @@
As standardized, the signature scheme takes several parameters, in addition to
the hash algorithm potentially used to hash the message being signed:
-- a hash algorithm use for the encoding function
+- a hash algorithm used for the encoding function
- a mask generation function
- most commonly MGF1, which in turn is parametrized by a hash algorithm
- a salt length
+- a trailer field - this is universally 0xBC as far as I've seen
Both the existing `mbedtls_` API and the PSA API support only MGF1 as the
-generation function, but there are discrepancy in handling the salt length and
-which of the various hash algorithms can differ from each other.
+generation function (and only 0xBC as the trailer field), but there are
+discrepancies in handling the salt length and which of the various hash
+algorithms can differ from each other.
### API comparison
@@ -100,11 +102,11 @@
- PSA:
- algorithm specification:
- hash alg used for message hashing, encoding and MGF1
- - salt length cannot be specified
+ - salt length can be either "standard" (== hashlen) or "any"
- signature generation:
- salt length: always using the maximum legal value
- verification:
- - salt length: any valid length accepted
+ - salt length: either == hashlen, or any depending on algorithm
The RSA/PK API is in principle more flexible than the PSA Crypto API. The
following sub-sections study whether and how this matters in practice.
@@ -122,7 +124,7 @@
In Mbed TLS, RSA-PSS parameters can be parsed and displayed for various
objects (certificates, CRLs, CSRs). During parsing, the following properties
are enforced:
-- (the extra "trailer field" parameter must have its default value)
+- the extra "trailer field" parameter must have its default value
- the mask generation function is MGF1
- encoding hash = message hashing algorithm (may differ from MGF1 hash)
@@ -135,19 +137,12 @@
Note: since X.509 parsing ensures that message hash = encoding hash, and
`mbedtls_pk_verify_ext()` use encoding hash = mgf1 hash, it looks like all
three hash algorithms must be equal, which would be good news as it would
-match a limitation of the PSA API. (TODO: double-check that.)
+match a limitation of the PSA API.
-Also, since we only use signature verification, the fact that PSA accepts any
-valid salt length means that no valid certificate would be wrongly rejected;
-however it means that signatures that don't match the announced salt length
-would be incorrectly accepted. At first glance, it looks like this doesn't
-allow an attacker to forge certificates, so this might be acceptable in
-practice, while not fully implementing all the checks in the standard. (TODO:
-triple-check that.)
-
-It is unclear what parameters people use in practice.
-
-TODO: look at what OpenSSL and GnuTLS do by default?
+It is unclear what parameters people use in practice. It looks like by default
+OpenSSL picks saltlen = keylen - hashlen - 2 (tested with openssl 1.1.1f).
+The `certool` command provided by GnuTLS seems to be picking saltlen = hashlen
+by default (tested with GnuTLS 3.6.13).
### Use in TLS
@@ -166,16 +161,16 @@
When signing, the salt length picked by PSA is the one required by TLS 1.3
(unless the key is unreasonably small).
-When verifying signatures, again is doesn't look like accepting any salt
-length would give an attacker any advantage, but this must be triple-checked
-(TODO).
+When verifying signatures, PSA will by default enforce the salt len is the one
+required by TLS 1.3.
### Current testing - X509
-TODO: look at hex testing (do we have negative testing of bad trailer field?)
+All test files use the default trailer field of 0xBC, as enforced by our
+parser. (There's a negative test for that using the
+`x509_parse_rsassa_pss_params` test function and hex data.)
-All test files use the default trailer field of 0xBC. Files with "bad" in the
-name are expected to be invalid and rejected in tests.
+Files with "bad" in the name are expected to be invalid and rejected in tests.
**Test certificates:**
@@ -280,9 +275,22 @@
These CSRss are signed with a 2048-bit key. It appears that they are
all using saltlen = keylen - hashlen - 2.
-### Possible course of actions
+### Possible courses of action
-TODO - once the previous section has been completed
+There's no question about what to do with TLS (any version); the only question
+is about X.509 signature verification. Options include:
+
+1. Doing all verifications with `PSA_ALG_RSA_PSS_ANY_SALT` - while this
+ wouldn't cause a concrete security issue, this would be non-compliant.
+2. Doing verifications with `PSA_ALG_RSA_PSS` when we're lucky and the encoded
+ saltlen happens to match hashlen, and falling back to `ANY_SALT` otherwise.
+Same issue as with the previous point, except more contained.
+3. Reject all certificates with saltlen != hashlen. This includes all
+ certificates generate with OpenSSL using the default parameters, so it's
+probably not acceptable.
+4. Request an extension to the PSA Crypto API and use one of the above options
+ in the meantime. Such an extension seems inconvenient and not motivated by
+strong security arguments, so it's unclear whether it would be accepted.
Limitations relevant for G2 (isolation of long-term secrets)
============================================================