signature: Clamp PSS salt len to MD len
authorClemens Lang <cllang@redhat.com>
Fri, 18 Nov 2022 11:35:33 +0000 (12:35 +0100)
committerTomas Mraz <tomas@openssl.org>
Fri, 9 Dec 2022 15:34:07 +0000 (16:34 +0100)
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 length 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.

J.-S. Coron shows in "Optimal Security Proofs for PSS and Other
Signature Schemes. Advances in Cryptology – Eurocrypt 2002, volume 2332
of Lecture Notes in Computer Science, pp. 272 – 287. Springer Verlag,
2002." that longer salts than the output size of modern hash functions
do not increase security: "For example,for an application in which at
most one billion signatures will be generated, k0 = 30 bits of random
salt are actually sufficient to guarantee the same level of security as
RSA, and taking a larger salt does not increase the security level."

Signed-off-by: Clemens Lang <cllang@redhat.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(cherry picked from commit 6c73ca4a2f4ea71f4a880670624e7b2fdb6f32da)

(Merged from https://github.com/openssl/openssl/pull/19862)

13 files changed:
CHANGES.md
crypto/rsa/rsa_ameth.c
crypto/rsa/rsa_pss.c
doc/man3/EVP_PKEY_CTX_ctrl.pod
doc/man7/EVP_SIGNATURE-RSA.pod
include/openssl/core_names.h
include/openssl/rsa.h
providers/implementations/signature/rsa_sig.c
test/recipes/15-test_rsapss.t
test/recipes/25-test_req.t
test/recipes/80-test_cms.t
test/smime-certs/mksmime-certs.sh
test/smime-certs/smrsa1024.pem [new file with mode: 0644]

index 0b5cdb07674ee24bce02adebbf66451152aa69f3..682a7726b383b2bcbd2dd1e3135eb9a9f70164c8 100644 (file)
@@ -85,6 +85,15 @@ OpenSSL 3.1
 
    *Tomáš Mráz*
 
+ * Change the default salt length for PKCS#1 RSASSA-PSS signatures to the
+   maximum size that is smaller or equal to the digest length to comply with
+   FIPS 186-4 section 5. This is implemented by a new option
+   `OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX` ("auto-digestmax") for the
+   `rsa_pss_saltlen` parameter, which is now the default. Signature
+   verification is not affected by this change and continues to work as before.
+
+   *Clemens Lang*
+
 OpenSSL 3.0
 -----------
 
index 61ec53d4244ca6aaf1856d0f3c45293a9bf241e9..e69a98d116c08f65fa00b42e0d95b7cb753211e6 100644 (file)
@@ -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);
index 33874bfef8a22f1ee0459a6ada919788ea70c3c4..430c36eb2a587dd100ba4e964192c0a7b7f99636 100644 (file)
@@ -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;
index 3075eaafd677d95b509339382050b01f15806c5c..9b96f42dbc9ed65153e71843a729bce3ed60c04a 100644 (file)
@@ -270,8 +270,8 @@ EVP_PKEY_CTX_get_rsa_padding() gets the RSA padding mode for I<ctx>.
 
 EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to I<saltlen>.
 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<PSS> block structure when verifying.  When signing, it has the same
 meaning as B<RSA_PSS_SALTLEN_MAX>.
 
+=item B<RSA_PSS_SALTLEN_AUTO_DIGEST_MAX>
+
+causes the salt length to be automatically determined based on the B<PSS> block
+structure when verifying, like B<RSA_PSS_SALTLEN_AUTO>.  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<ctx>.
index 1ce32cc44368118aa47d6eb140af698ebf282d2a..13d053e262a9150a586561ac7997fa0a5014e5e1 100644 (file)
@@ -68,6 +68,11 @@ Use the maximum salt length.
 
 Auto detect the salt length.
 
+=item "auto-digestmax" (B<OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX>)
+
+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
index d595248d8d3b8db719f8e7bdbefb638066225fb7..6c9bec7507e778c4d2c069252089aa3ae31a6712 100644 (file)
@@ -398,6 +398,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
index 30d84776e0dedaf58fbbfec985737ee9614e1190..d0c9599274230834cfb1ac24af6d2adff9e3bbdb 100644 (file)
@@ -140,6 +140,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
 
