2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include <openssl/crypto.h>
11 #include <openssl/evp.h>
12 #include <openssl/err.h>
13 #include "internal/refcount.h"
14 #include "crypto/evp.h"
15 #include "internal/provider.h"
16 #include "internal/numbers.h" /* includes SIZE_MAX */
17 #include "evp_local.h"
19 static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
21 EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH));
23 exchange->lock = CRYPTO_THREAD_lock_new();
24 if (exchange->lock == NULL) {
25 OPENSSL_free(exchange);
28 exchange->prov = prov;
29 ossl_provider_up_ref(prov);
35 static void *evp_keyexch_from_dispatch(int name_id,
36 const OSSL_DISPATCH *fns,
41 * Key exchange cannot work without a key, and key management
42 * from the same provider to manage its keys. We therefore fetch
43 * a key management method using the same algorithm and properties
44 * and pass that down to evp_generic_fetch to be passed on to our
45 * evp_keyexch_from_dispatch, which will attach the key management
46 * method to the newly created key exchange method as long as the
49 struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
50 EVP_KEYMGMT *keymgmt =
51 evp_keymgmt_fetch_by_number(keymgmt_data->ctx, name_id,
52 keymgmt_data->properties);
53 EVP_KEYEXCH *exchange = NULL;
54 int fncnt = 0, paramfncnt = 0;
56 if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) {
57 ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
61 if ((exchange = evp_keyexch_new(prov)) == NULL) {
62 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
66 exchange->name_id = name_id;
67 exchange->keymgmt = keymgmt;
68 keymgmt = NULL; /* avoid double free on failure below */
70 for (; fns->function_id != 0; fns++) {
71 switch (fns->function_id) {
72 case OSSL_FUNC_KEYEXCH_NEWCTX:
73 if (exchange->newctx != NULL)
75 exchange->newctx = OSSL_get_OP_keyexch_newctx(fns);
78 case OSSL_FUNC_KEYEXCH_INIT:
79 if (exchange->init != NULL)
81 exchange->init = OSSL_get_OP_keyexch_init(fns);
84 case OSSL_FUNC_KEYEXCH_SET_PEER:
85 if (exchange->set_peer != NULL)
87 exchange->set_peer = OSSL_get_OP_keyexch_set_peer(fns);
89 case OSSL_FUNC_KEYEXCH_DERIVE:
90 if (exchange->derive != NULL)
92 exchange->derive = OSSL_get_OP_keyexch_derive(fns);
95 case OSSL_FUNC_KEYEXCH_FREECTX:
96 if (exchange->freectx != NULL)
98 exchange->freectx = OSSL_get_OP_keyexch_freectx(fns);
101 case OSSL_FUNC_KEYEXCH_DUPCTX:
102 if (exchange->dupctx != NULL)
104 exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns);
106 case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS:
107 if (exchange->set_ctx_params != NULL)
109 exchange->set_ctx_params = OSSL_get_OP_keyexch_set_ctx_params(fns);
112 case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS:
113 if (exchange->settable_ctx_params != NULL)
115 exchange->settable_ctx_params
116 = OSSL_get_OP_keyexch_settable_ctx_params(fns);
121 if (fncnt != 4 || (paramfncnt != 0 && paramfncnt != 2)) {
123 * In order to be a consistent set of functions we must have at least
124 * a complete set of "exchange" functions: init, derive, newctx,
125 * and freectx. The set_ctx_params and settable_ctx_params functions are
126 * optional, but if one of them is present then the other one must also
127 * be present. The dupctx and set_peer functions are optional.
129 EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH,
130 EVP_R_INVALID_PROVIDER_FUNCTIONS);
137 EVP_KEYEXCH_free(exchange);
138 EVP_KEYMGMT_free(keymgmt);
142 void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
144 if (exchange != NULL) {
147 CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock);
150 EVP_KEYMGMT_free(exchange->keymgmt);
151 ossl_provider_free(exchange->prov);
152 CRYPTO_THREAD_lock_free(exchange->lock);
153 OPENSSL_free(exchange);
157 int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange)
161 CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock);
165 OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange)
167 return exchange->prov;
170 EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm,
171 const char *properties)
173 EVP_KEYEXCH *keyexch = NULL;
174 struct keymgmt_data_st keymgmt_data;
176 keymgmt_data.ctx = ctx;
177 keymgmt_data.properties = properties;
178 keyexch = evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
179 evp_keyexch_from_dispatch, &keymgmt_data,
180 (int (*)(void *))EVP_KEYEXCH_up_ref,
181 (void (*)(void *))EVP_KEYEXCH_free);
186 int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, EVP_KEYEXCH *exchange)
189 void *provkey = NULL;
191 evp_pkey_ctx_free_old_ops(ctx);
192 ctx->operation = EVP_PKEY_OP_DERIVE;
194 if (ctx->engine != NULL)
197 if (exchange != NULL) {
198 if (!EVP_KEYEXCH_up_ref(exchange))
201 int nid = ctx->pkey != NULL ? ctx->pkey->type : ctx->pmeth->pkey_id;
204 * TODO(3.0): Check for legacy handling. Remove this once all all
205 * algorithms are moved to providers.
207 if (ctx->pkey != NULL) {
208 switch (ctx->pkey->type) {
214 exchange = EVP_KEYEXCH_fetch(NULL, OBJ_nid2sn(nid), NULL);
219 if (exchange == NULL) {
220 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
225 ctx->op.kex.exchange = exchange;
226 if (ctx->pkey != NULL) {
227 provkey = evp_keymgmt_export_to_provider(ctx->pkey, exchange->keymgmt);
228 if (provkey == NULL) {
229 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
233 ctx->op.kex.exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
234 if (ctx->op.kex.exchprovctx == NULL) {
235 /* The provider key can stay in the cache */
236 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
239 ret = exchange->init(ctx->op.kex.exchprovctx, provkey);
243 ctx->operation = EVP_PKEY_OP_UNDEFINED;
247 if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
248 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX,
249 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
253 if (ctx->pmeth->derive_init == NULL)
255 ret = ctx->pmeth->derive_init(ctx);
257 ctx->operation = EVP_PKEY_OP_UNDEFINED;
261 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
263 return EVP_PKEY_derive_init_ex(ctx, NULL);
266 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
269 void *provkey = NULL;
272 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
273 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
277 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.exchprovctx == NULL)
280 if (ctx->op.kex.exchange->set_peer == NULL) {
281 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
282 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
286 provkey = evp_keymgmt_export_to_provider(peer,
287 ctx->op.kex.exchange->keymgmt);
288 if (provkey == NULL) {
289 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, ERR_R_INTERNAL_ERROR);
292 return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
295 if (ctx->pmeth == NULL
296 || !(ctx->pmeth->derive != NULL
297 || ctx->pmeth->encrypt != NULL
298 || ctx->pmeth->decrypt != NULL)
299 || ctx->pmeth->ctrl == NULL) {
300 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
301 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
304 if (ctx->operation != EVP_PKEY_OP_DERIVE
305 && ctx->operation != EVP_PKEY_OP_ENCRYPT
306 && ctx->operation != EVP_PKEY_OP_DECRYPT) {
307 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
308 EVP_R_OPERATON_NOT_INITIALIZED);
312 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
320 if (ctx->pkey == NULL) {
321 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
325 if (ctx->pkey->type != peer->type) {
326 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES);
331 * For clarity. The error is if parameters in peer are
332 * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return
333 * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
334 * (different key types) is impossible here because it is checked earlier.
335 * -2 is OK for us here, as well as 1, so we can check for 0 only.
337 if (!EVP_PKEY_missing_parameters(peer) &&
338 !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
339 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS);
343 EVP_PKEY_free(ctx->peerkey);
346 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
353 EVP_PKEY_up_ref(peer);
357 int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
362 EVPerr(EVP_F_EVP_PKEY_DERIVE,
363 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
367 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
368 EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
372 if (ctx->op.kex.exchprovctx == NULL)
375 ret = ctx->op.kex.exchange->derive(ctx->op.kex.exchprovctx, key, pkeylen,
380 if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
381 EVPerr(EVP_F_EVP_PKEY_DERIVE,
382 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
386 M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
387 return ctx->pmeth->derive(ctx, key, pkeylen);
390 int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
392 return evp_is_a(keyexch->prov, keyexch->name_id, name);
395 void EVP_KEYEXCH_do_all_provided(OPENSSL_CTX *libctx,
396 void (*fn)(EVP_KEYEXCH *keyexch, void *arg),
399 struct keymgmt_data_st keymgmt_data;
401 keymgmt_data.ctx = libctx;
402 keymgmt_data.properties = NULL;
403 evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
404 (void (*)(void *, void *))fn, arg,
405 evp_keyexch_from_dispatch, &keymgmt_data,
406 (void (*)(void *))EVP_KEYEXCH_free);