From a325a23bc83f4efd60130001c417ca5b96bdbff1 Mon Sep 17 00:00:00 2001
From: Clemens Lang <cllang@redhat.com>
Date: Thu, 17 Nov 2022 19:33:02 +0100
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

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.

We also add indicator for RSA_NO_PADDING here to avoid patch-over-patch.
Dmitry Belyavskiy <dbelyavs@redhat.com>

Signed-off-by: Clemens Lang <cllang@redhat.com>
---
 include/openssl/evp.h                         |  4 ++++
 providers/implementations/signature/rsa_sig.c | 21 +++++++++++++++++
 util/perl/OpenSSL/paramnames.pm               | 23 ++++++++++---------
 3 files changed, 37 insertions(+), 11 deletions(-)

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..0c45008a00 100644
--- a/providers/implementations/signature/rsa_sig.c
+++ b/providers/implementations/signature/rsa_sig.c
@@ -1127,6 +1127,24 @@ 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 (rsa_pss_compute_saltlen(prsactx) > EVP_MD_get_size(prsactx->md)) {
+                fips_indicator = EVP_SIGNATURE_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
+            }
+        } else if (prsactx->pad_mode == RSA_NO_PADDING) {
+            if (prsactx->md == NULL) /* Should always be the case */
+                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
 };
 
diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm
index 8b2d430f17..a109e44521 100644
--- a/util/perl/OpenSSL/paramnames.pm
+++ b/util/perl/OpenSSL/paramnames.pm
@@ -377,17 +377,18 @@ my %params = (
     'EXCHANGE_PARAM_KDF_UKM' =>               "kdf-ukm",
 
 # Signature parameters
-    'SIGNATURE_PARAM_ALGORITHM_ID' =>       "algorithm-id",
-    'SIGNATURE_PARAM_PAD_MODE' =>           '*PKEY_PARAM_PAD_MODE',
-    'SIGNATURE_PARAM_DIGEST' =>             '*PKEY_PARAM_DIGEST',
-    'SIGNATURE_PARAM_PROPERTIES' =>         '*PKEY_PARAM_PROPERTIES',
-    'SIGNATURE_PARAM_PSS_SALTLEN' =>        "saltlen",
-    'SIGNATURE_PARAM_MGF1_DIGEST' =>        '*PKEY_PARAM_MGF1_DIGEST',
-    'SIGNATURE_PARAM_MGF1_PROPERTIES' =>    '*PKEY_PARAM_MGF1_PROPERTIES',
-    'SIGNATURE_PARAM_DIGEST_SIZE' =>        '*PKEY_PARAM_DIGEST_SIZE',
-    'SIGNATURE_PARAM_NONCE_TYPE' =>         "nonce-type",
-    'SIGNATURE_PARAM_INSTANCE' =>           "instance",
-    'SIGNATURE_PARAM_CONTEXT_STRING' =>     "context-string",
+    'SIGNATURE_PARAM_ALGORITHM_ID' =>          "algorithm-id",
+    'SIGNATURE_PARAM_PAD_MODE' =>              '*PKEY_PARAM_PAD_MODE',
+    'SIGNATURE_PARAM_DIGEST' =>                '*PKEY_PARAM_DIGEST',
+    'SIGNATURE_PARAM_PROPERTIES' =>            '*PKEY_PARAM_PROPERTIES',
+    'SIGNATURE_PARAM_PSS_SALTLEN' =>           "saltlen",
+    'SIGNATURE_PARAM_MGF1_DIGEST' =>           '*PKEY_PARAM_MGF1_DIGEST',
+    'SIGNATURE_PARAM_MGF1_PROPERTIES' =>       '*PKEY_PARAM_MGF1_PROPERTIES',
+    'SIGNATURE_PARAM_DIGEST_SIZE' =>           '*PKEY_PARAM_DIGEST_SIZE',
+    'SIGNATURE_PARAM_REDHAT_FIPS_INDICATOR' => "redhat-fips-indicator",
+    'SIGNATURE_PARAM_NONCE_TYPE' =>            "nonce-type",
+    'SIGNATURE_PARAM_INSTANCE' =>              "instance",
+    'SIGNATURE_PARAM_CONTEXT_STRING' =>        "context-string",
 
 # Asym cipher parameters
     'ASYM_CIPHER_PARAM_DIGEST' =>                   '*PKEY_PARAM_DIGEST',
-- 
2.38.1

