X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=providers%2Fimplementations%2Fkeymgmt%2Frsa_kmgmt.c;h=4e77f5c4a79d368afe36ff168ad8d4a4fbd85482;hb=2972af109e10c5ce30e548190e3eee28327d6043;hp=aaa9815aa94ec65ba1a29ae7536f2142ba8fe9a2;hpb=29be60235b9bf86bb38f28349b405bb112250d4b;p=oweals%2Fopenssl.git diff --git a/providers/implementations/keymgmt/rsa_kmgmt.c b/providers/implementations/keymgmt/rsa_kmgmt.c index aaa9815aa9..4e77f5c4a7 100644 --- a/providers/implementations/keymgmt/rsa_kmgmt.c +++ b/providers/implementations/keymgmt/rsa_kmgmt.c @@ -7,17 +7,46 @@ * https://www.openssl.org/source/license.html */ +/* + * RSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include #include +#include #include +#include #include #include +#include "internal/param_build.h" #include "prov/implementations.h" +#include "prov/providercommon.h" +#include "prov/provider_ctx.h" #include "crypto/rsa.h" -static OSSL_OP_keymgmt_importkey_fn rsa_importkey; -static OSSL_OP_keymgmt_exportkey_fn rsa_exportkey; +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; +static OSSL_OP_keymgmt_has_fn rsa_has; +static OSSL_OP_keymgmt_match_fn rsa_match; +static OSSL_OP_keymgmt_validate_fn rsa_validate; +static OSSL_OP_keymgmt_import_fn rsa_import; +static OSSL_OP_keymgmt_import_types_fn rsa_import_types; +static OSSL_OP_keymgmt_export_fn rsa_export; +static OSSL_OP_keymgmt_export_types_fn rsa_export_types; + +#define RSA_DEFAULT_MD "SHA256" +#define RSA_POSSIBLE_SELECTIONS \ + (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) DEFINE_STACK_OF(BIGNUM) DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM) @@ -96,10 +125,9 @@ static int params_to_key(RSA *rsa, const OSSL_PARAM params[]) return 0; } -static int export_numbers(OSSL_PARAM params[], const char *key, +static int export_numbers(OSSL_PARAM_BLD *tmpl, const char *key, STACK_OF(BIGNUM_const) *numbers) { - OSSL_PARAM *p = NULL; int i, nnum; if (numbers == NULL) @@ -107,24 +135,18 @@ static int export_numbers(OSSL_PARAM params[], const char *key, nnum = sk_BIGNUM_const_num(numbers); - for (p = params, i = 0; - i < nnum && (p = OSSL_PARAM_locate(p, key)) != NULL; - p++, i++) { - if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(numbers, i))) + for (i = 0; i < nnum; i++) { + if (!ossl_param_bld_push_BN(tmpl, key, + sk_BIGNUM_const_value(numbers, i))) return 0; } - /* - * If we didn't export the amount of numbers we have, the caller didn't - * specify enough OSSL_PARAM entries named |key|. - */ - return i == nnum; + return 1; } -static int key_to_params(RSA *rsa, OSSL_PARAM params[]) +static int key_to_params(RSA *rsa, OSSL_PARAM_BLD *tmpl) { int ret = 0; - OSSL_PARAM *p; const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL; STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); @@ -136,19 +158,19 @@ static int key_to_params(RSA *rsa, OSSL_PARAM params[]) RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); rsa_get0_all_params(rsa, factors, exps, coeffs); - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_N)) != NULL - && !OSSL_PARAM_set_BN(p, rsa_n)) + if (rsa_n != NULL + && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, rsa_n)) goto err; - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_E)) != NULL - && !OSSL_PARAM_set_BN(p, rsa_e)) + if (rsa_e != NULL + && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, rsa_e)) goto err; - if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_D)) != NULL - && !OSSL_PARAM_set_BN(p, rsa_d)) + if (rsa_d != NULL + && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, rsa_d)) goto err; - if (!export_numbers(params, OSSL_PKEY_PARAM_RSA_FACTOR, factors) - || !export_numbers(params, OSSL_PKEY_PARAM_RSA_EXPONENT, exps) - || !export_numbers(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs)) + if (!export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR, factors) + || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT, exps) + || !export_numbers(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT, coeffs)) goto err; ret = 1; @@ -159,23 +181,90 @@ static int key_to_params(RSA *rsa, OSSL_PARAM params[]) return ret; } -static void *rsa_importkey(void *provctx, const OSSL_PARAM params[]) +static void *rsa_newdata(void *provctx) { - RSA *rsa; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx); - if ((rsa = RSA_new()) == NULL - || !params_to_key(rsa, params)) { - RSA_free(rsa); - rsa = NULL; - } - return rsa; + return rsa_new_with_ctx(libctx); } -static int rsa_exportkey(void *key, OSSL_PARAM params[]) +static void rsa_freedata(void *keydata) { - RSA *rsa = key; + RSA_free(keydata); +} - return rsa != NULL && key_to_params(rsa, params); +static int rsa_has(void *keydata, int selection) +{ + RSA *rsa = keydata; + int ok = 0; + + if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) + ok = 1; + + ok = ok && (RSA_get0_e(rsa) != NULL); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = ok && (RSA_get0_n(rsa) != NULL); + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ok = ok && (RSA_get0_d(rsa) != NULL); + return ok; +} + +static int rsa_match(const void *keydata1, const void *keydata2, int selection) +{ + const RSA *rsa1 = keydata1; + const RSA *rsa2 = keydata2; + int ok = 1; + + /* There is always an |e| */ + ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0; + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = ok && BN_cmp(RSA_get0_n(rsa1), RSA_get0_n(rsa2)) == 0; + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ok = ok && BN_cmp(RSA_get0_d(rsa1), RSA_get0_d(rsa2)) == 0; + return ok; +} + +static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[]) +{ + RSA *rsa = keydata; + int ok = 1; + + if (rsa == NULL) + return 0; + + /* TODO(3.0) PSS and OAEP should bring on parameters */ + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + ok = ok && params_to_key(rsa, params); + + return ok; +} + +static int rsa_export(void *keydata, int selection, + OSSL_CALLBACK *param_callback, void *cbarg) +{ + RSA *rsa = keydata; + OSSL_PARAM_BLD tmpl; + OSSL_PARAM *params = NULL; + int ok = 1; + + if (rsa == NULL) + return 0; + + /* TODO(3.0) PSS and OAEP should bring on parameters */ + + ossl_param_bld_init(&tmpl); + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + ok = ok && key_to_params(rsa, &tmpl); + + if (!ok + || (params = ossl_param_bld_to_param(&tmpl)) == NULL) + return 0; + + ok = param_callback(params, cbarg); + ossl_param_bld_free(params); + return ok; } /* @@ -229,21 +318,232 @@ static const OSSL_PARAM rsa_key_types[] = { * so we at least pretend to have some limits. */ -static const OSSL_PARAM *rsa_exportkey_types(void) +static const OSSL_PARAM *rsa_imexport_types(int selection) +{ + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) + return rsa_key_types; + return NULL; +} + +static const OSSL_PARAM *rsa_import_types(int selection) +{ + return rsa_imexport_types(selection); +} + + +static const OSSL_PARAM *rsa_export_types(int selection) { - return rsa_key_types; + return rsa_imexport_types(selection); } -static const OSSL_PARAM *rsa_importkey_types(void) +static int rsa_get_params(void *key, OSSL_PARAM params[]) { - return rsa_key_types; + RSA *rsa = key; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL + && !OSSL_PARAM_set_int(p, RSA_bits(rsa))) + return 0; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL + && !OSSL_PARAM_set_int(p, RSA_security_bits(rsa))) + return 0; + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL + && !OSSL_PARAM_set_int(p, RSA_size(rsa))) + return 0; + +# if 0 /* TODO(3.0): PSS support pending */ + if ((p = OSSL_PARAM_locate(params, + OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL + && RSA_get0_pss_params(rsa) != NULL) { + const EVP_MD *md, *mgf1md; + int min_saltlen; + + if (!rsa_pss_get_param(RSA_get0_pss_params(rsa), + &md, &mgf1md, &min_saltlen)) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return 0; + } + if (!OSSL_PARAM_set_utf8_string(p, EVP_MD_name(md))) + return 0; + } +#endif + if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL +/* TODO(3.0): PSS support pending */ +#if 0 + && RSA_get0_pss_params(rsa) == NULL +#endif + ) { + if (!OSSL_PARAM_set_utf8_string(p, RSA_DEFAULT_MD)) + return 0; + } + + return 1; +} + +static const OSSL_PARAM rsa_params[] = { + OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), + OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), + OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *rsa_gettable_params(void) +{ + return rsa_params; +} + +static int rsa_validate(void *keydata, int selection) +{ + RSA *rsa = keydata; + int ok = 0; + + if ((selection & RSA_POSSIBLE_SELECTIONS) != 0) + ok = 1; + + /* If the whole key is selected, we do a pairwise validation */ + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) + == OSSL_KEYMGMT_SELECT_KEYPAIR) { + ok = ok && rsa_validate_pairwise(rsa); + } else { + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + ok = ok && rsa_validate_private(rsa); + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) + ok = ok && rsa_validate_public(rsa); + } + 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_IMPORTKEY, (void (*)(void))rsa_importkey }, - { OSSL_FUNC_KEYMGMT_IMPORTKEY_TYPES, (void (*)(void))rsa_importkey_types }, - { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))rsa_exportkey }, - { OSSL_FUNC_KEYMGMT_EXPORTKEY_TYPES, (void (*)(void))rsa_exportkey_types }, - { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))RSA_free }, + { 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 }, + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has }, + { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match }, + { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate }, + { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import }, + { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types }, + { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))rsa_export }, + { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))rsa_export_types }, { 0, NULL } };