#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
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;
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;
}
}
} else
to->length = from->length;
+ to->dirty_cnt++;
return 1;
}
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,
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 = {
DH_free((DH *)*pval);
*pval = NULL;
return 2;
+ } else if (operation == ASN1_OP_D2I_POST) {
+ ((DH *)*pval)->dirty_cnt++;
}
return 1;
}
goto err;
if (!BN_set_word(ret->g, g))
goto err;
+ ret->dirty_cnt++;
ok = 1;
err:
if (ok == -1) {
dh->pub_key = pub_key;
dh->priv_key = priv_key;
+ dh->dirty_cnt++;
ok = 1;
err:
if (ok != 1)
dh->length = BN_num_bits(q);
}
+ dh->dirty_cnt++;
return 1;
}
dh->priv_key = priv_key;
}
+ dh->dirty_cnt++;
return 1;
}
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 {
dh->p = (BIGNUM *)p;
dh->g = (BIGNUM *)&_bignum_const_2;
dh->length = nbits;
+ dh->dirty_cnt++;
return dh;
}
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
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
{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),
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 */
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;
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);
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;
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:
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,
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
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);
=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
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
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
=head1 SEE ALSO
-L<provider(7)/Fetching algorithms>
+L<provider(7)/Fetching algorithms>, L<OSSL_PROVIDER(3)>
=head1 HISTORY
# 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
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);
# 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
-SUBDIRS=digests ciphers exchange
+SUBDIRS=digests ciphers exchange keymgmt
SOURCE[../../libcrypto]=\
provider_err.c provlib.c
LIBS=../../../libcrypto
IF[{- !$disabled{dh} -}]
SOURCE[../../../libcrypto]=\
- dh.c
+ dh_exch.c
ENDIF
+++ /dev/null
-/*
- * 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/crypto.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/dh.h>
-#include <openssl/params.h>
-#include "internal/provider_algs.h"
-
-static OSSL_OP_keyexch_newctx_fn dh_newctx;
-static OSSL_OP_keyexch_init_fn dh_init;
-static OSSL_OP_keyexch_set_peer_fn dh_set_peer;
-static OSSL_OP_keyexch_derive_fn dh_derive;
-static OSSL_OP_keyexch_freectx_fn dh_freectx;
-static OSSL_OP_keyexch_dupctx_fn dh_dupctx;
-
-
-typedef struct {
- DH *dh;
- DH *dhpeer;
- int pad;
-} PROV_DH_CTX;
-
-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[])
-{
- PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
-
- DH_free(pdhctx->dh);
- pdhctx->dh = param_to_dh(params, 1);
-
- return pdhctx->dh != NULL;
-}
-
-static int dh_set_peer(void *vpdhctx, OSSL_PARAM params[])
-{
- PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
-
- DH_free(pdhctx->dhpeer);
- pdhctx->dhpeer = param_to_dh(params, 0);
-
- return pdhctx->dhpeer != NULL;
-}
-
-static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen,
- size_t outlen)
-{
- PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
- int ret;
- size_t dhsize;
- const BIGNUM *pub_key = NULL;
-
- /* TODO(3.0): Add errors to stack */
- if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL)
- return 0;
-
- dhsize = (size_t)DH_size(pdhctx->dh);
- if (key == NULL) {
- *keylen = dhsize;
- return 1;
- }
- if (outlen < dhsize)
- return 0;
-
- DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
- ret = (pdhctx->pad) ? DH_compute_key_padded(key, pub_key, pdhctx->dh)
- : DH_compute_key(key, pub_key, pdhctx->dh);
- if (ret <= 0)
- return 0;
-
- *keylen = ret;
- return 1;
-}
-
-static void dh_freectx(void *vpdhctx)
-{
- PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
-
- DH_free(pdhctx->dh);
- DH_free(pdhctx->dhpeer);
-
- OPENSSL_free(pdhctx);
-}
-
-static void *dh_dupctx(void *vpdhctx)
-{
- PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
- PROV_DH_CTX *dstctx;
-
- dstctx = OPENSSL_zalloc(sizeof(*srcctx));
-
- *dstctx = *srcctx;
- if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) {
- OPENSSL_free(dstctx);
- return NULL;
- }
-
- if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) {
- DH_free(dstctx->dh);
- OPENSSL_free(dstctx);
- return NULL;
- }
-
- return dstctx;
-}
-
-static int dh_set_params(void *vpdhctx, OSSL_PARAM params[])
-{
- PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
- const OSSL_PARAM *p;
- int pad;
-
- if (pdhctx == NULL || params == NULL)
- return 0;
-
- p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_PAD);
- if (p == NULL || !OSSL_PARAM_get_int(p, &pad))
- return 0;
-
- pdhctx->pad = pad;
-
- return 1;
-}
-
-const OSSL_DISPATCH dh_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 },
- { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
- { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
- { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
- { OSSL_FUNC_KEYEXCH_SET_PARAMS, (void (*)(void))dh_set_params },
- { 0, NULL }
-};
--- /dev/null
+/*
+ * 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/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include <openssl/params.h>
+#include "internal/provider_algs.h"
+
+static OSSL_OP_keyexch_newctx_fn dh_newctx;
+static OSSL_OP_keyexch_init_fn dh_init;
+static OSSL_OP_keyexch_set_peer_fn dh_set_peer;
+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;
+ DH *dhpeer;
+ int pad;
+} PROV_DH_CTX;
+
+static void *dh_newctx(void *provctx)
+{
+ return OPENSSL_zalloc(sizeof(PROV_DH_CTX));
+}
+
+static int dh_init(void *vpdhctx, void *vdh)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dh);
+ pdhctx->dh = vdh;
+ DH_up_ref(pdhctx->dh);
+
+ return pdhctx->dh != NULL;
+}
+
+static int dh_set_peer(void *vpdhctx, void *vdh)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dhpeer);
+ pdhctx->dhpeer = vdh;
+ DH_up_ref(pdhctx->dhpeer);
+
+ return pdhctx->dhpeer != NULL;
+}
+
+static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen,
+ size_t outlen)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ int ret;
+ size_t dhsize;
+ const BIGNUM *pub_key = NULL;
+
+ /* TODO(3.0): Add errors to stack */
+ if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL)
+ return 0;
+
+ dhsize = (size_t)DH_size(pdhctx->dh);
+ if (key == NULL) {
+ *keylen = dhsize;
+ return 1;
+ }
+ if (outlen < dhsize)
+ return 0;
+
+ DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
+ ret = (pdhctx->pad) ? DH_compute_key_padded(key, pub_key, pdhctx->dh)
+ : DH_compute_key(key, pub_key, pdhctx->dh);
+ if (ret <= 0)
+ return 0;
+
+ *keylen = ret;
+ return 1;
+}
+
+static void dh_freectx(void *vpdhctx)
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+
+ DH_free(pdhctx->dh);
+ DH_free(pdhctx->dhpeer);
+
+ OPENSSL_free(pdhctx);
+}
+
+static void *dh_dupctx(void *vpdhctx)
+{
+ PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
+ PROV_DH_CTX *dstctx;
+
+ dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+
+ *dstctx = *srcctx;
+ if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) {
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) {
+ DH_free(dstctx->dh);
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+
+ return dstctx;
+}
+
+static int dh_set_params(void *vpdhctx, const OSSL_PARAM params[])
+{
+ PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
+ const OSSL_PARAM *p;
+ int pad;
+
+ if (pdhctx == NULL || params == NULL)
+ return 0;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
+ if (p == NULL || !OSSL_PARAM_get_int(p, &pad))
+ return 0;
+
+ pdhctx->pad = pad;
+
+ return 1;
+}
+
+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 },
+ { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
+ { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
+ { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
+ { OSSL_FUNC_KEYEXCH_SET_PARAMS, (void (*)(void))dh_set_params },
+ { 0, NULL }
+};
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[];
--- /dev/null
+LIBS=../../../libcrypto
+IF[{- !$disabled{dh} -}]
+ SOURCE[../../../libcrypto]=\
+ dh_kmgmt.c
+ENDIF
--- /dev/null
+/*
+ * 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 }
+};
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 }
};
return deflt_digests;
case OSSL_OP_CIPHER:
return deflt_ciphers;
+ case OSSL_OP_KEYMGMT:
+ return deflt_keymgmt;
case OSSL_OP_KEYEXCH:
return deflt_keyexch;
}
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: