xref: /freebsd/crypto/openssl/crypto/evp/asymcipher.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2006-2021 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_pkey_asym_cipher_init(EVP_PKEY_CTX * ctx,int operation,const OSSL_PARAM params[])20*b077aed3SPierre Pronchery static int evp_pkey_asym_cipher_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     void *provkey = NULL;
25*b077aed3SPierre Pronchery     EVP_ASYM_CIPHER *cipher = NULL;
26*b077aed3SPierre Pronchery     EVP_KEYMGMT *tmp_keymgmt = NULL;
27*b077aed3SPierre Pronchery     const OSSL_PROVIDER *tmp_prov = NULL;
28*b077aed3SPierre Pronchery     const char *supported_ciph = NULL;
29*b077aed3SPierre Pronchery     int iter;
30*b077aed3SPierre Pronchery 
31*b077aed3SPierre Pronchery     if (ctx == NULL) {
32*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
33*b077aed3SPierre Pronchery         return -2;
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     ERR_set_mark();
40*b077aed3SPierre Pronchery 
41*b077aed3SPierre Pronchery     if (evp_pkey_ctx_is_legacy(ctx))
42*b077aed3SPierre Pronchery         goto legacy;
43*b077aed3SPierre Pronchery 
44*b077aed3SPierre Pronchery     if (ctx->pkey == NULL) {
45*b077aed3SPierre Pronchery         ERR_clear_last_mark();
46*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET);
47*b077aed3SPierre Pronchery         goto err;
48*b077aed3SPierre Pronchery     }
49*b077aed3SPierre Pronchery 
50*b077aed3SPierre Pronchery     /*
51*b077aed3SPierre Pronchery      * Try to derive the supported asym cipher from |ctx->keymgmt|.
52*b077aed3SPierre Pronchery      */
53*b077aed3SPierre Pronchery     if (!ossl_assert(ctx->pkey->keymgmt == NULL
54*b077aed3SPierre Pronchery                      || ctx->pkey->keymgmt == ctx->keymgmt)) {
55*b077aed3SPierre Pronchery         ERR_clear_last_mark();
56*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
57*b077aed3SPierre Pronchery         goto err;
58*b077aed3SPierre Pronchery     }
59*b077aed3SPierre Pronchery     supported_ciph
60*b077aed3SPierre Pronchery         = evp_keymgmt_util_query_operation_name(ctx->keymgmt,
61*b077aed3SPierre Pronchery                                                 OSSL_OP_ASYM_CIPHER);
62*b077aed3SPierre Pronchery     if (supported_ciph == NULL) {
63*b077aed3SPierre Pronchery         ERR_clear_last_mark();
64*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
65*b077aed3SPierre Pronchery         goto err;
66*b077aed3SPierre Pronchery     }
67*b077aed3SPierre Pronchery 
68*b077aed3SPierre Pronchery     /*
69*b077aed3SPierre Pronchery      * We perform two iterations:
70*b077aed3SPierre Pronchery      *
71*b077aed3SPierre Pronchery      * 1.  Do the normal asym cipher fetch, using the fetching data given by
72*b077aed3SPierre Pronchery      *     the EVP_PKEY_CTX.
73*b077aed3SPierre Pronchery      * 2.  Do the provider specific asym cipher fetch, from the same provider
74*b077aed3SPierre Pronchery      *     as |ctx->keymgmt|
75*b077aed3SPierre Pronchery      *
76*b077aed3SPierre Pronchery      * We then try to fetch the keymgmt from the same provider as the
77*b077aed3SPierre Pronchery      * asym cipher, and try to export |ctx->pkey| to that keymgmt (when
78*b077aed3SPierre Pronchery      * this keymgmt happens to be the same as |ctx->keymgmt|, the export
79*b077aed3SPierre Pronchery      * is a no-op, but we call it anyway to not complicate the code even
80*b077aed3SPierre Pronchery      * more).
81*b077aed3SPierre Pronchery      * If the export call succeeds (returns a non-NULL provider key pointer),
82*b077aed3SPierre Pronchery      * we're done and can perform the operation itself.  If not, we perform
83*b077aed3SPierre Pronchery      * the second iteration, or jump to legacy.
84*b077aed3SPierre Pronchery      */
85*b077aed3SPierre Pronchery     for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
86*b077aed3SPierre Pronchery         EVP_KEYMGMT *tmp_keymgmt_tofree;
87*b077aed3SPierre Pronchery 
88*b077aed3SPierre Pronchery         /*
89*b077aed3SPierre Pronchery          * If we're on the second iteration, free the results from the first.
90*b077aed3SPierre Pronchery          * They are NULL on the first iteration, so no need to check what
91*b077aed3SPierre Pronchery          * iteration we're on.
92*b077aed3SPierre Pronchery          */
93*b077aed3SPierre Pronchery         EVP_ASYM_CIPHER_free(cipher);
94*b077aed3SPierre Pronchery         EVP_KEYMGMT_free(tmp_keymgmt);
95*b077aed3SPierre Pronchery 
96*b077aed3SPierre Pronchery         switch (iter) {
97*b077aed3SPierre Pronchery         case 1:
98*b077aed3SPierre Pronchery             cipher = EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph,
99*b077aed3SPierre Pronchery                                            ctx->propquery);
100*b077aed3SPierre Pronchery             if (cipher != NULL)
101*b077aed3SPierre Pronchery                 tmp_prov = EVP_ASYM_CIPHER_get0_provider(cipher);
102*b077aed3SPierre Pronchery             break;
103*b077aed3SPierre Pronchery         case 2:
104*b077aed3SPierre Pronchery             tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt);
105*b077aed3SPierre Pronchery             cipher =
106*b077aed3SPierre Pronchery                 evp_asym_cipher_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
107*b077aed3SPierre Pronchery                                                 supported_ciph, ctx->propquery);
108*b077aed3SPierre Pronchery             if (cipher == NULL)
109*b077aed3SPierre Pronchery                 goto legacy;
110*b077aed3SPierre Pronchery             break;
111*b077aed3SPierre Pronchery         }
112*b077aed3SPierre Pronchery         if (cipher == NULL)
113*b077aed3SPierre Pronchery             continue;
114*b077aed3SPierre Pronchery 
115*b077aed3SPierre Pronchery         /*
116*b077aed3SPierre Pronchery          * Ensure that the key is provided, either natively, or as a cached
117*b077aed3SPierre Pronchery          * export.  We start by fetching the keymgmt with the same name as
118*b077aed3SPierre Pronchery          * |ctx->pkey|, but from the provider of the asym cipher method, using
119*b077aed3SPierre Pronchery          * the same property query as when fetching the asym cipher method.
120*b077aed3SPierre Pronchery          * With the keymgmt we found (if we did), we try to export |ctx->pkey|
121*b077aed3SPierre Pronchery          * to it (evp_pkey_export_to_provider() is smart enough to only actually
122*b077aed3SPierre Pronchery          * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt)
123*b077aed3SPierre Pronchery          */
124*b077aed3SPierre Pronchery         tmp_keymgmt_tofree = tmp_keymgmt
125*b077aed3SPierre Pronchery             = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov,
126*b077aed3SPierre Pronchery                                           EVP_KEYMGMT_get0_name(ctx->keymgmt),
127*b077aed3SPierre Pronchery                                           ctx->propquery);
128*b077aed3SPierre Pronchery         if (tmp_keymgmt != NULL)
129*b077aed3SPierre Pronchery             provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
130*b077aed3SPierre Pronchery                                                   &tmp_keymgmt, ctx->propquery);
131*b077aed3SPierre Pronchery         if (tmp_keymgmt == NULL)
132*b077aed3SPierre Pronchery             EVP_KEYMGMT_free(tmp_keymgmt_tofree);
133*b077aed3SPierre Pronchery     }
134*b077aed3SPierre Pronchery 
135*b077aed3SPierre Pronchery     if (provkey == NULL) {
136*b077aed3SPierre Pronchery         EVP_ASYM_CIPHER_free(cipher);
137*b077aed3SPierre Pronchery         goto legacy;
138*b077aed3SPierre Pronchery     }
139*b077aed3SPierre Pronchery 
140*b077aed3SPierre Pronchery     ERR_pop_to_mark();
141*b077aed3SPierre Pronchery 
142*b077aed3SPierre Pronchery     /* No more legacy from here down to legacy: */
143*b077aed3SPierre Pronchery 
144*b077aed3SPierre Pronchery     ctx->op.ciph.cipher = cipher;
145*b077aed3SPierre Pronchery     ctx->op.ciph.algctx = cipher->newctx(ossl_provider_ctx(cipher->prov));
146*b077aed3SPierre Pronchery     if (ctx->op.ciph.algctx == NULL) {
147*b077aed3SPierre Pronchery         /* The provider key can stay in the cache */
148*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
149*b077aed3SPierre Pronchery         goto err;
150*b077aed3SPierre Pronchery     }
151*b077aed3SPierre Pronchery 
152*b077aed3SPierre Pronchery     switch (operation) {
153*b077aed3SPierre Pronchery     case EVP_PKEY_OP_ENCRYPT:
154*b077aed3SPierre Pronchery         if (cipher->encrypt_init == NULL) {
155*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
156*b077aed3SPierre Pronchery             ret = -2;
157*b077aed3SPierre Pronchery             goto err;
158*b077aed3SPierre Pronchery         }
159*b077aed3SPierre Pronchery         ret = cipher->encrypt_init(ctx->op.ciph.algctx, provkey, params);
160*b077aed3SPierre Pronchery         break;
161*b077aed3SPierre Pronchery     case EVP_PKEY_OP_DECRYPT:
162*b077aed3SPierre Pronchery         if (cipher->decrypt_init == NULL) {
163*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
164*b077aed3SPierre Pronchery             ret = -2;
165*b077aed3SPierre Pronchery             goto err;
166*b077aed3SPierre Pronchery         }
167*b077aed3SPierre Pronchery         ret = cipher->decrypt_init(ctx->op.ciph.algctx, provkey, params);
168*b077aed3SPierre Pronchery         break;
169*b077aed3SPierre Pronchery     default:
170*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
171*b077aed3SPierre Pronchery         goto err;
172*b077aed3SPierre Pronchery     }
173*b077aed3SPierre Pronchery 
174*b077aed3SPierre Pronchery     if (ret <= 0)
175*b077aed3SPierre Pronchery         goto err;
176*b077aed3SPierre Pronchery     EVP_KEYMGMT_free(tmp_keymgmt);
177*b077aed3SPierre Pronchery     return 1;
178*b077aed3SPierre Pronchery 
179*b077aed3SPierre Pronchery  legacy:
180*b077aed3SPierre Pronchery     /*
181*b077aed3SPierre Pronchery      * If we don't have the full support we need with provided methods,
182*b077aed3SPierre Pronchery      * let's go see if legacy does.
183*b077aed3SPierre Pronchery      */
184*b077aed3SPierre Pronchery     ERR_pop_to_mark();
185*b077aed3SPierre Pronchery     EVP_KEYMGMT_free(tmp_keymgmt);
186*b077aed3SPierre Pronchery     tmp_keymgmt = NULL;
187*b077aed3SPierre Pronchery 
188*b077aed3SPierre Pronchery     if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
189*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
190*b077aed3SPierre Pronchery         return -2;
191*b077aed3SPierre Pronchery     }
192*b077aed3SPierre Pronchery     switch(ctx->operation) {
193*b077aed3SPierre Pronchery     case EVP_PKEY_OP_ENCRYPT:
194*b077aed3SPierre Pronchery         if (ctx->pmeth->encrypt_init == NULL)
195*b077aed3SPierre Pronchery             return 1;
196*b077aed3SPierre Pronchery         ret = ctx->pmeth->encrypt_init(ctx);
197*b077aed3SPierre Pronchery         break;
198*b077aed3SPierre Pronchery     case EVP_PKEY_OP_DECRYPT:
199*b077aed3SPierre Pronchery         if (ctx->pmeth->decrypt_init == NULL)
200*b077aed3SPierre Pronchery             return 1;
201*b077aed3SPierre Pronchery         ret = ctx->pmeth->decrypt_init(ctx);
202*b077aed3SPierre Pronchery         break;
203*b077aed3SPierre Pronchery     default:
204*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
205*b077aed3SPierre Pronchery         ret = -1;
206*b077aed3SPierre Pronchery     }
207*b077aed3SPierre Pronchery 
208*b077aed3SPierre Pronchery  err:
209*b077aed3SPierre Pronchery     if (ret <= 0) {
210*b077aed3SPierre Pronchery         evp_pkey_ctx_free_old_ops(ctx);
211*b077aed3SPierre Pronchery         ctx->operation = EVP_PKEY_OP_UNDEFINED;
212*b077aed3SPierre Pronchery     }
213*b077aed3SPierre Pronchery     EVP_KEYMGMT_free(tmp_keymgmt);
214*b077aed3SPierre Pronchery     return ret;
215*b077aed3SPierre Pronchery }
216*b077aed3SPierre Pronchery 
EVP_PKEY_encrypt_init(EVP_PKEY_CTX * ctx)217*b077aed3SPierre Pronchery int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
218*b077aed3SPierre Pronchery {
219*b077aed3SPierre Pronchery     return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT, NULL);
220*b077aed3SPierre Pronchery }
221*b077aed3SPierre Pronchery 
EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])222*b077aed3SPierre Pronchery int EVP_PKEY_encrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
223*b077aed3SPierre Pronchery {
224*b077aed3SPierre Pronchery     return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_ENCRYPT, params);
225*b077aed3SPierre Pronchery }
226*b077aed3SPierre Pronchery 
EVP_PKEY_encrypt(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen)227*b077aed3SPierre Pronchery int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
228*b077aed3SPierre Pronchery                      unsigned char *out, size_t *outlen,
229*b077aed3SPierre Pronchery                      const unsigned char *in, size_t inlen)
230*b077aed3SPierre Pronchery {
231*b077aed3SPierre Pronchery     int ret;
232*b077aed3SPierre Pronchery 
233*b077aed3SPierre Pronchery     if (ctx == NULL) {
234*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
235*b077aed3SPierre Pronchery         return -2;
236*b077aed3SPierre Pronchery     }
237*b077aed3SPierre Pronchery 
238*b077aed3SPierre Pronchery     if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
239*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
240*b077aed3SPierre Pronchery         return -1;
241*b077aed3SPierre Pronchery     }
242*b077aed3SPierre Pronchery 
243*b077aed3SPierre Pronchery     if (ctx->op.ciph.algctx == NULL)
244*b077aed3SPierre Pronchery         goto legacy;
245*b077aed3SPierre Pronchery 
246*b077aed3SPierre Pronchery     ret = ctx->op.ciph.cipher->encrypt(ctx->op.ciph.algctx, out, outlen,
247*b077aed3SPierre Pronchery                                        (out == NULL ? 0 : *outlen), in, inlen);
248*b077aed3SPierre Pronchery     return ret;
249*b077aed3SPierre Pronchery 
250*b077aed3SPierre Pronchery  legacy:
251*b077aed3SPierre Pronchery     if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) {
252*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
253*b077aed3SPierre Pronchery         return -2;
254*b077aed3SPierre Pronchery     }
255*b077aed3SPierre Pronchery     M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
256*b077aed3SPierre Pronchery         return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
257*b077aed3SPierre Pronchery }
258*b077aed3SPierre Pronchery 
EVP_PKEY_decrypt_init(EVP_PKEY_CTX * ctx)259*b077aed3SPierre Pronchery int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
260*b077aed3SPierre Pronchery {
261*b077aed3SPierre Pronchery     return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT, NULL);
262*b077aed3SPierre Pronchery }
263*b077aed3SPierre Pronchery 
EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX * ctx,const OSSL_PARAM params[])264*b077aed3SPierre Pronchery int EVP_PKEY_decrypt_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
265*b077aed3SPierre Pronchery {
266*b077aed3SPierre Pronchery     return evp_pkey_asym_cipher_init(ctx, EVP_PKEY_OP_DECRYPT, params);
267*b077aed3SPierre Pronchery }
268*b077aed3SPierre Pronchery 
EVP_PKEY_decrypt(EVP_PKEY_CTX * ctx,unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen)269*b077aed3SPierre Pronchery int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
270*b077aed3SPierre Pronchery                      unsigned char *out, size_t *outlen,
271*b077aed3SPierre Pronchery                      const unsigned char *in, size_t inlen)
272*b077aed3SPierre Pronchery {
273*b077aed3SPierre Pronchery     int ret;
274*b077aed3SPierre Pronchery 
275*b077aed3SPierre Pronchery     if (ctx == NULL) {
276*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
277*b077aed3SPierre Pronchery         return -2;
278*b077aed3SPierre Pronchery     }
279*b077aed3SPierre Pronchery 
280*b077aed3SPierre Pronchery     if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
281*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
282*b077aed3SPierre Pronchery         return -1;
283*b077aed3SPierre Pronchery     }
284*b077aed3SPierre Pronchery 
285*b077aed3SPierre Pronchery     if (ctx->op.ciph.algctx == NULL)
286*b077aed3SPierre Pronchery         goto legacy;
287*b077aed3SPierre Pronchery 
288*b077aed3SPierre Pronchery     ret = ctx->op.ciph.cipher->decrypt(ctx->op.ciph.algctx, out, outlen,
289*b077aed3SPierre Pronchery                                        (out == NULL ? 0 : *outlen), in, inlen);
290*b077aed3SPierre Pronchery     return ret;
291*b077aed3SPierre Pronchery 
292*b077aed3SPierre Pronchery  legacy:
293*b077aed3SPierre Pronchery     if (ctx->pmeth == NULL || ctx->pmeth->decrypt == NULL) {
294*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
295*b077aed3SPierre Pronchery         return -2;
296*b077aed3SPierre Pronchery     }
297*b077aed3SPierre Pronchery     M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
298*b077aed3SPierre Pronchery         return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
299*b077aed3SPierre Pronchery }
300*b077aed3SPierre Pronchery 
301*b077aed3SPierre Pronchery 
evp_asym_cipher_new(OSSL_PROVIDER * prov)302*b077aed3SPierre Pronchery static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov)
303*b077aed3SPierre Pronchery {
304*b077aed3SPierre Pronchery     EVP_ASYM_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_ASYM_CIPHER));
305*b077aed3SPierre Pronchery 
306*b077aed3SPierre Pronchery     if (cipher == NULL) {
307*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
308*b077aed3SPierre Pronchery         return NULL;
309*b077aed3SPierre Pronchery     }
310*b077aed3SPierre Pronchery 
311*b077aed3SPierre Pronchery     cipher->lock = CRYPTO_THREAD_lock_new();
312*b077aed3SPierre Pronchery     if (cipher->lock == NULL) {
313*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
314*b077aed3SPierre Pronchery         OPENSSL_free(cipher);
315*b077aed3SPierre Pronchery         return NULL;
316*b077aed3SPierre Pronchery     }
317*b077aed3SPierre Pronchery     cipher->prov = prov;
318*b077aed3SPierre Pronchery     ossl_provider_up_ref(prov);
319*b077aed3SPierre Pronchery     cipher->refcnt = 1;
320*b077aed3SPierre Pronchery 
321*b077aed3SPierre Pronchery     return cipher;
322*b077aed3SPierre Pronchery }
323*b077aed3SPierre Pronchery 
evp_asym_cipher_from_algorithm(int name_id,const OSSL_ALGORITHM * algodef,OSSL_PROVIDER * prov)324*b077aed3SPierre Pronchery static void *evp_asym_cipher_from_algorithm(int name_id,
325*b077aed3SPierre Pronchery                                             const OSSL_ALGORITHM *algodef,
326*b077aed3SPierre Pronchery                                             OSSL_PROVIDER *prov)
327*b077aed3SPierre Pronchery {
328*b077aed3SPierre Pronchery     const OSSL_DISPATCH *fns = algodef->implementation;
329*b077aed3SPierre Pronchery     EVP_ASYM_CIPHER *cipher = NULL;
330*b077aed3SPierre Pronchery     int ctxfncnt = 0, encfncnt = 0, decfncnt = 0;
331*b077aed3SPierre Pronchery     int gparamfncnt = 0, sparamfncnt = 0;
332*b077aed3SPierre Pronchery 
333*b077aed3SPierre Pronchery     if ((cipher = evp_asym_cipher_new(prov)) == NULL) {
334*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
335*b077aed3SPierre Pronchery         goto err;
336*b077aed3SPierre Pronchery     }
337*b077aed3SPierre Pronchery 
338*b077aed3SPierre Pronchery     cipher->name_id = name_id;
339*b077aed3SPierre Pronchery     if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL)
340*b077aed3SPierre Pronchery         goto err;
341*b077aed3SPierre Pronchery     cipher->description = algodef->algorithm_description;
342*b077aed3SPierre Pronchery 
343*b077aed3SPierre Pronchery     for (; fns->function_id != 0; fns++) {
344*b077aed3SPierre Pronchery         switch (fns->function_id) {
345*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_NEWCTX:
346*b077aed3SPierre Pronchery             if (cipher->newctx != NULL)
347*b077aed3SPierre Pronchery                 break;
348*b077aed3SPierre Pronchery             cipher->newctx = OSSL_FUNC_asym_cipher_newctx(fns);
349*b077aed3SPierre Pronchery             ctxfncnt++;
350*b077aed3SPierre Pronchery             break;
351*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT:
352*b077aed3SPierre Pronchery             if (cipher->encrypt_init != NULL)
353*b077aed3SPierre Pronchery                 break;
354*b077aed3SPierre Pronchery             cipher->encrypt_init = OSSL_FUNC_asym_cipher_encrypt_init(fns);
355*b077aed3SPierre Pronchery             encfncnt++;
356*b077aed3SPierre Pronchery             break;
357*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_ENCRYPT:
358*b077aed3SPierre Pronchery             if (cipher->encrypt != NULL)
359*b077aed3SPierre Pronchery                 break;
360*b077aed3SPierre Pronchery             cipher->encrypt = OSSL_FUNC_asym_cipher_encrypt(fns);
361*b077aed3SPierre Pronchery             encfncnt++;
362*b077aed3SPierre Pronchery             break;
363*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT:
364*b077aed3SPierre Pronchery             if (cipher->decrypt_init != NULL)
365*b077aed3SPierre Pronchery                 break;
366*b077aed3SPierre Pronchery             cipher->decrypt_init = OSSL_FUNC_asym_cipher_decrypt_init(fns);
367*b077aed3SPierre Pronchery             decfncnt++;
368*b077aed3SPierre Pronchery             break;
369*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_DECRYPT:
370*b077aed3SPierre Pronchery             if (cipher->decrypt != NULL)
371*b077aed3SPierre Pronchery                 break;
372*b077aed3SPierre Pronchery             cipher->decrypt = OSSL_FUNC_asym_cipher_decrypt(fns);
373*b077aed3SPierre Pronchery             decfncnt++;
374*b077aed3SPierre Pronchery             break;
375*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_FREECTX:
376*b077aed3SPierre Pronchery             if (cipher->freectx != NULL)
377*b077aed3SPierre Pronchery                 break;
378*b077aed3SPierre Pronchery             cipher->freectx = OSSL_FUNC_asym_cipher_freectx(fns);
379*b077aed3SPierre Pronchery             ctxfncnt++;
380*b077aed3SPierre Pronchery             break;
381*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_DUPCTX:
382*b077aed3SPierre Pronchery             if (cipher->dupctx != NULL)
383*b077aed3SPierre Pronchery                 break;
384*b077aed3SPierre Pronchery             cipher->dupctx = OSSL_FUNC_asym_cipher_dupctx(fns);
385*b077aed3SPierre Pronchery             break;
386*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS:
387*b077aed3SPierre Pronchery             if (cipher->get_ctx_params != NULL)
388*b077aed3SPierre Pronchery                 break;
389*b077aed3SPierre Pronchery             cipher->get_ctx_params
390*b077aed3SPierre Pronchery                 = OSSL_FUNC_asym_cipher_get_ctx_params(fns);
391*b077aed3SPierre Pronchery             gparamfncnt++;
392*b077aed3SPierre Pronchery             break;
393*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS:
394*b077aed3SPierre Pronchery             if (cipher->gettable_ctx_params != NULL)
395*b077aed3SPierre Pronchery                 break;
396*b077aed3SPierre Pronchery             cipher->gettable_ctx_params
397*b077aed3SPierre Pronchery                 = OSSL_FUNC_asym_cipher_gettable_ctx_params(fns);
398*b077aed3SPierre Pronchery             gparamfncnt++;
399*b077aed3SPierre Pronchery             break;
400*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS:
401*b077aed3SPierre Pronchery             if (cipher->set_ctx_params != NULL)
402*b077aed3SPierre Pronchery                 break;
403*b077aed3SPierre Pronchery             cipher->set_ctx_params
404*b077aed3SPierre Pronchery                 = OSSL_FUNC_asym_cipher_set_ctx_params(fns);
405*b077aed3SPierre Pronchery             sparamfncnt++;
406*b077aed3SPierre Pronchery             break;
407*b077aed3SPierre Pronchery         case OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS:
408*b077aed3SPierre Pronchery             if (cipher->settable_ctx_params != NULL)
409*b077aed3SPierre Pronchery                 break;
410*b077aed3SPierre Pronchery             cipher->settable_ctx_params
411*b077aed3SPierre Pronchery                 = OSSL_FUNC_asym_cipher_settable_ctx_params(fns);
412*b077aed3SPierre Pronchery             sparamfncnt++;
413*b077aed3SPierre Pronchery             break;
414*b077aed3SPierre Pronchery         }
415*b077aed3SPierre Pronchery     }
416*b077aed3SPierre Pronchery     if (ctxfncnt != 2
417*b077aed3SPierre Pronchery         || (encfncnt != 0 && encfncnt != 2)
418*b077aed3SPierre Pronchery         || (decfncnt != 0 && decfncnt != 2)
419*b077aed3SPierre Pronchery         || (encfncnt != 2 && decfncnt != 2)
420*b077aed3SPierre Pronchery         || (gparamfncnt != 0 && gparamfncnt != 2)
421*b077aed3SPierre Pronchery         || (sparamfncnt != 0 && sparamfncnt != 2)) {
422*b077aed3SPierre Pronchery         /*
423*b077aed3SPierre Pronchery          * In order to be a consistent set of functions we must have at least
424*b077aed3SPierre Pronchery          * a set of context functions (newctx and freectx) as well as a pair of
425*b077aed3SPierre Pronchery          * "cipher" functions: (encrypt_init, encrypt) or
426*b077aed3SPierre Pronchery          * (decrypt_init decrypt). set_ctx_params and settable_ctx_params are
427*b077aed3SPierre Pronchery          * optional, but if one of them is present then the other one must also
428*b077aed3SPierre Pronchery          * be present. The same applies to get_ctx_params and
429*b077aed3SPierre Pronchery          * gettable_ctx_params. The dupctx function is optional.
430*b077aed3SPierre Pronchery          */
431*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
432*b077aed3SPierre Pronchery         goto err;
433*b077aed3SPierre Pronchery     }
434*b077aed3SPierre Pronchery 
435*b077aed3SPierre Pronchery     return cipher;
436*b077aed3SPierre Pronchery  err:
437*b077aed3SPierre Pronchery     EVP_ASYM_CIPHER_free(cipher);
438*b077aed3SPierre Pronchery     return NULL;
439*b077aed3SPierre Pronchery }
440*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER * cipher)441*b077aed3SPierre Pronchery void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher)
442*b077aed3SPierre Pronchery {
443*b077aed3SPierre Pronchery     int i;
444*b077aed3SPierre Pronchery 
445*b077aed3SPierre Pronchery     if (cipher == NULL)
446*b077aed3SPierre Pronchery         return;
447*b077aed3SPierre Pronchery     CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
448*b077aed3SPierre Pronchery     if (i > 0)
449*b077aed3SPierre Pronchery         return;
450*b077aed3SPierre Pronchery     OPENSSL_free(cipher->type_name);
451*b077aed3SPierre Pronchery     ossl_provider_free(cipher->prov);
452*b077aed3SPierre Pronchery     CRYPTO_THREAD_lock_free(cipher->lock);
453*b077aed3SPierre Pronchery     OPENSSL_free(cipher);
454*b077aed3SPierre Pronchery }
455*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER * cipher)456*b077aed3SPierre Pronchery int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher)
457*b077aed3SPierre Pronchery {
458*b077aed3SPierre Pronchery     int ref = 0;
459*b077aed3SPierre Pronchery 
460*b077aed3SPierre Pronchery     CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
461*b077aed3SPierre Pronchery     return 1;
462*b077aed3SPierre Pronchery }
463*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER * cipher)464*b077aed3SPierre Pronchery OSSL_PROVIDER *EVP_ASYM_CIPHER_get0_provider(const EVP_ASYM_CIPHER *cipher)
465*b077aed3SPierre Pronchery {
466*b077aed3SPierre Pronchery     return cipher->prov;
467*b077aed3SPierre Pronchery }
468*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX * ctx,const char * algorithm,const char * properties)469*b077aed3SPierre Pronchery EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
470*b077aed3SPierre Pronchery                                        const char *properties)
471*b077aed3SPierre Pronchery {
472*b077aed3SPierre Pronchery     return evp_generic_fetch(ctx, OSSL_OP_ASYM_CIPHER, algorithm, properties,
473*b077aed3SPierre Pronchery                              evp_asym_cipher_from_algorithm,
474*b077aed3SPierre Pronchery                              (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
475*b077aed3SPierre Pronchery                              (void (*)(void *))EVP_ASYM_CIPHER_free);
476*b077aed3SPierre Pronchery }
477*b077aed3SPierre Pronchery 
evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER * prov,const char * algorithm,const char * properties)478*b077aed3SPierre Pronchery EVP_ASYM_CIPHER *evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER *prov,
479*b077aed3SPierre Pronchery                                                  const char *algorithm,
480*b077aed3SPierre Pronchery                                                  const char *properties)
481*b077aed3SPierre Pronchery {
482*b077aed3SPierre Pronchery     return evp_generic_fetch_from_prov(prov, OSSL_OP_ASYM_CIPHER,
483*b077aed3SPierre Pronchery                                        algorithm, properties,
484*b077aed3SPierre Pronchery                                        evp_asym_cipher_from_algorithm,
485*b077aed3SPierre Pronchery                                        (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
486*b077aed3SPierre Pronchery                                        (void (*)(void *))EVP_ASYM_CIPHER_free);
487*b077aed3SPierre Pronchery }
488*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER * cipher,const char * name)489*b077aed3SPierre Pronchery int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name)
490*b077aed3SPierre Pronchery {
491*b077aed3SPierre Pronchery     return evp_is_a(cipher->prov, cipher->name_id, NULL, name);
492*b077aed3SPierre Pronchery }
493*b077aed3SPierre Pronchery 
evp_asym_cipher_get_number(const EVP_ASYM_CIPHER * cipher)494*b077aed3SPierre Pronchery int evp_asym_cipher_get_number(const EVP_ASYM_CIPHER *cipher)
495*b077aed3SPierre Pronchery {
496*b077aed3SPierre Pronchery     return cipher->name_id;
497*b077aed3SPierre Pronchery }
498*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_get0_name(const EVP_ASYM_CIPHER * cipher)499*b077aed3SPierre Pronchery const char *EVP_ASYM_CIPHER_get0_name(const EVP_ASYM_CIPHER *cipher)
500*b077aed3SPierre Pronchery {
501*b077aed3SPierre Pronchery     return cipher->type_name;
502*b077aed3SPierre Pronchery }
503*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_get0_description(const EVP_ASYM_CIPHER * cipher)504*b077aed3SPierre Pronchery const char *EVP_ASYM_CIPHER_get0_description(const EVP_ASYM_CIPHER *cipher)
505*b077aed3SPierre Pronchery {
506*b077aed3SPierre Pronchery     return cipher->description;
507*b077aed3SPierre Pronchery }
508*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX * libctx,void (* fn)(EVP_ASYM_CIPHER * cipher,void * arg),void * arg)509*b077aed3SPierre Pronchery void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
510*b077aed3SPierre Pronchery                                      void (*fn)(EVP_ASYM_CIPHER *cipher,
511*b077aed3SPierre Pronchery                                                 void *arg),
512*b077aed3SPierre Pronchery                                      void *arg)
513*b077aed3SPierre Pronchery {
514*b077aed3SPierre Pronchery     evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER,
515*b077aed3SPierre Pronchery                        (void (*)(void *, void *))fn, arg,
516*b077aed3SPierre Pronchery                        evp_asym_cipher_from_algorithm,
517*b077aed3SPierre Pronchery                        (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
518*b077aed3SPierre Pronchery                        (void (*)(void *))EVP_ASYM_CIPHER_free);
519*b077aed3SPierre Pronchery }
520*b077aed3SPierre Pronchery 
521*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER * cipher,void (* fn)(const char * name,void * data),void * data)522*b077aed3SPierre Pronchery int EVP_ASYM_CIPHER_names_do_all(const EVP_ASYM_CIPHER *cipher,
523*b077aed3SPierre Pronchery                                  void (*fn)(const char *name, void *data),
524*b077aed3SPierre Pronchery                                  void *data)
525*b077aed3SPierre Pronchery {
526*b077aed3SPierre Pronchery     if (cipher->prov != NULL)
527*b077aed3SPierre Pronchery         return evp_names_do_all(cipher->prov, cipher->name_id, fn, data);
528*b077aed3SPierre Pronchery 
529*b077aed3SPierre Pronchery     return 1;
530*b077aed3SPierre Pronchery }
531*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER * cip)532*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_ASYM_CIPHER_gettable_ctx_params(const EVP_ASYM_CIPHER *cip)
533*b077aed3SPierre Pronchery {
534*b077aed3SPierre Pronchery     void *provctx;
535*b077aed3SPierre Pronchery 
536*b077aed3SPierre Pronchery     if (cip == NULL || cip->gettable_ctx_params == NULL)
537*b077aed3SPierre Pronchery         return NULL;
538*b077aed3SPierre Pronchery 
539*b077aed3SPierre Pronchery     provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_get0_provider(cip));
540*b077aed3SPierre Pronchery     return cip->gettable_ctx_params(NULL, provctx);
541*b077aed3SPierre Pronchery }
542*b077aed3SPierre Pronchery 
EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER * cip)543*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_ASYM_CIPHER_settable_ctx_params(const EVP_ASYM_CIPHER *cip)
544*b077aed3SPierre Pronchery {
545*b077aed3SPierre Pronchery     void *provctx;
546*b077aed3SPierre Pronchery 
547*b077aed3SPierre Pronchery     if (cip == NULL || cip->settable_ctx_params == NULL)
548*b077aed3SPierre Pronchery         return NULL;
549*b077aed3SPierre Pronchery 
550*b077aed3SPierre Pronchery     provctx = ossl_provider_ctx(EVP_ASYM_CIPHER_get0_provider(cip));
551*b077aed3SPierre Pronchery     return cip->settable_ctx_params(NULL, provctx);
552*b077aed3SPierre Pronchery }
553