]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/exchange.c
Reorganize local header files
[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 = 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);
230 goto err;
231 }
232 }
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);
237 goto err;
238 }
239 ret = exchange->init(ctx->op.kex.exchprovctx, provkey);
240
241 return ret ? 1 : 0;
242 err:
243 ctx->operation = EVP_PKEY_OP_UNDEFINED;
244 return 0;
245
246 legacy:
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);
250 return -2;
251 }
252
253 if (ctx->pmeth->derive_init == NULL)
254 return 1;
255 ret = ctx->pmeth->derive_init(ctx);
256 if (ret <= 0)
257 ctx->operation = EVP_PKEY_OP_UNDEFINED;
258 return ret;
259 }
260
261 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
262 {
263 return EVP_PKEY_derive_init_ex(ctx, NULL);
264 }
265
266 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
267 {
268 int ret;
269 void *provkey = NULL;
270
271 if (ctx == NULL) {
272 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
273 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
274 return -2;
275 }
276
277 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx) || ctx->op.kex.exchprovctx == NULL)
278 goto legacy;
279
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);
283 return -2;
284 }
285
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);
290 return 0;
291 }
292 return ctx->op.kex.exchange->set_peer(ctx->op.kex.exchprovctx, provkey);
293
294 legacy:
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);
302 return -2;
303 }
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);
309 return -1;
310 }
311
312 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
313
314 if (ret <= 0)
315 return ret;
316
317 if (ret == 2)
318 return 1;
319
320 if (ctx->pkey == NULL) {
321 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
322 return -1;
323 }
324
325 if (ctx->pkey->type != peer->type) {
326 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES);
327 return -1;
328 }
329
330 /*
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.
336 */
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);
340 return -1;
341 }
342
343 EVP_PKEY_free(ctx->peerkey);
344 ctx->peerkey = peer;
345
346 ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
347
348 if (ret <= 0) {
349 ctx->peerkey = NULL;
350 return ret;
351 }
352
353 EVP_PKEY_up_ref(peer);
354 return 1;
355 }
356
357 int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
358 {
359 int ret;
360
361 if (ctx == NULL) {
362 EVPerr(EVP_F_EVP_PKEY_DERIVE,
363 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
364 return -2;
365 }
366
367 if (!EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
368 EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
369 return -1;
370 }
371
372 if (ctx->op.kex.exchprovctx == NULL)
373 goto legacy;
374
375 ret = ctx->op.kex.exchange->derive(ctx->op.kex.exchprovctx, key, pkeylen,
376 SIZE_MAX);
377
378 return ret;
379 legacy:
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);
383 return -2;
384 }
385
386 M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
387 return ctx->pmeth->derive(ctx, key, pkeylen);
388 }