mirror of
https://github.com/openssl/openssl.git
synced 2025-03-25 20:00:44 +08:00
Adapt DH to use with KEYMGMT
The biggest part in this was to move the key->param builder from EVP to the DH ASN.1 method, and to implement the KEYMGMT support in the provider DH. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/9394)
This commit is contained in:
parent
037439c46a
commit
8b84b075ff
@ -16,6 +16,8 @@
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/param_build.h"
|
||||
|
||||
/*
|
||||
* i2d/d2i like DH parameter functions which use the appropriate routine for
|
||||
@ -181,7 +183,7 @@ static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
|
||||
DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
|
||||
goto dherr;
|
||||
}
|
||||
/* Calculate public key */
|
||||
/* Calculate public key, increments dirty_cnt */
|
||||
if (!DH_generate_key(dh))
|
||||
goto dherr;
|
||||
|
||||
@ -255,6 +257,7 @@ static int dh_param_decode(EVP_PKEY *pkey,
|
||||
DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB);
|
||||
return 0;
|
||||
}
|
||||
dh->dirty_cnt++;
|
||||
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
|
||||
return 1;
|
||||
}
|
||||
@ -415,6 +418,7 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
|
||||
}
|
||||
} else
|
||||
to->length = from->length;
|
||||
to->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -540,6 +544,50 @@ static int dh_pkey_param_check(const EVP_PKEY *pkey)
|
||||
return DH_check_ex(dh);
|
||||
}
|
||||
|
||||
static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
|
||||
{
|
||||
return pkey->pkey.dh->dirty_cnt;
|
||||
}
|
||||
|
||||
static void *dh_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
|
||||
{
|
||||
DH *dh = pk->pkey.dh;
|
||||
OSSL_PARAM_BLD tmpl;
|
||||
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);
|
||||
OSSL_PARAM *params;
|
||||
void *provkey = NULL;
|
||||
|
||||
if (p == NULL || g == NULL || pub_key == NULL)
|
||||
return NULL;
|
||||
|
||||
ossl_param_bld_init(&tmpl);
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_P, p)
|
||||
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_G, g)
|
||||
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key))
|
||||
return NULL;
|
||||
|
||||
if (q != NULL) {
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_Q, q))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (priv_key != NULL) {
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
|
||||
priv_key))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
params = ossl_param_bld_to_param(&tmpl);
|
||||
|
||||
/* We export, the provider imports */
|
||||
provkey = evp_keymgmt_importkey(keymgmt, params);
|
||||
|
||||
ossl_param_bld_free(params);
|
||||
return provkey;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
|
||||
EVP_PKEY_DH,
|
||||
EVP_PKEY_DH,
|
||||
@ -576,7 +624,12 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
|
||||
|
||||
0,
|
||||
dh_pkey_public_check,
|
||||
dh_pkey_param_check
|
||||
dh_pkey_param_check,
|
||||
|
||||
0, 0, 0, 0,
|
||||
|
||||
dh_pkey_dirty_cnt,
|
||||
dh_pkey_export_to,
|
||||
};
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
|
||||
|
@ -27,6 +27,8 @@ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
DH_free((DH *)*pval);
|
||||
*pval = NULL;
|
||||
return 2;
|
||||
} else if (operation == ASN1_OP_D2I_POST) {
|
||||
((DH *)*pval)->dirty_cnt++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
goto err;
|
||||
if (!BN_set_word(ret->g, g))
|
||||
goto err;
|
||||
ret->dirty_cnt++;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
|
@ -154,6 +154,7 @@ static int generate_key(DH *dh)
|
||||
|
||||
dh->pub_key = pub_key;
|
||||
dh->priv_key = priv_key;
|
||||
dh->dirty_cnt++;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok != 1)
|
||||
|
@ -209,6 +209,7 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
dh->length = BN_num_bits(q);
|
||||
}
|
||||
|
||||
dh->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -242,6 +243,7 @@ int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||
dh->priv_key = priv_key;
|
||||
}
|
||||
|
||||
dh->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,9 @@ struct dh_st {
|
||||
const DH_METHOD *meth;
|
||||
ENGINE *engine;
|
||||
CRYPTO_RWLOCK *lock;
|
||||
|
||||
/* Provider data */
|
||||
size_t dirty_cnt; /* If any key material changes, increment this */
|
||||
};
|
||||
|
||||
struct dh_method {
|
||||
|
@ -22,6 +22,7 @@ static DH *dh_param_init(const BIGNUM *p, int32_t nbits)
|
||||
dh->p = (BIGNUM *)p;
|
||||
dh->g = (BIGNUM *)&_bignum_const_2;
|
||||
dh->length = nbits;
|
||||
dh->dirty_cnt++;
|
||||
return dh;
|
||||
}
|
||||
|
||||
|
@ -821,6 +821,7 @@ EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl
|
||||
EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str
|
||||
EVP_F_EVP_KDF_CTX_NEW:240:EVP_KDF_CTX_new
|
||||
EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id
|
||||
EVP_F_EVP_KEYEXCH_FETCH:245:EVP_KEYEXCH_fetch
|
||||
EVP_F_EVP_KEYEXCH_FROM_DISPATCH:244:evp_keyexch_from_dispatch
|
||||
EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
|
||||
EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
|
||||
@ -2464,6 +2465,7 @@ EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
|
||||
EVP_R_NO_CIPHER_SET:131:no cipher set
|
||||
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
|
||||
EVP_R_NO_DIGEST_SET:139:no digest set
|
||||
EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
|
||||
EVP_R_NO_KEY_SET:154:no key set
|
||||
EVP_R_NO_OPERATION_SET:149:no operation set
|
||||
EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
|
||||
|
@ -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),
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
EVP_KEYEXCH_fetch, EVP_KEYEXCH_free, EVP_KEYEXCH_up_ref
|
||||
EVP_KEYEXCH_fetch, EVP_KEYEXCH_free, EVP_KEYEXCH_up_ref, EVP_KEYEXCH_provider
|
||||
- Functions to manage EVP_KEYEXCH algorithm objects
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@ -13,6 +13,7 @@ EVP_KEYEXCH_fetch, EVP_KEYEXCH_free, EVP_KEYEXCH_up_ref
|
||||
const char *properties);
|
||||
void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange);
|
||||
int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange);
|
||||
OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
@ -31,6 +32,8 @@ structure is freed.
|
||||
EVP_KEYEXCH_up_ref() increments the reference count for an B<EVP_KEYEXCH>
|
||||
structure.
|
||||
|
||||
EVP_KEYEXCH_provider() returns the provider that I<exchange> was fetched from.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
EVP_KEYEXCH_fetch() returns a pointer to a B<EVP_KEYEXCH> for success
|
||||
@ -40,7 +43,7 @@ EVP_KEYEXCH_up_ref() returns 1 for success or 0 otherwise.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<provider(7)/Fetching algorithms>
|
||||
L<provider(7)/Fetching algorithms>, L<OSSL_PROVIDER(3)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
@ -301,16 +301,14 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keymgmt_exportkey_types, (void))
|
||||
# define OSSL_FUNC_KEYEXCH_SET_PARAMS 7
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_newctx, (void *provctx))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_init, (void *ctx,
|
||||
OSSL_PARAM params[]))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_init, (void *ctx, void *provkey))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_derive, (void *ctx, unsigned char *key,
|
||||
size_t *keylen, size_t outlen))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_peer, (void *ctx,
|
||||
OSSL_PARAM params[]))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_peer, (void *ctx, void *provkey))
|
||||
OSSL_CORE_MAKE_FUNC(void, OP_keyexch_freectx, (void *ctx))
|
||||
OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_dupctx, (void *ctx))
|
||||
OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx,
|
||||
OSSL_PARAM params[]))
|
||||
const OSSL_PARAM params[]))
|
||||
|
||||
/* Highest known operation number */
|
||||
# define OSSL_OP__HIGHEST 3
|
||||
|
@ -1728,6 +1728,7 @@ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange);
|
||||
int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange);
|
||||
EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
||||
const char *properties);
|
||||
OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange);
|
||||
|
||||
void EVP_add_alg_module(void);
|
||||
|
||||
|
@ -213,6 +213,7 @@ int ERR_load_EVP_strings(void);
|
||||
# define EVP_R_NO_CIPHER_SET 131
|
||||
# define EVP_R_NO_DEFAULT_DIGEST 158
|
||||
# define EVP_R_NO_DIGEST_SET 139
|
||||
# define EVP_R_NO_KEYMGMT_PRESENT 196
|
||||
# define EVP_R_NO_KEY_SET 154
|
||||
# define EVP_R_NO_OPERATION_SET 149
|
||||
# define EVP_R_ONLY_ONESHOT_SUPPORTED 177
|
||||
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS=digests ciphers exchange
|
||||
SUBDIRS=digests ciphers exchange keymgmt
|
||||
|
||||
SOURCE[../../libcrypto]=\
|
||||
provider_err.c provlib.c
|
||||
|
@ -1,7 +1,7 @@
|
||||
LIBS=../../../libcrypto
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dh.c
|
||||
dh_exch.c
|
||||
ENDIF
|
||||
|
||||
|
||||
|
@ -21,6 +21,11 @@ static OSSL_OP_keyexch_derive_fn dh_derive;
|
||||
static OSSL_OP_keyexch_freectx_fn dh_freectx;
|
||||
static OSSL_OP_keyexch_dupctx_fn dh_dupctx;
|
||||
|
||||
/*
|
||||
* What's passed as an actual key is defined by the KEYMGMT interface.
|
||||
* We happen to know that our KEYMGMT simply passes DH structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
DH *dh;
|
||||
@ -33,71 +38,24 @@ static void *dh_newctx(void *provctx)
|
||||
return OPENSSL_zalloc(sizeof(PROV_DH_CTX));
|
||||
}
|
||||
|
||||
static DH *param_to_dh(OSSL_PARAM params[], int priv)
|
||||
{
|
||||
DH *dh = DH_new();
|
||||
OSSL_PARAM *paramptr;
|
||||
BIGNUM *p = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;
|
||||
|
||||
if (dh == NULL)
|
||||
return NULL;
|
||||
|
||||
paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_P);
|
||||
if (paramptr == NULL
|
||||
|| !OSSL_PARAM_get_BN(paramptr, &p))
|
||||
goto err;
|
||||
|
||||
paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_G);
|
||||
if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &g))
|
||||
goto err;
|
||||
|
||||
if (!DH_set0_pqg(dh, p, NULL, g))
|
||||
goto err;
|
||||
p = g = NULL;
|
||||
|
||||
paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PUB_KEY);
|
||||
if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &pub_key))
|
||||
goto err;
|
||||
|
||||
/* Private key is optional */
|
||||
if (priv) {
|
||||
paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PRIV_KEY);
|
||||
if (paramptr == NULL
|
||||
|| (priv_key = BN_secure_new()) == NULL
|
||||
|| !OSSL_PARAM_get_BN(paramptr, &priv_key))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!DH_set0_key(dh, pub_key, priv_key))
|
||||
goto err;
|
||||
|
||||
return dh;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(g);
|
||||
BN_free(pub_key);
|
||||
BN_free(priv_key);
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int dh_init(void *vpdhctx, OSSL_PARAM params[])
|
||||
static int dh_init(void *vpdhctx, void *vdh)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
|
||||
DH_free(pdhctx->dh);
|
||||
pdhctx->dh = param_to_dh(params, 1);
|
||||
pdhctx->dh = vdh;
|
||||
DH_up_ref(pdhctx->dh);
|
||||
|
||||
return pdhctx->dh != NULL;
|
||||
}
|
||||
|
||||
static int dh_set_peer(void *vpdhctx, OSSL_PARAM params[])
|
||||
static int dh_set_peer(void *vpdhctx, void *vdh)
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
|
||||
DH_free(pdhctx->dhpeer);
|
||||
pdhctx->dhpeer = param_to_dh(params, 0);
|
||||
pdhctx->dhpeer = vdh;
|
||||
DH_up_ref(pdhctx->dhpeer);
|
||||
|
||||
return pdhctx->dhpeer != NULL;
|
||||
}
|
||||
@ -164,7 +122,7 @@ static void *dh_dupctx(void *vpdhctx)
|
||||
return dstctx;
|
||||
}
|
||||
|
||||
static int dh_set_params(void *vpdhctx, OSSL_PARAM params[])
|
||||
static int dh_set_params(void *vpdhctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
|
||||
const OSSL_PARAM *p;
|
||||
@ -173,7 +131,7 @@ static int dh_set_params(void *vpdhctx, OSSL_PARAM params[])
|
||||
if (pdhctx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_PAD);
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
|
||||
if (p == NULL || !OSSL_PARAM_get_int(p, &pad))
|
||||
return 0;
|
||||
|
||||
@ -182,7 +140,7 @@ static int dh_set_params(void *vpdhctx, OSSL_PARAM params[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_functions[] = {
|
||||
const OSSL_DISPATCH dh_keyexch_functions[] = {
|
||||
{ OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
|
||||
{ OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
|
||||
{ OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
|
@ -58,5 +58,8 @@ extern const OSSL_DISPATCH aes256ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes192ctr_functions[];
|
||||
extern const OSSL_DISPATCH aes128ctr_functions[];
|
||||
|
||||
/* Key management */
|
||||
extern const OSSL_DISPATCH dh_keymgmt_functions[];
|
||||
|
||||
/* Key Exchange */
|
||||
extern const OSSL_DISPATCH dh_functions[];
|
||||
extern const OSSL_DISPATCH dh_keyexch_functions[];
|
||||
|
5
providers/common/keymgmt/build.info
Normal file
5
providers/common/keymgmt/build.info
Normal file
@ -0,0 +1,5 @@
|
||||
LIBS=../../../libcrypto
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[../../../libcrypto]=\
|
||||
dh_kmgmt.c
|
||||
ENDIF
|
88
providers/common/keymgmt/dh_kmgmt.c
Normal file
88
providers/common/keymgmt/dh_kmgmt.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2019 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
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/params.h>
|
||||
#include "internal/provider_algs.h"
|
||||
|
||||
static OSSL_OP_keymgmt_importkey_fn dh_importkey;
|
||||
|
||||
static int params_to_key(DH *dh, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *param_p, *param_g, *param_priv_key, *param_pub_key;
|
||||
BIGNUM *p = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
|
||||
|
||||
if (dh == NULL)
|
||||
return 0;
|
||||
|
||||
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_P);
|
||||
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_G);
|
||||
param_priv_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY);
|
||||
param_pub_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PUB_KEY);
|
||||
|
||||
/*
|
||||
* DH documentation says that a public key must be present if a
|
||||
* private key is present.
|
||||
* We want to have at least a public key either way, so we end up
|
||||
* requiring it unconditionally.
|
||||
*/
|
||||
if (param_pub_key == NULL)
|
||||
return 0;
|
||||
|
||||
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|
||||
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))
|
||||
|| (param_priv_key != NULL
|
||||
&& !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|
||||
|| !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
|
||||
goto err;
|
||||
|
||||
if (!DH_set0_pqg(dh, p, NULL, g))
|
||||
goto err;
|
||||
p = g = NULL;
|
||||
|
||||
if (!DH_set0_key(dh, pub_key, priv_key))
|
||||
goto err;
|
||||
priv_key = pub_key = NULL;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(g);
|
||||
BN_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *dh_importkey(void *provctx, const OSSL_PARAM params[])
|
||||
{
|
||||
DH *dh;
|
||||
|
||||
if ((dh = DH_new()) == NULL
|
||||
|| !params_to_key(dh, params)) {
|
||||
DH_free(dh);
|
||||
dh = NULL;
|
||||
}
|
||||
return dh;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_keymgmt_functions[] = {
|
||||
/*
|
||||
* TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
|
||||
* implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
|
||||
*/
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey },
|
||||
{ OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free },
|
||||
{ 0, NULL }
|
||||
};
|
@ -116,7 +116,14 @@ static const OSSL_ALGORITHM deflt_ciphers[] = {
|
||||
|
||||
static const OSSL_ALGORITHM deflt_keyexch[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "dhKeyAgreement", "default=yes", dh_functions },
|
||||
{ "dhKeyAgreement", "default=yes", dh_keyexch_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static const OSSL_ALGORITHM deflt_keymgmt[] = {
|
||||
#ifndef OPENSSL_NO_DH
|
||||
{ "dhKeyAgreement", "default=yes", dh_keymgmt_functions },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
@ -131,6 +138,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
|
||||
return deflt_digests;
|
||||
case OSSL_OP_CIPHER:
|
||||
return deflt_ciphers;
|
||||
case OSSL_OP_KEYMGMT:
|
||||
return deflt_keymgmt;
|
||||
case OSSL_OP_KEYEXCH:
|
||||
return deflt_keyexch;
|
||||
}
|
||||
|
@ -4698,3 +4698,4 @@ EVP_CIPHER_provider 4803 3_0_0 EXIST::FUNCTION:
|
||||
OSSL_PROVIDER_name 4804 3_0_0 EXIST::FUNCTION:
|
||||
EVP_CIPHER_do_all_ex 4805 3_0_0 EXIST::FUNCTION:
|
||||
EVP_MD_do_all_ex 4806 3_0_0 EXIST::FUNCTION:
|
||||
EVP_KEYEXCH_provider 4807 3_0_0 EXIST::FUNCTION:
|
||||
|
Loading…
x
Reference in New Issue
Block a user