]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/kem.c
EVP: Add internal functions to fetch type specific EVP methods from provider
[thirdparty/openssl.git] / crypto / evp / kem.c
CommitLineData
80f4fd18 1/*
8020d79b 2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
80f4fd18
SL
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 <stdio.h>
11#include <stdlib.h>
12#include <openssl/objects.h>
13#include <openssl/evp.h>
14#include "internal/cryptlib.h"
80f4fd18 15#include "internal/provider.h"
6c9bc258
TM
16#include "internal/core.h"
17#include "crypto/evp.h"
80f4fd18
SL
18#include "evp_local.h"
19
4b58d9b4
P
20static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
21 const OSSL_PARAM params[])
80f4fd18
SL
22{
23 int ret = 0;
24 EVP_KEM *kem = NULL;
25 EVP_KEYMGMT *tmp_keymgmt = NULL;
26 void *provkey = NULL;
27 const char *supported_kem = NULL;
28
29 if (ctx == NULL || ctx->keytype == NULL) {
30 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
31 return 0;
32 }
33
34 evp_pkey_ctx_free_old_ops(ctx);
35 ctx->operation = operation;
36
37 /*
5246183e 38 * Try to derive the supported kem from |ctx->keymgmt|.
80f4fd18 39 */
5246183e
RL
40 if (!ossl_assert(ctx->pkey->keymgmt == NULL
41 || ctx->pkey->keymgmt == ctx->keymgmt)) {
42 ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
43 goto err;
44 }
45 supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
46 OSSL_OP_KEM);
47 if (supported_kem == NULL) {
80f4fd18
SL
48 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
49 goto err;
50 }
80f4fd18
SL
51
52 kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery);
5246183e 53 if (kem == NULL) {
80f4fd18
SL
54 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
55 ret = -2;
56 goto err;
57 }
58
5246183e
RL
59 /*
60 * Ensure that the key is provided, either natively, or as a cached export.
61 * We start by fetching the keymgmt with the same name as |ctx->pkey|,
62 * but from the provider of the kem method, using the same property
63 * query as when fetching the kem method.
64 * With the keymgmt we found (if we did), we try to export |ctx->pkey|
65 * to it (evp_pkey_export_to_provider() is smart enough to only actually
66
67 * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
68 */
69 tmp_keymgmt
70 = evp_keymgmt_fetch_from_prov(EVP_KEM_get0_provider(kem),
71 EVP_KEYMGMT_get0_name(ctx->keymgmt),
72 ctx->propquery);
73 if (tmp_keymgmt != NULL)
74 provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
75 &tmp_keymgmt, ctx->propquery);
76 if (provkey == NULL) {
77 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
78 goto err;
79 }
80
80f4fd18 81 ctx->op.encap.kem = kem;
7c14d0c1
SL
82 ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
83 if (ctx->op.encap.algctx == NULL) {
80f4fd18
SL
84 /* The provider key can stay in the cache */
85 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
86 goto err;
87 }
88
89 switch (operation) {
90 case EVP_PKEY_OP_ENCAPSULATE:
91 if (kem->encapsulate_init == NULL) {
92 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
93 ret = -2;
94 goto err;
95 }
7c14d0c1 96 ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params);
80f4fd18
SL
97 break;
98 case EVP_PKEY_OP_DECAPSULATE:
99 if (kem->decapsulate_init == NULL) {
100 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
101 ret = -2;
102 goto err;
103 }
7c14d0c1 104 ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params);
80f4fd18
SL
105 break;
106 default:
107 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
108 goto err;
109 }
110
5246183e
RL
111 EVP_KEYMGMT_free(tmp_keymgmt);
112 tmp_keymgmt = NULL;
113
80f4fd18
SL
114 if (ret > 0)
115 return 1;
116 err:
117 if (ret <= 0) {
118 evp_pkey_ctx_free_old_ops(ctx);
119 ctx->operation = EVP_PKEY_OP_UNDEFINED;
120 }
5246183e 121 EVP_KEYMGMT_free(tmp_keymgmt);
80f4fd18
SL
122 return ret;
123}
124
4b58d9b4 125int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
80f4fd18 126{
4b58d9b4 127 return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params);
80f4fd18
SL
128}
129
130int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
131 unsigned char *out, size_t *outlen,
132 unsigned char *secret, size_t *secretlen)
133{
134 if (ctx == NULL)
135 return 0;
136
137 if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) {
bf23b9a1 138 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
80f4fd18
SL
139 return -1;
140 }
141
7c14d0c1 142 if (ctx->op.encap.algctx == NULL) {
9311d0c4 143 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
80f4fd18
SL
144 return -2;
145 }
146
147 if (out != NULL && secret == NULL)
148 return 0;
149
7c14d0c1 150 return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx,
80f4fd18
SL
151 out, outlen, secret, secretlen);
152}
153
4b58d9b4 154int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
80f4fd18 155{
4b58d9b4 156 return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params);
80f4fd18
SL
157}
158
159int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
160 unsigned char *secret, size_t *secretlen,
161 const unsigned char *in, size_t inlen)
162{
163 if (ctx == NULL
164 || (in == NULL || inlen == 0)
165 || (secret == NULL && secretlen == NULL))
166 return 0;
167
168 if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) {
bf23b9a1 169 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
80f4fd18
SL
170 return -1;
171 }
172
7c14d0c1 173 if (ctx->op.encap.algctx == NULL) {
9311d0c4 174 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
80f4fd18
SL
175 return -2;
176 }
7c14d0c1 177 return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx,
80f4fd18
SL
178 secret, secretlen, in, inlen);
179}
180
181static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov)
182{
183 EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM));
184
185 if (kem == NULL) {
186 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
187 return NULL;
188 }
189
190 kem->lock = CRYPTO_THREAD_lock_new();
191 if (kem->lock == NULL) {
192 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
193 OPENSSL_free(kem);
194 return NULL;
195 }
196 kem->prov = prov;
197 ossl_provider_up_ref(prov);
198 kem->refcnt = 1;
199
200 return kem;
201}
202
309a78aa
RL
203static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
204 OSSL_PROVIDER *prov)
80f4fd18 205{
309a78aa 206 const OSSL_DISPATCH *fns = algodef->implementation;
80f4fd18
SL
207 EVP_KEM *kem = NULL;
208 int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
209 int gparamfncnt = 0, sparamfncnt = 0;
210
211 if ((kem = evp_kem_new(prov)) == NULL) {
212 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
213 goto err;
214 }
215
216 kem->name_id = name_id;
6c9bc258
TM
217 if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
218 goto err;
309a78aa 219 kem->description = algodef->algorithm_description;
80f4fd18
SL
220
221 for (; fns->function_id != 0; fns++) {
222 switch (fns->function_id) {
223 case OSSL_FUNC_KEM_NEWCTX:
224 if (kem->newctx != NULL)
225 break;
226 kem->newctx = OSSL_FUNC_kem_newctx(fns);
227 ctxfncnt++;
228 break;
229 case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
230 if (kem->encapsulate_init != NULL)
231 break;
232 kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
233 encfncnt++;
234 break;
235 case OSSL_FUNC_KEM_ENCAPSULATE:
236 if (kem->encapsulate != NULL)
237 break;
238 kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
239 encfncnt++;
240 break;
241 case OSSL_FUNC_KEM_DECAPSULATE_INIT:
242 if (kem->decapsulate_init != NULL)
243 break;
244 kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
245 decfncnt++;
246 break;
247 case OSSL_FUNC_KEM_DECAPSULATE:
248 if (kem->decapsulate != NULL)
249 break;
250 kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
251 decfncnt++;
252 break;
253 case OSSL_FUNC_KEM_FREECTX:
254 if (kem->freectx != NULL)
255 break;
256 kem->freectx = OSSL_FUNC_kem_freectx(fns);
257 ctxfncnt++;
258 break;
259 case OSSL_FUNC_KEM_DUPCTX:
260 if (kem->dupctx != NULL)
261 break;
262 kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
263 break;
264 case OSSL_FUNC_KEM_GET_CTX_PARAMS:
265 if (kem->get_ctx_params != NULL)
266 break;
267 kem->get_ctx_params
268 = OSSL_FUNC_kem_get_ctx_params(fns);
269 gparamfncnt++;
270 break;
271 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
272 if (kem->gettable_ctx_params != NULL)
273 break;
274 kem->gettable_ctx_params
275 = OSSL_FUNC_kem_gettable_ctx_params(fns);
276 gparamfncnt++;
277 break;
278 case OSSL_FUNC_KEM_SET_CTX_PARAMS:
279 if (kem->set_ctx_params != NULL)
280 break;
281 kem->set_ctx_params
282 = OSSL_FUNC_kem_set_ctx_params(fns);
283 sparamfncnt++;
284 break;
285 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
286 if (kem->settable_ctx_params != NULL)
287 break;
288 kem->settable_ctx_params
289 = OSSL_FUNC_kem_settable_ctx_params(fns);
290 sparamfncnt++;
291 break;
292 }
293 }
294 if (ctxfncnt != 2
295 || (encfncnt != 0 && encfncnt != 2)
296 || (decfncnt != 0 && decfncnt != 2)
297 || (encfncnt != 2 && decfncnt != 2)
298 || (gparamfncnt != 0 && gparamfncnt != 2)
299 || (sparamfncnt != 0 && sparamfncnt != 2)) {
300 /*
301 * In order to be a consistent set of functions we must have at least
302 * a set of context functions (newctx and freectx) as well as a pair of
303 * "kem" functions: (encapsulate_init, encapsulate) or
304 * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are
305 * optional, but if one of them is present then the other one must also
306 * be present. The same applies to get_ctx_params and
307 * gettable_ctx_params. The dupctx function is optional.
308 */
309 ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
310 goto err;
311 }
312
313 return kem;
314 err:
315 EVP_KEM_free(kem);
316 return NULL;
317}
318
319void EVP_KEM_free(EVP_KEM *kem)
320{
543e740b
RS
321 int i;
322
323 if (kem == NULL)
324 return;
325
326 CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock);
327 if (i > 0)
328 return;
6c9bc258 329 OPENSSL_free(kem->type_name);
543e740b
RS
330 ossl_provider_free(kem->prov);
331 CRYPTO_THREAD_lock_free(kem->lock);
332 OPENSSL_free(kem);
80f4fd18
SL
333}
334
335int EVP_KEM_up_ref(EVP_KEM *kem)
336{
337 int ref = 0;
338
339 CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock);
340 return 1;
341}
342
ed576acd 343OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
80f4fd18
SL
344{
345 return kem->prov;
346}
347
b4250010 348EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
80f4fd18
SL
349 const char *properties)
350{
351 return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
309a78aa 352 evp_kem_from_algorithm,
80f4fd18
SL
353 (int (*)(void *))EVP_KEM_up_ref,
354 (void (*)(void *))EVP_KEM_free);
355}
356
ff778146
RL
357EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
358 const char *properties)
359{
360 return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
361 evp_kem_from_algorithm,
362 (int (*)(void *))EVP_KEM_up_ref,
363 (void (*)(void *))EVP_KEM_free);
364}
365
80f4fd18
SL
366int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
367{
368 return evp_is_a(kem->prov, kem->name_id, NULL, name);
369}
370
bcd5d3a2 371int evp_kem_get_number(const EVP_KEM *kem)
80f4fd18
SL
372{
373 return kem->name_id;
374}
375
ed576acd 376const char *EVP_KEM_get0_name(const EVP_KEM *kem)
6c9bc258
TM
377{
378 return kem->type_name;
379}
380
ed576acd 381const char *EVP_KEM_get0_description(const EVP_KEM *kem)
03888233
RL
382{
383 return kem->description;
384}
385
b4250010 386void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
80f4fd18
SL
387 void (*fn)(EVP_KEM *kem, void *arg),
388 void *arg)
389{
390 evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
309a78aa 391 evp_kem_from_algorithm,
cd770738 392 (int (*)(void *))EVP_KEM_up_ref,
80f4fd18
SL
393 (void (*)(void *))EVP_KEM_free);
394}
395
d84f5515
MC
396int EVP_KEM_names_do_all(const EVP_KEM *kem,
397 void (*fn)(const char *name, void *data),
398 void *data)
80f4fd18
SL
399{
400 if (kem->prov != NULL)
d84f5515
MC
401 return evp_names_do_all(kem->prov, kem->name_id, fn, data);
402
403 return 1;
80f4fd18 404}
5a950048
SL
405
406const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
407{
408 void *provctx;
409
410 if (kem == NULL || kem->gettable_ctx_params == NULL)
411 return NULL;
412
ed576acd 413 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
fb67126e 414 return kem->gettable_ctx_params(NULL, provctx);
5a950048
SL
415}
416
417const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
418{
419 void *provctx;
420
421 if (kem == NULL || kem->settable_ctx_params == NULL)
422 return NULL;
423
ed576acd 424 provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
fb67126e 425 return kem->settable_ctx_params(NULL, provctx);
5a950048 426}