Blame SOURCES/0090-signature-Clamp-PSS-salt-len-to-MD-len.patch

1ac26c
From 9cc914ff3e1fda124bdc76d72ebc9349ec19f8ae Mon Sep 17 00:00:00 2001
1ac26c
From: Clemens Lang <cllang@redhat.com>
1ac26c
Date: Fri, 18 Nov 2022 12:35:33 +0100
1ac26c
Subject: [PATCH 3/3] signature: Clamp PSS salt len to MD len
1ac26c
MIME-Version: 1.0
1ac26c
Content-Type: text/plain; charset=UTF-8
1ac26c
Content-Transfer-Encoding: 8bit
1ac26c
1ac26c
FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection
1ac26c
5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the
1ac26c
salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of
1ac26c
the hash function output block (in bytes)."
1ac26c
1ac26c
Introduce a new option RSA_PSS_SALTLEN_AUTO_DIGEST_MAX and make it the
1ac26c
default. The new value will behave like RSA_PSS_SALTLEN_AUTO, but will
1ac26c
not use more than the digest legth when signing, so that FIPS 186-4 is
1ac26c
not violated. This value has two advantages when compared with
1ac26c
RSA_PSS_SALTLEN_DIGEST: (1) It will continue to do auto-detection when
1ac26c
verifying signatures for maximum compatibility, where
1ac26c
RSA_PSS_SALTLEN_DIGEST would fail for other digest sizes. (2) It will
1ac26c
work for combinations where the maximum salt length is smaller than the
1ac26c
digest size, which typically happens with large digest sizes (e.g.,
1ac26c
SHA-512) and small RSA keys.
1ac26c
1ac26c
Signed-off-by: Clemens Lang <cllang@redhat.com>
1ac26c
---
1ac26c
 crypto/rsa/rsa_ameth.c                        | 18 ++++++++-
1ac26c
 crypto/rsa/rsa_pss.c                          | 26 ++++++++++--
1ac26c
 doc/man3/EVP_PKEY_CTX_ctrl.pod                | 11 ++++-
1ac26c
 doc/man7/EVP_SIGNATURE-RSA.pod                |  5 +++
1ac26c
 include/openssl/core_names.h                  |  1 +
1ac26c
 include/openssl/rsa.h                         |  3 ++
1ac26c
 providers/implementations/signature/rsa_sig.c | 40 ++++++++++++++-----
1ac26c
 test/recipes/25-test_req.t                    |  2 +-
1ac26c
 8 files changed, 87 insertions(+), 19 deletions(-)
1ac26c
1ac26c
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
1ac26c
index 61ec53d424..e69a98d116 100644
1ac26c
--- a/crypto/rsa/rsa_ameth.c
1ac26c
+++ b/crypto/rsa/rsa_ameth.c
1ac26c
@@ -450,6 +450,7 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
1ac26c
     const EVP_MD *sigmd, *mgf1md;
1ac26c
     EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
1ac26c
     int saltlen;
1ac26c
+    int saltlenMax = -1;
1ac26c
 
1ac26c
     if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
1ac26c
         return NULL;
1ac26c
@@ -457,14 +458,27 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
1ac26c
         return NULL;
1ac26c
     if (EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen) <= 0)
1ac26c
         return NULL;
1ac26c
-    if (saltlen == -1) {
1ac26c
+    if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
1ac26c
         saltlen = EVP_MD_get_size(sigmd);
1ac26c
-    } else if (saltlen == -2 || saltlen == -3) {
1ac26c
+    } else if (saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
+        /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm",
1ac26c
+         * subsection 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in
1ac26c
+         * bytes) of the salt (sLen) shall satisfy 0 <= sLen <= hLen, where
1ac26c
+         * hLen is the length of the hash function output block (in bytes)."
1ac26c
+         *
1ac26c
+         * Provide a way to use at most the digest length, so that the default
1ac26c
+         * does not violate FIPS 186-4. */
1ac26c
+        saltlen = RSA_PSS_SALTLEN_MAX;
1ac26c
+        saltlenMax = EVP_MD_get_size(sigmd);
1ac26c
+    }
1ac26c
+    if (saltlen == RSA_PSS_SALTLEN_MAX || saltlen == RSA_PSS_SALTLEN_AUTO) {
1ac26c
         saltlen = EVP_PKEY_get_size(pk) - EVP_MD_get_size(sigmd) - 2;
1ac26c
         if ((EVP_PKEY_get_bits(pk) & 0x7) == 1)
1ac26c
             saltlen--;
1ac26c
         if (saltlen < 0)
1ac26c
             return NULL;
1ac26c
+        if (saltlenMax >= 0 && saltlen > saltlenMax)
1ac26c
+            saltlen = saltlenMax;
1ac26c
     }
1ac26c
 
