Cleanup : directly include of `internal/nelem.h` when required.
[openssl.git] / providers / common / provider_util.c
1 /*
2  * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 /* We need to use some engine deprecated APIs */
11 #define OPENSSL_SUPPRESS_DEPRECATED
12
13 #include <openssl/evp.h>
14 #include <openssl/core_names.h>
15 #include <openssl/err.h>
16 #include <openssl/proverr.h>
17 #ifndef FIPS_MODULE
18 # include <openssl/engine.h>
19 # include "crypto/evp.h"
20 #endif
21 #include "prov/provider_util.h"
22
23 void ossl_prov_cipher_reset(PROV_CIPHER *pc)
24 {
25     EVP_CIPHER_free(pc->alloc_cipher);
26     pc->alloc_cipher = NULL;
27     pc->cipher = NULL;
28 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
29     ENGINE_finish(pc->engine);
30 #endif
31     pc->engine = NULL;
32 }
33
34 int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src)
35 {
36     if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher))
37         return 0;
38 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
39     if (src->engine != NULL && !ENGINE_init(src->engine)) {
40         EVP_CIPHER_free(src->alloc_cipher);
41         return 0;
42     }
43 #endif
44     dst->engine = src->engine;
45     dst->cipher = src->cipher;
46     dst->alloc_cipher = src->alloc_cipher;
47     return 1;
48 }
49
50 static int load_common(const OSSL_PARAM params[], const char **propquery,
51                        ENGINE **engine)
52 {
53     const OSSL_PARAM *p;
54
55     *propquery = NULL;
56     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);
57     if (p != NULL) {
58         if (p->data_type != OSSL_PARAM_UTF8_STRING)
59             return 0;
60         *propquery = p->data;
61     }
62
63 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
64     ENGINE_finish(*engine);
65 #endif
66     *engine = NULL;
67     /* Inside the FIPS module, we don't support legacy ciphers */
68 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
69     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE);
70     if (p != NULL) {
71         if (p->data_type != OSSL_PARAM_UTF8_STRING)
72             return 0;
73         /* Get a structural reference */
74         *engine = ENGINE_by_id(p->data);
75         if (*engine == NULL)
76             return 0;
77         /* Get a functional reference */
78         if (!ENGINE_init(*engine)) {
79             ENGINE_free(*engine);
80             *engine = NULL;
81             return 0;
82         }
83         /* Free the structural reference */
84         ENGINE_free(*engine);
85     }
86 #endif
87     return 1;
88 }
89
90 int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
91                                       const OSSL_PARAM params[],
92                                       OSSL_LIB_CTX *ctx)
93 {
94     const OSSL_PARAM *p;
95     const char *propquery;
96
97     if (params == NULL)
98         return 1;
99
100     if (!load_common(params, &propquery, &pc->engine))
101         return 0;
102
103     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER);
104     if (p == NULL)
105         return 1;
106     if (p->data_type != OSSL_PARAM_UTF8_STRING)
107         return 0;
108
109     EVP_CIPHER_free(pc->alloc_cipher);
110     ERR_set_mark();
111     pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery);
112 #ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy ciphers */
113     if (pc->cipher == NULL) {
114         const EVP_CIPHER *cipher;
115
116         cipher = EVP_get_cipherbyname(p->data);
117         /* Do not use global EVP_CIPHERs */
118         if (cipher != NULL && cipher->origin != EVP_ORIG_GLOBAL)
119             pc->cipher = cipher;
120     }
121 #endif
122     if (pc->cipher != NULL)
123         ERR_pop_to_mark();
124     else
125         ERR_clear_last_mark();
126     return pc->cipher != NULL;
127 }
128
129 const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc)
130 {
131     return pc->cipher;
132 }
133
134 ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc)
135 {
136     return pc->engine;
137 }
138
139 void ossl_prov_digest_reset(PROV_DIGEST *pd)
140 {
141     EVP_MD_free(pd->alloc_md);
142     pd->alloc_md = NULL;
143     pd->md = NULL;
144 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
145     ENGINE_finish(pd->engine);
146 #endif
147     pd->engine = NULL;
148 }
149
150 int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)
151 {
152     if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))
153         return 0;
154 #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
155     if (src->engine != NULL && !ENGINE_init(src->engine)) {
156         EVP_MD_free(src->alloc_md);
157         return 0;
158     }
159 #endif
160     dst->engine = src->engine;
161     dst->md = src->md;
162     dst->alloc_md = src->alloc_md;
163     return 1;
164 }
165
166 const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx,
167                                      const char *mdname, const char *propquery)
168 {
169     EVP_MD_free(pd->alloc_md);
170     pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery);
171
172     return pd->md;
173 }
174
175 int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
176                                       const OSSL_PARAM params[],
177                                       OSSL_LIB_CTX *ctx)
178 {
179     const OSSL_PARAM *p;
180     const char *propquery;
181
182     if (params == NULL)
183         return 1;
184
185     if (!load_common(params, &propquery, &pd->engine))
186         return 0;
187
188     p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
189     if (p == NULL)
190         return 1;
191     if (p->data_type != OSSL_PARAM_UTF8_STRING)
192         return 0;
193
194     ERR_set_mark();
195     ossl_prov_digest_fetch(pd, ctx, p->data, propquery);
196 #ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy digests */
197     if (pd->md == NULL) {
198         const EVP_MD *md;
199
200         md = EVP_get_digestbyname(p->data);
201         /* Do not use global EVP_MDs */
202         if (md != NULL && md->origin != EVP_ORIG_GLOBAL)
203             pd->md = md;
204     }
205 #endif
206     if (pd->md != NULL)
207         ERR_pop_to_mark();
208     else
209         ERR_clear_last_mark();
210     return pd->md != NULL;
211 }
212
213 const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd)
214 {
215     return pd->md;
216 }
217
218 ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd)
219 {
220     return pd->engine;
221 }
222
223 int ossl_prov_set_macctx(EVP_MAC_CTX *macctx,
224                          const OSSL_PARAM params[],
225                          const char *ciphername,
226                          const char *mdname,
227                          const char *engine,
228                          const char *properties,
229                          const unsigned char *key,
230                          size_t keylen)
231 {
232     const OSSL_PARAM *p;
233     OSSL_PARAM mac_params[6], *mp = mac_params;
234
235     if (params != NULL) {
236         if (mdname == NULL) {
237             if ((p = OSSL_PARAM_locate_const(params,
238                                             OSSL_ALG_PARAM_DIGEST)) != NULL) {
239                 if (p->data_type != OSSL_PARAM_UTF8_STRING)
240                     return 0;
241                 mdname = p->data;
242             }
243         }
244         if (ciphername == NULL) {
245             if ((p = OSSL_PARAM_locate_const(params,
246                                             OSSL_ALG_PARAM_CIPHER)) != NULL) {
247                 if (p->data_type != OSSL_PARAM_UTF8_STRING)
248                     return 0;
249                 ciphername = p->data;
250             }
251         }
252         if (engine == NULL) {
253             if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE))
254                     != NULL) {
255                 if (p->data_type != OSSL_PARAM_UTF8_STRING)
256                     return 0;
257                 engine = p->data;
258             }
259         }
260     }
261
262     if (mdname != NULL)
263         *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
264                                                  (char *)mdname, 0);
265     if (ciphername != NULL)
266         *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
267                                                  (char *)ciphername, 0);
268     if (properties != NULL)
269         *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
270                                                  (char *)properties, 0);
271
272 #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
273     if (engine != NULL)
274         *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE,
275                                                  (char *) engine, 0);
276 #endif
277
278     if (key != NULL)
279         *mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
280                                                   (unsigned char *)key,
281                                                   keylen);
282
283     *mp = OSSL_PARAM_construct_end();
284
285     return EVP_MAC_CTX_set_params(macctx, mac_params);
286
287 }
288
289 int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
290                                       const OSSL_PARAM params[],
291                                       const char *macname,
292                                       const char *ciphername,
293                                       const char *mdname,
294                                       OSSL_LIB_CTX *libctx)
295 {
296     const OSSL_PARAM *p;
297     const char *properties = NULL;
298
299     if (macname == NULL
300         && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {
301         if (p->data_type != OSSL_PARAM_UTF8_STRING)
302             return 0;
303         macname = p->data;
304     }
305     if ((p = OSSL_PARAM_locate_const(params,
306                                      OSSL_ALG_PARAM_PROPERTIES)) != NULL) {
307         if (p->data_type != OSSL_PARAM_UTF8_STRING)
308             return 0;
309         properties = p->data;
310     }
311
312     /* If we got a new mac name, we make a new EVP_MAC_CTX */
313     if (macname != NULL) {
314         EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);
315
316         EVP_MAC_CTX_free(*macctx);
317         *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);
318         /* The context holds on to the MAC */
319         EVP_MAC_free(mac);
320         if (*macctx == NULL)
321             return 0;
322     }
323
324     /*
325      * If there is no MAC yet (and therefore, no MAC context), we ignore
326      * all other parameters.
327      */
328     if (*macctx == NULL)
329         return 1;
330
331     if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL,
332                              properties, NULL, 0))
333         return 1;
334
335     EVP_MAC_CTX_free(*macctx);
336     *macctx = NULL;
337     return 0;
338 }
339
340 void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
341                                          OSSL_ALGORITHM *out)
342 {
343     int i, j;
344
345     if (out[0].algorithm_names == NULL) {
346         for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) {
347             if (in[i].capable == NULL || in[i].capable())
348                 out[j++] = in[i].alg;
349         }
350         out[j++] = in[i].alg;
351     }
352 }
353
354 /* Duplicate a lump of memory safely */
355 int ossl_prov_memdup(const void *src, size_t src_len,
356                      unsigned char **dest, size_t *dest_len)
357 {
358     if (src != NULL) {
359         if ((*dest = OPENSSL_memdup(src, src_len)) == NULL)
360             return 0;
361         *dest_len = src_len;
362     } else {
363         *dest = NULL;
364         *dest_len = 0;
365     }
366     return 1;
367 }