]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/exchange.c
dfc309ecd777fbc95882deba92551141622c5745
[thirdparty/openssl.git] / crypto / evp / exchange.c
1 /*
2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
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"
14 #include "crypto/evp.h"
15 #include "internal/provider.h"
16 #include "internal/numbers.h" /* includes SIZE_MAX */
17 #include "evp_local.h"
18
19 static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
20 {
21 EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH));
22
23 exchange->lock = CRYPTO_THREAD_lock_new();
24 if (exchange->lock == NULL) {
25 OPENSSL_free(exchange);
26 return NULL;
27 }
28 exchange->prov = prov;
29 ossl_provider_up_ref(prov);
30 exchange->refcnt = 1;
31
32 return exchange;
33 }
34
35 static void *evp_keyexch_from_dispatch(int name_id,
36 const OSSL_DISPATCH *fns,
37 OSSL_PROVIDER *prov,
38 void *vkeymgmt_data)
39 {
40 /*
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
47 * provider matches.
48 */
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;
55
56 if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) {
57 ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
58 goto err;
59 }
60
61 if ((exchange = evp_keyexch_new(prov)) == NULL) {
62 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
63 goto err;
64 }
65
66 exchange->name_id = name_id;
67 exchange->keymgmt = keymgmt;
68 keymgmt = NULL; /* avoid double free on failure below */
69
70 for (; fns->function_id != 0; fns++) {
71 switch (fns->function_id) {
72 case OSSL_FUNC_KEYEXCH_NEWCTX:
73 if (exchange->newctx != NULL)
74 break;
75 exchange->newctx = OSSL_get_OP_keyexch_newctx(fns);
76 fncnt++;
77 break;
78 case OSSL_FUNC_KEYEXCH_INIT:
79 if (exchange->init != NULL)
80 break;
81 exchange->init = OSSL_get_OP_keyexch_init(fns);
82 fncnt++;
83 break;
84 case OSSL_FUNC_KEYEXCH_SET_PEER:
85 if (exchange->set_peer != NULL)
86 break;
87 exchange->set_peer = OSSL_get_OP_keyexch_set_peer(fns);
88 break;
89 case OSSL_FUNC_KEYEXCH_DERIVE:
90 if (exchange->derive != NULL)
91 break;
92 exchange->derive = OSSL_get_OP_keyexch_derive(fns);
93 fncnt++;
94 break;
95 case OSSL_FUNC_KEYEXCH_FREECTX:
96 if (exchange->freectx != NULL)
97 break;
98 exchange->freectx = OSSL_get_OP_keyexch_freectx(fns);
99 fncnt++;
100 break;
101 case OSSL_FUNC_KEYEXCH_DUPCTX:
102 if (exchange->dupctx != NULL)
103 break;
104 exchange->dupctx = OSSL_get_OP_keyexch_dupctx(fns);
105 break;
106 case OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS:
107 if (exchange->set_ctx_params != NULL)
108 break;
109 exchange->set_ctx_params = OSSL_get_OP_keyexch_set_ctx_params(fns);
110 paramfncnt++;
111 break;
112 case OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS:
113 if (exchange->settable_ctx_params != NULL)
114 break;
115 exchange->settable_ctx_params
116 = OSSL_get_OP_keyexch_settable_ctx_params(fns);
117 paramfncnt++;
118 break;
119 }
120 }
121 if (fncnt != 4 || (paramfncnt != 0 && paramfncnt != 2)) {
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,
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.
128 */
129 EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH,
130 EVP_R_INVALID_PROVIDER_FUNCTIONS);
131 goto err;
132 }
133
134 return exchange;
135
136 err:
137 EVP_KEYEXCH_free(exchange);
138 EVP_KEYMGMT_free(keymgmt);
139 return NULL;
140 }
141
142 void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
143 {
144 if (exchange != NULL) {
145 int i;
146
147 CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock);
148 if (i > 0)
149 return;
150 EVP_KEYMGMT_free(exchange->keymgmt);
151 ossl_provider_free(exchange->prov);
152 CRYPTO_THREAD_lock_free(exchange->lock);
153 OPENSSL_free(exchange);
154 }
155 }
156
157 int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange)
158 {
159 int ref = 0;
160
161 CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock);
162 return 1;
163 }
164
165 OSSL_PROVIDER *EVP_KEYEXCH_provider(const EVP_KEYEXCH *exchange)
166 {
167 return exchange->prov;
168 }
169
170 EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm,
171 const char *properties)
172 {
173 EVP_KEYEXCH *keyexch = NULL;
174 struct keymgmt_data_st keymgmt_data;
175
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);
182
183 return keyexch;
184 }
185
186 int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, EVP_KEYEXCH *exchange)
187 {
188 int ret;
189 void *provkey = NULL;
190
191 evp_pkey_ctx_free_old_ops(ctx);
192 ctx->operation = EVP_PKEY_OP_DERIVE;
193
194 if (ctx->engine != NULL)
195 goto legacy;
196
197 if (exchange != NULL) {
198 if (!EVP_KEYEXCH_up_ref(exchange))
199 goto err;
200 } else {
201 int nid = ctx->pkey != NULL ? ctx->pkey->type : ctx->pmeth->pkey_id;
202
203 /*
204 * TODO(3.0): Check for legacy handling. Remove this once all all
205 * algorithms are moved to providers.
206 */
207 if (ctx->pkey != NULL) {
208 switch (ctx->pkey->type) {
209 case EVP_PKEY_DH:
210 break;
211 default:
212 goto legacy;
213 }
214 exchange = EVP_KEYEXCH_fetch(NULL, OBJ_nid2sn(nid), NULL);
215 } else {
216 goto legacy;
217 }
218
219 if (exchange == NULL) {
220 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
221 goto err;
222 }
223 }
224
225 ctx->op.kex.exchange = exchange;
226 if (ctx->pkey != NULL) {
227 provkey =
228 evp_keymgmt_export_to_provider(ctx->pkey, exchange->keymgmt, 0);
229 if (provkey == NULL) {
230 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
231 goto err;
232 }
233 }
234 ctx->op.kex.exchprovctx = exchange->newctx(ossl_provider_ctx(exchange->prov));
235 if (ctx->op.kex.exchprovctx == NULL) {
236 /* The provider key can stay in the cache */
237 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX, EVP_R_INITIALIZATION_ERROR);
238 goto err;
239 }
240 ret = exchange->init(ctx->op.kex.exchprovctx, provkey);
241
242 return ret ? 1 : 0;
243 err:
244 ctx->operation = EVP_PKEY_OP_UNDEFINED;
245 return 0;
246
247 legacy:
248 if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
249 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT_EX,
250 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
251 return -2;
252 }
253
254 if (ctx->pmeth->derive_init == NULL)
255 return 1;
256 ret = ctx->pmeth->derive_init(ctx);
257 if (ret <= 0)
258 ctx->operation = EVP_PKEY_OP_UNDEFINED;
259 return ret;
260 }
261
262 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
263 {
264 return EVP_PKEY_derive_init_ex(ctx, NULL);
265 }
266
267 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
268 {
269 int ret;
270 void *provkey = NULL;
271
272 if (ctx == NULL) {
273 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
274 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
275 return -2;
276 }
277
278 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.exchprovctx == NULL)
279 goto legacy;
280
281 if (ctx->op.kex.exchange->set_peer == NULL) {
282 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
283 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
284 return -2;
285 }
286
287 provkey =
288 evp_keymgmt_export_to_provider(peer, ctx->op.kex.exchange->keymgmt, 0);
289 if (provkey == NULL) {
290 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, ERR_R_INTERNAL_ERROR);
291 return 0;
292 }
293 return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
294
295 legacy:
296 if (ctx->pmeth == NULL
297 || !(ctx->pmeth->derive != NULL
298 || ctx->pmeth->encrypt != NULL
299 || ctx->pmeth->decrypt != NULL)
300 || ctx->pmeth->ctrl == NULL) {
301 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
302 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
303 return -2;
304 }
305 if (ctx->operation != EVP_PKEY_OP_DERIVE
306 && ctx->operation != EVP_PKEY_OP_ENCRYPT
307 && ctx->operation != EVP_PKEY_OP_DECRYPT) {
308 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
309 EVP_R_OPERATON_NOT_INITIALIZED);
310 return -1;
311 }
312
313 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
314
315 if (ret <= 0)
316 return ret;
317
318 if (ret == 2)
319 return 1;
320
321 if (ctx->pkey == NULL) {
322 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
323 return -1;
324 }
325
326 if (ctx->pkey->type != peer->type) {
327 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES);
328 return -1;
329 }
330
331 /*
332 * For clarity. The error is if parameters in peer are
333 * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return
334 * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
335 * (different key types) is impossible here because it is checked earlier.
336 * -2 is OK for us here, as well as 1, so we can check for 0 only.
337 */
338 if (!EVP_PKEY_missing_parameters(peer) &&
339 !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
340 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS);
341 return -1;
342 }
343
344 EVP_PKEY_free(ctx->peerkey);
345 ctx->peerkey = peer;
346
347 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
348
349 if (ret <= 0) {
350 ctx->peerkey = NULL;
351 return ret;
352 }
353
354 EVP_PKEY_up_ref(peer);
355 return 1;
356 }
357
358 int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
359 {
360 int ret;
361
362 if (ctx == NULL) {
363 EVPerr(EVP_F_EVP_PKEY_DERIVE,
364 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
365 return -2;
366 }
367
368 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
369 EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
370 return -1;
371 }
372
373 if (ctx->op.kex.exchprovctx == NULL)
374 goto legacy;
375
376 ret = ctx->op.kex.exchange->derive(ctx->op.kex.exchprovctx, key, pkeylen,
377 SIZE_MAX);
378
379 return ret;
380 legacy:
381 if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->derive == NULL) {
382 EVPerr(EVP_F_EVP_PKEY_DERIVE,
383 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
384 return -2;
385 }
386
387 M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
388 return ctx->pmeth->derive(ctx, key, pkeylen);
389 }
390
391 int EVP_KEYEXCH_number(const EVP_KEYEXCH *keyexch)
392 {
393 return keyexch->name_id;
394 }
395
396 int EVP_KEYEXCH_is_a(const EVP_KEYEXCH *keyexch, const char *name)
397 {
398 return evp_is_a(keyexch->prov, keyexch->name_id, name);
399 }
400
401 void EVP_KEYEXCH_do_all_provided(OPENSSL_CTX *libctx,
402 void (*fn)(EVP_KEYEXCH *keyexch, void *arg),
403 void *arg)
404 {
405 struct keymgmt_data_st keymgmt_data;
406
407 keymgmt_data.ctx = libctx;
408 keymgmt_data.properties = NULL;
409 evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
410 (void (*)(void *, void *))fn, arg,
411 evp_keyexch_from_dispatch, &keymgmt_data,
412 (void (*)(void *))EVP_KEYEXCH_free);
413 }
414
415 void EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch,
416 void (*fn)(const char *name, void *data),
417 void *data)
418 {
419 if (keyexch->prov != NULL)
420 evp_names_do_all(keyexch->prov, keyexch->name_id, fn, data);
421 }