1ac26c
     return ossl_rsa_pss_params_create(sigmd, mgf1md, saltlen);
1ac26c
diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c
1ac26c
index 33874bfef8..430c36eb2a 100644
1ac26c
--- a/crypto/rsa/rsa_pss.c
1ac26c
+++ b/crypto/rsa/rsa_pss.c
1ac26c
@@ -61,11 +61,12 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
1ac26c
      *      -1      sLen == hLen
1ac26c
      *      -2      salt length is autorecovered from signature
1ac26c
      *      -3      salt length is maximized
1ac26c
+     *      -4      salt length is autorecovered from signature
1ac26c
      *      -N      reserved
1ac26c
      */
1ac26c
     if (sLen == RSA_PSS_SALTLEN_DIGEST) {
1ac26c
         sLen = hLen;
1ac26c
-    } else if (sLen < RSA_PSS_SALTLEN_MAX) {
1ac26c
+    } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
         ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED);
1ac26c
         goto err;
1ac26c
     }
1ac26c
@@ -112,7 +113,9 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
1ac26c
         ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED);
1ac26c
         goto err;
1ac26c
     }
1ac26c
-    if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) {
1ac26c
+    if (sLen != RSA_PSS_SALTLEN_AUTO
1ac26c
+            && sLen != RSA_PSS_SALTLEN_AUTO_DIGEST_MAX
1ac26c
+            && (maskedDBLen - i) != sLen) {
1ac26c
         ERR_raise_data(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED,
1ac26c
                        "expected: %d retrieved: %d", sLen,
1ac26c
                        maskedDBLen - i);
1ac26c
@@ -160,6 +163,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
1ac26c
     int hLen, maskedDBLen, MSBits, emLen;
1ac26c
     unsigned char *H, *salt = NULL, *p;
1ac26c
     EVP_MD_CTX *ctx = NULL;
1ac26c
+    int sLenMax = -1;
1ac26c
 
1ac26c
     if (mgf1Hash == NULL)
1ac26c
         mgf1Hash = Hash;
1ac26c
@@ -172,13 +176,25 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
1ac26c
      *      -1      sLen == hLen
1ac26c
      *      -2      salt length is maximized
1ac26c
      *      -3      same as above (on signing)
1ac26c
+     *      -4      salt length is min(hLen, maximum salt length)
1ac26c
      *      -N      reserved
1ac26c
      */
1ac26c
+    /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection
1ac26c
+     * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the
1ac26c
+     * salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of
1ac26c
+     * the hash function output block (in bytes)."
1ac26c
+     *
1ac26c
+     * Provide a way to use at most the digest length, so that the default does
1ac26c
+     * not violate FIPS 186-4. */
1ac26c
     if (sLen == RSA_PSS_SALTLEN_DIGEST) {
1ac26c
         sLen = hLen;
1ac26c
-    } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) {
1ac26c
+    } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN
1ac26c
+            || sLen == RSA_PSS_SALTLEN_AUTO) {
1ac26c
         sLen = RSA_PSS_SALTLEN_MAX;
1ac26c
-    } else if (sLen < RSA_PSS_SALTLEN_MAX) {
1ac26c
+    } else if (sLen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
+        sLen = RSA_PSS_SALTLEN_MAX;
1ac26c
+        sLenMax = hLen;
1ac26c
+    } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
         ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED);
1ac26c
         goto err;
1ac26c
     }
1ac26c
@@ -195,6 +211,8 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
1ac26c
     }
