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
[], 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 kem
->lock
= CRYPTO_THREAD_lock_new();
282 if (kem
->lock
== NULL
) {
283 ERR_raise(ERR_LIB_EVP
, ERR_R_CRYPTO_LIB
);
288 ossl_provider_up_ref(prov
);
294 static void *evp_kem_from_algorithm(int name_id
, const OSSL_ALGORITHM
*algodef
,
297 const OSSL_DISPATCH
*fns
= algodef
->implementation
;
299 int ctxfncnt
= 0, encfncnt
= 0, decfncnt
= 0;
300 int gparamfncnt
= 0, sparamfncnt
= 0;
302 if ((kem
= evp_kem_new(prov
)) == NULL
) {
303 ERR_raise(ERR_LIB_EVP
, ERR_R_EVP_LIB
);
307 kem
->name_id
= name_id
;
308 if ((kem
->type_name
= ossl_algorithm_get1_first_name(algodef
)) == NULL
)
310 kem
->description
= algodef
->algorithm_description
;
312 for (; fns
->function_id
!= 0; fns
++) {
313 switch (fns
->function_id
) {
314 case OSSL_FUNC_KEM_NEWCTX
:
315 if (kem
->newctx
!= NULL
)
317 kem
->newctx
= OSSL_FUNC_kem_newctx(fns
);
320 case OSSL_FUNC_KEM_ENCAPSULATE_INIT
:
321 if (kem
->encapsulate_init
!= NULL
)
323 kem
->encapsulate_init
= OSSL_FUNC_kem_encapsulate_init(fns
);
326 case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT
:
327 if (kem
->auth_encapsulate_init
!= NULL
)
329 kem
->auth_encapsulate_init
= OSSL_FUNC_kem_auth_encapsulate_init(fns
);
332 case OSSL_FUNC_KEM_ENCAPSULATE
:
333 if (kem
->encapsulate
!= NULL
)
335 kem
->encapsulate
= OSSL_FUNC_kem_encapsulate(fns
);
338 case OSSL_FUNC_KEM_DECAPSULATE_INIT
:
339 if (kem
->decapsulate_init
!= NULL
)
341 kem
->decapsulate_init
= OSSL_FUNC_kem_decapsulate_init(fns
);
344 case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT
:
345 if (kem
->auth_decapsulate_init
!= NULL
)
347 kem
->auth_decapsulate_init
= OSSL_FUNC_kem_auth_decapsulate_init(fns
);
350 case OSSL_FUNC_KEM_DECAPSULATE
:
351 if (kem
->decapsulate
!= NULL
)
353 kem
->decapsulate
= OSSL_FUNC_kem_decapsulate(fns
);
356 case OSSL_FUNC_KEM_FREECTX
:
357 if (kem
->freectx
!= NULL
)
359 kem
->freectx
= OSSL_FUNC_kem_freectx(fns
);
362 case OSSL_FUNC_KEM_DUPCTX
:
363 if (kem
->dupctx
!= NULL
)
365 kem
->dupctx
= OSSL_FUNC_kem_dupctx(fns
);
367 case OSSL_FUNC_KEM_GET_CTX_PARAMS
:
368 if (kem
->get_ctx_params
!= NULL
)
371 = OSSL_FUNC_kem_get_ctx_params(fns
);
374 case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS
:
375 if (kem
->gettable_ctx_params
!= NULL
)
377 kem
->gettable_ctx_params
378 = OSSL_FUNC_kem_gettable_ctx_params(fns
);
381 case OSSL_FUNC_KEM_SET_CTX_PARAMS
:
382 if (kem
->set_ctx_params
!= NULL
)
385 = OSSL_FUNC_kem_set_ctx_params(fns
);
388 case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS
:
389 if (kem
->settable_ctx_params
!= NULL
)
391 kem
->settable_ctx_params
392 = OSSL_FUNC_kem_settable_ctx_params(fns
);
398 || (encfncnt
!= 0 && encfncnt
!= 2 && encfncnt
!= 3)
399 || (decfncnt
!= 0 && decfncnt
!= 2 && decfncnt
!= 3)
400 || (encfncnt
!= decfncnt
)
401 || (gparamfncnt
!= 0 && gparamfncnt
!= 2)
402 || (sparamfncnt
!= 0 && sparamfncnt
!= 2)) {
404 * In order to be a consistent set of functions we must have at least
405 * a set of context functions (newctx and freectx) as well as a pair
406 * (or triplet) of "kem" functions:
407 * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or
408 * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate).
409 * set_ctx_params and settable_ctx_params are optional, but if one of
410 * them is present then the other one must also be present. The same
411 * applies to get_ctx_params and gettable_ctx_params.
412 * The dupctx function is optional.
414 ERR_raise(ERR_LIB_EVP
, EVP_R_INVALID_PROVIDER_FUNCTIONS
);
424 void EVP_KEM_free(EVP_KEM
*kem
)
431 CRYPTO_DOWN_REF(&kem
->refcnt
, &i
, kem
->lock
);
434 OPENSSL_free(kem
->type_name
);
435 ossl_provider_free(kem
->prov
);
436 CRYPTO_THREAD_lock_free(kem
->lock
);
440 int EVP_KEM_up_ref(EVP_KEM
*kem
)
444 CRYPTO_UP_REF(&kem
->refcnt
, &ref
, kem
->lock
);
448 OSSL_PROVIDER
*EVP_KEM_get0_provider(const EVP_KEM
*kem
)
453 EVP_KEM
*EVP_KEM_fetch(OSSL_LIB_CTX
*ctx
, const char *algorithm
,
454 const char *properties
)
456 return evp_generic_fetch(ctx
, OSSL_OP_KEM
, algorithm
, properties
,
457 evp_kem_from_algorithm
,
458 (int (*)(void *))EVP_KEM_up_ref
,
459 (void (*)(void *))EVP_KEM_free
);
462 EVP_KEM
*evp_kem_fetch_from_prov(OSSL_PROVIDER
*prov
, const char *algorithm
,
463 const char *properties
)
465 return evp_generic_fetch_from_prov(prov
, OSSL_OP_KEM
, algorithm
, properties
,
466 evp_kem_from_algorithm
,
467 (int (*)(void *))EVP_KEM_up_ref
,
468 (void (*)(void *))EVP_KEM_free
);
471 int EVP_KEM_is_a(const EVP_KEM
*kem
, const char *name
)
473 return kem
!= NULL
&& evp_is_a(kem
->prov
, kem
->name_id
, NULL
, name
);
476 int evp_kem_get_number(const EVP_KEM
*kem
)
481 const char *EVP_KEM_get0_name(const EVP_KEM
*kem
)
483 return kem
->type_name
;
486 const char *EVP_KEM_get0_description(const EVP_KEM
*kem
)
488 return kem
->description
;
491 void EVP_KEM_do_all_provided(OSSL_LIB_CTX
*libctx
,
492 void (*fn
)(EVP_KEM
*kem
, void *arg
),
495 evp_generic_do_all(libctx
, OSSL_OP_KEM
, (void (*)(void *, void *))fn
, arg
,
496 evp_kem_from_algorithm
,
497 (int (*)(void *))EVP_KEM_up_ref
,
498 (void (*)(void *))EVP_KEM_free
);
501 int EVP_KEM_names_do_all(const EVP_KEM
*kem
,
502 void (*fn
)(const char *name
, void *data
),
505 if (kem
->prov
!= NULL
)
506 return evp_names_do_all(kem
->prov
, kem
->name_id
, fn
, data
);
511 const OSSL_PARAM
*EVP_KEM_gettable_ctx_params(const EVP_KEM
*kem
)
515 if (kem
== NULL
|| kem
->gettable_ctx_params
== NULL
)
518 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
519 return kem
->gettable_ctx_params(NULL
, provctx
);
522 const OSSL_PARAM
*EVP_KEM_settable_ctx_params(const EVP_KEM
*kem
)
526 if (kem
== NULL
|| kem
->settable_ctx_params
== NULL
)
529 provctx
= ossl_provider_ctx(EVP_KEM_get0_provider(kem
));
530 return kem
->settable_ctx_params(NULL
, provctx
);