diff --git a/0088-signature-Add-indicator-for-PSS-salt-length.patch b/0088-signature-Add-indicator-for-PSS-salt-length.patch new file mode 100644 index 0000000..9f5a99e --- /dev/null +++ b/0088-signature-Add-indicator-for-PSS-salt-length.patch @@ -0,0 +1,110 @@ +From 02612d36c664e03821ed80a205fdca80232afd64 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 +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)." + +It is not exactly clear from this text whether hLen refers to the +message digest or the hash function used for the mask generation +function MGF1. PKCS#1 v2.1 suggests it is the former: + +| Typical salt lengths in octets are hLen (the length of the output of +| the hash function Hash) and 0. In both cases the security of +| RSASSA-PSS can be closely related to the hardness of inverting RSAVP1. +| Bellare and Rogaway [4] give a tight lower bound for the security of +| the original RSA-PSS scheme, which corresponds roughly to the former +| case, while Coron [12] gives a lower bound for the related Full Domain +| Hashing scheme, which corresponds roughly to the latter case. In [13] +| Coron provides a general treatment with various salt lengths ranging +| from 0 to hLen; see [27] for discussion. See also [31], which adapts +| the security proofs in [4][13] to address the differences between the +| original and the present version of RSA-PSS as listed in Note 1 above. + +Since OpenSSL defaults to creating signatures with the maximum salt +length, blocking the use of longer salts would probably lead to +significant problems in practice. Instead, introduce an explicit +indicator that can be obtained from the EVP_PKEY_CTX object using +EVP_PKEY_CTX_get_params() with the + OSSL_SIGNATURE_PARAM_REDHAT_FIPS_INDICATOR +parameter. + +Signed-off-by: Clemens Lang +--- + include/openssl/core_names.h | 1 + + include/openssl/evp.h | 4 ++++ + providers/implementations/signature/rsa_sig.c | 18 ++++++++++++++++++ + 3 files changed, 23 insertions(+) + +diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h +index 94fab83193..69c59f0b46 100644 +--- a/include/openssl/core_names.h ++++ b/include/openssl/core_names.h +@@ -453,6 +453,7 @@ extern "C" { + #define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \ + OSSL_PKEY_PARAM_MGF1_PROPERTIES + #define OSSL_SIGNATURE_PARAM_DIGEST_SIZE OSSL_PKEY_PARAM_DIGEST_SIZE ++#define OSSL_SIGNATURE_PARAM_REDHAT_FIPS_INDICATOR "redhat-fips-indicator" + + /* Asym cipher parameters */ + #define OSSL_ASYM_CIPHER_PARAM_DIGEST OSSL_PKEY_PARAM_DIGEST +diff --git a/include/openssl/evp.h b/include/openssl/evp.h +index a5e78efd6e..f239200465 100644 +--- a/include/openssl/evp.h ++++ b/include/openssl/evp.h +@@ -797,6 +797,10 @@ __owur int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, + __owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, + int *outl); + ++# define EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_UNDETERMINED 0 ++# define EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_APPROVED 1 ++# define EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_NOT_APPROVED 2 ++ + __owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, + 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 +--- 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) + } + } + ++#ifdef FIPS_MODULE ++ p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_REDHAT_FIPS_INDICATOR); ++ if (p != NULL) { ++ int fips_indicator = EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_APPROVED; ++ 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)) { ++ fips_indicator = EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_NOT_APPROVED; ++ } ++ } ++ return OSSL_PARAM_set_int(p, fips_indicator); ++ } ++#endif ++ + return 1; + } + +@@ -1136,6 +1151,9 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), ++#ifdef FIPS_MODULE ++ OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_REDHAT_FIPS_INDICATOR, NULL), ++#endif + OSSL_PARAM_END + }; + +-- +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 new file mode 100644 index 0000000..975b810 --- /dev/null +++ b/0089-signature-Clamp-PSS-salt-len-to-MD-len.patch @@ -0,0 +1,153 @@ +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)) + 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/openssl.spec b/openssl.spec index 2ed1533..7975059 100644 --- a/openssl.spec +++ b/openssl.spec @@ -180,6 +180,10 @@ Patch85: 0085-FIPS-RSA-disable-shake.patch Patch86: 0086-avoid-bio-memleak.patch #https://github.com/openssl/openssl/pull/19501 Patch87: 0087-FIPS-RSA-selftest-params.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 License: ASL 2.0 URL: http://www.openssl.org/ @@ -527,6 +531,10 @@ install -m644 %{SOURCE9} \ Resolves: rhbz#2144000 - Set minimum password length for PBKDF2 in FIPS mode Resolves: rhbz#2144003 +- Add explicit indicator for PSS salt length in FIPS mode + Resolves: rhbz#2144012 +- Clamp default PSS salt length to digest size for FIPS 186-4 compliance + Related: rhbz#2144012 * Tue Nov 01 2022 Dmitry Belyavskiy - 1:3.0.1-43 - CVE-2022-3602: X.509 Email Address Buffer Overflow