PROV: Add RSA functionality for key generation

This includes added support in legacy controls

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10289)
This commit is contained in:
Richard Levitte 2019-10-27 15:28:29 +01:00
parent 6292475573
commit 2972af109e
6 changed files with 229 additions and 13 deletions

View 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;

View 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

View 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 */

View 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);

View File

@ -28,6 +28,11 @@
#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 },

View 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