]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/exchange.c
Don't hold a lock when calling a callback in ossl_namemap_doall_names
[thirdparty/openssl.git] / crypto / evp / exchange.c
CommitLineData
ff64702b 1/*
4333b89f 2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
ff64702b
MC
3 *
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
8 */
9
10#include <openssl/crypto.h>
11#include <openssl/evp.h>
12#include <openssl/err.h>
13#include "internal/refcount.h"
25f2138b 14#include "crypto/evp.h"
ff64702b 15#include "internal/provider.h"
ac5a61ca 16#include "internal/numbers.h" /* includes SIZE_MAX */
706457b7 17#include "evp_local.h"
ff64702b
MC
18
19static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
20{
21 EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH));
22
c1ff5994
MC
23 if (exchange == NULL) {
24 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
25 return NULL;
26 }
27
ff64702b
MC
28 exchange->lock = CRYPTO_THREAD_lock_new();
29 if (exchange->lock == NULL) {
c1ff5994 30 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
ff64702b
MC
31 OPENSSL_free(exchange);
32 return NULL;
33 }
34 exchange->prov = prov;
35 ossl_provider_up_ref(prov);
36 exchange->refcnt = 1;
37
38 return exchange;
39}
40
f7c16d48 41static void *evp_keyexch_from_dispatch(int name_id,
6b9e3724 42 const OSSL_DISPATCH *fns,
0ddf74bf 43 OSSL_PROVIDER *prov)
ff64702b
MC
44{
45 EVP_KEYEXCH *exchange = NULL;
4fe54d67 46 int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0;
ff64702b 47
f7c16d48 48 if ((exchange = evp_keyexch_new(prov)) == NULL) {
3ca9d210
RL
49 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
50 goto err;
6b9e3724 51 }
ff64702b 52
f7c16d48 53 exchange->name_id = name_id;
3ca9d210 54
ff64702b
MC
55 for (; fns->function_id != 0; fns++) {
56 switch (fns->function_id) {
57 case OSSL_FUNC_KEYEXCH_NEWCTX:
58 if (exchange->newctx != NULL)
59 break;
363b1e5d 60 exchange->newctx = OSSL_FUNC_keyexch_newctx(fns);
ff64702b
MC
61 fncnt++;
62 break;
63 case OSSL_FUNC_KEYEXCH_INIT:
64 if (exchange->init != NULL)
65 break;
363b1e5d 66 exchange->init = OSSL_FUNC_keyexch_init(fns);
ff64702b
MC
67 fncnt++;
68 break;
69 case OSSL_FUNC_KEYEXCH_SET_PEER:
70 if (exchange->set_peer != NULL)
71 break;
363b1e5d 72 exchange->set_peer = OSSL_FUNC_keyexch_set_peer(fns);
ff64702b
MC
73 break;
74 case OSSL_FUNC_KEYEXCH_DERIVE:
75 if (exchange->derive != NULL)
76 break;
363b1e5d 77 exchange->derive = OSSL_FUNC_keyexch_derive(fns);
ff64702b
MC
78 fncnt++;
79 break;
80 case OSSL_FUNC_KEYEXCH_FREECTX:
81 if (exchange->freectx != NULL)
82 break;
363b1e5d 83 exchange->freectx = OSSL_FUNC_keyexch_freectx(fns);
ff64702b
MC
84 fncnt++;
85 break;
86 case OSSL_FUNC_KEYEXCH_DUPCTX:
87 if (exchange->dupctx != NULL)
88 break;
363b1e5d 89 exchange->dupctx = OSSL_FUNC_keyexch_dupctx(fns);
ff64702b 90 break;
4fe54d67
NT
91 case OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS:
92 if (exchange->get_ctx_params != NULL)
93 break;
363b1e5d 94 exchange->get_ctx_params = OSSL_FUNC_keyexch_get_ctx_params(fns);
4fe54d67
NT
95 gparamfncnt++;
96 break;
97 case OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS:
98 if (exchange->gettable_ctx_params != NULL)
99 break;
100 exchange->gettable_ctx_params
363b1e5d 101 = OSSL_FUNC_keyexch_gettable_ctx_params(fns);
4fe54d67
NT
102 gparamfncnt++;
103 break;
9c45222d
MC
104 case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS:
105 if (exchange->set_ctx_params != NULL)
35aca9ec 106 break;
363b1e5d 107 exchange->set_ctx_params = OSSL_FUNC_keyexch_set_ctx_params(fns);
4fe54d67 108 sparamfncnt++;
9c45222d
MC
109 break;
110 case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS:
111 if (exchange->settable_ctx_params != NULL)
112 break;
113 exchange->settable_ctx_params
363b1e5d 114 = OSSL_FUNC_keyexch_settable_ctx_params(fns);
4fe54d67 115 sparamfncnt++;
35aca9ec 116 break;
ff64702b
MC
117 }
118 }
4fe54d67
NT
119 if (fncnt != 4
120 || (gparamfncnt != 0 && gparamfncnt != 2)
121 || (sparamfncnt != 0 && sparamfncnt != 2)) {
ff64702b
MC
122 /*
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,
9c45222d
MC
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
4fe54d67
NT
127 * be present. Same goes for get_ctx_params and gettable_ctx_params.
128 * The dupctx and set_peer functions are optional.
ff64702b 129 */
9311d0c4 130 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
3ca9d210 131 goto err;
ff64702b
MC
132 }
133
134 return exchange;
3ca9d210
RL
135
136 err:
137 EVP_KEYEXCH_free(exchange);
3ca9d210 138 return NULL;
ff64702b
MC
139}
140
141void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
142{
143 if (exchange != NULL) {
144 int i;
145
146 CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock);
147 if (i > 0)
148 return;
149 ossl_provider_free(exchange->prov);
150 CRYPTO_THREAD_lock_free(exchange->lock);
151 OPENSSL_free(exchange);
152 }
153}
154
155int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange)
156{
157 int ref = 0;
158
159 CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock);
160 return 1;
161}
162
8b84b075
RL
163OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange)
164{
165 return exchange->prov;
166}
167
b4250010 168EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
ff64702b
MC
169 const char *properties)
170{
0ddf74bf
RL
171 return evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
172 evp_keyexch_from_dispatch,
173 (int (*)(void *))EVP_KEYEXCH_up_ref,
174 (void (*)(void *))EVP_KEYEXCH_free);
ff64702b
MC
175}
176
c0e0984f 177int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
ff64702b
MC
178{
179 int ret;
8b84b075 180 void *provkey = NULL;
c0e0984f 181 EVP_KEYEXCH *exchange = NULL;
f6aa5774
RL
182 EVP_KEYMGMT *tmp_keymgmt = NULL;
183 const char *supported_exch = NULL;
c0e0984f
RL
184
185 if (ctx == NULL) {
6d9a54c6 186 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
c0e0984f
RL
187 return -2;
188 }
ff64702b 189
864b89ce 190 evp_pkey_ctx_free_old_ops(ctx);
ff64702b
MC
191 ctx->operation = EVP_PKEY_OP_DERIVE;
192
0b9dd384
RL
193 /*
194 * TODO when we stop falling back to legacy, this and the ERR_pop_to_mark()
195 * calls can be removed.
196 */
197 ERR_set_mark();
198
f21c9c64 199 if (evp_pkey_ctx_is_legacy(ctx))
ff64702b
MC
200 goto legacy;
201
3c6ed955
RL
202 /*
203 * Ensure that the key is provided, either natively, or as a cached export.
ac2d58c7 204 * If not, goto legacy
3c6ed955 205 */
f6aa5774 206 tmp_keymgmt = ctx->keymgmt;
ac2d58c7
MC
207 if (ctx->pkey == NULL) {
208 /*
209 * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create
210 * a blank one.
211 */
212 EVP_PKEY *pkey = EVP_PKEY_new();
213
214 if (pkey == NULL || !EVP_PKEY_set_type_by_keymgmt(pkey, tmp_keymgmt)) {
215 ERR_clear_last_mark();
216 EVP_PKEY_free(pkey);
217 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
218 goto err;
219 }
220 provkey = pkey->keydata = evp_keymgmt_newdata(tmp_keymgmt);
221 if (provkey == NULL)
222 EVP_PKEY_free(pkey);
223 else
224 ctx->pkey = pkey;
225 } else {
226 provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
227 &tmp_keymgmt, ctx->propquery);
228 }
f6aa5774
RL
229 if (provkey == NULL)
230 goto legacy;
231 if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
0b9dd384 232 ERR_clear_last_mark();
f6aa5774
RL
233 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
234 goto err;
c0e0984f 235 }
f6aa5774
RL
236 EVP_KEYMGMT_free(ctx->keymgmt);
237 ctx->keymgmt = tmp_keymgmt;
238
239 if (ctx->keymgmt->query_operation_name != NULL)
240 supported_exch = ctx->keymgmt->query_operation_name(OSSL_OP_KEYEXCH);
241
242 /*
243 * If we didn't get a supported exch, assume there is one with the
244 * same name as the key type.
245 */
246 if (supported_exch == NULL)
247 supported_exch = ctx->keytype;
248
249 /*
250 * Because we cleared out old ops, we shouldn't need to worry about
251 * checking if exchange is already there.
252 */
253 exchange = EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery);
254
255 if (exchange == NULL
c0e0984f
RL
256 || (EVP_KEYMGMT_provider(ctx->keymgmt)
257 != EVP_KEYEXCH_provider(exchange))) {
ff64702b 258 /*
0b9dd384
RL
259 * We don't need to free ctx->keymgmt here, as it's not necessarily
260 * tied to this operation. It will be freed by EVP_PKEY_CTX_free().
ff64702b 261 */
c0e0984f
RL
262 EVP_KEYEXCH_free(exchange);
263 goto legacy;
ff64702b
MC
264 }
265
0b9dd384
RL
266 /*
267 * TODO remove this when legacy is gone
268 * If we don't have the full support we need with provided methods,
269 * let's go see if legacy does.
270 */
271 ERR_pop_to_mark();
272
273 /* No more legacy from here down to legacy: */
c0e0984f 274
864b89ce 275 ctx->op.kex.exchange = exchange;
864b89ce
MC
276 ctx->op.kex.exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
277 if (ctx->op.kex.exchprovctx == NULL) {
8b84b075 278 /* The provider key can stay in the cache */
9311d0c4 279 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
ff64702b
MC
280 goto err;
281 }
864b89ce 282 ret = exchange->init(ctx->op.kex.exchprovctx, provkey);
ff64702b
MC
283
284 return ret ? 1 : 0;
285 err:
c7fa9297 286 evp_pkey_ctx_free_old_ops(ctx);
ff64702b
MC
287 ctx->operation = EVP_PKEY_OP_UNDEFINED;
288 return 0;
289
290 legacy:
0b9dd384
RL
291 /*
292 * TODO remove this when legacy is gone
293 * If we don't have the full support we need with provided methods,
294 * let's go see if legacy does.
295 */
296 ERR_pop_to_mark();
297
f844f9eb 298#ifdef FIPS_MODULE
62f49b90
SL
299 return 0;
300#else
e0d8523e 301 if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
9311d0c4 302 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ff64702b
MC
303 return -2;
304 }
305
306 if (ctx->pmeth->derive_init == NULL)
307 return 1;
308 ret = ctx->pmeth->derive_init(ctx);
309 if (ret <= 0)
310 ctx->operation = EVP_PKEY_OP_UNDEFINED;
311 return ret;
62f49b90 312#endif
ff64702b
MC
313}
314
ff64702b
MC
315int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
316{
62f49b90 317 int ret = 0;
8b84b075 318 void *provkey = NULL;
ff64702b
MC
319
320 if (ctx == NULL) {
6d9a54c6
TM
321 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
322 return -1;
ff64702b
MC
323 }
324
864b89ce 325 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.exchprovctx == NULL)
ff64702b
MC
326 goto legacy;
327
864b89ce 328 if (ctx->op.kex.exchange->set_peer == NULL) {
9311d0c4 329 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ff64702b
MC
330 return -2;
331 }
332
3c6ed955
RL
333 provkey = evp_pkey_export_to_provider(peer, ctx->libctx, &ctx->keymgmt,
334 ctx->propquery);
3f7ce7f1
RL
335 /*
336 * If making the key provided wasn't possible, legacy may be able to pick
337 * it up
338 */
e0d8523e
RL
339 if (provkey == NULL)
340 goto legacy;
864b89ce 341 return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
ff64702b
MC
342
343 legacy:
f844f9eb 344#ifdef FIPS_MODULE
62f49b90
SL
345 return ret;
346#else
3f7ce7f1
RL
347 /*
348 * TODO(3.0) investigate the case where the operation is deemed legacy,
349 * but the given peer key is provider only.
350 */
ff64702b
MC
351 if (ctx->pmeth == NULL
352 || !(ctx->pmeth->derive != NULL
353 || ctx->pmeth->encrypt != NULL
354 || ctx->pmeth->decrypt != NULL)
355 || ctx->pmeth->ctrl == NULL) {
9311d0c4 356 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ff64702b
MC
357 return -2;
358 }
359 if (ctx->operation != EVP_PKEY_OP_DERIVE
360 && ctx->operation != EVP_PKEY_OP_ENCRYPT
361 && ctx->operation != EVP_PKEY_OP_DECRYPT) {
9311d0c4 362 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
ff64702b
MC
363 return -1;
364 }
365
366 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
367
368 if (ret <= 0)
369 return ret;
370
371 if (ret == 2)
372 return 1;
373
374 if (ctx->pkey == NULL) {
9311d0c4 375 ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
ff64702b
MC
376 return -1;
377 }
378
379 if (ctx->pkey->type != peer->type) {
9311d0c4 380 ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
ff64702b
MC
381 return -1;
382 }
383
384 /*
385 * For clarity. The error is if parameters in peer are
c74aaa39 386 * present (!missing) but don't match. EVP_PKEY_parameters_eq may return
ff64702b
MC
387 * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
388 * (different key types) is impossible here because it is checked earlier.
389 * -2 is OK for us here, as well as 1, so we can check for 0 only.
390 */
391 if (!EVP_PKEY_missing_parameters(peer) &&
c74aaa39 392 !EVP_PKEY_parameters_eq(ctx->pkey, peer)) {
9311d0c4 393 ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
ff64702b
MC
394 return -1;
395 }
396
397 EVP_PKEY_free(ctx->peerkey);
398 ctx->peerkey = peer;
399
400 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
401
402 if (ret <= 0) {
403 ctx->peerkey = NULL;
404 return ret;
405 }
406
407 EVP_PKEY_up_ref(peer);
408 return 1;
62f49b90 409#endif
ff64702b
MC
410}
411
412int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
413{
414 int ret;
415
6d9a54c6
TM
416 if (ctx == NULL || pkeylen == NULL) {
417 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
418 return -1;
ff64702b
MC
419 }
420
864b89ce 421 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
9311d0c4 422 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
ff64702b
MC
423 return -1;
424 }
425
864b89ce 426 if (ctx->op.kex.exchprovctx == NULL)
ff64702b
MC
427 goto legacy;
428
864b89ce 429 ret = ctx->op.kex.exchange->derive(ctx->op.kex.exchprovctx, key, pkeylen,
6d9a54c6 430 key != NULL ? *pkeylen : 0);
ff64702b
MC
431
432 return ret;
433 legacy:
6d9a54c6 434 if (ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
9311d0c4 435 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ff64702b
MC
436 return -2;
437 }
438
439 M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
440 return ctx->pmeth->derive(ctx, key, pkeylen);
441}
251e610c 442
506cb0f6
RL
443int EVP_KEYEXCH_number(const EVP_KEYEXCH *keyexch)
444{
445 return keyexch->name_id;
446}
447
251e610c
RL
448int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
449{
e4a1d023 450 return evp_is_a(keyexch->prov, keyexch->name_id, NULL, name);
251e610c
RL
451}
452
b4250010 453void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
251e610c
RL
454 void (*fn)(EVP_KEYEXCH *keyexch, void *arg),
455 void *arg)
456{
251e610c
RL
457 evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
458 (void (*)(void *, void *))fn, arg,
0ddf74bf 459 evp_keyexch_from_dispatch,
251e610c
RL
460 (void (*)(void *))EVP_KEYEXCH_free);
461}
f651c727 462
d84f5515
MC
463int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch,
464 void (*fn)(const char *name, void *data),
465 void *data)
f651c727
RL
466{
467 if (keyexch->prov != NULL)
d84f5515
MC
468 return evp_names_do_all(keyexch->prov, keyexch->name_id, fn, data);
469
470 return 1;
f651c727 471}
e3efe7a5
SL
472
473const OSSL_PARAM *EVP_KEYEXCH_gettable_ctx_params(const EVP_KEYEXCH *keyexch)
474{
475 void *provctx;
476
477 if (keyexch == NULL || keyexch->gettable_ctx_params == NULL)
478 return NULL;
479
480 provctx = ossl_provider_ctx(EVP_KEYEXCH_provider(keyexch));
481 return keyexch->gettable_ctx_params(provctx);
482}
483
484const OSSL_PARAM *EVP_KEYEXCH_settable_ctx_params(const EVP_KEYEXCH *keyexch)
485{
486 void *provctx;
487
488 if (keyexch == NULL || keyexch->settable_ctx_params == NULL)
489 return NULL;
490 provctx = ossl_provider_ctx(EVP_KEYEXCH_provider(keyexch));
491 return keyexch->settable_ctx_params(provctx);
492}