From c0667361a5cd06139e5eb1abd2acd84aa0d5b1b7 Mon Sep 17 00:00:00 2001 From: Clemens Lang Date: Fri, 25 Nov 2022 15:32:03 +0100 Subject: [PATCH] Fix explicit indicator for PSS salt length The previous state of the patch did not work correctly when used with negative salt lengths, which OpenSSL uses a magic values. Setting the saltlength to max would yield an approved state in the indicator, while it is not approved. Additionally, update the patch to change the default PSS salt length with the current state of discussion upstream (see https://github.com/openssl/openssl/pull/19724). Resolves: rhbz#2142087 Signed-off-by: Clemens Lang --- ...re-Add-indicator-for-PSS-salt-length.patch | 8 +- 0089-PSS-salt-length-from-provider.patch | 114 ++++++ ...gnature-Clamp-PSS-salt-len-to-MD-len.patch | 153 -------- ...gnature-Clamp-PSS-salt-len-to-MD-len.patch | 338 ++++++++++++++++++ ...e.patch => 0091-FIPS-RSA-encapsulate.patch | 0 ....patch => 0092-provider-improvements.patch | 0 openssl.spec | 13 +- 7 files changed, 466 insertions(+), 160 deletions(-) create mode 100644 0089-PSS-salt-length-from-provider.patch delete mode 100644 0089-signature-Clamp-PSS-salt-len-to-MD-len.patch create mode 100644 0090-signature-Clamp-PSS-salt-len-to-MD-len.patch rename 0090-FIPS-RSA-encapsulate.patch => 0091-FIPS-RSA-encapsulate.patch (100%) rename 0091-provider-improvements.patch => 0092-provider-improvements.patch (100%) diff --git a/0088-signature-Add-indicator-for-PSS-salt-length.patch b/0088-signature-Add-indicator-for-PSS-salt-length.patch index 9f5a99e..97a0679 100644 --- a/0088-signature-Add-indicator-for-PSS-salt-length.patch +++ b/0088-signature-Add-indicator-for-PSS-salt-length.patch @@ -1,7 +1,7 @@ -From 02612d36c664e03821ed80a205fdca80232afd64 Mon Sep 17 00:00:00 2001 +From a325a23bc83f4efd60130001c417ca5b96bdbff1 Mon Sep 17 00:00:00 2001 From: Clemens Lang Date: Thu, 17 Nov 2022 19:33:02 +0100 -Subject: [PATCH 1/2] signature: Add indicator for PSS salt length +Subject: [PATCH 1/3] signature: Add indicator for PSS salt length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -70,7 +70,7 @@ index a5e78efd6e..f239200465 100644 EVP_PKEY *pkey); __owur int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c -index 49e7f9158a..f905fd6a04 100644 +index 49e7f9158a..0c45008a00 100644 --- a/providers/implementations/signature/rsa_sig.c +++ b/providers/implementations/signature/rsa_sig.c @@ -1127,6 +1127,21 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) @@ -84,7 +84,7 @@ index 49e7f9158a..f905fd6a04 100644 + if (prsactx->pad_mode == RSA_PKCS1_PSS_PADDING) { + if (prsactx->md == NULL) { + fips_indicator = EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_UNDETERMINED; -+ } else if (prsactx->saltlen > EVP_MD_get_size(prsactx->md)) { ++ } else if (rsa_pss_compute_saltlen(prsactx) > EVP_MD_get_size(prsactx->md)) { + fips_indicator = EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_NOT_APPROVED; + } + } diff --git a/0089-PSS-salt-length-from-provider.patch b/0089-PSS-salt-length-from-provider.patch new file mode 100644 index 0000000..8e61747 --- /dev/null +++ b/0089-PSS-salt-length-from-provider.patch @@ -0,0 +1,114 @@ +From 0879fac692cb1bff0ec4c196cb364d970ad3ecec Mon Sep 17 00:00:00 2001 +From: Clemens Lang +Date: Mon, 21 Nov 2022 14:33:57 +0100 +Subject: [PATCH 2/3] Obtain PSS salt length from provider + +Rather than computing the PSS salt length again in core using +ossl_rsa_ctx_to_pss_string, which calls rsa_ctx_to_pss and computes the +salt length, obtain it from the provider using the +OSSL_SIGNATURE_PARAM_ALGORITHM_ID param to handle the case where the +interpretation of the magic constants in the provider differs from that +of OpenSSL core. + +Signed-off-by: Clemens Lang +--- + crypto/cms/cms_rsa.c | 19 +++++++++++++++---- + crypto/rsa/rsa_ameth.c | 34 +++++++++++++++++++++------------- + 2 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c +index 20ed816918..997567fdbf 100644 +--- a/crypto/cms/cms_rsa.c ++++ b/crypto/cms/cms_rsa.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include "crypto/asn1.h" + #include "crypto/rsa.h" + #include "cms_local.h" +@@ -191,7 +192,10 @@ static int rsa_cms_sign(CMS_SignerInfo *si) + int pad_mode = RSA_PKCS1_PADDING; + X509_ALGOR *alg; + EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si); +- ASN1_STRING *os = NULL; ++ unsigned char aid[128]; ++ const unsigned char *pp = aid; ++ size_t aid_len = 0; ++ OSSL_PARAM params[2]; + + CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg); + if (pkctx != NULL) { +@@ -205,10 +209,17 @@ static int rsa_cms_sign(CMS_SignerInfo *si) + /* We don't support it */ + if (pad_mode != RSA_PKCS1_PSS_PADDING) + return 0; +- os = ossl_rsa_ctx_to_pss_string(pkctx); +- if (os == NULL) ++ ++ params[0] = OSSL_PARAM_construct_octet_string( ++ OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid)); ++ params[1] = OSSL_PARAM_construct_end(); ++ ++ if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0) ++ return 0; ++ if ((aid_len = params[0].return_size) == 0) ++ return 0; ++ if (d2i_X509_ALGOR(&alg, &pp, aid_len) == NULL) + return 0; +- X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os); + return 1; + } + +diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c +index c15554505b..61ec53d424 100644 +--- a/crypto/rsa/rsa_ameth.c ++++ b/crypto/rsa/rsa_ameth.c +@@ -637,22 +637,30 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *asn, + if (pad_mode == RSA_PKCS1_PADDING) + return 2; + if (pad_mode == RSA_PKCS1_PSS_PADDING) { +- ASN1_STRING *os1 = NULL; +- os1 = ossl_rsa_ctx_to_pss_string(pkctx); +- if (!os1) ++ unsigned char aid[128]; ++ size_t aid_len = 0; ++ OSSL_PARAM params[2]; ++ ++ params[0] = OSSL_PARAM_construct_octet_string( ++ OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid)); ++ params[1] = OSSL_PARAM_construct_end(); ++ ++ if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0) + return 0; +- /* Duplicate parameters if we have to */ +- if (alg2) { +- ASN1_STRING *os2 = ASN1_STRING_dup(os1); +- if (!os2) { +- ASN1_STRING_free(os1); ++ if ((aid_len = params[0].return_size) == 0) ++ return 0; ++ ++ if (alg1 != NULL) { ++ const unsigned char *pp = aid; ++ if (d2i_X509_ALGOR(&alg1, &pp, aid_len) == NULL) ++ return 0; ++ } ++ if (alg2 != NULL) { ++ const unsigned char *pp = aid; ++ if (d2i_X509_ALGOR(&alg2, &pp, aid_len) == NULL) + return 0; +- } +- X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS), +- V_ASN1_SEQUENCE, os2); + } +- X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS), +- V_ASN1_SEQUENCE, os1); ++ + return 3; + } + return 2; +-- +2.38.1 + diff --git a/0089-signature-Clamp-PSS-salt-len-to-MD-len.patch b/0089-signature-Clamp-PSS-salt-len-to-MD-len.patch deleted file mode 100644 index 8e41bf4..0000000 --- a/0089-signature-Clamp-PSS-salt-len-to-MD-len.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 39a91c33e2b89a0fe42e3791d3dc304519a52182 Mon Sep 17 00:00:00 2001 -From: Clemens Lang -Date: Fri, 18 Nov 2022 12:35:33 +0100 -Subject: [PATCH] signature: Clamp PSS salt len to MD len - -Since FIPS 186-4 subsection 5.5 limits the acceptable PSS salt length to -the size of the message digest, change the default automatic behavior -when signing to use at most the digest size as salt length. Shorter -values are still possible when long hashes are used with short keys. - -Signed-off-by: Clemens Lang ---- - crypto/rsa/rsa_ameth.c | 19 +++++++++++++++++-- - crypto/rsa/rsa_pss.c | 11 +++++++++++ - doc/man3/EVP_PKEY_CTX_ctrl.pod | 4 +++- - providers/implementations/signature/rsa_sig.c | 18 ++++++++++++++++-- - 4 files changed, 47 insertions(+), 5 deletions(-) - -diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c -index b1580ca..dc81627 100644 ---- a/crypto/rsa/rsa_ameth.c -+++ b/crypto/rsa/rsa_ameth.c -@@ -449,6 +449,7 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) - const EVP_MD *sigmd, *mgf1md; - EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx); - int saltlen; -+ int saltlenMax = -1; - - if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0) - return NULL; -@@ -456,14 +457,28 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) - return NULL; - if (EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen) <= 0) - return NULL; -- if (saltlen == -1) { -+ if (saltlen == RSA_PSS_SALTLEN_DIGEST) { - saltlen = EVP_MD_get_size(sigmd); -- } else if (saltlen == -2 || saltlen == -3) { -+ } else if (saltlen == RSA_PSS_SALTLEN_AUTO) { -+ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", -+ * subsection 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in -+ * bytes) of the salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen -+ * is the length of the hash function output block (in bytes)." -+ * -+ * Switch the meaning of RSA_PSS_SALTLEN_AUTO to use at most the digest -+ * length in FIPS mode, so that the default does not violate FIPS -+ * 186-4. */ -+ saltlen = RSA_PSS_SALTLEN_MAX; -+ saltlenMax = EVP_MD_get_size(sigmd); -+ } -+ if (saltlen == RSA_PSS_SALTLEN_MAX) { - saltlen = EVP_PKEY_get_size(pk) - EVP_MD_get_size(sigmd) - 2; - if ((EVP_PKEY_get_bits(pk) & 0x7) == 1) - saltlen--; - if (saltlen < 0) - return NULL; -+ if (saltlenMax >= 0 && saltlen > saltlenMax) -+ saltlen = saltlenMax; - } - - return ossl_rsa_pss_params_create(sigmd, mgf1md, saltlen); -diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c -index e8681b0..d8f9207 100644 ---- a/crypto/rsa/rsa_pss.c -+++ b/crypto/rsa/rsa_pss.c -@@ -168,6 +168,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, - int hLen, maskedDBLen, MSBits, emLen; - unsigned char *H, *salt = NULL, *p; - EVP_MD_CTX *ctx = NULL; -+ int sLenMax = -1; - - if (mgf1Hash == NULL) - mgf1Hash = Hash; -@@ -190,10 +191,18 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, - * -3 same as above (on signing) - * -N reserved - */ -+ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection -+ * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the -+ * salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen is the length of -+ * the hash function output block (in bytes)." -+ * -+ * Switch the meaning of RSA_PSS_SALTLEN_AUTO to use at most the digest -+ * length in FIPS mode, so that the default does not violate FIPS 186-4. */ - if (sLen == RSA_PSS_SALTLEN_DIGEST) { - sLen = hLen; - } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) { - sLen = RSA_PSS_SALTLEN_MAX; -+ sLenMax = hLen; - } else if (sLen < RSA_PSS_SALTLEN_MAX) { - ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED); - goto err; -@@ -211,6 +220,8 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, - } - if (sLen == RSA_PSS_SALTLEN_MAX) { - sLen = emLen - hLen - 2; -+ if (sLenMax >= 0 && sLen > sLenMax) -+ sLen = sLenMax; - } else if (sLen > emLen - hLen - 2) { - ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); - goto err; -diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod -index 3075eaa..5463472 100644 ---- a/doc/man3/EVP_PKEY_CTX_ctrl.pod -+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod -@@ -287,7 +287,9 @@ sets the salt length to the maximum permissible value. - - causes the salt length to be automatically determined based on the - B block structure when verifying. When signing, it has the same --meaning as B. -+meaning as B up to a maximum of the digest length to -+comply with FIPS 186-4 section 5.5. This maximum is specific to Red Hat, -+upstream also uses larger values. - - =back - -diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c -index 3ce5efd..519c6a2 100644 ---- a/providers/implementations/signature/rsa_sig.c -+++ b/providers/implementations/signature/rsa_sig.c -@@ -200,13 +200,27 @@ static void *rsa_newctx(void *provctx, const char *propq) - static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx) - { - int saltlen = ctx->saltlen; -- -+ int saltlenMax = -1; -+ -+ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection -+ * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the -+ * salt (sLen) shall satisfy 0 ≤ sLen ≤ hLen, where hLen is the length of -+ * the hash function output block (in bytes)." -+ * -+ * Switch the meaning of RSA_PSS_SALTLEN_AUTO to use at most the digest -+ * length in FIPS mode, so that the default does not violate FIPS 186-4. */ - if (saltlen == RSA_PSS_SALTLEN_DIGEST) { - saltlen = EVP_MD_get_size(ctx->md); -- } else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) { -+ } else if (saltlen == RSA_PSS_SALTLEN_AUTO) { -+ saltlen = RSA_PSS_SALTLEN_MAX; -+ saltlenMax = EVP_MD_get_size(ctx->md); -+ } -+ if (saltlen == RSA_PSS_SALTLEN_MAX) { - saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2; - if ((RSA_bits(ctx->rsa) & 0x7) == 1) - saltlen--; -+ if (saltlenMax >= 0 && saltlen > saltlenMax) -+ saltlen = saltlenMax; - } - if (saltlen < 0) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); --- -2.38.1 - diff --git a/0090-signature-Clamp-PSS-salt-len-to-MD-len.patch b/0090-signature-Clamp-PSS-salt-len-to-MD-len.patch new file mode 100644 index 0000000..efe7751 --- /dev/null +++ b/0090-signature-Clamp-PSS-salt-len-to-MD-len.patch @@ -0,0 +1,338 @@ +From 9cc914ff3e1fda124bdc76d72ebc9349ec19f8ae Mon Sep 17 00:00:00 2001 +From: Clemens Lang +Date: Fri, 18 Nov 2022 12:35:33 +0100 +Subject: [PATCH 3/3] signature: Clamp PSS salt len to MD len +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection +5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the +salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of +the hash function output block (in bytes)." + +Introduce a new option RSA_PSS_SALTLEN_AUTO_DIGEST_MAX and make it the +default. The new value will behave like RSA_PSS_SALTLEN_AUTO, but will +not use more than the digest legth when signing, so that FIPS 186-4 is +not violated. This value has two advantages when compared with +RSA_PSS_SALTLEN_DIGEST: (1) It will continue to do auto-detection when +verifying signatures for maximum compatibility, where +RSA_PSS_SALTLEN_DIGEST would fail for other digest sizes. (2) It will +work for combinations where the maximum salt length is smaller than the +digest size, which typically happens with large digest sizes (e.g., +SHA-512) and small RSA keys. + +Signed-off-by: Clemens Lang +--- + crypto/rsa/rsa_ameth.c | 18 ++++++++- + crypto/rsa/rsa_pss.c | 26 ++++++++++-- + doc/man3/EVP_PKEY_CTX_ctrl.pod | 11 ++++- + doc/man7/EVP_SIGNATURE-RSA.pod | 5 +++ + include/openssl/core_names.h | 1 + + include/openssl/rsa.h | 3 ++ + providers/implementations/signature/rsa_sig.c | 40 ++++++++++++++----- + test/recipes/25-test_req.t | 2 +- + 8 files changed, 87 insertions(+), 19 deletions(-) + +diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c +index 61ec53d424..e69a98d116 100644 +--- a/crypto/rsa/rsa_ameth.c ++++ b/crypto/rsa/rsa_ameth.c +@@ -450,6 +450,7 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) + const EVP_MD *sigmd, *mgf1md; + EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx); + int saltlen; ++ int saltlenMax = -1; + + if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0) + return NULL; +@@ -457,14 +458,27 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) + return NULL; + if (EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen) <= 0) + return NULL; +- if (saltlen == -1) { ++ if (saltlen == RSA_PSS_SALTLEN_DIGEST) { + saltlen = EVP_MD_get_size(sigmd); +- } else if (saltlen == -2 || saltlen == -3) { ++ } else if (saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { ++ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", ++ * subsection 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in ++ * bytes) of the salt (sLen) shall satisfy 0 <= sLen <= hLen, where ++ * hLen is the length of the hash function output block (in bytes)." ++ * ++ * Provide a way to use at most the digest length, so that the default ++ * does not violate FIPS 186-4. */ ++ saltlen = RSA_PSS_SALTLEN_MAX; ++ saltlenMax = EVP_MD_get_size(sigmd); ++ } ++ if (saltlen == RSA_PSS_SALTLEN_MAX || saltlen == RSA_PSS_SALTLEN_AUTO) { + saltlen = EVP_PKEY_get_size(pk) - EVP_MD_get_size(sigmd) - 2; + if ((EVP_PKEY_get_bits(pk) & 0x7) == 1) + saltlen--; + if (saltlen < 0) + return NULL; ++ if (saltlenMax >= 0 && saltlen > saltlenMax) ++ saltlen = saltlenMax; + } + + return ossl_rsa_pss_params_create(sigmd, mgf1md, saltlen); +diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c +index 33874bfef8..430c36eb2a 100644 +--- a/crypto/rsa/rsa_pss.c ++++ b/crypto/rsa/rsa_pss.c +@@ -61,11 +61,12 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + * -1 sLen == hLen + * -2 salt length is autorecovered from signature + * -3 salt length is maximized ++ * -4 salt length is autorecovered from signature + * -N reserved + */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; +- } else if (sLen < RSA_PSS_SALTLEN_MAX) { ++ } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { + ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED); + goto err; + } +@@ -112,7 +113,9 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED); + goto err; + } +- if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) { ++ if (sLen != RSA_PSS_SALTLEN_AUTO ++ && sLen != RSA_PSS_SALTLEN_AUTO_DIGEST_MAX ++ && (maskedDBLen - i) != sLen) { + ERR_raise_data(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED, + "expected: %d retrieved: %d", sLen, + maskedDBLen - i); +@@ -160,6 +163,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + int hLen, maskedDBLen, MSBits, emLen; + unsigned char *H, *salt = NULL, *p; + EVP_MD_CTX *ctx = NULL; ++ int sLenMax = -1; + + if (mgf1Hash == NULL) + mgf1Hash = Hash; +@@ -172,13 +176,25 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + * -1 sLen == hLen + * -2 salt length is maximized + * -3 same as above (on signing) ++ * -4 salt length is min(hLen, maximum salt length) + * -N reserved + */ ++ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection ++ * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the ++ * salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of ++ * the hash function output block (in bytes)." ++ * ++ * Provide a way to use at most the digest length, so that the default does ++ * not violate FIPS 186-4. */ + if (sLen == RSA_PSS_SALTLEN_DIGEST) { + sLen = hLen; +- } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) { ++ } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN ++ || sLen == RSA_PSS_SALTLEN_AUTO) { + sLen = RSA_PSS_SALTLEN_MAX; +- } else if (sLen < RSA_PSS_SALTLEN_MAX) { ++ } else if (sLen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { ++ sLen = RSA_PSS_SALTLEN_MAX; ++ sLenMax = hLen; ++ } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { + ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED); + goto err; + } +@@ -195,6 +211,8 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + } + if (sLen == RSA_PSS_SALTLEN_MAX) { + sLen = emLen - hLen - 2; ++ if (sLenMax >= 0 && sLen > sLenMax) ++ sLen = sLenMax; + } else if (sLen > emLen - hLen - 2) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + goto err; +diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod +index 3075eaafd6..9b96f42dbc 100644 +--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod ++++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod +@@ -270,8 +270,8 @@ EVP_PKEY_CTX_get_rsa_padding() gets the RSA padding mode for I. + + EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to I. + As its name implies it is only supported for PSS padding. If this function is +-not called then the maximum salt length is used when signing and auto detection +-when verifying. Three special values are supported: ++not called then the salt length is maximized up to the digest length when ++signing and auto detection when verifying. Four special values are supported: + + =over 4 + +@@ -289,6 +289,13 @@ causes the salt length to be automatically determined based on the + B block structure when verifying. When signing, it has the same + meaning as B. + ++=item B ++ ++causes the salt length to be automatically determined based on the B block ++structure when verifying, like B. When signing, the salt ++length is maximized up to a maximum of the digest length to comply with FIPS ++186-4 section 5.5. ++ + =back + + EVP_PKEY_CTX_get_rsa_pss_saltlen() gets the RSA PSS salt length for I. +diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod +index 1ce32cc443..13d053e262 100644 +--- a/doc/man7/EVP_SIGNATURE-RSA.pod ++++ b/doc/man7/EVP_SIGNATURE-RSA.pod +@@ -68,6 +68,11 @@ Use the maximum salt length. + + Auto detect the salt length. + ++=item "auto-digestmax" (B) ++ ++Auto detect the salt length when verifying. Maximize the salt length up to the ++digest size when signing to comply with FIPS 186-4 section 5.5. ++ + =back + + =back +diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h +index 69c59f0b46..5779f41427 100644 +--- a/include/openssl/core_names.h ++++ b/include/openssl/core_names.h +@@ -399,6 +399,7 @@ extern "C" { + #define OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST "digest" + #define OSSL_PKEY_RSA_PSS_SALT_LEN_MAX "max" + #define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO "auto" ++#define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX "auto-digestmax" + + /* Key generation parameters */ + #define OSSL_PKEY_PARAM_RSA_BITS OSSL_PKEY_PARAM_BITS +diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h +index a55c9727c6..daf55bc6d4 100644 +--- a/include/openssl/rsa.h ++++ b/include/openssl/rsa.h +@@ -137,6 +137,9 @@ int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp); + # define RSA_PSS_SALTLEN_AUTO -2 + /* Set salt length to maximum possible */ + # define RSA_PSS_SALTLEN_MAX -3 ++/* Auto-detect on verify, set salt length to min(maximum possible, digest ++ * length) on sign */ ++# define RSA_PSS_SALTLEN_AUTO_DIGEST_MAX -4 + /* Old compatible max salt length for sign only */ + # define RSA_PSS_SALTLEN_MAX_SIGN -2 + +diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c +index 0c45008a00..1a787d77db 100644 +--- a/providers/implementations/signature/rsa_sig.c ++++ b/providers/implementations/signature/rsa_sig.c +@@ -191,8 +191,8 @@ static void *rsa_newctx(void *provctx, const char *propq) + prsactx->libctx = PROV_LIBCTX_OF(provctx); + prsactx->flag_allow_md = 1; + prsactx->propq = propq_copy; +- /* Maximum for sign, auto for verify */ +- prsactx->saltlen = RSA_PSS_SALTLEN_AUTO; ++ /* Maximum up to digest length for sign, auto for verify */ ++ prsactx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; + prsactx->min_saltlen = -1; + return prsactx; + } +@@ -200,13 +200,27 @@ static void *rsa_newctx(void *provctx, const char *propq) + static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx) + { + int saltlen = ctx->saltlen; +- ++ int saltlenMax = -1; ++ ++ /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection ++ * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the ++ * salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of ++ * the hash function output block (in bytes)." ++ * ++ * Provide a way to use at most the digest length, so that the default does ++ * not violate FIPS 186-4. */ + if (saltlen == RSA_PSS_SALTLEN_DIGEST) { + saltlen = EVP_MD_get_size(ctx->md); +- } else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) { ++ } else if (saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { ++ saltlen = RSA_PSS_SALTLEN_MAX; ++ saltlenMax = EVP_MD_get_size(ctx->md); ++ } ++ if (saltlen == RSA_PSS_SALTLEN_MAX || saltlen == RSA_PSS_SALTLEN_AUTO) { + saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2; + if ((RSA_bits(ctx->rsa) & 0x7) == 1) + saltlen--; ++ if (saltlenMax >= 0 && saltlen > saltlenMax) ++ saltlen = saltlenMax; + } + if (saltlen < 0) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); +@@ -411,8 +425,8 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, + + prsactx->operation = operation; + +- /* Maximum for sign, auto for verify */ +- prsactx->saltlen = RSA_PSS_SALTLEN_AUTO; ++ /* Maximize up to digest length for sign, auto for verify */ ++ prsactx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; + prsactx->min_saltlen = -1; + + switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) { +@@ -1110,6 +1124,9 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) + case RSA_PSS_SALTLEN_AUTO: + value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO; + break; ++ case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: ++ value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX; ++ break; + default: + { + int len = BIO_snprintf(p->data, p->data_size, "%d", +@@ -1297,6 +1314,8 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) + saltlen = RSA_PSS_SALTLEN_MAX; + else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0) + saltlen = RSA_PSS_SALTLEN_AUTO; ++ else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0) ++ saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; + else + saltlen = atoi(p->data); + break; +@@ -1305,11 +1324,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) + } + + /* +- * RSA_PSS_SALTLEN_MAX seems curiously named in this check. +- * Contrary to what it's name suggests, it's the currently +- * lowest saltlen number possible. ++ * RSA_PSS_SALTLEN_AUTO_DIGEST_MAX seems curiously named in this check. ++ * Contrary to what it's name suggests, it's the currently lowest ++ * saltlen number possible. + */ +- if (saltlen < RSA_PSS_SALTLEN_MAX) { ++ if (saltlen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } +@@ -1317,6 +1336,7 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) + if (rsa_pss_restricted(prsactx)) { + switch (saltlen) { + case RSA_PSS_SALTLEN_AUTO: ++ case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: + if (prsactx->operation == EVP_PKEY_OP_VERIFY) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, + "Cannot use autodetected salt length"); +diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t +index e615f1b338..35541aed12 100644 +--- a/test/recipes/25-test_req.t ++++ b/test/recipes/25-test_req.t +@@ -199,7 +199,7 @@ subtest "generating certificate requests with RSA-PSS" => sub { + ok(!run(app(["openssl", "req", + "-config", srctop_file("test", "test.cnf"), + "-new", "-out", "testreq-rsapss3.pem", "-utf8", +- "-sigopt", "rsa_pss_saltlen:-4", ++ "-sigopt", "rsa_pss_saltlen:-5", + "-key", srctop_file("test", "testrsapss.pem")])), + "Generating request with expected failure"); + +-- +2.38.1 + diff --git a/0090-FIPS-RSA-encapsulate.patch b/0091-FIPS-RSA-encapsulate.patch similarity index 100% rename from 0090-FIPS-RSA-encapsulate.patch rename to 0091-FIPS-RSA-encapsulate.patch diff --git a/0091-provider-improvements.patch b/0092-provider-improvements.patch similarity index 100% rename from 0091-provider-improvements.patch rename to 0092-provider-improvements.patch diff --git a/openssl.spec b/openssl.spec index 1a2b7e5..a196871 100644 --- a/openssl.spec +++ b/openssl.spec @@ -147,11 +147,13 @@ Patch85: 0085-FIPS-RSA-disable-shake.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2142087 Patch88: 0088-signature-Add-indicator-for-PSS-salt-length.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2142087 -Patch89: 0089-signature-Clamp-PSS-salt-len-to-MD-len.patch +Patch89: 0089-PSS-salt-length-from-provider.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2142087 +Patch90: 0090-signature-Clamp-PSS-salt-len-to-MD-len.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2144561 -Patch90: 0090-FIPS-RSA-encapsulate.patch +Patch91: 0091-FIPS-RSA-encapsulate.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2142517 -Patch91: 0091-provider-improvements.patch +Patch92: 0092-provider-improvements.patch License: ASL 2.0 URL: http://www.openssl.org/ @@ -493,6 +495,11 @@ install -m644 %{SOURCE9} \ Resolves: rhbz#2083879 - Backport of ppc64le Montgomery multiply enhancement Resolves: rhbz#2130708 +- Fix explicit indicator for PSS salt length in FIPS mode when used with + negative magic values + Resolves: rhbz#2142087 +- Update change to default PSS salt length with patch state from upstream + Related: rhbz#2142087 * Tue Nov 22 2022 Dmitry Belyavskiy - 1:3.0.7-1 - Rebasing to OpenSSL 3.0.7