2 * Copyright 2020-2021 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
[])
25 EVP_KEYMGMT
*tmp_keymgmt
= NULL
;
26 const OSSL_PROVIDER
*tmp_prov
= 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
);
45 * Try to derive the supported kem from |ctx->keymgmt|.
47 if (!ossl_assert(ctx
->pkey
->keymgmt
== NULL
48 || ctx
->pkey
->keymgmt
== ctx
->keymgmt
)) {
49 ERR_raise(ERR_LIB_EVP
, ERR_R_INTERNAL_ERROR
);
52 supported_kem
= evp_keymgmt_util_query_operation_name(ctx
->keymgmt
,
54 if (supported_kem
== NULL
) {
55 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
60 * Because we cleared out old ops, we shouldn't need to worry about
61 * checking if kem is already there.
62 * We perform two iterations:
64 * 1. Do the normal kem fetch, using the fetching data given by
66 * 2. Do the provider specific kem fetch, from the same provider
69 * We then try to fetch the keymgmt from the same provider as the
70 * kem, and try to export |ctx->pkey| to that keymgmt (when this
71 * keymgmt happens to be the same as |ctx->keymgmt|, the export is
72 * a no-op, but we call it anyway to not complicate the code even
74 * If the export call succeeds (returns a non-NULL provider key pointer),
75 * we're done and can perform the operation itself. If not, we perform
76 * the second iteration, or jump to legacy.
78 for (iter
= 1, provkey
= NULL
; iter
< 3 && provkey
== NULL
; iter
++) {
79 EVP_KEYMGMT
*tmp_keymgmt_tofree
= NULL
;
82 * If we're on the second iteration, free the results from the first.
83 * They are NULL on the first iteration, so no need to check what
87 EVP_KEYMGMT_free(tmp_keymgmt
);
91 kem
= EVP_KEM_fetch(ctx
->libctx
, supported_kem
, ctx
->propquery
);
93 tmp_prov
= EVP_KEM_get0_provider(kem
);
96 tmp_prov
= EVP_KEYMGMT_get0_provider(ctx
->keymgmt
);
97 kem
= evp_kem_fetch_from_prov((OSSL_PROVIDER
*)tmp_prov
,
98 supported_kem
, ctx
->propquery
);
101 ERR_raise(ERR_LIB_EVP
,
102 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
111 * Ensure that the key is provided, either natively, or as a cached
112 * export. We start by fetching the keymgmt with the same name as
113 * |ctx->pkey|, but from the provider of the kem method, using the
114 * same property query as when fetching the kem method.
115 * With the keymgmt we found (if we did), we try to export |ctx->pkey|
116 * to it (evp_pkey_export_to_provider() is smart enough to only actually
118 * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
120 tmp_keymgmt_tofree
= tmp_keymgmt
=
121 evp_keymgmt_fetch_from_prov((OSSL_PROVIDER
*)tmp_prov
,
122 EVP_KEYMGMT_get0_name(ctx
->keymgmt
),
124 if (tmp_keymgmt
!= NULL
)
125 provkey
= evp_pkey_export_to_provider(ctx
->pkey
, ctx
->libctx
,
126 &tmp_keymgmt
, ctx
->propquery
);
127 if (tmp_keymgmt
== NULL
)
128 EVP_KEYMGMT_free(tmp_keymgmt_tofree
);
131 if (provkey
== NULL
) {
133 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
137 ctx
->op
.encap
.kem
= kem
;
138 ctx
->op
.encap
.algctx
= kem
->newctx(ossl_provider_ctx(kem
->prov
));
139 if (ctx
->op
.encap
.algctx
== NULL
) {
140 /* The provider key can stay in the cache */
141 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
146 case EVP_PKEY_OP_ENCAPSULATE
:
147 if (kem
->encapsulate_init
== NULL
) {
148 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
152 ret
= kem
->encapsulate_init(ctx
->op
.encap
.algctx
, provkey
, params
);
154 case EVP_PKEY_OP_DECAPSULATE
:
155 if (kem
->decapsulate_init
== NULL
) {
156 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
160 ret
= kem
->decapsulate_init(ctx
->op
.encap
.algctx
, provkey
, params
);
163 ERR_raise(ERR_LIB_EVP
, EVP_R_INITIALIZATION_ERROR
);
167 EVP_KEYMGMT_free(tmp_keymgmt
);
174 evp_pkey_ctx_free_old_ops(ctx
);
175 ctx
->operation
= EVP_PKEY_OP_UNDEFINED
;
177 EVP_KEYMGMT_free(tmp_keymgmt
);
181 int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX
*ctx
, const OSSL_PARAM params
[])
183 return evp_kem_init(ctx
, EVP_PKEY_OP_ENCAPSULATE
, params
);
186 int EVP_PKEY_encapsulate(EVP_PKEY_CTX
*ctx
,
187 unsigned char *out
, size_t *outlen
,
188 unsigned char *secret
, size_t *secretlen
)
193 if (ctx
->operation
!= EVP_PKEY_OP_ENCAPSULATE
) {
194 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_INITIALIZED
);
198 if (ctx
->op
.encap
.algctx
== NULL
) {
199 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
203 if (out
!= NULL
&& secret
== NULL
)
206 return ctx
->op
.encap
.kem
->encapsulate(ctx
->op
.encap
.algctx
,
207 out
, outlen
, secret
, secretlen
);
210 int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX
*ctx
, const OSSL_PARAM params
[])
212 return evp_kem_init(ctx
, EVP_PKEY_OP_DECAPSULATE
, params
);
215 int EVP_PKEY_decapsulate(EVP_PKEY_CTX
*ctx
,
216 unsigned char *secret
, size_t *secretlen
,
217 const unsigned char *in
, size_t inlen
)
220 || (in
== NULL
|| inlen
== 0)
221 || (secret
== NULL
&& secretlen
== NULL
))
224 if (ctx
->operation
!= EVP_PKEY_OP_DECAPSULATE
) {
225 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_INITIALIZED
);
229 if (ctx
->op
.encap
.algctx
== NULL
) {
230 ERR_raise(ERR_LIB_EVP
, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
);
233 return ctx
->op
.encap
.kem
->decapsulate(ctx
->op
.encap
.algctx
,
234 secret
, secretlen
, in
, inlen
);
237 static EVP_KEM
*evp_kem_new(OSSL_PROVIDER
*prov
)
239 EVP_KEM
*kem
= OPENSSL_zalloc(sizeof(EVP_KEM
));
242 ERR_raise(ERR_LIB_EVP
, ERR_R_MALLOC_FAILURE
);
246 kem
->lock
= CRYPTO_THREAD_lock_new();
247 if (kem
->lock
== NULL
) {
248 ERR_raise(ERR_LIB_EVP
, ERR_R_MALLOC_FAILURE
);
253 ossl_provider_up_ref(prov
);
259 static void *evp_kem_from_algorithm(int name_id
, const OSSL_ALGORITHM
*algodef
,
262 const OSSL_DISPATCH
*fns
= algodef
->implementation
;
264 int ctxfncnt
= 0, encfncnt
= 0, decfncnt
= 0;
265 int gparamfncnt
= 0, sparamfncnt
= 0;
267 if ((kem
= evp_kem_new(prov
)) == NULL
) {
268 ERR_raise(ERR_LIB_EVP
, ERR_R_MALLOC_FAILURE
);
272 kem
->name_id
= name_id
;
273 if ((kem
->type_name
= ossl_algorithm_get1_first_name(algodef
)) == NULL
)
275 kem
->description
= algodef
->algorithm_description
;
277 for (; fns
->function_id
!= 0; fns
++) {
278 switch (fns
->function_id
) {
279 case OSSL_FUNC_KEM_NEWCTX
:
280 if (kem
->newctx
!= NULL
)
282 kem
->newctx
= OSSL_FUNC_kem_newctx(fns
);
285 case OSSL_FUNC_KEM_ENCAPSULATE_INIT
:
286 if (kem
->encapsulate_init
!= NULL
)
288 kem
->encapsulate_init
= OSSL_FUNC_kem_encapsulate_init(fns
);
291 case OSSL_FUNC_KEM_ENCAPSULATE
:
292 if (kem
->encapsulate
!= NULL
)
294 kem
->encapsulate
= OSSL_FUNC_kem_encapsulate(fns
);
297 case OSSL_FUNC_KEM_DECAPSULATE_INIT
:
298 if (kem
->decapsulate_init
!= NULL
)
300 kem
->decapsulate_init
= OSSL_FUNC_kem_decapsulate_init(fns
);
303 case OSSL_FUNC_KEM_DECAPSULATE
:
304 if (kem
->decapsulate
!= NULL
)
306 kem
->decapsulate
= OSSL_FUNC_kem_decapsulate(fns
);
309 case OSSL_FUNC_KEM_FREECTX
:
310 if (kem
->freectx
!= NULL
)
312 kem
->freectx
= OSSL_FUNC_kem_freectx(fns
);
315 case OSSL_FUNC_KEM_DUPCTX
:
316 if (kem
->dupctx
!= NULL
)
318 kem
->dupctx
= OSSL_FUNC_kem_dupctx(fns
);
320 case OSSL_FUNC_KEM_GET_CTX_PARAMS
:
321 if (kem
->get_ctx_params
!= NULL
)
324 = OSSL_FUNC_kem_get_ctx_params(fns
);
327 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS
:
328 if (kem
->gettable_ctx_params
!= NULL
)
330 kem
->gettable_ctx_params
331 = OSSL_FUNC_kem_gettable_ctx_params(fns
);
334 case OSSL_FUNC_KEM_SET_CTX_PARAMS
:
335 if (kem
->set_ctx_params
!= NULL
)
338 = OSSL_FUNC_kem_set_ctx_params(fns
);
341 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS
:
342 if (kem
->settable_ctx_params
!= NULL
)
344 kem
->settable_ctx_params
345 = OSSL_FUNC_kem_settable_ctx_params(fns
);
351 || (encfncnt
!= 0 && encfncnt
!= 2)
352 || (decfncnt
!= 0 && decfncnt
!= 2)
353 || (encfncnt
!= 2 && decfncnt
!= 2)
354 || (gparamfncnt
!= 0 && gparamfncnt
!= 2)
355 || (sparamfncnt
!= 0 && sparamfncnt
!= 2)) {
357 * In order to be a consistent set of functions we must have at least
358 * a set of context functions (newctx and freectx) as well as a pair of
359 * "kem" functions: (encapsulate_init, encapsulate) or
360 * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are
361 * optional, but if one of them is present then the other one must also
362 * be present. The same applies to get_ctx_params and
363 * gettable_ctx_params. The dupctx function is optional.
365 ERR_raise(ERR_LIB_EVP
, EVP_R_INVALID_PROVIDER_FUNCTIONS
);
375 void EVP_KEM_free(EVP_KEM
*kem
)
382 CRYPTO_DOWN_REF(&kem
->refcnt
, &i
, kem
->lock
);
385 OPENSSL_free(kem
->type_name
);
386 ossl_provider_free(kem
->prov
);
387 CRYPTO_THREAD_lock_free(kem
->lock
);
391 int EVP_KEM_up_ref(EVP_KEM
*kem
)
395 CRYPTO_UP_REF(&kem
->refcnt
, &ref
, kem
->lock
);
399 OSSL_PROVIDER
*EVP_KEM_get0_provider(const EVP_KEM
*kem
)
404 EVP_KEM
*EVP_KEM_fetch(OSSL_LIB_CTX
*ctx
, const char *algorithm
,
405 const char *properties
)
407 return evp_generic_fetch(ctx
, OSSL_OP_KEM
, algorithm
, properties
,
408 evp_kem_from_algorithm
,
409 (int (*)(void *))EVP_KEM_up_ref
,
410 (void (*)(void *))EVP_KEM_free
);
413 EVP_KEM
*evp_kem_fetch_from_prov(OSSL_PROVIDER
*prov
, const char *algorithm
,
414 const char *properties
)
416 return evp_generic_fetch_from_prov(prov
, OSSL_OP_KEM
, algorithm
, properties
,
417 evp_kem_from_algorithm
,
418 (int (*)(void *))EVP_KEM_up_ref
,
419 (void (*)(void *))EVP_KEM_free
);
422 int EVP_KEM_is_a(const EVP_KEM
*kem
, const char *name
)
424 return kem
!= NULL
&& evp_is_a(kem
->prov
, kem
->name_id
, NULL
, name
);
427 int evp_kem_get_number(const EVP_KEM
*kem
)
432 const char *EVP_KEM_get0_name(const EVP_KEM
*kem
)
434 return kem
->type_name
;
437 const char *EVP_KEM_get0_description(const EVP_KEM
*kem
)
439 return kem
->description
;
442 void EVP_KEM_do_all_provided(OSSL_LIB_CTX
*libctx
,
443 void (*fn
)(EVP_KEM
*kem
, void *arg
),
446 evp_generic_do_all(libctx
, OSSL_OP_KEM
, (void (*)(void *, void *))fn
, arg
,
447 evp_kem_from_algorithm
,
448 (int (*)(void *))EVP_KEM_up_ref
,
449 (void (*)(void *))EVP_KEM_free
);
452 int EVP_KEM_names_do_all(const EVP_KEM
*kem
,
453 void (*fn
)(const char *name
, void *data
),
456 if (kem
->prov
!= NULL
)
457 return evp_names_do_all(kem
->prov
, kem
->name_id
, fn
, data
);
462 const OSSL_PARAM
*EVP_KEM_gettable_ctx_params(const EVP_KEM
*kem
)
466 if (kem
== NULL
|| kem
->gettable_ctx_params
== NULL
)
469 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
470 return kem
->gettable_ctx_params(NULL
, provctx
);
473 const OSSL_PARAM
*EVP_KEM_settable_ctx_params(const EVP_KEM
*kem
)
477 if (kem
== NULL
|| kem
->settable_ctx_params
== NULL
)
480 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
481 return kem
->settable_ctx_params(NULL
, provctx
);