diff options
Diffstat (limited to 'crypto/evp')
-rw-r--r-- | crypto/evp/evp_err.c | 1 | ||||
-rw-r--r-- | crypto/evp/evp_lib.c | 134 | ||||
-rw-r--r-- | crypto/evp/evp_locl.h | 2 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 71 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 2 |
5 files changed, 45 insertions, 165 deletions
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index d517099053..92df593821 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -95,6 +95,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "no key set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "no operation set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ONLY_ONESHOT_SUPPORTED), diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 0825c102b5..9091f8b475 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -760,137 +760,3 @@ int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen), OPENSSL_free(bin); return rv; } - -#ifndef FIPS_MODE -# ifndef OPENSSL_NO_DH -/* - * TODO(3.0): Temporarily unavailable in FIPS mode. This will need to be added - * in later. - */ - -# define MAX_PARAMS 10 -typedef struct { - /* Number of the current param */ - size_t curr; - struct { - /* Key for the current param */ - const char *key; - /* Value for the current param */ - const BIGNUM *bnparam; - /* Size of the buffer required for the BN */ - size_t bufsz; - } params[MAX_PARAMS]; - /* Running count of the total size required */ - size_t totsz; - int ispublic; -} PARAMS_TEMPLATE; - -static int push_param_bn(PARAMS_TEMPLATE *tmpl, const char *key, - const BIGNUM *bn) -{ - int sz; - - sz = BN_num_bytes(bn); - if (sz <= 0) - return 0; - tmpl->params[tmpl->curr].key = key; - tmpl->params[tmpl->curr].bnparam = bn; - tmpl->params[tmpl->curr++].bufsz = (size_t)sz; - tmpl->totsz += sizeof(OSSL_PARAM) + (size_t)sz; - - return 1; -} - -static OSSL_PARAM *param_template_to_param(PARAMS_TEMPLATE *tmpl, size_t *sz) -{ - size_t i; - void *buf; - OSSL_PARAM *param = NULL; - unsigned char *currbuf = NULL; - - if (tmpl->totsz == 0) - return NULL; - - /* Add some space for the end of OSSL_PARAM marker */ - tmpl->totsz += sizeof(*param); - - if (tmpl->ispublic) - buf = OPENSSL_zalloc(tmpl->totsz); - else - buf = OPENSSL_secure_zalloc(tmpl->totsz); - if (buf == NULL) - return NULL; - param = buf; - - currbuf = (unsigned char *)buf + (sizeof(*param) * (tmpl->curr + 1)); - - for (i = 0; i < tmpl->curr; i++) { - if (!ossl_assert((currbuf - (unsigned char *)buf ) - + tmpl->params[i].bufsz <= tmpl->totsz)) - goto err; - if (BN_bn2nativepad(tmpl->params[i].bnparam, currbuf, - tmpl->params[i].bufsz) < 0) - goto err; - param[i] = OSSL_PARAM_construct_BN(tmpl->params[i].key, currbuf, - tmpl->params[i].bufsz); - currbuf += tmpl->params[i].bufsz; - } - param[i] = OSSL_PARAM_construct_end(); - - if (sz != NULL) - *sz = tmpl->totsz; - return param; - - err: - if (tmpl->ispublic) - OPENSSL_free(param); - else - OPENSSL_clear_free(param, tmpl->totsz); - return NULL; -} - -static OSSL_PARAM *evp_pkey_dh_to_param(EVP_PKEY *pkey, size_t *sz) -{ - DH *dh = pkey->pkey.dh; - PARAMS_TEMPLATE tmpl = {0}; - const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh); - const BIGNUM *pub_key = DH_get0_pub_key(dh); - const BIGNUM *priv_key = DH_get0_priv_key(dh); - - if (p == NULL || g == NULL || pub_key == NULL) - return NULL; - - if (!push_param_bn(&tmpl, OSSL_PKEY_PARAM_DH_P, p) - || !push_param_bn(&tmpl, OSSL_PKEY_PARAM_DH_G, g) - || !push_param_bn(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key)) - return NULL; - - if (q != NULL) { - if (!push_param_bn(&tmpl, OSSL_PKEY_PARAM_DH_Q, q)) - return NULL; - } - - if (priv_key != NULL) { - if (!push_param_bn(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY, priv_key)) - return NULL; - } else { - tmpl.ispublic = 1; - } - - return param_template_to_param(&tmpl, sz); -} -# endif /* OPENSSL_NO_DH */ - -OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz) -{ - switch (pkey->type) { -# ifndef OPENSSL_NO_DH - case EVP_PKEY_DH: - return evp_pkey_dh_to_param(pkey, sz); -# endif - default: - return NULL; - } -} - -#endif /* FIPS_MODE */ diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index ce46163140..848ef299ca 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -94,6 +94,8 @@ struct evp_keyexch_st { CRYPTO_REF_COUNT refcnt; CRYPTO_RWLOCK *lock; + EVP_KEYMGMT *keymgmt; + OSSL_OP_keyexch_newctx_fn *newctx; OSSL_OP_keyexch_init_fn *init; OSSL_OP_keyexch_set_peer_fn *set_peer; diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index d8afcbd633..1c48e7f0ba 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -112,6 +112,7 @@ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange) CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock); if (i > 0) return; + EVP_KEYMGMT_free(exchange->keymgmt); ossl_provider_free(exchange->prov); OPENSSL_free(exchange->name); CRYPTO_THREAD_lock_free(exchange->lock); @@ -127,20 +128,46 @@ int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange) return 1; } +OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange) +{ + return exchange->prov; +} + EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm, const char *properties) { - return evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties, - evp_keyexch_from_dispatch, - (int (*)(void *))EVP_KEYEXCH_up_ref, - (void (*)(void *))EVP_KEYEXCH_free); + /* + * Key exchange cannot work without a key, and we key management + * from the same provider to manage its keys. + */ + EVP_KEYEXCH *keyexch = + evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties, + evp_keyexch_from_dispatch, + (int (*)(void *))EVP_KEYEXCH_up_ref, + (void (*)(void *))EVP_KEYEXCH_free); + + /* If the method is newly created, there's no keymgmt attached */ + if (keyexch->keymgmt == NULL) { + EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(ctx, algorithm, properties); + + if (keymgmt == NULL + || (EVP_KEYEXCH_provider(keyexch) + != EVP_KEYMGMT_provider(keymgmt))) { + EVP_KEYEXCH_free(keyexch); + EVP_KEYMGMT_free(keymgmt); + EVPerr(EVP_F_EVP_KEYEXCH_FETCH, EVP_R_NO_KEYMGMT_PRESENT); + return NULL; + } + + keyexch->keymgmt = keymgmt; + } + return keyexch; } int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, EVP_KEYEXCH *exchange) { int ret; - OSSL_PARAM *param = NULL; - size_t paramsz = 0; + void *provkey = NULL; ctx->operation = EVP_PKEY_OP_DERIVE; @@ -180,26 +207,19 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, EVP_KEYEXCH *exchange) EVP_KEYEXCH_free(ctx->exchange); ctx->exchange = exchange; if (ctx->pkey != NULL) { - param = evp_pkey_to_param(ctx->pkey, ¶msz); - if (param == NULL) { + provkey = evp_keymgmt_export_to_provider(ctx->pkey, exchange->keymgmt); + if (provkey == NULL) { EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR); goto err; } } ctx->exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov)); if (ctx->exchprovctx == NULL) { - OPENSSL_secure_clear_free(param, paramsz); + /* The provider key can stay in the cache */ EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR); goto err; } - ret = exchange->init(ctx->exchprovctx, param); - /* - * TODO(3.0): Really we should detect whether to call OPENSSL_free or - * OPENSSL_secure_clear_free based on the presence of a private key or not. - * Since we always expect a private key to be present we just call - * OPENSSL_secure_clear_free for now. - */ - OPENSSL_secure_clear_free(param, paramsz); + ret = exchange->init(ctx->exchprovctx, provkey); return ret ? 1 : 0; err: @@ -229,7 +249,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) { int ret; - OSSL_PARAM *param = NULL; + void *provkey = NULL; if (ctx == NULL) { EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, @@ -252,21 +272,12 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) return -2; } - param = evp_pkey_to_param(peer, NULL); - if (param == NULL) { + provkey = evp_keymgmt_export_to_provider(peer, ctx->exchange->keymgmt); + if (provkey == NULL) { EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, ERR_R_INTERNAL_ERROR); return 0; } - ret = ctx->exchange->set_peer(ctx->exchprovctx, param); - /* - * TODO(3.0): Really we should detect whether to call OPENSSL_free or - * OPENSSL_secure_clear_free based on the presence of a private key or not. - * Since we always expect a public key to be present we just call - * OPENSSL_free for now. - */ - OPENSSL_free(param); - - return ret; + return ctx->exchange->set_peer(ctx->exchprovctx, provkey); legacy: if (ctx->pmeth == NULL diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index cc26f06d9b..31b4ae4411 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -171,7 +171,7 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) if (pkey != NULL) EVP_PKEY_up_ref(pkey); - if (pmeth != NULL && pmeth->init) { + if (pmeth != NULL && pmeth->init != NULL) { if (pmeth->init(ret) <= 0) { ret->pmeth = NULL; EVP_PKEY_CTX_free(ret); |