1ac26c
     if (sLen == RSA_PSS_SALTLEN_MAX) {
1ac26c
         sLen = emLen - hLen - 2;
1ac26c
+        if (sLenMax >= 0 && sLen > sLenMax)
1ac26c
+            sLen = sLenMax;
1ac26c
     } else if (sLen > emLen - hLen - 2) {
1ac26c
         ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
1ac26c
         goto err;
1ac26c
diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
1ac26c
index 3075eaafd6..9b96f42dbc 100644
1ac26c
--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
1ac26c
+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
1ac26c
@@ -270,8 +270,8 @@ EVP_PKEY_CTX_get_rsa_padding() gets the RSA padding mode for I<ctx>.
1ac26c
 
1ac26c
 EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to I<saltlen>.
1ac26c
 As its name implies it is only supported for PSS padding. If this function is
1ac26c
-not called then the maximum salt length is used when signing and auto detection
1ac26c
-when verifying. Three special values are supported:
1ac26c
+not called then the salt length is maximized up to the digest length when
1ac26c
+signing and auto detection when verifying. Four special values are supported:
1ac26c
 
1ac26c
 =over 4
1ac26c
 
1ac26c
@@ -289,6 +289,13 @@ causes the salt length to be automatically determined based on the
1ac26c
 B<PSS> block structure when verifying.  When signing, it has the same
1ac26c
 meaning as B<RSA_PSS_SALTLEN_MAX>.
1ac26c
 
1ac26c
+=item B<RSA_PSS_SALTLEN_AUTO_DIGEST_MAX>
1ac26c
+
1ac26c
+causes the salt length to be automatically determined based on the B<PSS> block
1ac26c
+structure when verifying, like B<RSA_PSS_SALTLEN_AUTO>.  When signing, the salt
1ac26c
+length is maximized up to a maximum of the digest length to comply with FIPS
1ac26c
+186-4 section 5.5.
1ac26c
+
1ac26c
 =back
1ac26c
 
1ac26c
 EVP_PKEY_CTX_get_rsa_pss_saltlen() gets the RSA PSS salt length for I<ctx>.
1ac26c
diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod
1ac26c
index 1ce32cc443..13d053e262 100644
1ac26c
--- a/doc/man7/EVP_SIGNATURE-RSA.pod
1ac26c
+++ b/doc/man7/EVP_SIGNATURE-RSA.pod
1ac26c
@@ -68,6 +68,11 @@ Use the maximum salt length.
1ac26c
 
1ac26c
 Auto detect the salt length.
1ac26c
 
1ac26c
+=item "auto-digestmax" (B<OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX>)
1ac26c
+
1ac26c
+Auto detect the salt length when verifying.  Maximize the salt length up to the
1ac26c
+digest size when signing to comply with FIPS 186-4 section 5.5.
1ac26c
+
1ac26c
 =back
1ac26c
 
1ac26c
 =back
1ac26c
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
1ac26c
index 69c59f0b46..5779f41427 100644
1ac26c
--- a/include/openssl/core_names.h
1ac26c
+++ b/include/openssl/core_names.h
1ac26c
@@ -399,6 +399,7 @@ extern "C" {
1ac26c
 #define OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST "digest"
1ac26c
 #define OSSL_PKEY_RSA_PSS_SALT_LEN_MAX    "max"
1ac26c
 #define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO   "auto"
1ac26c
+#define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX "auto-digestmax"
1ac26c
 
1ac26c
 /* Key generation parameters */
1ac26c
 #define OSSL_PKEY_PARAM_RSA_BITS             OSSL_PKEY_PARAM_BITS
1ac26c
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
1ac26c
index a55c9727c6..daf55bc6d4 100644
1ac26c
--- a/include/openssl/rsa.h
1ac26c
+++ b/include/openssl/rsa.h
1ac26c
@@ -137,6 +137,9 @@ int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
1ac26c
 # define RSA_PSS_SALTLEN_AUTO   -2
1ac26c
 /* Set salt length to maximum possible */
1ac26c
 # define RSA_PSS_SALTLEN_MAX    -3
1ac26c
+/* Auto-detect on verify, set salt length to min(maximum possible, digest
1ac26c
+ * length) on sign */
1ac26c
+# define RSA_PSS_SALTLEN_AUTO_DIGEST_MAX  -4
1ac26c
 /* Old compatible max salt length for sign only */
1ac26c
 # define RSA_PSS_SALTLEN_MAX_SIGN    -2
1ac26c
 
1ac26c
diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c
1ac26c
index 0c45008a00..1a787d77db 100644
1ac26c
--- a/providers/implementations/signature/rsa_sig.c
1ac26c
+++ b/providers/implementations/signature/rsa_sig.c
1ac26c
@@ -191,8 +191,8 @@ static void *rsa_newctx(void *provctx, const char *propq)
1ac26c
     prsactx->libctx = PROV_LIBCTX_OF(provctx);
1ac26c
     prsactx->flag_allow_md = 1;
1ac26c
     prsactx->propq = propq_copy;
1ac26c
-    /* Maximum for sign, auto for verify */
1ac26c
-    prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
1ac26c
+    /* Maximum up to digest length for sign, auto for verify */
1ac26c
+    prsactx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
1ac26c
     prsactx->min_saltlen = -1;
1ac26c
     return prsactx;
1ac26c
 }
1ac26c
@@ -200,13 +200,27 @@ static void *rsa_newctx(void *provctx, const char *propq)
1ac26c
 static int rsa_pss_compute_saltlen(PROV_RSA_CTX *ctx)
1ac26c
 {
1ac26c
     int saltlen = ctx->saltlen;
1ac26c
- 
1ac26c
+    int saltlenMax = -1;
1ac26c
+
1ac26c
+    /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection
1ac26c
+     * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the
1ac26c
+     * salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of
1ac26c
+     * the hash function output block (in bytes)."
1ac26c
+     *
1ac26c
+     * Provide a way to use at most the digest length, so that the default does
1ac26c
+     * not violate FIPS 186-4. */
1ac26c
     if (saltlen == RSA_PSS_SALTLEN_DIGEST) {
1ac26c
         saltlen = EVP_MD_get_size(ctx->md);
1ac26c
-    } else if (saltlen == RSA_PSS_SALTLEN_AUTO || saltlen == RSA_PSS_SALTLEN_MAX) {
1ac26c
+    } else if (saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
+        saltlen = RSA_PSS_SALTLEN_MAX;
1ac26c
+        saltlenMax = EVP_MD_get_size(ctx->md);
1ac26c
+    }
1ac26c
+    if (saltlen == RSA_PSS_SALTLEN_MAX || saltlen == RSA_PSS_SALTLEN_AUTO) {
1ac26c
         saltlen = RSA_size(ctx->rsa) - EVP_MD_get_size(ctx->md) - 2;
1ac26c
         if ((RSA_bits(ctx->rsa) & 0x7) == 1)
1ac26c
             saltlen--;
1ac26c
+        if (saltlenMax >= 0 && saltlen > saltlenMax)
1ac26c
+            saltlen = saltlenMax;
1ac26c
     }
1ac26c
     if (saltlen < 0) {
1ac26c
         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
1ac26c
@@ -411,8 +425,8 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa,
1ac26c
 
1ac26c
     prsactx->operation = operation;
1ac26c
 
1ac26c
-    /* Maximum for sign, auto for verify */
1ac26c
-    prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
1ac26c
+    /* Maximize up to digest length for sign, auto for verify */
1ac26c
+    prsactx->saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
1ac26c
     prsactx->min_saltlen = -1;
1ac26c
 
1ac26c
     switch (RSA_test_flags(prsactx->rsa, RSA_FLAG_TYPE_MASK)) {
1ac26c
@@ -1110,6 +1124,9 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
1ac26c
             case RSA_PSS_SALTLEN_AUTO:
1ac26c
                 value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO;
1ac26c
                 break;
1ac26c
+            case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX:
1ac26c
+                value = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX;
1ac26c
+                break;
1ac26c
             default:
1ac26c
                 {
1ac26c
                     int len = BIO_snprintf(p->data, p->data_size, "%d",
1ac26c
@@ -1297,6 +1314,8 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
1ac26c
                 saltlen = RSA_PSS_SALTLEN_MAX;
1ac26c
             else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
1ac26c
                 saltlen = RSA_PSS_SALTLEN_AUTO;
1ac26c
+            else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0)
1ac26c
+                saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
1ac26c
             else
1ac26c
                 saltlen = atoi(p->data);
1ac26c
             break;
1ac26c
@@ -1305,11 +1324,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
1ac26c
         }
1ac26c
 
1ac26c
         /*
1ac26c
-         * RSA_PSS_SALTLEN_MAX seems curiously named in this check.
1ac26c
-         * Contrary to what it's name suggests, it's the currently
1ac26c
-         * lowest saltlen number possible.
1ac26c
+         * RSA_PSS_SALTLEN_AUTO_DIGEST_MAX seems curiously named in this check.
1ac26c
+         * Contrary to what it's name suggests, it's the currently lowest
1ac26c
+         * saltlen number possible.
1ac26c
          */
1ac26c
-        if (saltlen < RSA_PSS_SALTLEN_MAX) {
1ac26c
+        if (saltlen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) {
1ac26c
             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH);
1ac26c
             return 0;
1ac26c
         }
1ac26c
@@ -1317,6 +1336,7 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
1ac26c
         if (rsa_pss_restricted(prsactx)) {
1ac26c
             switch (saltlen) {
1ac26c
             case RSA_PSS_SALTLEN_AUTO:
1ac26c
+            case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX:
1ac26c
                 if (prsactx->operation == EVP_PKEY_OP_VERIFY) {
1ac26c
                     ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
1ac26c
                                    "Cannot use autodetected salt length");
1ac26c
diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t
1ac26c
index e615f1b338..35541aed12 100644
1ac26c
--- a/test/recipes/25-test_req.t
1ac26c
+++ b/test/recipes/25-test_req.t
1ac26c
@@ -199,7 +199,7 @@ subtest "generating certificate requests with RSA-PSS" => sub {
1ac26c
         ok(!run(app(["openssl", "req",
1ac26c
                      "-config", srctop_file("test", "test.cnf"),
1ac26c
                      "-new", "-out", "testreq-rsapss3.pem", "-utf8",
1ac26c
-                     "-sigopt", "rsa_pss_saltlen:-4",
1ac26c
+                     "-sigopt", "rsa_pss_saltlen:-5",
1ac26c
                      "-key", srctop_file("test", "testrsapss.pem")])),
1ac26c
            "Generating request with expected failure");
1ac26c
 
1ac26c
-- 
1ac26c
2.38.1
1ac26c