-
Notifications
You must be signed in to change notification settings - Fork 220
Honor restricted PSS min saltlen for AUTO verify #3470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -158,9 +158,9 @@ int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed, size_t seed_len, | |||||||||||||
|
|
||||||||||||||
| static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||||||||||||
|
|
||||||||||||||
| int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, | ||||||||||||||
| int rsa_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, | ||||||||||||||
| const EVP_MD *Hash, const EVP_MD *mgf1Hash, | ||||||||||||||
| const uint8_t *EM, int sLen) { | ||||||||||||||
| const uint8_t *EM, int sLen, int min_sLen) { | ||||||||||||||
| // We have to avoid the underlying SHA services updating the indicator | ||||||||||||||
| // state, so we lock the state here. | ||||||||||||||
| FIPS_service_indicator_lock_state(); | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: call to undeclared function 'FIPS_service_indicator_lock_state'; ISO C99 and later do not support implicit function declarations [clang-diagnostic-implicit-function-declaration] FIPS_service_indicator_lock_state();
^ |
||||||||||||||
|
|
@@ -175,14 +175,14 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, | |||||||||||||
|
|
||||||||||||||
| // Negative sLen has special meanings: | ||||||||||||||
| // RSA_PSS_SALTLEN_DIGEST sLen == hLen | ||||||||||||||
| // -2 salt length is autorecovered from signature | ||||||||||||||
| // -N reserved | ||||||||||||||
| // RSA_PSS_SALTLEN_AUTO salt length is autorecovered from signature | ||||||||||||||
| // -N reserved | ||||||||||||||
| size_t hLen = EVP_MD_size(Hash); | ||||||||||||||
| if (sLen == RSA_PSS_SALTLEN_DIGEST) { | ||||||||||||||
| sLen = (int)hLen; | ||||||||||||||
| } else if (sLen == -2) { | ||||||||||||||
| sLen = -2; | ||||||||||||||
| } else if (sLen < -2) { | ||||||||||||||
| } else if (sLen == RSA_PSS_SALTLEN_AUTO) { | ||||||||||||||
| sLen = RSA_PSS_SALTLEN_AUTO; | ||||||||||||||
| } else if (sLen < RSA_PSS_SALTLEN_AUTO) { | ||||||||||||||
| OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); | ||||||||||||||
| goto err; | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -197,7 +197,8 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, | |||||||||||||
| EM++; | ||||||||||||||
| emLen--; | ||||||||||||||
| } | ||||||||||||||
| // |sLen| may be -2 for the non-standard salt length recovery mode. | ||||||||||||||
| // |sLen| may be |RSA_PSS_SALTLEN_AUTO| for the non-standard salt length | ||||||||||||||
| // recovery mode. | ||||||||||||||
| if (emLen < hLen + 2 || | ||||||||||||||
| (sLen >= 0 && emLen < hLen + (size_t)sLen + 2)) { | ||||||||||||||
| OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); | ||||||||||||||
|
|
@@ -237,8 +238,14 @@ OPENSSL_END_ALLOW_DEPRECATED | |||||||||||||
| goto err; | ||||||||||||||
| } | ||||||||||||||
| salt_start++; | ||||||||||||||
| size_t recovered_sLen = maskedDBLen - salt_start; | ||||||||||||||
| // If a salt length was specified, check it matches. | ||||||||||||||
| if (sLen >= 0 && maskedDBLen - salt_start != (size_t)sLen) { | ||||||||||||||
| if (sLen >= 0 && recovered_sLen != (size_t)sLen) { | ||||||||||||||
| OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); | ||||||||||||||
| goto err; | ||||||||||||||
| } | ||||||||||||||
| // A restricted |EVP_PKEY_RSA_PSS| key also sets a minimum salt length. | ||||||||||||||
| if (min_sLen >= 0 && recovered_sLen < (size_t)min_sLen) { | ||||||||||||||
|
Comment on lines
+247
to
+248
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The floor here is correct, but it makes an invariant load-bearing that is currently spelled out three separate times.
All three are the same predicate -- Could we collapse them into one helper? Something like this in // rsa_pss_max_saltlen returns the maximum PSS salt length usable with |rsa| and
// a |hLen|-byte digest, or a negative value if |rsa| is too small. This is the
// value |RSA_PSS_SALTLEN_AUTO| resolves to when signing.
int rsa_pss_max_saltlen(const RSA *rsa, size_t hLen);
If you would rather keep this PR tight, the alternative is a round-trip case in the new test: |
||||||||||||||
| OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); | ||||||||||||||
| goto err; | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -264,6 +271,13 @@ OPENSSL_END_ALLOW_DEPRECATED | |||||||||||||
| return ret; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, | ||||||||||||||
| const EVP_MD *Hash, const EVP_MD *mgf1Hash, | ||||||||||||||
| const uint8_t *EM, int sLen) { | ||||||||||||||
| return rsa_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, mgf1Hash, EM, sLen, | ||||||||||||||
| RSA_PSS_NO_SALTLEN_MINIMUM); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM, | ||||||||||||||
| const unsigned char *mHash, | ||||||||||||||
| const EVP_MD *Hash, const EVP_MD *mgf1Hash, | ||||||||||||||
|
|
@@ -302,12 +316,12 @@ int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM, | |||||||||||||
|
|
||||||||||||||
| // Negative sLenRequested has special meanings: | ||||||||||||||
| // RSA_PSS_SALTLEN_DIGEST sLen == hLen | ||||||||||||||
| // -2 salt length is maximized | ||||||||||||||
| // -N reserved | ||||||||||||||
| // RSA_PSS_SALTLEN_AUTO salt length is maximized | ||||||||||||||
| // -N reserved | ||||||||||||||
| size_t sLen; | ||||||||||||||
| if (sLenRequested == RSA_PSS_SALTLEN_DIGEST) { | ||||||||||||||
| sLen = hLen; | ||||||||||||||
| } else if (sLenRequested == -2) { | ||||||||||||||
| } else if (sLenRequested == RSA_PSS_SALTLEN_AUTO) { | ||||||||||||||
| sLen = emLen - hLen - 2; | ||||||||||||||
| } else if (sLenRequested < 0) { | ||||||||||||||
| OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED); | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this passes
rctx->min_saltlen, whose "no restriction" sentinel isNO_PSS_SALT_LEN_RESTRICTION(-1, top of this file), into a parameter documented against a different macro,RSA_PSS_NO_SALTLEN_MINIMUM(-1,fipsmodule/rsa/internal.h).It is correct today, and robust rather than accidental, since the callee's doc says "like any negative value, imposes no minimum". But two names for one sentinel across the evp/rsa boundary invites drift. Could we either use the
rsa/internal.hmacro here, or note the correspondence at this call site?