EVP: fix keygen for EVP_PKEY_RSA_PSS
authorDaniel Bevenius <daniel.bevenius@gmail.com>
Fri, 9 Oct 2020 04:07:43 +0000 (06:07 +0200)
committerTomas Mraz <tomas@openssl.org>
Thu, 28 Jan 2021 15:25:16 +0000 (16:25 +0100)
This commit attempts to fix the an issue when generating a key of type
EVP_PKEY_RSA_PSS. Currently, EVP_PKEY_CTX_set_rsa_keygen_bits will
return -1 if the key id is not of type EVP_PKEY_RSA. This commit adds
EVP_PKEY_RSA_PSS to also be accepted.

The macro EVP_PKEY_CTX_set_rsa_pss_keygen_md si converted into a
function and it is now called in legacy_ctrl_to_param.

Fixes #12384

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13099)

crypto/evp/pmeth_lib.c
crypto/rsa/rsa_lib.c
doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_md.pod
include/openssl/core_names.h
include/openssl/rsa.h
test/evp_extra_test.c
util/libcrypto.num

index 7c2e6482099df73bd61184df9068f3dcaa1eb733..7fb32df86ad82fd7e1a0d28d8c29fbf70a572952 100644 (file)
@@ -1315,6 +1315,14 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
             return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1);
         }
     }
+
+    if (keytype == EVP_PKEY_RSA_PSS) {
+      switch(cmd) {
+        case EVP_PKEY_CTRL_MD:
+          return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, p2);
+      }
+    }
+
     /*
      * keytype == -1 is used when several key types share the same structure,
      * or for generic controls that are the same across multiple key types.
index da0fd4a6ebd3b90564a63bbf2c98035c39b8d606..6ca4f3a5414359e25a21cfda0c3520934ad8f1fa 100644 (file)
@@ -902,6 +902,70 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode)
 
 }
 
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+    const char *name;
+
+    if (ctx == NULL || md == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* If key type not RSA return error */
+    if (ctx->pmeth != NULL
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+        return -1;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.keymgmt.genctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
+                                 EVP_PKEY_CTRL_MD, 0, (void *)md);
+
+    name = EVP_MD_name(md);
+
+    return EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(ctx, name, NULL);
+}
+
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+                                            const char *mdname,
+                                            const char *mdprops)
+{
+    OSSL_PARAM rsa_params[3], *p = rsa_params;
+
+    if (ctx == NULL || mdname == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* If key type not RSA return error */
+    if (ctx->pmeth != NULL
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+        return -1;
+
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_RSA_DIGEST,
+                                            /*
+                                             * Cast away the const. This is read
+                                             * only so should be safe
+                                             */
+                                            (char *)mdname, 0);
+    if (mdprops != NULL) {
+        *p++ = OSSL_PARAM_construct_utf8_string(
+                    OSSL_PKEY_PARAM_RSA_DIGEST_PROPS,
+                    /*
+                     * Cast away the const. This is read only so should be safe
+                     */
+                    (char *)mdprops, 0);
+    }
+    *p++ = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, rsa_params);
+}
+
 int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
 {
     const char *name;
@@ -1332,7 +1396,8 @@ int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits)
     }
 
     /* If key type not RSA return error */
-    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA)
+    if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_RSA &&
+        ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
         return -1;
 
     /* TODO(3.0): Remove this eventually when no more legacy */
index 1407c8f71a9f7063973ecf3e758afc70f4d3ae85..b842dcbd6237dac819d240242ec5ff5ad715cee8 100644 (file)
@@ -3,6 +3,7 @@
 =head1 NAME
 
 EVP_PKEY_CTX_set_rsa_pss_keygen_md,
+EVP_PKEY_CTX_set_rsa_pss_keygen_md_name,
 EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md,
 EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name,
 EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen
@@ -14,6 +15,9 @@ EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen
 
  int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *pctx,
                                         const EVP_MD *md);
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+                                             const char *mdname,
+                                             const char *mdprops);
  int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *pctx,
                                              const EVP_MD *md);
  int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *pctx,
@@ -59,6 +63,8 @@ when (for example) a certificate request is signed.
 
 EVP_PKEY_CTX_set_rsa_pss_keygen_md() restricts the digest algorithm the
 generated key can use to I<md>.
+EVP_PKEY_CTX_set_rsa_pss_keygen_md_name() does the same thing, but
+passes the algorithm by name rather than by B<EVP_MD>.
 
 EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md() restricts the MGF1 algorithm the
 generated key can use to I<md>.
index f579e7df3345e1c41bda8018b28c96ab40779137..07b95e043b8b4a7ad0575419a6b17cda067a158b 100644 (file)
@@ -385,13 +385,13 @@ extern "C" {
 #define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO   "auto"
 
 /* Key generation parameters */
-#define OSSL_PKEY_PARAM_RSA_BITS            OSSL_PKEY_PARAM_BITS
-#define OSSL_PKEY_PARAM_RSA_PRIMES          "primes"
-#define OSSL_PKEY_PARAM_RSA_DIGEST          OSSL_PKEY_PARAM_DIGEST
-#define OSSL_PKEY_PARAM_RSA_DIGEST_PROPS    OSSL_PKEY_PARAM_PROPERTIES
-#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC     OSSL_PKEY_PARAM_MASKGENFUNC
-#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST     OSSL_PKEY_PARAM_MGF1_DIGEST
-#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN     "saltlen"
+#define OSSL_PKEY_PARAM_RSA_BITS             OSSL_PKEY_PARAM_BITS
+#define OSSL_PKEY_PARAM_RSA_PRIMES           "primes"
+#define OSSL_PKEY_PARAM_RSA_DIGEST           OSSL_PKEY_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_RSA_DIGEST_PROPS     OSSL_PKEY_PARAM_PROPERTIES
+#define OSSL_PKEY_PARAM_RSA_MASKGENFUNC      OSSL_PKEY_PARAM_MASKGENFUNC
+#define OSSL_PKEY_PARAM_RSA_MGF1_DIGEST      OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_PKEY_PARAM_RSA_PSS_SALTLEN      "saltlen"
 
 /* Key generation parameters */
 #define OSSL_PKEY_PARAM_FFC_TYPE         "type"
index 82f4a9adbafb4aa73e1bd9b8d9c2b536c5cebfc6..46cc9badec118eefddc03ca9c52b78463368a396 100644 (file)
@@ -150,6 +150,11 @@ int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
 int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md_name(EVP_PKEY_CTX *ctx,
                                                  const char *mdname);
 
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
+int EVP_PKEY_CTX_set_rsa_pss_keygen_md_name(EVP_PKEY_CTX *ctx,
+                                            const char *mdname,
+                                            const char *mdprops);
+
 int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
 int EVP_PKEY_CTX_set_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
                                       const char *mdprops);
@@ -159,12 +164,6 @@ int EVP_PKEY_CTX_get_rsa_oaep_md_name(EVP_PKEY_CTX *ctx, char *name,
 int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen);
 int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label);
 
-# define  EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS,  \
-                          EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD,  \
-                          0, (void *)(md))
-
-
 # define EVP_PKEY_CTRL_RSA_PADDING       (EVP_PKEY_ALG_CTRL + 1)
 # define EVP_PKEY_CTRL_RSA_PSS_SALTLEN   (EVP_PKEY_ALG_CTRL + 2)
 
index 2ef16bc07c4b6030ddf320a3a6ab2cf1554e1a51..6cca821cf1f517628a2416fb3b98fccb48e9305a 100644 (file)
@@ -29,6 +29,7 @@
 #include <openssl/dh.h>
 #include <openssl/aes.h>
 #include <openssl/decoder.h>
+#include <openssl/rsa.h>
 #include "testutil.h"
 #include "internal/nelem.h"
 #include "internal/sizes.h"
@@ -2256,6 +2257,31 @@ err:
     return ret;
 }
 
+static int test_EVP_rsa_pss_with_keygen_bits(void)
+{
+    int ret;
+    OSSL_PROVIDER *provider;
+    EVP_PKEY_CTX *ctx;
+    EVP_PKEY *pkey;
+    const EVP_MD *md;
+    pkey = NULL;
+    ret = 0;
+    provider = OSSL_PROVIDER_load(NULL, "default");
+    md = EVP_get_digestbyname("sha256");
+
+    ret = TEST_ptr((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL)))
+        && TEST_true(EVP_PKEY_keygen_init(ctx))
+        && TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 512), 0)
+        && TEST_true(EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md))
+        && TEST_true(EVP_PKEY_keygen(ctx, &pkey));
+
+    EVP_PKEY_free(pkey);
+    EVP_PKEY_CTX_free(ctx);
+    OSSL_PROVIDER_unload(provider);
+    return ret;
+}
+
+
 int setup_tests(void)
 {
     testctx = OSSL_LIB_CTX_new();
@@ -2321,6 +2347,7 @@ int setup_tests(void)
 
     ADD_TEST(test_rand_agglomeration);
     ADD_ALL_TESTS(test_evp_iv, 10);
+    ADD_TEST(test_EVP_rsa_pss_with_keygen_bits);
 
     return 1;
 }
index 509c694d698928f892ca6d441e809f12fdcb68d7..f5195183956edfa93b9b508d3293939cd16d4cee 100644 (file)
@@ -5287,6 +5287,8 @@ PEM_write_bio_PUBKEY_ex                 ? 3_0_0   EXIST::FUNCTION:
 EVP_PKEY_get_group_name                 ?      3_0_0   EXIST::FUNCTION:
 CRYPTO_atomic_or                        ?      3_0_0   EXIST::FUNCTION:
 CRYPTO_atomic_load                      ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_set_rsa_pss_keygen_md      ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_set_rsa_pss_keygen_md_name ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_settable_params                ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_set_params                     ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_set_int_param                  ?      3_0_0   EXIST::FUNCTION: