xref: /freebsd/crypto/openssl/crypto/evp/kem.c (revision b077aed3)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #include <stdio.h>
11*b077aed3SPierre Pronchery #include <stdlib.h>
12*b077aed3SPierre Pronchery #include <openssl/objects.h>
13*b077aed3SPierre Pronchery #include <openssl/evp.h>
14*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
15*b077aed3SPierre Pronchery #include "internal/provider.h"
16*b077aed3SPierre Pronchery #include "internal/core.h"
17*b077aed3SPierre Pronchery #include "crypto/evp.h"
18*b077aed3SPierre Pronchery #include "evp_local.h"
19*b077aed3SPierre Pronchery 
evp_kem_init(EVP_PKEY_CTX * ctx,int operation,const OSSL_PARAM params[])20*b077aed3SPierre Pronchery static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
21*b077aed3SPierre Pronchery                         const OSSL_PARAM params[])
22*b077aed3SPierre Pronchery {
23*b077aed3SPierre Pronchery     int ret = 0;
24*b077aed3SPierre Pronchery     EVP_KEM *kem = NULL;
25*b077aed3SPierre Pronchery     EVP_KEYMGMT *tmp_keymgmt = NULL;
26*b077aed3SPierre Pronchery     const OSSL_PROVIDER *tmp_prov = NULL;
27*b077aed3SPierre Pronchery     void *provkey = NULL;
28*b077aed3SPierre Pronchery     const char *supported_kem = NULL;
29*b077aed3SPierre Pronchery     int iter;
30*b077aed3SPierre Pronchery 
31*b077aed3SPierre Pronchery     if (ctx == NULL || ctx->keytype == NULL) {
32*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
33*b077aed3SPierre Pronchery         return 0;
34*b077aed3SPierre Pronchery     }
35*b077aed3SPierre Pronchery 
36*b077aed3SPierre Pronchery     evp_pkey_ctx_free_old_ops(ctx);
37*b077aed3SPierre Pronchery     ctx->operation = operation;
38*b077aed3SPierre Pronchery 
39*b077aed3SPierre Pronchery     if (ctx->pkey == NULL) {
40*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
41*b077aed3SPierre Pronchery         goto err;
42*b077aed3SPierre Pronchery     }
43*b077aed3SPierre Pronchery 
44*b077aed3SPierre Pronchery     /*
45*b077aed3SPierre Pronchery      * Try to derive the supported kem from |ctx->keymgmt|.
46*b077aed3SPierre Pronchery      */
47*b077aed3SPierre Pronchery     if (!ossl_assert(ctx->pkey->keymgmt == NULL
48*b077aed3SPierre Pronchery                      || ctx->pkey->keymgmt == ctx->keymgmt)) {
49*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
50*b077aed3SPierre Pronchery         goto err;
51*b077aed3SPierre Pronchery     }
52*b077aed3SPierre Pronchery     supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
53*b077aed3SPierre Pronchery                                                           OSSL_OP_KEM);
54*b077aed3SPierre Pronchery     if (supported_kem == NULL) {
55*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
56*b077aed3SPierre Pronchery         goto err;
57*b077aed3SPierre Pronchery     }
58*b077aed3SPierre Pronchery 
59*b077aed3SPierre Pronchery     /*
60*b077aed3SPierre Pronchery      * Because we cleared out old ops, we shouldn't need to worry about
61*b077aed3SPierre Pronchery      * checking if kem is already there.
62*b077aed3SPierre Pronchery      * We perform two iterations:
63*b077aed3SPierre Pronchery      *
64*b077aed3SPierre Pronchery      * 1.  Do the normal kem fetch, using the fetching data given by
65*b077aed3SPierre Pronchery      *     the EVP_PKEY_CTX.
66*b077aed3SPierre Pronchery      * 2.  Do the provider specific kem fetch, from the same provider
67*b077aed3SPierre Pronchery      *     as |ctx->keymgmt|
68*b077aed3SPierre Pronchery      *
69*b077aed3SPierre Pronchery      * We then try to fetch the keymgmt from the same provider as the
70*b077aed3SPierre Pronchery      * kem, and try to export |ctx->pkey| to that keymgmt (when this
71*b077aed3SPierre Pronchery      * keymgmt happens to be the same as |ctx->keymgmt|, the export is
72*b077aed3SPierre Pronchery      * a no-op, but we call it anyway to not complicate the code even
73*b077aed3SPierre Pronchery      * more).
74*b077aed3SPierre Pronchery      * If the export call succeeds (returns a non-NULL provider key pointer),
75*b077aed3SPierre Pronchery      * we're done and can perform the operation itself.  If not, we perform
76*b077aed3SPierre Pronchery      * the second iteration, or jump to legacy.
77*b077aed3SPierre Pronchery      */
78*b077aed3SPierre Pronchery     for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
79*b077aed3SPierre Pronchery         EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
80*b077aed3SPierre Pronchery 
81*b077aed3SPierre Pronchery         /*
82*b077aed3SPierre Pronchery          * If we're on the second iteration, free the results from the first.
83*b077aed3SPierre Pronchery          * They are NULL on the first iteration, so no need to check what
84*b077aed3SPierre Pronchery          * iteration we're on.
85*b077aed3SPierre Pronchery          */
86*b077aed3SPierre Pronchery         EVP_KEM_free(kem);
87*b077aed3SPierre Pronchery         EVP_KEYMGMT_free(tmp_keymgmt);
88*b077aed3SPierre Pronchery 
89*b077aed3SPierre Pronchery         switch (iter) {
90*b077aed3SPierre Pronchery         case 1:
91*b077aed3SPierre Pronchery             kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery);
92*b077aed3SPierre Pronchery             if (kem != NULL)
93*b077aed3SPierre Pronchery                 tmp_prov = EVP_KEM_get0_provider(kem);
94*b077aed3SPierre Pronchery             break;
95*b077aed3SPierre Pronchery         case 2:
96*b077aed3SPierre Pronchery             tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
97*b077aed3SPierre Pronchery             kem = evp_kem_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
98*b077aed3SPierre Pronchery                                           supported_kem, ctx->propquery);
99*b077aed3SPierre Pronchery 
100*b077aed3SPierre Pronchery             if (kem == NULL) {
101*b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_EVP,
102*b077aed3SPierre Pronchery                           EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
103*b077aed3SPierre Pronchery                 ret = -2;
104*b077aed3SPierre Pronchery                 goto err;
105*b077aed3SPierre Pronchery             }
106*b077aed3SPierre Pronchery         }
107*b077aed3SPierre Pronchery         if (kem == NULL)
108*b077aed3SPierre Pronchery             continue;
109*b077aed3SPierre Pronchery 
110*b077aed3SPierre Pronchery         /*
111*b077aed3SPierre Pronchery          * Ensure that the key is provided, either natively, or as a cached
112*b077aed3SPierre Pronchery          * export.  We start by fetching the keymgmt with the same name as
113*b077aed3SPierre Pronchery          * |ctx->pkey|, but from the provider of the kem method, using the
114*b077aed3SPierre Pronchery          * same property query as when fetching the kem method.
115*b077aed3SPierre Pronchery          * With the keymgmt we found (if we did), we try to export |ctx->pkey|
116*b077aed3SPierre Pronchery          * to it (evp_pkey_export_to_provider() is smart enough to only actually
117*b077aed3SPierre Pronchery 
118*b077aed3SPierre Pronchery          * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
119*b077aed3SPierre Pronchery          */
120*b077aed3SPierre Pronchery         tmp_keymgmt_tofree = tmp_keymgmt =
121*b077aed3SPierre Pronchery             evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
122*b077aed3SPierre Pronchery                                         EVP_KEYMGMT_get0_name(ctx->keymgmt),
123*b077aed3SPierre Pronchery                                         ctx->propquery);
124*b077aed3SPierre Pronchery         if (tmp_keymgmt != NULL)
125*b077aed3SPierre Pronchery             provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
126*b077aed3SPierre Pronchery                                                   &tmp_keymgmt, ctx->propquery);
127*b077aed3SPierre Pronchery         if (tmp_keymgmt == NULL)
128*b077aed3SPierre Pronchery             EVP_KEYMGMT_free(tmp_keymgmt_tofree);
129*b077aed3SPierre Pronchery     }
130*b077aed3SPierre Pronchery 
131*b077aed3SPierre Pronchery     if (provkey == NULL) {
132*b077aed3SPierre Pronchery         EVP_KEM_free(kem);
133*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
134*b077aed3SPierre Pronchery         goto err;
135*b077aed3SPierre Pronchery     }
136*b077aed3SPierre Pronchery 
137*b077aed3SPierre Pronchery     ctx->op.encap.kem = kem;
138*b077aed3SPierre Pronchery     ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov));
139*b077aed3SPierre Pronchery     if (ctx->op.encap.algctx == NULL) {
140*b077aed3SPierre Pronchery         /* The provider key can stay in the cache */
141*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
142*b077aed3SPierre Pronchery         goto err;
143*b077aed3SPierre Pronchery     }
144*b077aed3SPierre Pronchery 
145*b077aed3SPierre Pronchery     switch (operation) {
146*b077aed3SPierre Pronchery     case EVP_PKEY_OP_ENCAPSULATE:
147*b077aed3SPierre Pronchery         if (kem->encapsulate_init == NULL) {
148*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
149*b077aed3SPierre Pronchery             ret = -2;
150*b077aed3SPierre Pronchery             goto err;
151*b077aed3SPierre Pronchery         }
152*b077aed3SPierre Pronchery         ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params);
153*b077aed3SPierre Pronchery         break;
154*b077aed3SPierre Pronchery     case EVP_PKEY_OP_DECAPSULATE:
155*b077aed3SPierre Pronchery         if (kem->decapsulate_init == NULL) {
156*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
157*b077aed3SPierre Pronchery             ret = -2;
158*b077aed3SPierre Pronchery             goto err;
159*b077aed3SPierre Pronchery         }
160*b077aed3SPierre Pronchery         ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params);
161*b077aed3SPierre Pronchery         break;
162*b077aed3SPierre Pronchery     default:
163*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
164*b077aed3SPierre Pronchery         goto err;
165*b077aed3SPierre Pronchery     }
166*b077aed3SPierre Pronchery 
167*b077aed3SPierre Pronchery     EVP_KEYMGMT_free(tmp_keymgmt);
168*b077aed3SPierre Pronchery     tmp_keymgmt = NULL;
169*b077aed3SPierre Pronchery 
170*b077aed3SPierre Pronchery     if (ret > 0)
171*b077aed3SPierre Pronchery         return 1;
172*b077aed3SPierre Pronchery  err:
173*b077aed3SPierre Pronchery     if (ret <= 0) {
174*b077aed3SPierre Pronchery         evp_pkey_ctx_free_old_ops(ctx);
175*b077aed3SPierre Pronchery         ctx->operation = EVP_PKEY_OP_UNDEFINED;
176*b077aed3SPierre Pronchery     }
177*b077aed3SPierre Pronchery     EVP_KEYMGMT_free(tmp_keymgmt);
178*b077aed3SPierre Pronchery     return ret;
179*b077aed3SPierre Pronchery }
180*b077aed3SPierre Pronchery 
EVP_PKEY_encapsulate_init(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])181*b077aed3SPierre Pronchery int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
182*b077aed3SPierre Pronchery {
183*b077aed3SPierre Pronchery     return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params);
184*b077aed3SPierre Pronchery }
185*b077aed3SPierre Pronchery 
EVP_PKEY_encapsulate(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,unsigned char * secret,size_t * secretlen)186*b077aed3SPierre Pronchery int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
187*b077aed3SPierre Pronchery                          unsigned char *out, size_t *outlen,
188*b077aed3SPierre Pronchery                          unsigned char *secret, size_t *secretlen)
189*b077aed3SPierre Pronchery {
190*b077aed3SPierre Pronchery     if (ctx == NULL)
191*b077aed3SPierre Pronchery         return 0;
192*b077aed3SPierre Pronchery 
193*b077aed3SPierre Pronchery     if (ctx->operation != EVP_PKEY_OP_ENCAPSULATE) {
194*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
195*b077aed3SPierre Pronchery         return -1;
196*b077aed3SPierre Pronchery     }
197*b077aed3SPierre Pronchery 
198*b077aed3SPierre Pronchery     if (ctx->op.encap.algctx == NULL) {
199*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
200*b077aed3SPierre Pronchery         return -2;
201*b077aed3SPierre Pronchery     }
202*b077aed3SPierre Pronchery 
203*b077aed3SPierre Pronchery     if (out != NULL && secret == NULL)
204*b077aed3SPierre Pronchery         return 0;
205*b077aed3SPierre Pronchery 
206*b077aed3SPierre Pronchery     return ctx->op.encap.kem->encapsulate(ctx->op.encap.algctx,
207*b077aed3SPierre Pronchery                                           out, outlen, secret, secretlen);
208*b077aed3SPierre Pronchery }
209*b077aed3SPierre Pronchery 
EVP_PKEY_decapsulate_init(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])210*b077aed3SPierre Pronchery int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
211*b077aed3SPierre Pronchery {
212*b077aed3SPierre Pronchery     return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params);
213*b077aed3SPierre Pronchery }
214*b077aed3SPierre Pronchery 
EVP_PKEY_decapsulate(EVP_PKEY_CTX * ctx,unsigned char * secret,size_t * secretlen,const unsigned char * in,size_t inlen)215*b077aed3SPierre Pronchery int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
216*b077aed3SPierre Pronchery                          unsigned char *secret, size_t *secretlen,
217*b077aed3SPierre Pronchery                          const unsigned char *in, size_t inlen)
218*b077aed3SPierre Pronchery {
219*b077aed3SPierre Pronchery     if (ctx == NULL
220*b077aed3SPierre Pronchery         || (in == NULL || inlen == 0)
221*b077aed3SPierre Pronchery         || (secret == NULL && secretlen == NULL))
222*b077aed3SPierre Pronchery         return 0;
223*b077aed3SPierre Pronchery 
224*b077aed3SPierre Pronchery     if (ctx->operation != EVP_PKEY_OP_DECAPSULATE) {
225*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
226*b077aed3SPierre Pronchery         return -1;
227*b077aed3SPierre Pronchery     }
228*b077aed3SPierre Pronchery 
229*b077aed3SPierre Pronchery     if (ctx->op.encap.algctx == NULL) {
230*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
231*b077aed3SPierre Pronchery         return -2;
232*b077aed3SPierre Pronchery     }
233*b077aed3SPierre Pronchery     return ctx->op.encap.kem->decapsulate(ctx->op.encap.algctx,
234*b077aed3SPierre Pronchery                                           secret, secretlen, in, inlen);
235*b077aed3SPierre Pronchery }
236*b077aed3SPierre Pronchery 
evp_kem_new(OSSL_PROVIDER * prov)237*b077aed3SPierre Pronchery static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov)
238*b077aed3SPierre Pronchery {
239*b077aed3SPierre Pronchery     EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM));
240*b077aed3SPierre Pronchery 
241*b077aed3SPierre Pronchery     if (kem == NULL) {
242*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
243*b077aed3SPierre Pronchery         return NULL;
244*b077aed3SPierre Pronchery     }
245*b077aed3SPierre Pronchery 
246*b077aed3SPierre Pronchery     kem->lock = CRYPTO_THREAD_lock_new();
247*b077aed3SPierre Pronchery     if (kem->lock == NULL) {
248*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
249*b077aed3SPierre Pronchery         OPENSSL_free(kem);
250*b077aed3SPierre Pronchery         return NULL;
251*b077aed3SPierre Pronchery     }
252*b077aed3SPierre Pronchery     kem->prov = prov;
253*b077aed3SPierre Pronchery     ossl_provider_up_ref(prov);
254*b077aed3SPierre Pronchery     kem->refcnt = 1;
255*b077aed3SPierre Pronchery 
256*b077aed3SPierre Pronchery     return kem;
257*b077aed3SPierre Pronchery }
258*b077aed3SPierre Pronchery 
evp_kem_from_algorithm(int name_id,const OSSL_ALGORITHM * algodef,OSSL_PROVIDER * prov)259*b077aed3SPierre Pronchery static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef,
260*b077aed3SPierre Pronchery                                     OSSL_PROVIDER *prov)
261*b077aed3SPierre Pronchery {
262*b077aed3SPierre Pronchery     const OSSL_DISPATCH *fns = algodef->implementation;
263*b077aed3SPierre Pronchery     EVP_KEM *kem = NULL;
264*b077aed3SPierre Pronchery     int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
265*b077aed3SPierre Pronchery     int gparamfncnt = 0, sparamfncnt = 0;
266*b077aed3SPierre Pronchery 
267*b077aed3SPierre Pronchery     if ((kem = evp_kem_new(prov)) == NULL) {
268*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
269*b077aed3SPierre Pronchery         goto err;
270*b077aed3SPierre Pronchery     }
271*b077aed3SPierre Pronchery 
272*b077aed3SPierre Pronchery     kem->name_id = name_id;
273*b077aed3SPierre Pronchery     if ((kem->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
274*b077aed3SPierre Pronchery         goto err;
275*b077aed3SPierre Pronchery     kem->description = algodef->algorithm_description;
276*b077aed3SPierre Pronchery 
277*b077aed3SPierre Pronchery     for (; fns->function_id != 0; fns++) {
278*b077aed3SPierre Pronchery         switch (fns->function_id) {
279*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_NEWCTX:
280*b077aed3SPierre Pronchery             if (kem->newctx != NULL)
281*b077aed3SPierre Pronchery                 break;
282*b077aed3SPierre Pronchery             kem->newctx = OSSL_FUNC_kem_newctx(fns);
283*b077aed3SPierre Pronchery             ctxfncnt++;
284*b077aed3SPierre Pronchery             break;
285*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_ENCAPSULATE_INIT:
286*b077aed3SPierre Pronchery             if (kem->encapsulate_init != NULL)
287*b077aed3SPierre Pronchery                 break;
288*b077aed3SPierre Pronchery             kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns);
289*b077aed3SPierre Pronchery             encfncnt++;
290*b077aed3SPierre Pronchery             break;
291*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_ENCAPSULATE:
292*b077aed3SPierre Pronchery             if (kem->encapsulate != NULL)
293*b077aed3SPierre Pronchery                 break;
294*b077aed3SPierre Pronchery             kem->encapsulate = OSSL_FUNC_kem_encapsulate(fns);
295*b077aed3SPierre Pronchery             encfncnt++;
296*b077aed3SPierre Pronchery             break;
297*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_DECAPSULATE_INIT:
298*b077aed3SPierre Pronchery             if (kem->decapsulate_init != NULL)
299*b077aed3SPierre Pronchery                 break;
300*b077aed3SPierre Pronchery             kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns);
301*b077aed3SPierre Pronchery             decfncnt++;
302*b077aed3SPierre Pronchery             break;
303*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_DECAPSULATE:
304*b077aed3SPierre Pronchery             if (kem->decapsulate != NULL)
305*b077aed3SPierre Pronchery                 break;
306*b077aed3SPierre Pronchery             kem->decapsulate = OSSL_FUNC_kem_decapsulate(fns);
307*b077aed3SPierre Pronchery             decfncnt++;
308*b077aed3SPierre Pronchery             break;
309*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_FREECTX:
310*b077aed3SPierre Pronchery             if (kem->freectx != NULL)
311*b077aed3SPierre Pronchery                 break;
312*b077aed3SPierre Pronchery             kem->freectx = OSSL_FUNC_kem_freectx(fns);
313*b077aed3SPierre Pronchery             ctxfncnt++;
314*b077aed3SPierre Pronchery             break;
315*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_DUPCTX:
316*b077aed3SPierre Pronchery             if (kem->dupctx != NULL)
317*b077aed3SPierre Pronchery                 break;
318*b077aed3SPierre Pronchery             kem->dupctx = OSSL_FUNC_kem_dupctx(fns);
319*b077aed3SPierre Pronchery             break;
320*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_GET_CTX_PARAMS:
321*b077aed3SPierre Pronchery             if (kem->get_ctx_params != NULL)
322*b077aed3SPierre Pronchery                 break;
323*b077aed3SPierre Pronchery             kem->get_ctx_params
324*b077aed3SPierre Pronchery                 = OSSL_FUNC_kem_get_ctx_params(fns);
325*b077aed3SPierre Pronchery             gparamfncnt++;
326*b077aed3SPierre Pronchery             break;
327*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS:
328*b077aed3SPierre Pronchery             if (kem->gettable_ctx_params != NULL)
329*b077aed3SPierre Pronchery                 break;
330*b077aed3SPierre Pronchery             kem->gettable_ctx_params
331*b077aed3SPierre Pronchery                 = OSSL_FUNC_kem_gettable_ctx_params(fns);
332*b077aed3SPierre Pronchery             gparamfncnt++;
333*b077aed3SPierre Pronchery             break;
334*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_SET_CTX_PARAMS:
335*b077aed3SPierre Pronchery             if (kem->set_ctx_params != NULL)
336*b077aed3SPierre Pronchery                 break;
337*b077aed3SPierre Pronchery             kem->set_ctx_params
338*b077aed3SPierre Pronchery                 = OSSL_FUNC_kem_set_ctx_params(fns);
339*b077aed3SPierre Pronchery             sparamfncnt++;
340*b077aed3SPierre Pronchery             break;
341*b077aed3SPierre Pronchery         case OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS:
342*b077aed3SPierre Pronchery             if (kem->settable_ctx_params != NULL)
343*b077aed3SPierre Pronchery                 break;
344*b077aed3SPierre Pronchery             kem->settable_ctx_params
345*b077aed3SPierre Pronchery                 = OSSL_FUNC_kem_settable_ctx_params(fns);
346*b077aed3SPierre Pronchery             sparamfncnt++;
347*b077aed3SPierre Pronchery             break;
348*b077aed3SPierre Pronchery         }
349*b077aed3SPierre Pronchery     }
350*b077aed3SPierre Pronchery     if (ctxfncnt != 2
351*b077aed3SPierre Pronchery         || (encfncnt != 0 && encfncnt != 2)
352*b077aed3SPierre Pronchery         || (decfncnt != 0 && decfncnt != 2)
353*b077aed3SPierre Pronchery         || (encfncnt != 2 && decfncnt != 2)
354*b077aed3SPierre Pronchery         || (gparamfncnt != 0 && gparamfncnt != 2)
355*b077aed3SPierre Pronchery         || (sparamfncnt != 0 && sparamfncnt != 2)) {
356*b077aed3SPierre Pronchery         /*
357*b077aed3SPierre Pronchery          * In order to be a consistent set of functions we must have at least
358*b077aed3SPierre Pronchery          * a set of context functions (newctx and freectx) as well as a pair of
359*b077aed3SPierre Pronchery          * "kem" functions: (encapsulate_init, encapsulate) or
360*b077aed3SPierre Pronchery          * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are
361*b077aed3SPierre Pronchery          * optional, but if one of them is present then the other one must also
362*b077aed3SPierre Pronchery          * be present. The same applies to get_ctx_params and
363*b077aed3SPierre Pronchery          * gettable_ctx_params. The dupctx function is optional.
364*b077aed3SPierre Pronchery          */
365*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
366*b077aed3SPierre Pronchery         goto err;
367*b077aed3SPierre Pronchery     }
368*b077aed3SPierre Pronchery 
369*b077aed3SPierre Pronchery     return kem;
370*b077aed3SPierre Pronchery  err:
371*b077aed3SPierre Pronchery     EVP_KEM_free(kem);
372*b077aed3SPierre Pronchery     return NULL;
373*b077aed3SPierre Pronchery }
374*b077aed3SPierre Pronchery 
EVP_KEM_free(EVP_KEM * kem)375*b077aed3SPierre Pronchery void EVP_KEM_free(EVP_KEM *kem)
376*b077aed3SPierre Pronchery {
377*b077aed3SPierre Pronchery     int i;
378*b077aed3SPierre Pronchery 
379*b077aed3SPierre Pronchery     if (kem == NULL)
380*b077aed3SPierre Pronchery         return;
381*b077aed3SPierre Pronchery 
382*b077aed3SPierre Pronchery     CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock);
383*b077aed3SPierre Pronchery     if (i > 0)
384*b077aed3SPierre Pronchery         return;
385*b077aed3SPierre Pronchery     OPENSSL_free(kem->type_name);
386*b077aed3SPierre Pronchery     ossl_provider_free(kem->prov);
387*b077aed3SPierre Pronchery     CRYPTO_THREAD_lock_free(kem->lock);
388*b077aed3SPierre Pronchery     OPENSSL_free(kem);
389*b077aed3SPierre Pronchery }
390*b077aed3SPierre Pronchery 
EVP_KEM_up_ref(EVP_KEM * kem)391*b077aed3SPierre Pronchery int EVP_KEM_up_ref(EVP_KEM *kem)
392*b077aed3SPierre Pronchery {
393*b077aed3SPierre Pronchery     int ref = 0;
394*b077aed3SPierre Pronchery 
395*b077aed3SPierre Pronchery     CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock);
396*b077aed3SPierre Pronchery     return 1;
397*b077aed3SPierre Pronchery }
398*b077aed3SPierre Pronchery 
EVP_KEM_get0_provider(const EVP_KEM * kem)399*b077aed3SPierre Pronchery OSSL_PROVIDER *EVP_KEM_get0_provider(const EVP_KEM *kem)
400*b077aed3SPierre Pronchery {
401*b077aed3SPierre Pronchery     return kem->prov;
402*b077aed3SPierre Pronchery }
403*b077aed3SPierre Pronchery 
EVP_KEM_fetch(OSSL_LIB_CTX * ctx,const char * algorithm,const char * properties)404*b077aed3SPierre Pronchery EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
405*b077aed3SPierre Pronchery                        const char *properties)
406*b077aed3SPierre Pronchery {
407*b077aed3SPierre Pronchery     return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties,
408*b077aed3SPierre Pronchery                              evp_kem_from_algorithm,
409*b077aed3SPierre Pronchery                              (int (*)(void *))EVP_KEM_up_ref,
410*b077aed3SPierre Pronchery                              (void (*)(void *))EVP_KEM_free);
411*b077aed3SPierre Pronchery }
412*b077aed3SPierre Pronchery 
evp_kem_fetch_from_prov(OSSL_PROVIDER * prov,const char * algorithm,const char * properties)413*b077aed3SPierre Pronchery EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm,
414*b077aed3SPierre Pronchery                                  const char *properties)
415*b077aed3SPierre Pronchery {
416*b077aed3SPierre Pronchery     return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties,
417*b077aed3SPierre Pronchery                                        evp_kem_from_algorithm,
418*b077aed3SPierre Pronchery                                        (int (*)(void *))EVP_KEM_up_ref,
419*b077aed3SPierre Pronchery                                        (void (*)(void *))EVP_KEM_free);
420*b077aed3SPierre Pronchery }
421*b077aed3SPierre Pronchery 
EVP_KEM_is_a(const EVP_KEM * kem,const char * name)422*b077aed3SPierre Pronchery int EVP_KEM_is_a(const EVP_KEM *kem, const char *name)
423*b077aed3SPierre Pronchery {
424*b077aed3SPierre Pronchery     return kem != NULL && evp_is_a(kem->prov, kem->name_id, NULL, name);
425*b077aed3SPierre Pronchery }
426*b077aed3SPierre Pronchery 
evp_kem_get_number(const EVP_KEM * kem)427*b077aed3SPierre Pronchery int evp_kem_get_number(const EVP_KEM *kem)
428*b077aed3SPierre Pronchery {
429*b077aed3SPierre Pronchery     return kem->name_id;
430*b077aed3SPierre Pronchery }
431*b077aed3SPierre Pronchery 
EVP_KEM_get0_name(const EVP_KEM * kem)432*b077aed3SPierre Pronchery const char *EVP_KEM_get0_name(const EVP_KEM *kem)
433*b077aed3SPierre Pronchery {
434*b077aed3SPierre Pronchery     return kem->type_name;
435*b077aed3SPierre Pronchery }
436*b077aed3SPierre Pronchery 
EVP_KEM_get0_description(const EVP_KEM * kem)437*b077aed3SPierre Pronchery const char *EVP_KEM_get0_description(const EVP_KEM *kem)
438*b077aed3SPierre Pronchery {
439*b077aed3SPierre Pronchery     return kem->description;
440*b077aed3SPierre Pronchery }
441*b077aed3SPierre Pronchery 
EVP_KEM_do_all_provided(OSSL_LIB_CTX * libctx,void (* fn)(EVP_KEM * kem,void * arg),void * arg)442*b077aed3SPierre Pronchery void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
443*b077aed3SPierre Pronchery                              void (*fn)(EVP_KEM *kem, void *arg),
444*b077aed3SPierre Pronchery                              void *arg)
445*b077aed3SPierre Pronchery {
446*b077aed3SPierre Pronchery     evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
447*b077aed3SPierre Pronchery                        evp_kem_from_algorithm,
448*b077aed3SPierre Pronchery                        (int (*)(void *))EVP_KEM_up_ref,
449*b077aed3SPierre Pronchery                        (void (*)(void *))EVP_KEM_free);
450*b077aed3SPierre Pronchery }
451*b077aed3SPierre Pronchery 
EVP_KEM_names_do_all(const EVP_KEM * kem,void (* fn)(const char * name,void * data),void * data)452*b077aed3SPierre Pronchery int EVP_KEM_names_do_all(const EVP_KEM *kem,
453*b077aed3SPierre Pronchery                          void (*fn)(const char *name, void *data),
454*b077aed3SPierre Pronchery                          void *data)
455*b077aed3SPierre Pronchery {
456*b077aed3SPierre Pronchery     if (kem->prov != NULL)
457*b077aed3SPierre Pronchery         return evp_names_do_all(kem->prov, kem->name_id, fn, data);
458*b077aed3SPierre Pronchery 
459*b077aed3SPierre Pronchery     return 1;
460*b077aed3SPierre Pronchery }
461*b077aed3SPierre Pronchery 
EVP_KEM_gettable_ctx_params(const EVP_KEM * kem)462*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KEM_gettable_ctx_params(const EVP_KEM *kem)
463*b077aed3SPierre Pronchery {
464*b077aed3SPierre Pronchery     void *provctx;
465*b077aed3SPierre Pronchery 
466*b077aed3SPierre Pronchery     if (kem == NULL || kem->gettable_ctx_params == NULL)
467*b077aed3SPierre Pronchery         return NULL;
468*b077aed3SPierre Pronchery 
469*b077aed3SPierre Pronchery     provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
470*b077aed3SPierre Pronchery     return kem->gettable_ctx_params(NULL, provctx);
471*b077aed3SPierre Pronchery }
472*b077aed3SPierre Pronchery 
EVP_KEM_settable_ctx_params(const EVP_KEM * kem)473*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KEM_settable_ctx_params(const EVP_KEM *kem)
474*b077aed3SPierre Pronchery {
475*b077aed3SPierre Pronchery     void *provctx;
476*b077aed3SPierre Pronchery 
477*b077aed3SPierre Pronchery     if (kem == NULL || kem->settable_ctx_params == NULL)
478*b077aed3SPierre Pronchery         return NULL;
479*b077aed3SPierre Pronchery 
480*b077aed3SPierre Pronchery     provctx = ossl_provider_ctx(EVP_KEM_get0_provider(kem));
481*b077aed3SPierre Pronchery     return kem->settable_ctx_params(NULL, provctx);
482*b077aed3SPierre Pronchery }
483