1/*
2 * Copyright 2019-2023 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#include <openssl/crypto.h>
11#include <openssl/core_dispatch.h>
12#include <openssl/evp.h>
13#include <openssl/err.h>
14#include "internal/provider.h"
15#include "internal/refcount.h"
16#include "internal/core.h"
17#include "crypto/evp.h"
18#include "evp_local.h"
19
20static void *keymgmt_new(void)
21{
22    EVP_KEYMGMT *keymgmt = NULL;
23
24    if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
25        || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
26        EVP_KEYMGMT_free(keymgmt);
27        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
28        return NULL;
29    }
30
31    keymgmt->refcnt = 1;
32
33    return keymgmt;
34}
35
36static void *keymgmt_from_algorithm(int name_id,
37                                    const OSSL_ALGORITHM *algodef,
38                                    OSSL_PROVIDER *prov)
39{
40    const OSSL_DISPATCH *fns = algodef->implementation;
41    EVP_KEYMGMT *keymgmt = NULL;
42    int setparamfncnt = 0, getparamfncnt = 0;
43    int setgenparamfncnt = 0;
44    int importfncnt = 0, exportfncnt = 0;
45
46    if ((keymgmt = keymgmt_new()) == NULL)
47        return NULL;
48
49    keymgmt->name_id = name_id;
50    if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
51        EVP_KEYMGMT_free(keymgmt);
52        return NULL;
53    }
54    keymgmt->description = algodef->algorithm_description;
55
56    for (; fns->function_id != 0; fns++) {
57        switch (fns->function_id) {
58        case OSSL_FUNC_KEYMGMT_NEW:
59            if (keymgmt->new == NULL)
60                keymgmt->new = OSSL_FUNC_keymgmt_new(fns);
61            break;
62        case OSSL_FUNC_KEYMGMT_GEN_INIT:
63            if (keymgmt->gen_init == NULL)
64                keymgmt->gen_init = OSSL_FUNC_keymgmt_gen_init(fns);
65            break;
66        case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
67            if (keymgmt->gen_set_template == NULL)
68                keymgmt->gen_set_template =
69                    OSSL_FUNC_keymgmt_gen_set_template(fns);
70            break;
71        case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
72            if (keymgmt->gen_set_params == NULL) {
73                setgenparamfncnt++;
74                keymgmt->gen_set_params =
75                    OSSL_FUNC_keymgmt_gen_set_params(fns);
76            }
77            break;
78        case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
79            if (keymgmt->gen_settable_params == NULL) {
80                setgenparamfncnt++;
81                keymgmt->gen_settable_params =
82                    OSSL_FUNC_keymgmt_gen_settable_params(fns);
83            }
84            break;
85        case OSSL_FUNC_KEYMGMT_GEN:
86            if (keymgmt->gen == NULL)
87                keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns);
88            break;
89        case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
90            if (keymgmt->gen_cleanup == NULL)
91                keymgmt->gen_cleanup = OSSL_FUNC_keymgmt_gen_cleanup(fns);
92            break;
93        case OSSL_FUNC_KEYMGMT_FREE:
94            if (keymgmt->free == NULL)
95                keymgmt->free = OSSL_FUNC_keymgmt_free(fns);
96            break;
97        case OSSL_FUNC_KEYMGMT_LOAD:
98            if (keymgmt->load == NULL)
99                keymgmt->load = OSSL_FUNC_keymgmt_load(fns);
100            break;
101        case OSSL_FUNC_KEYMGMT_GET_PARAMS:
102            if (keymgmt->get_params == NULL) {
103                getparamfncnt++;
104                keymgmt->get_params = OSSL_FUNC_keymgmt_get_params(fns);
105            }
106            break;
107        case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
108            if (keymgmt->gettable_params == NULL) {
109                getparamfncnt++;
110                keymgmt->gettable_params =
111                    OSSL_FUNC_keymgmt_gettable_params(fns);
112            }
113            break;
114         case OSSL_FUNC_KEYMGMT_SET_PARAMS:
115            if (keymgmt->set_params == NULL) {
116                setparamfncnt++;
117                keymgmt->set_params = OSSL_FUNC_keymgmt_set_params(fns);
118            }
119            break;
120        case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
121            if (keymgmt->settable_params == NULL) {
122                setparamfncnt++;
123                keymgmt->settable_params =
124                    OSSL_FUNC_keymgmt_settable_params(fns);
125            }
126            break;
127        case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
128            if (keymgmt->query_operation_name == NULL)
129                keymgmt->query_operation_name =
130                    OSSL_FUNC_keymgmt_query_operation_name(fns);
131            break;
132        case OSSL_FUNC_KEYMGMT_HAS:
133            if (keymgmt->has == NULL)
134                keymgmt->has = OSSL_FUNC_keymgmt_has(fns);
135            break;
136        case OSSL_FUNC_KEYMGMT_DUP:
137            if (keymgmt->dup == NULL)
138                keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
139            break;
140        case OSSL_FUNC_KEYMGMT_VALIDATE:
141            if (keymgmt->validate == NULL)
142                keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
143            break;
144        case OSSL_FUNC_KEYMGMT_MATCH:
145            if (keymgmt->match == NULL)
146                keymgmt->match = OSSL_FUNC_keymgmt_match(fns);
147            break;
148        case OSSL_FUNC_KEYMGMT_IMPORT:
149            if (keymgmt->import == NULL) {
150                importfncnt++;
151                keymgmt->import = OSSL_FUNC_keymgmt_import(fns);
152            }
153            break;
154        case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
155            if (keymgmt->import_types == NULL) {
156                importfncnt++;
157                keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns);
158            }
159            break;
160        case OSSL_FUNC_KEYMGMT_EXPORT:
161            if (keymgmt->export == NULL) {
162                exportfncnt++;
163                keymgmt->export = OSSL_FUNC_keymgmt_export(fns);
164            }
165            break;
166        case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
167            if (keymgmt->export_types == NULL) {
168                exportfncnt++;
169                keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns);
170            }
171            break;
172        }
173    }
174    /*
175     * Try to check that the method is sensible.
176     * At least one constructor and the destructor are MANDATORY
177     * The functions 'has' is MANDATORY
178     * It makes no sense being able to free stuff if you can't create it.
179     * It makes no sense providing OSSL_PARAM descriptors for import and
180     * export if you can't import or export.
181     */
182    if (keymgmt->free == NULL
183        || (keymgmt->new == NULL
184            && keymgmt->gen == NULL
185            && keymgmt->load == NULL)
186        || keymgmt->has == NULL
187        || (getparamfncnt != 0 && getparamfncnt != 2)
188        || (setparamfncnt != 0 && setparamfncnt != 2)
189        || (setgenparamfncnt != 0 && setgenparamfncnt != 2)
190        || (importfncnt != 0 && importfncnt != 2)
191        || (exportfncnt != 0 && exportfncnt != 2)
192        || (keymgmt->gen != NULL
193            && (keymgmt->gen_init == NULL
194                || keymgmt->gen_cleanup == NULL))) {
195        EVP_KEYMGMT_free(keymgmt);
196        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
197        return NULL;
198    }
199    keymgmt->prov = prov;
200    if (prov != NULL)
201        ossl_provider_up_ref(prov);
202
203    return keymgmt;
204}
205
206EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OSSL_LIB_CTX *ctx, int name_id,
207                                         const char *properties)
208{
209    return evp_generic_fetch_by_number(ctx,
210                                       OSSL_OP_KEYMGMT, name_id, properties,
211                                       keymgmt_from_algorithm,
212                                       (int (*)(void *))EVP_KEYMGMT_up_ref,
213                                       (void (*)(void *))EVP_KEYMGMT_free);
214}
215
216EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
217                                         const char *name,
218                                         const char *properties)
219{
220    return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYMGMT,
221                                       name, properties,
222                                       keymgmt_from_algorithm,
223                                       (int (*)(void *))EVP_KEYMGMT_up_ref,
224                                       (void (*)(void *))EVP_KEYMGMT_free);
225}
226
227EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
228                               const char *properties)
229{
230    return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
231                             keymgmt_from_algorithm,
232                             (int (*)(void *))EVP_KEYMGMT_up_ref,
233                             (void (*)(void *))EVP_KEYMGMT_free);
234}
235
236int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
237{
238    int ref = 0;
239
240    CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
241    return 1;
242}
243
244void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
245{
246    int ref = 0;
247
248    if (keymgmt == NULL)
249        return;
250
251    CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
252    if (ref > 0)
253        return;
254    OPENSSL_free(keymgmt->type_name);
255    ossl_provider_free(keymgmt->prov);
256    CRYPTO_THREAD_lock_free(keymgmt->lock);
257    OPENSSL_free(keymgmt);
258}
259
260const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt)
261{
262    return keymgmt->prov;
263}
264
265int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
266{
267    return keymgmt->name_id;
268}
269
270const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
271{
272    return keymgmt->description;
273}
274
275const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt)
276{
277    return keymgmt->type_name;
278}
279
280int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
281{
282    return keymgmt != NULL
283           && evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
284}
285
286void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
287                                 void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
288                                 void *arg)
289{
290    evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
291                       (void (*)(void *, void *))fn, arg,
292                       keymgmt_from_algorithm,
293                       (int (*)(void *))EVP_KEYMGMT_up_ref,
294                       (void (*)(void *))EVP_KEYMGMT_free);
295}
296
297int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
298                             void (*fn)(const char *name, void *data),
299                             void *data)
300{
301    if (keymgmt->prov != NULL)
302        return evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
303
304    return 1;
305}
306
307/*
308 * Internal API that interfaces with the method function pointers
309 */
310void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
311{
312    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
313
314    /*
315     * 'new' is currently mandatory on its own, but when new
316     * constructors appear, it won't be quite as mandatory,
317     * so we have a check for future cases.
318     */
319    if (keymgmt->new == NULL)
320        return NULL;
321    return keymgmt->new(provctx);
322}
323
324void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
325{
326    /* This is mandatory, no need to check for its presence */
327    keymgmt->free(keydata);
328}
329
330void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
331                           const OSSL_PARAM params[])
332{
333    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
334
335    if (keymgmt->gen_init == NULL)
336        return NULL;
337    return keymgmt->gen_init(provctx, selection, params);
338}
339
340int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
341                                 void *template)
342{
343    /*
344     * It's arguable if we actually should return success in this case, as
345     * it allows the caller to set a template key, which is then ignored.
346     * However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
347     * so we do this in the interest of backward compatibility.
348     */
349    if (keymgmt->gen_set_template == NULL)
350        return 1;
351    return keymgmt->gen_set_template(genctx, template);
352}
353
354int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
355                               const OSSL_PARAM params[])
356{
357    if (keymgmt->gen_set_params == NULL)
358        return 0;
359    return keymgmt->gen_set_params(genctx, params);
360}
361
362const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt)
363{
364    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
365
366    if (keymgmt->gen_settable_params == NULL)
367        return NULL;
368    return keymgmt->gen_settable_params(NULL, provctx);
369}
370
371void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
372                      OSSL_CALLBACK *cb, void *cbarg)
373{
374    if (keymgmt->gen == NULL)
375        return NULL;
376    return keymgmt->gen(genctx, cb, cbarg);
377}
378
379void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
380{
381    if (keymgmt->gen_cleanup != NULL)
382        keymgmt->gen_cleanup(genctx);
383}
384
385int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt)
386{
387    return keymgmt != NULL && keymgmt->load != NULL;
388}
389
390void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
391                       const void *objref, size_t objref_sz)
392{
393    if (evp_keymgmt_has_load(keymgmt))
394        return keymgmt->load(objref, objref_sz);
395    return NULL;
396}
397
398int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
399                           OSSL_PARAM params[])
400{
401    if (keymgmt->get_params == NULL)
402        return 1;
403    return keymgmt->get_params(keydata, params);
404}
405
406const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt)
407{
408    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
409
410    if (keymgmt->gettable_params == NULL)
411        return NULL;
412    return keymgmt->gettable_params(provctx);
413}
414
415int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
416                           const OSSL_PARAM params[])
417{
418    if (keymgmt->set_params == NULL)
419        return 1;
420    return keymgmt->set_params(keydata, params);
421}
422
423const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt)
424{
425    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
426
427    if (keymgmt->settable_params == NULL)
428        return NULL;
429    return keymgmt->settable_params(provctx);
430}
431
432int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
433{
434    /* This is mandatory, no need to check for its presence */
435    return keymgmt->has(keydata, selection);
436}
437
438int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
439                         int selection, int checktype)
440{
441    /* We assume valid if the implementation doesn't have a function */
442    if (keymgmt->validate == NULL)
443        return 1;
444    return keymgmt->validate(keydata, selection, checktype);
445}
446
447int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
448                      const void *keydata1, const void *keydata2,
449                      int selection)
450{
451    /* We assume no match if the implementation doesn't have a function */
452    if (keymgmt->match == NULL)
453        return 0;
454    return keymgmt->match(keydata1, keydata2, selection);
455}
456
457int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
458                       int selection, const OSSL_PARAM params[])
459{
460    if (keymgmt->import == NULL)
461        return 0;
462    return keymgmt->import(keydata, selection, params);
463}
464
465const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
466                                           int selection)
467{
468    if (keymgmt->import_types == NULL)
469        return NULL;
470    return keymgmt->import_types(selection);
471}
472
473int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
474                       int selection, OSSL_CALLBACK *param_cb, void *cbarg)
475{
476    if (keymgmt->export == NULL)
477        return 0;
478    return keymgmt->export(keydata, selection, param_cb, cbarg);
479}
480
481const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
482                                           int selection)
483{
484    if (keymgmt->export_types == NULL)
485        return NULL;
486    return keymgmt->export_types(selection);
487}
488
489void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
490                      int selection)
491{
492    /* We assume no dup if the implementation doesn't have a function */
493    if (keymgmt->dup == NULL)
494        return NULL;
495    return keymgmt->dup(keydata_from, selection);
496}
497