From: Richard Levitte Date: Sun, 27 Oct 2019 14:09:26 +0000 (+0100) Subject: EVP: Add new domparams and key generation functionality X-Git-Tag: openssl-3.0.0-alpha1~279 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6292475573367434f91f7526301388d50c6d0d67;p=oweals%2Fopenssl.git EVP: Add new domparams and key generation functionality The following functions are added: EVP_PKEY_gen_set_params(), replacing the older EVP_PKEY_CTX_ctrl() EVP_PKEY_gen(), replacing both EVP_PKEY_keygen() and EVP_PKEY_paramgen() These functions are made to work together with already existing domparams and key generation functionality: EVP_PKEY_CTX_new_provided(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen_init(), etc. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/10289) --- diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 68ccdbb8ee..94be3c2a9c 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -350,3 +350,23 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection) return 1; } + +void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, + void *genctx, OSSL_CALLBACK *cb, void *cbarg) +{ + void *keydata = evp_keymgmt_gen(keymgmt, genctx, cb, cbarg); + + if (keydata != NULL) { + if (!EVP_KEYMGMT_up_ref(keymgmt)) { + evp_keymgmt_freedata(keymgmt, keydata); + return NULL; + } + + evp_keymgmt_util_clear_operation_cache(target); + target->keymgmt = keymgmt; + target->keydata = keydata; + evp_keymgmt_util_cache_keyinfo(target); + } + + return keydata; +} diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 586ffaf041..3012790cee 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1012,7 +1012,7 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) } #ifndef FIPS_MODE -static void evp_pkey_free_legacy(EVP_PKEY *x) +void evp_pkey_free_legacy(EVP_PKEY *x) { if (x->ameth != NULL) { if (x->ameth->pkey_free != NULL) diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 84149fabd7..03f1426d85 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -9,7 +9,10 @@ #include #include +#include +#include #include "internal/cryptlib.h" +#include "internal/core.h" #include #include #include "crypto/bn.h" @@ -17,102 +20,225 @@ #include "crypto/evp.h" #include "evp_local.h" -#ifndef FIPS_MODE -int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) +static int gen_init(EVP_PKEY_CTX *ctx, int operation) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; + int ret = 0; + + if (ctx == NULL) + goto not_supported; + + evp_pkey_ctx_free_old_ops(ctx); + ctx->operation = operation; + + if (ctx->engine != NULL || ctx->keytype == NULL) + goto legacy; + + if (ctx->keymgmt == NULL) { + ctx->keymgmt = + EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, ctx->propquery); + if (ctx->keymgmt == NULL + || ctx->keymgmt->gen_init == NULL) { + EVP_KEYMGMT_free(ctx->keymgmt); + ctx->keymgmt = NULL; + goto legacy; + } + } + if (ctx->keymgmt->gen_init == NULL) + goto not_supported; + + switch (operation) { + case EVP_PKEY_OP_PARAMGEN: + ctx->op.keymgmt.genctx = + evp_keymgmt_gen_init(ctx->keymgmt, + OSSL_KEYMGMT_SELECT_ALL_PARAMETERS); + break; + case EVP_PKEY_OP_KEYGEN: + ctx->op.keymgmt.genctx = + evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR); + break; + } + + if (ctx->op.keymgmt.genctx == NULL) + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + else + ret = 1; + goto end; + + legacy: +#ifdef FIPS_MODE + goto not_supported; +#else + if (ctx->pmeth == NULL + || (operation == EVP_PKEY_OP_PARAMGEN + && ctx->pmeth->paramgen == NULL) + || (operation == EVP_PKEY_OP_KEYGEN + && ctx->pmeth->keygen == NULL)) + goto not_supported; + + ret = 1; + switch (operation) { + case EVP_PKEY_OP_PARAMGEN: + if (ctx->pmeth->paramgen_init != NULL) + ret = ctx->pmeth->paramgen_init(ctx); + break; + case EVP_PKEY_OP_KEYGEN: + if (ctx->pmeth->keygen_init != NULL) + ret = ctx->pmeth->keygen_init(ctx); + break; } - ctx->operation = EVP_PKEY_OP_PARAMGEN; - if (!ctx->pmeth->paramgen_init) - return 1; - ret = ctx->pmeth->paramgen_init(ctx); +#endif + + end: if (ret <= 0) ctx->operation = EVP_PKEY_OP_UNDEFINED; return ret; + + not_supported: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto end; } -int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } + return gen_init(ctx, EVP_PKEY_OP_PARAMGEN); +} - if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED); - return -1; - } +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) +{ + return gen_init(ctx, EVP_PKEY_OP_KEYGEN); +} + +static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg) +{ + EVP_PKEY_CTX *ctx = arg; + const OSSL_PARAM *param = NULL; + int p = -1, n = -1; + + if (ctx->pkey_gencb == NULL) + return 1; /* No callback? That's fine */ + + if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL)) + == NULL + || !OSSL_PARAM_get_int(param, &p)) + return 0; + if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION)) + == NULL + || !OSSL_PARAM_get_int(param, &n)) + return 0; + + ctx->keygen_info[0] = p; + ctx->keygen_info[1] = n; + + return ctx->pkey_gencb(ctx); +} + +int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ + int ret = 0; + OSSL_CALLBACK cb; + EVP_PKEY *allocated_pkey = NULL; if (ppkey == NULL) return -1; + if (ctx == NULL) + goto not_supported; + + if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0) + goto not_initialized; + if (*ppkey == NULL) - *ppkey = EVP_PKEY_new(); + *ppkey = allocated_pkey = EVP_PKEY_new(); if (*ppkey == NULL) { - EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return -1; } - ret = ctx->pmeth->paramgen(ctx, *ppkey); + if (ctx->keymgmt == NULL) + goto legacy; + + ret = 1; + if (ctx->pkey != NULL) { + EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt; + void *keydata = + evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + + if (keydata == NULL) + goto not_supported; + ret = evp_keymgmt_gen_set_template(ctx->keymgmt, + ctx->op.keymgmt.genctx, keydata); + } + + /* + * the returned value from evp_keymgmt_util_gen() is cached in *ppkey, + * so we so not need to save it, just check it. + */ + ret = ret + && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx, + ossl_callback_to_pkey_gencb, ctx) + != NULL); + +#ifndef FIPS_MODE + /* In case |*ppkey| was originally a legacy key */ + if (ret) + evp_pkey_free_legacy(*ppkey); +#endif + + goto end; + + legacy: +#ifdef FIPS_MODE + goto not_supported; +#else + switch (ctx->operation) { + case EVP_PKEY_OP_PARAMGEN: + ret = ctx->pmeth->paramgen(ctx, *ppkey); + break; + case EVP_PKEY_OP_KEYGEN: + ret = ctx->pmeth->keygen(ctx, *ppkey); + break; + default: + goto not_supported; + } +#endif + + end: if (ret <= 0) { - EVP_PKEY_free(*ppkey); - *ppkey = NULL; + if (allocated_pkey != NULL) + *ppkey = NULL; + EVP_PKEY_free(allocated_pkey); } return ret; + + not_supported: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto end; + not_initialized: + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); + ret = -1; + goto end; } -int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) { - int ret; - if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; + if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); + return -1; } - ctx->operation = EVP_PKEY_OP_KEYGEN; - if (!ctx->pmeth->keygen_init) - return 1; - ret = ctx->pmeth->keygen_init(ctx); - if (ret <= 0) - ctx->operation = EVP_PKEY_OP_UNDEFINED; - return ret; + return EVP_PKEY_gen(ctx, ppkey); } int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) { - int ret; - - if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return -2; - } if (ctx->operation != EVP_PKEY_OP_KEYGEN) { - EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED); + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED); return -1; } - - if (ppkey == NULL) - return -1; - - if (*ppkey == NULL) - *ppkey = EVP_PKEY_new(); - if (*ppkey == NULL) - return -1; - - ret = ctx->pmeth->keygen(ctx, *ppkey); - if (ret <= 0) { - EVP_PKEY_free(*ppkey); - *ppkey = NULL; - } - return ret; + return EVP_PKEY_gen(ctx, ppkey); } void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) @@ -152,6 +278,8 @@ int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) return ctx->keygen_info[idx]; } +#ifndef FIPS_MODE + EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key, int keylen) { diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 906b08156f..f7bdbebbc1 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -292,6 +292,9 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher); ctx->op.ciph.ciphprovctx = NULL; ctx->op.ciph.cipher = NULL; + } else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) { + if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL) + evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx); } #endif } @@ -569,6 +572,12 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) && ctx->op.ciph.cipher->set_ctx_params != NULL) return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx, params); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_set_params != NULL) + return evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx, + params); return 0; } @@ -629,6 +638,10 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx) && ctx->op.ciph.cipher != NULL && ctx->op.ciph.cipher->settable_ctx_params != NULL) return ctx->op.ciph.cipher->settable_ctx_params(); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_settable_params != NULL) + return evp_keymgmt_gen_settable_params(ctx->keymgmt); return NULL; } @@ -859,6 +872,12 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype, ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; + case EVP_PKEY_CTRL_RSA_KEYGEN_BITS: + return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, p1); + case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP: + return EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, p2); + case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES: + return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1); } } return 0; @@ -878,7 +897,9 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) && ctx->op.sig.sigprovctx != NULL) || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx != NULL)) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2); if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) { @@ -979,7 +1000,9 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) && ctx->op.sig.sigprovctx != NULL) || (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx) - && ctx->op.ciph.ciphprovctx != NULL)) + && ctx->op.ciph.ciphprovctx != NULL) + || (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->op.keymgmt.genctx != NULL)) return legacy_ctrl_str_to_param(ctx, name, value); if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { diff --git a/doc/man3/EVP_PKEY_gen.pod b/doc/man3/EVP_PKEY_gen.pod new file mode 100644 index 0000000000..212ea2a742 --- /dev/null +++ b/doc/man3/EVP_PKEY_gen.pod @@ -0,0 +1,217 @@ +=pod + +=head1 NAME + +EVP_PKEY_keygen_init, EVP_PKEY_paramgen_init, EVP_PKEY_gen, +EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb, +EVP_PKEY_CTX_get_keygen_info, EVP_PKEY_CTX_set_app_data, +EVP_PKEY_CTX_get_app_data, +EVP_PKEY_gen_cb, +EVP_PKEY_paramgen, EVP_PKEY_keygen +- key and parameter generation and check functions + +=head1 SYNOPSIS + + #include + + int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + + typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); + + void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); + EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + + int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + + void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); + void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + +=head1 DESCRIPTION + +Generating keys is sometimes straight forward, just generate the key's +numbers and be done with it. However, there are certain key types that need +key parameters, often called domain parameters but not necessarily limited +to that, that also need to be generated. In addition to this, the caller +may want to set user provided generation parameters that further affect key +parameter or key generation, such as the desired key size. + +To flexibly allow all that's just been described, key parameter and key +generation is divided into an initialization of a key algorithm context, +functions to set user provided parameters, and finally the key parameter or +key generation function itself. + +The key algorithm context must be created using L or +variants thereof, see that manual for details. + +EVP_PKEY_keygen_init() initializes a public key algorithm context using key +I for a key generation operation. + +EVP_PKEY_paramgen_init() is similar to EVP_PKEY_keygen_init() except key +parameters are generated. + +After initialization, generation parameters may be provided with +L or L, or any other +function described in those manuals. + +EVP_PKEY_gen() performs the generation operation, the resulting key +parameters or key are written to I<*ppkey>. If I<*ppkey> is NULL when this +function is called, it will be allocated, and should be freed by the caller +when no longer useful, using L. + +EVP_PKEY_paramgen() and EVP_PKEY_keygen() do exactly the same thing as +EVP_PKEY_gen(), after checking that the corresponding EVP_PKEY_paramgen_init() +or EVP_PKEY_keygen_init() was used to initialize I. +These are older functions that are kept for backward compatibility. +It is safe to use EVP_PKEY_gen() instead. + +The function EVP_PKEY_set_cb() sets the key or parameter generation callback +to I. The function EVP_PKEY_CTX_get_cb() returns the key or parameter +generation callback. + +The function EVP_PKEY_CTX_get_keygen_info() returns parameters associated +with the generation operation. If I is -1 the total number of +parameters available is returned. Any non negative value returns the value of +that parameter. EVP_PKEY_CTX_gen_keygen_info() with a non-negative value for +I should only be called within the generation callback. + +If the callback returns 0 then the key generation operation is aborted and an +error occurs. This might occur during a time consuming operation where +a user clicks on a "cancel" button. + +The functions EVP_PKEY_CTX_set_app_data() and EVP_PKEY_CTX_get_app_data() set +and retrieve an opaque pointer. This can be used to set some application +defined value which can be retrieved in the callback: for example a handle +which is used to update a "progress dialog". + +=head1 RETURN VALUES + +EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and +EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure. +In particular a return value of -2 indicates the operation is not supported by +the public key algorithm. + +=head1 NOTES + +After the call to EVP_PKEY_keygen_init() or EVP_PKEY_paramgen_init() algorithm +specific control operations can be performed to set any appropriate parameters +for the operation. + +The functions EVP_PKEY_keygen() and EVP_PKEY_paramgen() can be called more than +once on the same context if several operations are performed using the same +parameters. + +The meaning of the parameters passed to the callback will depend on the +algorithm and the specific implementation of the algorithm. Some might not +give any useful information at all during key or parameter generation. Others +might not even call the callback. + +The operation performed by key or parameter generation depends on the algorithm +used. In some cases (e.g. EC with a supplied named curve) the "generation" +option merely sets the appropriate fields in an EVP_PKEY structure. + +In OpenSSL an EVP_PKEY structure containing a private key also contains the +public key components and parameters (if any). An OpenSSL private key is +equivalent to what some libraries call a "key pair". A private key can be used +in functions which require the use of a public key or parameters. + +=head1 EXAMPLES + +Generate a 2048 bit RSA key: + + #include + #include + + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey = NULL; + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (!ctx) + /* Error occurred */ + if (EVP_PKEY_keygen_init(ctx) <= 0) + /* Error */ + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0) + /* Error */ + + /* Generate key */ + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + /* Error */ + +Generate a key from a set of parameters: + + #include + #include + + EVP_PKEY_CTX *ctx; + ENGINE *eng; + EVP_PKEY *pkey = NULL, *param; + + /* Assumed param, eng are set up already */ + ctx = EVP_PKEY_CTX_new(param, eng); + if (!ctx) + /* Error occurred */ + if (EVP_PKEY_keygen_init(ctx) <= 0) + /* Error */ + + /* Generate key */ + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + /* Error */ + +Example of generation callback for OpenSSL public key implementations: + + /* Application data is a BIO to output status to */ + + EVP_PKEY_CTX_set_app_data(ctx, status_bio); + + static int genpkey_cb(EVP_PKEY_CTX *ctx) + { + char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(b, &c, 1); + (void)BIO_flush(b); + return 1; + } + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L + +=head1 HISTORY + +EVP_PKEY_keygen_init(), int EVP_PKEY_paramgen_init(), EVP_PKEY_keygen(), +EVP_PKEY_paramgen(), EVP_PKEY_gen_cb(), EVP_PKEY_CTX_set_cb(), +EVP_PKEY_CTX_get_cb(), EVP_PKEY_CTX_get_keygen_info(), +EVP_PKEY_CTX_set_app_data() and EVP_PKEY_CTX_get_app_data() were added in +OpenSSL 1.0.0. + +EVP_PKEY_gen() was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_keygen.pod deleted file mode 100644 index e326b82ffa..0000000000 --- a/doc/man3/EVP_PKEY_keygen.pod +++ /dev/null @@ -1,182 +0,0 @@ -=pod - -=head1 NAME - -EVP_PKEY_keygen_init, EVP_PKEY_keygen, EVP_PKEY_paramgen_init, -EVP_PKEY_paramgen, EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb, -EVP_PKEY_CTX_get_keygen_info, EVP_PKEY_CTX_set_app_data, -EVP_PKEY_CTX_get_app_data, -EVP_PKEY_gen_cb -- key and parameter generation and check functions - -=head1 SYNOPSIS - - #include - - int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); - int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); - int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); - int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); - - typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); - - void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); - EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); - - int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); - - void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); - void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); - -=head1 DESCRIPTION - -The EVP_PKEY_keygen_init() function initializes a public key algorithm -context using key B for a key generation operation. - -The EVP_PKEY_keygen() function performs a key generation operation, the -generated key is written to B. - -The functions EVP_PKEY_paramgen_init() and EVP_PKEY_paramgen() are similar -except parameters are generated. - -The function EVP_PKEY_set_cb() sets the key or parameter generation callback -to B. The function EVP_PKEY_CTX_get_cb() returns the key or parameter -generation callback. - -The function EVP_PKEY_CTX_get_keygen_info() returns parameters associated -with the generation operation. If B is -1 the total number of -parameters available is returned. Any non negative value returns the value of -that parameter. EVP_PKEY_CTX_gen_keygen_info() with a non-negative value for -B should only be called within the generation callback. - -If the callback returns 0 then the key generation operation is aborted and an -error occurs. This might occur during a time consuming operation where -a user clicks on a "cancel" button. - -The functions EVP_PKEY_CTX_set_app_data() and EVP_PKEY_CTX_get_app_data() set -and retrieve an opaque pointer. This can be used to set some application -defined value which can be retrieved in the callback: for example a handle -which is used to update a "progress dialog". - -=head1 NOTES - -After the call to EVP_PKEY_keygen_init() or EVP_PKEY_paramgen_init() algorithm -specific control operations can be performed to set any appropriate parameters -for the operation. - -The functions EVP_PKEY_keygen() and EVP_PKEY_paramgen() can be called more than -once on the same context if several operations are performed using the same -parameters. - -The meaning of the parameters passed to the callback will depend on the -algorithm and the specific implementation of the algorithm. Some might not -give any useful information at all during key or parameter generation. Others -might not even call the callback. - -The operation performed by key or parameter generation depends on the algorithm -used. In some cases (e.g. EC with a supplied named curve) the "generation" -option merely sets the appropriate fields in an EVP_PKEY structure. - -In OpenSSL an EVP_PKEY structure containing a private key also contains the -public key components and parameters (if any). An OpenSSL private key is -equivalent to what some libraries call a "key pair". A private key can be used -in functions which require the use of a public key or parameters. - -=head1 RETURN VALUES - -EVP_PKEY_keygen_init(), EVP_PKEY_paramgen_init(), EVP_PKEY_keygen() and -EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure. -In particular a return value of -2 indicates the operation is not supported by -the public key algorithm. - -=head1 EXAMPLES - -Generate a 2048 bit RSA key: - - #include - #include - - EVP_PKEY_CTX *ctx; - EVP_PKEY *pkey = NULL; - - ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); - if (!ctx) - /* Error occurred */ - if (EVP_PKEY_keygen_init(ctx) <= 0) - /* Error */ - if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0) - /* Error */ - - /* Generate key */ - if (EVP_PKEY_keygen(ctx, &pkey) <= 0) - /* Error */ - -Generate a key from a set of parameters: - - #include - #include - - EVP_PKEY_CTX *ctx; - ENGINE *eng; - EVP_PKEY *pkey = NULL, *param; - - /* Assumed param, eng are set up already */ - ctx = EVP_PKEY_CTX_new(param, eng); - if (!ctx) - /* Error occurred */ - if (EVP_PKEY_keygen_init(ctx) <= 0) - /* Error */ - - /* Generate key */ - if (EVP_PKEY_keygen(ctx, &pkey) <= 0) - /* Error */ - -Example of generation callback for OpenSSL public key implementations: - - /* Application data is a BIO to output status to */ - - EVP_PKEY_CTX_set_app_data(ctx, status_bio); - - static int genpkey_cb(EVP_PKEY_CTX *ctx) - { - char c = '*'; - BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; - } - -=head1 SEE ALSO - -L, -L, -L, -L, -L, -L, -L - -=head1 HISTORY - -These functions were added in OpenSSL 1.0.0. - -=head1 COPYRIGHT - -Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 42ac56a1d5..744731aefe 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -34,6 +34,10 @@ struct evp_pkey_ctx_st { EVP_KEYMGMT *keymgmt; union { + struct { + void *genctx; + } keymgmt; + struct { EVP_KEYEXCH *exchange; void *exchprovctx; @@ -50,6 +54,14 @@ struct evp_pkey_ctx_st { } ciph; } op; + /* Application specific data, usually used by the callback */ + void *app_data; + /* Keygen callback */ + EVP_PKEY_gen_cb *pkey_gencb; + /* implementation specific keygen data */ + int *keygen_info; + int keygen_info_count; + /* Legacy fields below */ /* Method associated with this operation */ @@ -62,13 +74,6 @@ struct evp_pkey_ctx_st { EVP_PKEY *peerkey; /* Algorithm specific data */ void *data; - /* Application specific data */ - void *app_data; - /* Keygen callback */ - EVP_PKEY_gen_cb *pkey_gencb; - /* implementation specific keygen data */ - int *keygen_info; - int keygen_info_count; } /* EVP_PKEY_CTX */ ; #define EVP_PKEY_FLAG_DYNAMIC 1 @@ -596,6 +601,10 @@ struct evp_pkey_st { ((ctx)->operation == EVP_PKEY_OP_ENCRYPT \ || (ctx)->operation == EVP_PKEY_OP_DECRYPT) +#define EVP_PKEY_CTX_IS_GEN_OP(ctx) \ + ((ctx)->operation == EVP_PKEY_OP_PARAMGEN \ + || (ctx)->operation == EVP_PKEY_OP_KEYGEN) + void openssl_add_all_ciphers_int(void); void openssl_add_all_digests_int(void); void evp_cleanup_int(void); @@ -606,6 +615,9 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, EVP_KEYMGMT **keymgmt, const char *propquery); +#ifndef FIPS_MODE +void evp_pkey_free_legacy(EVP_PKEY *x); +#endif /* * KEYMGMT utility functions @@ -622,6 +634,8 @@ void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, int evp_keymgmt_util_has(EVP_PKEY *pk, int selection); int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection); int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection); +void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, + void *genctx, OSSL_CALLBACK *cb, void *cbarg); /* diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 5e3a13a34b..e2639ec1fc 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -220,6 +220,9 @@ extern "C" { #define OSSL_PKEY_PARAM_RSA_FACTOR "rsa-factor" #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_PRIMES "primes" /* Key Exchange parameters */ @@ -279,6 +282,10 @@ extern "C" { /* Passphrase callback parameters */ #define OSSL_PASSPHRASE_PARAM_INFO "info" +/* Keygen callback parameters, from provider to libcrypto */ +#define OSSL_GEN_PARAM_POTENTIAL "potential" /* integer */ +#define OSSL_GEN_PARAM_ITERATION "iteration" /* integer */ + # ifdef __cplusplus } # endif diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 202675cc70..a3e0581913 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1596,6 +1596,7 @@ int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); int EVP_PKEY_check(EVP_PKEY_CTX *ctx); int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx); int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); diff --git a/util/libcrypto.num b/util/libcrypto.num index 15dd512a49..9c9213aff4 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4980,3 +4980,4 @@ OSSL_CMP_SRV_CTX_set_send_unprotected_errors ? 3_0_0 EXIST::FUNCTION:CMP 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: