PROV: Add RSA functionality for key generation
authorRichard Levitte <levitte@openssl.org>
Sun, 27 Oct 2019 14:28:29 +0000 (15:28 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 12 Mar 2020 09:44:02 +0000 (10:44 +0100)
This includes added support in legacy controls

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10289)

crypto/evp/pmeth_lib.c
crypto/rsa/rsa_lib.c
include/openssl/core_names.h
include/openssl/rsa.h
providers/implementations/keymgmt/rsa_kmgmt.c
util/libcrypto.num

index f7bdbebbc170b51df5fbca5ee0a85593e0b35029..a81908a9626ba3dff1dc0a78be938463006a9b4f 100644 (file)
@@ -951,6 +951,12 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
         name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL;
     else if (strcmp(name, "rsa_pss_saltlen") == 0)
         name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN;
+    else if (strcmp(name, "rsa_keygen_bits") == 0)
+        name = OSSL_PKEY_PARAM_RSA_BITS;
+    else if (strcmp(name, "rsa_keygen_pubexp") == 0)
+        name = OSSL_PKEY_PARAM_RSA_E;
+    else if (strcmp(name, "rsa_keygen_primes") == 0)
+        name = OSSL_PKEY_PARAM_RSA_PRIMES;
 # ifndef OPENSSL_NO_DH
     else if (strcmp(name, "dh_pad") == 0)
         name = OSSL_EXCHANGE_PARAM_PAD;
index ada5388bb2e59d6eba1ab9b196562e7fa9492401..0a0d3e84db4b52cd1ce6673f99d168d4fa295142 100644 (file)
@@ -20,6 +20,7 @@
 #include <openssl/evp.h>
 #include "internal/cryptlib.h"
 #include "internal/refcount.h"
+#include "internal/param_build.h"
 #include "crypto/bn.h"
 #include "crypto/evp.h"
 #include "crypto/rsa.h"
@@ -1266,4 +1267,94 @@ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen)
     return 1;
 
 }
+
+int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits)
+{
+    OSSL_PARAM params[2], *p = params;
+    size_t bits2 = bits;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        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)
+        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, EVP_PKEY_OP_KEYGEN,
+                                 EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL);
+
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &bits2);
+    *p++ = OSSL_PARAM_construct_end();
+
+    if (!EVP_PKEY_CTX_set_params(ctx, params))
+        return 0;
+
+    return 1;
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp)
+{
+    OSSL_PARAM_BLD tmpl;
+    OSSL_PARAM *params;
+    int ret;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        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)
+        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, EVP_PKEY_OP_KEYGEN,
+                                 EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp);
+
+    ossl_param_bld_init(&tmpl);
+    if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_RSA_E, pubexp)
+        || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
+        return 0;
+
+    ret = EVP_PKEY_CTX_set_params(ctx, params);
+    ossl_param_bld_free(params);
+    return ret;
+}
+
+int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes)
+{
+    OSSL_PARAM params[2], *p = params;
+    size_t primes2 = primes;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
+        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)
+        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, EVP_PKEY_OP_KEYGEN,
+                                 EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes,
+                                 NULL);
+
+    *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, &primes2);
+    *p++ = OSSL_PARAM_construct_end();
+
+    if (!EVP_PKEY_CTX_set_params(ctx, params))
+        return 0;
+
+    return 1;
+}
 #endif
index e2639ec1fcbb38012ff9e45cde63e00e1335de79..1f67475a9ae738e6537caf9fc452307c04802c07 100644 (file)
@@ -221,7 +221,7 @@ extern "C" {
 #define OSSL_PKEY_PARAM_RSA_EXPONENT    "rsa-exponent"
 #define OSSL_PKEY_PARAM_RSA_COEFFICIENT "rsa-coefficient"
 /* Key generation parameters */
-#define OSSL_PKEY_PARAM_RSA_BITS        "bits"
+#define OSSL_PKEY_PARAM_RSA_BITS        OSSL_PKEY_PARAM_BITS
 #define OSSL_PKEY_PARAM_RSA_PRIMES      "primes"
 
 /* Key Exchange parameters */
index 1f0687df242ccb47aa79859a1b91871ee1c1e45a..49040bf7e689782867e933564a574bbef4951813 100644 (file)
@@ -111,6 +111,10 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode);
 int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
 int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
 
+int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits);
+int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
+int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
+
 /* Salt length matches digest */
 #  define RSA_PSS_SALTLEN_DIGEST -1
 /* Verify only: auto detect salt length */
@@ -124,18 +128,6 @@ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
         EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
                           EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
 
-#  define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
-        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
-                          EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
-
-#  define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \
-        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
-                          EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
-
-#  define EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, primes) \
-        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
-                          EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, primes, NULL)
-
 int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
 int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
                                       const char *mdprops);
index 8c7673ad492e2218df15fe7bd61c041754cd531a..4e77f5c4a79d368afe36ff168ad8d4a4fbd85482 100644 (file)
 #include "crypto/rsa.h"
 
 static OSSL_OP_keymgmt_new_fn rsa_newdata;