index 7023a866131e38c214ac7326fdd83274dab81833..bf98a9afc0e80d50c6aa3fcd25d6598ee7579a5f 100644 (file)
@@ -189,8 +189,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;
 }
@@ -198,13 +198,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);
@@ -408,8 +422,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)) {
@@ -1107,6 +1121,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",
@@ -1270,6 +1287,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;
@@ -1278,11 +1297,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;
         }
@@ -1290,6 +1309,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");
index c566ade933e9d61f364045c0f342cfb1219f82cf..e5dbab1d88d5ef98c2825e35142aa629898ddaa2 100644 (file)
@@ -16,7 +16,7 @@ use OpenSSL::Test::Utils;
 
 setup("test_rsapss");
 
-plan tests => 11;
+plan tests => 16;
 
 #using test/testrsa.pem which happens to be a 512 bit RSA
 ok(run(app(['openssl', 'dgst', '-sign', srctop_file('test', 'testrsa.pem'), '-sha1',
@@ -67,6 +67,15 @@ ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
             srctop_file('test', 'testrsa.pem')])),
    "openssl dgst -sign rsa512bit.pem -sha1 -sigopt rsa_pss_saltlen:max produces 42 bits of PSS salt");
 
+ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
+            '-sha1',
+            '-sigopt', 'rsa_padding_mode:pss',
+            '-sigopt', 'rsa_pss_saltlen:auto-digestmax',
+            '-sigopt', 'rsa_mgf1_md:sha512',
+            '-signature', 'testrsapss-restricted.sig',
+            srctop_file('test', 'testrsa.pem')])),
+   "openssl dgst -prverify rsa512bit.pem -sha1 -sigopt rsa_pss_saltlen:auto-digestmax verifies signatures with saltlen > digestlen");
+
 ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
             '-sha1',
             '-sigopt', 'rsa_padding_mode:pss',
@@ -74,6 +83,32 @@ ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
             srctop_file('test', 'testrsa.pem')])),
    "openssl dgst -prverify [plain RSA key, PSS padding mode, no PSS restrictions]");
 
+ok(run(app(['openssl', 'dgst', '-sign', srctop_file('test', 'testrsa.pem'), '-sha1',
+            '-sigopt', 'rsa_padding_mode:pss',
+            '-sigopt', 'rsa_pss_saltlen:auto-digestmax',
+            '-out', 'testrsapss-sha1-autodigestmax.sig',
+            srctop_file('test', 'testrsa.pem')])),
+   "openssl dgst -sign -sha1 -rsa_pss_saltlen:auto-digestmax");
+ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'), '-sha1',
+            '-sigopt', 'rsa_padding_mode:pss',
+            '-sigopt', 'rsa_pss_saltlen:20',
+            '-signature', 'testrsapss-sha1-autodigestmax.sig',
+            srctop_file('test', 'testrsa.pem')])),
+   "openssl dgst -sign -sha1 -rsa_padding_mode:auto-digestmax produces 20 (i.e., digestlen) bits of PSS salt");
+
+ok(run(app(['openssl', 'dgst', '-sign', srctop_file('test', 'testrsa.pem'), '-sha256',
+            '-sigopt', 'rsa_padding_mode:pss',
+            '-sigopt', 'rsa_pss_saltlen:auto-digestmax',
+            '-out', 'testrsapss-sha256-autodigestmax.sig',
+            srctop_file('test', 'testrsa.pem')])),
+   "openssl dgst -sign -sha256 -rsa_pss_saltlen:auto-digestmax");
+ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'), '-sha256',
+            '-sigopt', 'rsa_padding_mode:pss',
+            '-sigopt', 'rsa_pss_saltlen:30',
+            '-signature', 'testrsapss-sha256-autodigestmax.sig',
+            srctop_file('test', 'testrsa.pem')])),
+   "openssl dgst -sign rsa512bit.pem -sha256 -rsa_padding_mode:auto-digestmax produces 30 bits of PSS salt (due to 512bit key)");
+
 # Test that RSA-PSS keys are supported by genpkey and rsa commands.
 {
    my $rsapss = "rsapss.key";
index e615f1b338855f30f6dfa2ce823aa92516772941..35541aed12784f8049a76a1e04d4dff2ee61008c 100644 (file)
@@ -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");
 
index 4dd94b321d8e2ab88bff5de5088941399bc32bde..d0c757673d2dcd401f2409bd6f41e0c9c4ba9adb 100644 (file)
@@ -636,6 +636,34 @@ my @smime_cms_param_tests = (
     ]
 );
 
+my @smime_cms_param_tests_autodigestmax = (
+    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=auto-digestmax, digestsize < maximum salt length",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+        "-signer", $smrsa1, "-md", "sha256",
+        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:auto-digestmax",
+        "-out", "{output}.cms" ],
+      # digest is SHA-256, which produces 32, bytes of output
+      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 32; },
+      [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
+        "-CAfile", $smroot, "-out", "{output}.txt" ],
+      \&final_compare
+    ],
+
+    [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=auto-digestmax, digestsize > maximum salt length",
+      [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+        "-signer", $smrsa1024, "-md", "sha512",
+        "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:auto-digestmax",
+        "-out", "{output}.cms" ],
+      # digest is SHA-512, which produces 64, bytes of output, but an RSA-PSS
+      # signature with a 1024 bit RSA key can only accomodate 62
+      sub { my %opts = @_; rsapssSaltlen("$opts{output}.cms") == 62; },
+      [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
+        "-CAfile", $smroot, "-out", "{output}.txt" ],
+      \&final_compare
+    ]
+);
+
+
 my @contenttype_cms_test = (
     [ "signed content test - check that content type is added to additional signerinfo, RSA keys",
       [ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
@@ -733,7 +761,21 @@ subtest "CMS <=> CMS consistency tests\n" => sub {
 
 subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
     plan tests =>
-        (scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests);
+        (scalar @smime_cms_param_tests) + (scalar @smime_cms_comp_tests) +
+        (scalar @smime_cms_param_tests_autodigestmax) + 1;
+
+    ok(run(app(["openssl", "cms", @prov,
+                "-sign", "-in", $smcont,
+                "-outform", "PEM",
+                "-nodetach",
+                "-signer", $smrsa1,
+                "-keyopt", "rsa_padding_mode:pss",
+                "-keyopt", "rsa_pss_saltlen:auto-digestmax",
+                "-out", "digestmaxtest.cms"])));
+    # Providers that do not support rsa_pss_saltlen:auto-digestmax will parse
+    # it as 0
+    my $no_autodigestmax = rsapssSaltlen("digestmaxtest.cms") == 0;
+    1 while unlink "digestmaxtest.cms";
 
     runner_loop(prefix => 'cms2cms-mod', cmd1 => 'cms', cmd2 => 'cms',
                 tests => [ @smime_cms_param_tests ]);
@@ -745,6 +787,15 @@ subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub {
       runner_loop(prefix => 'cms2cms-comp', cmd1 => 'cms', cmd2 => 'cms',
                   tests => [ @smime_cms_comp_tests ]);
     }
+
+  SKIP: {
+    skip("rsa_pss_saltlen:auto-digestmax not supported",
+         scalar @smime_cms_param_tests_autodigestmax)
+       if $no_autodigestmax;
+
+       runner_loop(prefix => 'cms2cms-comp', 'cmd1' => 'cms', cmd2 => 'cms',
+                   tests => [ @smime_cms_param_tests_autodigestmax ]);
+  }
 };
 
 # Returns the number of matches of a Content Type Attribute in a binary file.
index 76766a763d0e614722ebb9dd5085d51cbd845dbf..bc9ec9bea90672843b60dd2e7ae41f80c8851436 100644 (file)
@@ -34,6 +34,11 @@ CN="Test S/MIME EE RSA #3" $OPENSSL req -config ca.cnf -noenc \
 $OPENSSL x509 -req -in req.pem -CA smroot.pem -days 36500 \
        -extfile ca.cnf -extensions usr_cert -CAcreateserial >>smrsa3.pem
 
+CN="Test S/MIME EE RSA 1024" $OPENSSL req -config ca.cnf -noenc \
+       -keyout smrsa1024.pem -out req.pem -newkey rsa:1024
+$OPENSSL x509 -req -in req.pem -CA smroot.pem -days 36500 \
+       -extfile ca.cnf -extensions usr_cert -CAcreateserial >>smrsa1024.pem
+
 # Create DSA parameters
 
 $OPENSSL dsaparam -out dsap.pem 2048
diff --git a/test/smime-certs/smrsa1024.pem b/test/smime-certs/smrsa1024.pem
new file mode 100644 (file)
index 0000000..aa58e64
--- /dev/null
@@ -0,0 +1,34 @@
+-----BEGIN PRIVATE KEY-----
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKuDWQObVMeON25c
+MY1YprdkKdZhyJ3zisFHyJ1jmXQ13aMqaBlNYzx9ECAGQTSw2De6tsJF0jpX3IHO
+X7OcZyhg8XkBdFJvJ2RsYwyghcWLvoAznCt/Pqi3m2HRgc+6FCHmh5wjK7McZ9sH
+uGGbnh+5GJzuFmcitcwlVM8d1ctZAgMBAAECgYBL04ARFiU/LGLZSa0mnmDmh0Pv
+4b8+BaP8m23YF2aKeB4Kuv7W4N3Uqj3sypcdYmnVCZku/otY++sjAEhTMfxwpexf
+JtKKfdZiE1QYQRSZROVIayTePPKsROzb4cSeB42MbNawpc5EgVazJ1dNHAjp/nQ2
+r6G7QusGW/Xiu26qWQJBAN/Yd4easmM/AdE9YpnfIWMH83SP/qyyOeaTg9fmLSlo
+gVSvoUvZqgmsA7uRPYcmDK0mFHvUTftEFuMypo5/WocCQQDEJnGkGq2h1q35uIyg
+8lvD7i8oJLU6BaCrhdqzSmKu0iZ1pgdG8K7dukydb3/wlDlc7owEaVZy97IxSnE2
+I8MfAkBeWffICMS4YI57i8xL32lLPMa5kxhd4qHVNsiT8EmI8qvQ7lamihDKEt9f
+6FBu7vLY6PwpVcuo5YJgMbFSzwtxAkBlcAws9a79luv5zLrNMQjL1o2EkRc3nlls
+2pgzSDCof/1rsiTpRubnu8SLVnIvlDfmG2dFkMQoSHhajUjm2q+5AkBDqdYuYcC5
+A+DhYRjOvFtJLvH24hpozePDEbhaZ/n9/KifGay/DM4orsP+i8MAK0tDItOcBx8q
++trNS22a/OeZ
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIC9DCCAdygAwIBAgIUM31BmU3N68LYuXEBXyetpxj6VaAwDQYJKoZIhvcNAQEL
+BQAwRDELMAkGA1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxHTAbBgNV
+BAMMFFRlc3QgUy9NSU1FIFJTQSBSb290MCAXDTIyMTIwNTEyNTUzOFoYDzIxMjIx
+MTExMTI1NTM4WjBHMQswCQYDVQQGEwJVSzEWMBQGA1UECgwNT3BlblNTTCBHcm91
+cDEgMB4GA1UEAwwXVGVzdCBTL01JTUUgRUUgUlNBIDEwMjQwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAKuDWQObVMeON25cMY1YprdkKdZhyJ3zisFHyJ1jmXQ1
+3aMqaBlNYzx9ECAGQTSw2De6tsJF0jpX3IHOX7OcZyhg8XkBdFJvJ2RsYwyghcWL
+voAznCt/Pqi3m2HRgc+6FCHmh5wjK7McZ9sHuGGbnh+5GJzuFmcitcwlVM8d1ctZ
+AgMBAAGjXTBbMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgXgMB0GA1UdDgQWBBS6
+gOltltAF44S/iXtMTCNb52A8GTAfBgNVHSMEGDAWgBQVwRMha+JVX6dqHVcg1s/z
+qXNkWTANBgkqhkiG9w0BAQsFAAOCAQEAcpJNhv+YHXKqq0gHb64a7s96Szl2sbFv
+VNuFDq2jAfxsIfhBbSfmA1+ivYsJ9E5nYxZapyW6oWuET7oCoybGlZTJoEx4YmHm
+3f9tuBJeFsbKvP4OJJAzRy3OUvrEjFrngiMPb/IoSiZOG6BC1LWPydLvDvBs614G
+2RbWeFQRalgtaBB4y1X2ohIOZAbZaacCbCAs827t3l1HoEmVJw9NSwTml0P98xyu
+icfUFiyrqHHt8JmbH+GuZngJfwmIJ0YtfwY6y0ABv7MXsRkpWeqtdSc1Zff+LrTl
+289mzFFOn/8wOb7ojhW4MQiTznIudj7ArVKHATHG6v/G1b1zdyIRow==
+-----END CERTIFICATE-----