2 * Copyright 2020-2023 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
12 #include <openssl/objects.h>
13 #include <openssl/evp.h>
14 #include "internal/cryptlib.h"
15 #include "internal/provider.h"
16 #include "internal/core.h"
17 #include "crypto/evp.h"
18 #include "evp_local.h"
20 static int evp_kem_init(EVP_PKEY_CTX
*ctx
, int operation
,
21 const OSSL_PARAM params
[], EVP_PKEY
*authkey
)
25 EVP_KEYMGMT
*tmp_keymgmt
= NULL
;
26 const OSSL_PROVIDER
*tmp_prov
= NULL
;
27 void *provkey
= NULL
, *provauthkey
= NULL
;
28 const char *supported_kem
= NULL
;
31 if (ctx
== NULL
|| ctx
->keytype
== NULL
) {
32 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
36 evp_pkey_ctx_free_old_ops(ctx
);
37 ctx
->operation
= operation
;
39 if (ctx
->pkey
== NULL
) {
40 ERR_raise(ERR_LIB_EVP
, EVP_R_NO_KEY_SET
);
43 if (authkey
!= NULL
&& authkey
->type
!= ctx
->pkey
->type
) {
44 ERR_raise(ERR_LIB_EVP
, EVP_R_DIFFERENT_KEY_TYPES
);
48 * Try to derive the supported kem from |ctx->keymgmt|.
50 if (!ossl_assert(ctx
->pkey
->keymgmt
== NULL
51 || ctx
->pkey
->keymgmt
== ctx
->keymgmt
)) {
52 ERR_raise(ERR_LIB_EVP
, ERR_R_INTERNAL_ERROR
);
55 supported_kem
= evp_keymgmt_util_query_operation_name(ctx
->keymgmt
,
57 if (supported_kem
== NULL
) {
58 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
63 * Because we cleared out old ops, we shouldn't need to worry about
64 * checking if kem is already there.
65 * We perform two iterations:
67 * 1. Do the normal kem fetch, using the fetching data given by
69 * 2. Do the provider specific kem fetch, from the same provider
72 * We then try to fetch the keymgmt from the same provider as the
73 * kem, and try to export |ctx->pkey| to that keymgmt (when this
74 * keymgmt happens to be the same as |ctx->keymgmt|, the export is
75 * a no-op, but we call it anyway to not complicate the code even
77 * If the export call succeeds (returns a non-NULL provider key pointer),
78 * we're done and can perform the operation itself. If not, we perform
79 * the second iteration, or jump to legacy.
81 for (iter
= 1, provkey
= NULL
; iter
< 3 && provkey
== NULL
; iter
++) {
82 EVP_KEYMGMT
*tmp_keymgmt_tofree
= NULL
;
85 * If we're on the second iteration, free the results from the first.
86 * They are NULL on the first iteration, so no need to check what
90 EVP_KEYMGMT_free(tmp_keymgmt
);
94 kem
= EVP_KEM_fetch(ctx
->libctx
, supported_kem
, ctx
->propquery
);
96 tmp_prov
= EVP_KEM_get0_provider(kem
);
99 tmp_prov
= EVP_KEYMGMT_get0_provider(ctx
->keymgmt
);
100 kem
= evp_kem_fetch_from_prov((OSSL_PROVIDER
*)tmp_prov
,
101 supported_kem
, ctx
->propquery
);
104 ERR_raise(ERR_LIB_EVP
,
105 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
114 * Ensure that the key is provided, either natively, or as a cached
115 * export. We start by fetching the keymgmt with the same name as
116 * |ctx->pkey|, but from the provider of the kem method, using the
117 * same property query as when fetching the kem method.
118 * With the keymgmt we found (if we did), we try to export |ctx->pkey|
119 * to it (evp_pkey_export_to_provider() is smart enough to only actually
120 * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
122 tmp_keymgmt_tofree
= tmp_keymgmt
=
123 evp_keymgmt_fetch_from_prov((OSSL_PROVIDER
*)tmp_prov
,
124 EVP_KEYMGMT_get0_name(ctx
->keymgmt
),
126 if (tmp_keymgmt
!= NULL
) {
127 provkey
= evp_pkey_export_to_provider(ctx
->pkey
, ctx
->libctx
,
128 &tmp_keymgmt
, ctx
->propquery
);
129 if (provkey
!= NULL
&& authkey
!= NULL
) {
130 provauthkey
= evp_pkey_export_to_provider(authkey
, ctx
->libctx
,
133 if (provauthkey
== NULL
) {
135 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
140 if (tmp_keymgmt
== NULL
)
141 EVP_KEYMGMT_free(tmp_keymgmt_tofree
);
144 if (provkey
== NULL
) {
146 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
150 ctx
->op
.encap
.kem
= kem
;
151 ctx
->op
.encap
.algctx
= kem
->newctx(ossl_provider_ctx(kem
->prov
));
152 if (ctx
->op
.encap
.algctx
== NULL
) {
153 /* The provider key can stay in the cache */
154 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
159 case EVP_PKEY_OP_ENCAPSULATE
:
160 if (provauthkey
!= NULL
&& kem
->auth_encapsulate_init
!= NULL
) {
161 ret
= kem
->auth_encapsulate_init(ctx
->op
.encap
.algctx
, provkey
,
162 provauthkey
, params
);
163 } else if (provauthkey
== NULL
&& kem
->encapsulate_init
!= NULL
) {
164 ret
= kem
->encapsulate_init(ctx
->op
.encap
.algctx
, provkey
, params
);
166 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
171 case EVP_PKEY_OP_DECAPSULATE
:
172 if (provauthkey
!= NULL
&& kem
->auth_decapsulate_init
!= NULL
) {
173 ret
= kem
->auth_decapsulate_init(ctx
->op
.encap
.algctx
, provkey
,
174 provauthkey
, params
);
175 } else if (provauthkey
== NULL
&& kem
->encapsulate_init
!= NULL
) {
176 ret
= kem
->decapsulate_init(ctx
->op
.encap
.algctx
, provkey
, params
);
178 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
184 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
188 EVP_KEYMGMT_free(tmp_keymgmt
);
195 evp_pkey_ctx_free_old_ops(ctx
);
196 ctx
->operation
= EVP_PKEY_OP_UNDEFINED
;
198 EVP_KEYMGMT_free(tmp_keymgmt
);
202 int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*authpriv
,
203 const OSSL_PARAM params
[])
205 if (authpriv
== NULL
)
207 return evp_kem_init(ctx
, EVP_PKEY_OP_ENCAPSULATE
, params
, authpriv
);
210 int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX
*ctx
, const OSSL_PARAM params
[])
212 return evp_kem_init(ctx
, EVP_PKEY_OP_ENCAPSULATE
, params
, NULL
);
215 int EVP_PKEY_encapsulate(EVP_PKEY_CTX
*ctx
,
216 unsigned char *out
, size_t *outlen
,
217 unsigned char *secret
, size_t *secretlen
)
222 if (ctx
->operation
!= EVP_PKEY_OP_ENCAPSULATE
) {
223 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_INITIALIZED
);
227 if (ctx
->op
.encap
.algctx
== NULL
) {
228 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
232 if (out
!= NULL
&& secret
== NULL
)
235 return ctx
->op
.encap
.kem
->encapsulate(ctx
->op
.encap
.algctx
,
236 out
, outlen
, secret
, secretlen
);
239 int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX
*ctx
, const OSSL_PARAM params
[])
241 return evp_kem_init(ctx
, EVP_PKEY_OP_DECAPSULATE
, params
, NULL
);
244 int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*authpub
,
245 const OSSL_PARAM params
[])
249 return evp_kem_init(ctx
, EVP_PKEY_OP_DECAPSULATE
, params
, authpub
);
252 int EVP_PKEY_decapsulate(EVP_PKEY_CTX
*ctx
,
253 unsigned char *secret
, size_t *secretlen
,
254 const unsigned char *in
, size_t inlen
)
257 || (in
== NULL
|| inlen
== 0)
258 || (secret
== NULL
&& secretlen
== NULL
))
261 if (ctx
->operation
!= EVP_PKEY_OP_DECAPSULATE
) {
262 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_INITIALIZED
);
266 if (ctx
->op
.encap
.algctx
== NULL
) {
267 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
270 return ctx
->op
.encap
.kem
->decapsulate(ctx
->op
.encap
.algctx
,
271 secret
, secretlen
, in
, inlen
);
274 static EVP_KEM
*evp_kem_new(OSSL_PROVIDER
*prov
)
276 EVP_KEM
*kem
= OPENSSL_zalloc(sizeof(EVP_KEM
));
281 if (!CRYPTO_NEW_REF(&kem
->refcnt
, 1)) {
286 ossl_provider_up_ref(prov
);
291 static void *evp_kem_from_algorithm(int name_id
, const OSSL_ALGORITHM
*algodef
,
294 const OSSL_DISPATCH
*fns
= algodef
->implementation
;
296 int ctxfncnt
= 0, encfncnt
= 0, decfncnt
= 0;
297 int gparamfncnt
= 0, sparamfncnt
= 0;
299 if ((kem
= evp_kem_new(prov
)) == NULL
) {
300 ERR_raise(ERR_LIB_EVP
, ERR_R_EVP_LIB
);
304 kem
->name_id
= name_id
;
305 if ((kem
->type_name
= ossl_algorithm_get1_first_name(algodef
)) == NULL
)
307 kem
->description
= algodef
->algorithm_description
;
309 for (; fns
->function_id
!= 0; fns
++) {
310 switch (fns
->function_id
) {
311 case OSSL_FUNC_KEM_NEWCTX
:
312 if (kem
->newctx
!= NULL
)
314 kem
->newctx
= OSSL_FUNC_kem_newctx(fns
);
317 case OSSL_FUNC_KEM_ENCAPSULATE_INIT
:
318 if (kem
->encapsulate_init
!= NULL
)
320 kem
->encapsulate_init
= OSSL_FUNC_kem_encapsulate_init(fns
);
323 case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT
:
324 if (kem
->auth_encapsulate_init
!= NULL
)
326 kem
->auth_encapsulate_init
= OSSL_FUNC_kem_auth_encapsulate_init(fns
);
329 case OSSL_FUNC_KEM_ENCAPSULATE
:
330 if (kem
->encapsulate
!= NULL
)
332 kem
->encapsulate
= OSSL_FUNC_kem_encapsulate(fns
);
335 case OSSL_FUNC_KEM_DECAPSULATE_INIT
:
336 if (kem
->decapsulate_init
!= NULL
)
338 kem
->decapsulate_init
= OSSL_FUNC_kem_decapsulate_init(fns
);
341 case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT
:
342 if (kem
->auth_decapsulate_init
!= NULL
)
344 kem
->auth_decapsulate_init
= OSSL_FUNC_kem_auth_decapsulate_init(fns
);
347 case OSSL_FUNC_KEM_DECAPSULATE
:
348 if (kem
->decapsulate
!= NULL
)
350 kem
->decapsulate
= OSSL_FUNC_kem_decapsulate(fns
);
353 case OSSL_FUNC_KEM_FREECTX
:
354 if (kem
->freectx
!= NULL
)
356 kem
->freectx
= OSSL_FUNC_kem_freectx(fns
);
359 case OSSL_FUNC_KEM_DUPCTX
:
360 if (kem
->dupctx
!= NULL
)
362 kem
->dupctx
= OSSL_FUNC_kem_dupctx(fns
);
364 case OSSL_FUNC_KEM_GET_CTX_PARAMS
:
365 if (kem
->get_ctx_params
!= NULL
)
368 = OSSL_FUNC_kem_get_ctx_params(fns
);
371 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS
:
372 if (kem
->gettable_ctx_params
!= NULL
)
374 kem
->gettable_ctx_params
375 = OSSL_FUNC_kem_gettable_ctx_params(fns
);
378 case OSSL_FUNC_KEM_SET_CTX_PARAMS
:
379 if (kem
->set_ctx_params
!= NULL
)
382 = OSSL_FUNC_kem_set_ctx_params(fns
);
385 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS
:
386 if (kem
->settable_ctx_params
!= NULL
)
388 kem
->settable_ctx_params
389 = OSSL_FUNC_kem_settable_ctx_params(fns
);
395 || (encfncnt
!= 0 && encfncnt
!= 2 && encfncnt
!= 3)
396 || (decfncnt
!= 0 && decfncnt
!= 2 && decfncnt
!= 3)
397 || (encfncnt
!= decfncnt
)
398 || (gparamfncnt
!= 0 && gparamfncnt
!= 2)
399 || (sparamfncnt
!= 0 && sparamfncnt
!= 2)) {
401 * In order to be a consistent set of functions we must have at least
402 * a set of context functions (newctx and freectx) as well as a pair
403 * (or triplet) of "kem" functions:
404 * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or
405 * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate).
406 * set_ctx_params and settable_ctx_params are optional, but if one of
407 * them is present then the other one must also be present. The same
408 * applies to get_ctx_params and gettable_ctx_params.
409 * The dupctx function is optional.
411 ERR_raise(ERR_LIB_EVP
, EVP_R_INVALID_PROVIDER_FUNCTIONS
);
421 void EVP_KEM_free(EVP_KEM
*kem
)
428 CRYPTO_DOWN_REF(&kem
->refcnt
, &i
);
431 OPENSSL_free(kem
->type_name
);
432 ossl_provider_free(kem
->prov
);
433 CRYPTO_FREE_REF(&kem
->refcnt
);
437 int EVP_KEM_up_ref(EVP_KEM
*kem
)
441 CRYPTO_UP_REF(&kem
->refcnt
, &ref
);
445 OSSL_PROVIDER
*EVP_KEM_get0_provider(const EVP_KEM
*kem
)
450 EVP_KEM
*EVP_KEM_fetch(OSSL_LIB_CTX
*ctx
, const char *algorithm
,
451 const char *properties
)
453 return evp_generic_fetch(ctx
, OSSL_OP_KEM
, algorithm
, properties
,
454 evp_kem_from_algorithm
,
455 (int (*)(void *))EVP_KEM_up_ref
,
456 (void (*)(void *))EVP_KEM_free
);
459 EVP_KEM
*evp_kem_fetch_from_prov(OSSL_PROVIDER
*prov
, const char *algorithm
,
460 const char *properties
)
462 return evp_generic_fetch_from_prov(prov
, OSSL_OP_KEM
, algorithm
, properties
,
463 evp_kem_from_algorithm
,
464 (int (*)(void *))EVP_KEM_up_ref
,
465 (void (*)(void *))EVP_KEM_free
);
468 int EVP_KEM_is_a(const EVP_KEM
*kem
, const char *name
)
470 return kem
!= NULL
&& evp_is_a(kem
->prov
, kem
->name_id
, NULL
, name
);
473 int evp_kem_get_number(const EVP_KEM
*kem
)
478 const char *EVP_KEM_get0_name(const EVP_KEM
*kem
)
480 return kem
->type_name
;
483 const char *EVP_KEM_get0_description(const EVP_KEM
*kem
)
485 return kem
->description
;
488 void EVP_KEM_do_all_provided(OSSL_LIB_CTX
*libctx
,
489 void (*fn
)(EVP_KEM
*kem
, void *arg
),
492 evp_generic_do_all(libctx
, OSSL_OP_KEM
, (void (*)(void *, void *))fn
, arg
,
493 evp_kem_from_algorithm
,
494 (int (*)(void *))EVP_KEM_up_ref
,
495 (void (*)(void *))EVP_KEM_free
);
498 int EVP_KEM_names_do_all(const EVP_KEM
*kem
,
499 void (*fn
)(const char *name
, void *data
),
502 if (kem
->prov
!= NULL
)
503 return evp_names_do_all(kem
->prov
, kem
->name_id
, fn
, data
);
508 const OSSL_PARAM
*EVP_KEM_gettable_ctx_params(const EVP_KEM
*kem
)
512 if (kem
== NULL
|| kem
->gettable_ctx_params
== NULL
)
515 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
516 return kem
->gettable_ctx_params(NULL
, provctx
);
519 const OSSL_PARAM
*EVP_KEM_settable_ctx_params(const EVP_KEM
*kem
)
523 if (kem
== NULL
|| kem
->settable_ctx_params
== NULL
)
526 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
527 return kem
->settable_ctx_params(NULL
, provctx
);