+static OSSL_OP_keymgmt_gen_init_fn rsa_gen_init;
+static OSSL_OP_keymgmt_gen_set_params_fn rsa_gen_set_params;
+static OSSL_OP_keymgmt_gen_settable_params_fn rsa_gen_settable_params;
+static OSSL_OP_keymgmt_gen_fn rsa_gen;
+static OSSL_OP_keymgmt_gen_cleanup_fn rsa_gen_cleanup;
 static OSSL_OP_keymgmt_free_fn rsa_freedata;
 static OSSL_OP_keymgmt_get_params_fn rsa_get_params;
 static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params;
@@ -409,8 +414,127 @@ static int rsa_validate(void *keydata, int selection)
     return ok;
 }
 
+struct rsa_gen_ctx {
+    OPENSSL_CTX *libctx;
+
+    size_t nbits;
+    BIGNUM *pub_exp;
+    size_t primes;
+
+    /* For generation callback */
+    OSSL_CALLBACK *cb;
+    void *cbarg;
+};
+
+static int rsa_gencb(int p, int n, BN_GENCB *cb)
+{
+    struct rsa_gen_ctx *gctx = BN_GENCB_get_arg(cb);
+    OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+
+    params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
+    params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
+
+    return gctx->cb(params, gctx->cbarg);
+}
+
+static void *rsa_gen_init(void *provctx, int selection)
+{
+    OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+    struct rsa_gen_ctx *gctx = NULL;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+        return NULL;
+
+    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
+        gctx->libctx = libctx;
+        if ((gctx->pub_exp = BN_new()) == NULL
+            || !BN_set_word(gctx->pub_exp, RSA_F4)) {
+            BN_free(gctx->pub_exp);
+            gctx = NULL;
+        } else {
+            gctx->nbits = 2048;
+            gctx->primes = RSA_DEFAULT_PRIME_NUM;
+        }
+    }
+    return gctx;
+}
+
+static int rsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
+{
+    struct rsa_gen_ctx *gctx = genctx;
+    const OSSL_PARAM *p;
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_BITS)) != NULL
+        && !OSSL_PARAM_get_size_t(p, &gctx->nbits))
+        return 0;
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_PRIMES)) != NULL
+        && !OSSL_PARAM_get_size_t(p, &gctx->primes))
+        return 0;
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E)) != NULL
+        && !OSSL_PARAM_get_BN(p, &gctx->pub_exp))
+        return 0;
+    return 1;
+}
+
+static const OSSL_PARAM *rsa_gen_settable_params(void *provctx)
+{
+    static OSSL_PARAM settable[] = {
+        OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_BITS, NULL),
+        OSSL_PARAM_size_t(OSSL_PKEY_PARAM_RSA_PRIMES, NULL),
+        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_E, NULL, 0),
+        OSSL_PARAM_END
+    };
+
+    return settable;
+}
+
+static void *rsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+    struct rsa_gen_ctx *gctx = genctx;
+    RSA *rsa = NULL;
+    BN_GENCB *gencb = NULL;
+
+    if (gctx == NULL
+        || (rsa = rsa_new_with_ctx(gctx->libctx)) == NULL)
+        return NULL;
+
+    gctx->cb = osslcb;
+    gctx->cbarg = cbarg;
+    gencb = BN_GENCB_new();
+    if (gencb != NULL)
+        BN_GENCB_set(gencb, rsa_gencb, genctx);
+
+    if (!RSA_generate_multi_prime_key(rsa, (int)gctx->nbits, (int)gctx->primes,
+                                      gctx->pub_exp, gencb)) {
+        RSA_free(rsa);
+        rsa = NULL;
+    }
+
+    BN_GENCB_free(gencb);
+
+    return rsa;
+}
+
+static void rsa_gen_cleanup(void *genctx)
+{
+    struct rsa_gen_ctx *gctx = genctx;
+
+    if (gctx == NULL)
+        return;
+
+    BN_clear_free(gctx->pub_exp);
+    OPENSSL_free(gctx);
+}
+
 const OSSL_DISPATCH rsa_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))rsa_newdata },
+    { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))rsa_gen_init },
+    { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
+      (void (*)(void))rsa_gen_set_params },
+    { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
+      (void (*)(void))rsa_gen_settable_params },
+    { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))rsa_gen },
+    { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))rsa_gen_cleanup },
     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))rsa_freedata },
     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
index 9c9213aff425f0aa85f19b0a92d1c7dfea0cd2e2..30978d2fb0a0e28d2588f97fdede8a281c857066 100644 (file)
@@ -4981,3 +4981,6 @@ OSSL_CMP_SRV_CTX_set_accept_unprotected ? 3_0_0   EXIST::FUNCTION:CMP
 OSSL_CMP_SRV_CTX_set_accept_raverified  ?      3_0_0   EXIST::FUNCTION:CMP
 OSSL_CMP_SRV_CTX_set_grant_implicit_confirm ?  3_0_0   EXIST::FUNCTION:CMP
 EVP_PKEY_gen                            ?      3_0_0   EXIST::FUNCTION:
+EVP_PKEY_CTX_set_rsa_keygen_bits        ?      3_0_0   EXIST::FUNCTION:RSA
+EVP_PKEY_CTX_set_rsa_keygen_pubexp      ?      3_0_0   EXIST::FUNCTION:RSA
+EVP_PKEY_CTX_set_rsa_keygen_primes      ?      3_0_0   EXIST::FUNCTION:RSA