1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery * Copyright 2019-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 <openssl/evp.h>
11*b077aed3SPierre Pronchery #include <openssl/err.h>
12*b077aed3SPierre Pronchery #include <openssl/core.h>
13*b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
14*b077aed3SPierre Pronchery #include <openssl/kdf.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_kdf_up_ref(void * vkdf)20*b077aed3SPierre Pronchery static int evp_kdf_up_ref(void *vkdf)
21*b077aed3SPierre Pronchery {
22*b077aed3SPierre Pronchery EVP_KDF *kdf = (EVP_KDF *)vkdf;
23*b077aed3SPierre Pronchery int ref = 0;
24*b077aed3SPierre Pronchery
25*b077aed3SPierre Pronchery CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock);
26*b077aed3SPierre Pronchery return 1;
27*b077aed3SPierre Pronchery }
28*b077aed3SPierre Pronchery
evp_kdf_free(void * vkdf)29*b077aed3SPierre Pronchery static void evp_kdf_free(void *vkdf)
30*b077aed3SPierre Pronchery {
31*b077aed3SPierre Pronchery EVP_KDF *kdf = (EVP_KDF *)vkdf;
32*b077aed3SPierre Pronchery int ref = 0;
33*b077aed3SPierre Pronchery
34*b077aed3SPierre Pronchery if (kdf == NULL)
35*b077aed3SPierre Pronchery return;
36*b077aed3SPierre Pronchery
37*b077aed3SPierre Pronchery CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock);
38*b077aed3SPierre Pronchery if (ref > 0)
39*b077aed3SPierre Pronchery return;
40*b077aed3SPierre Pronchery OPENSSL_free(kdf->type_name);
41*b077aed3SPierre Pronchery ossl_provider_free(kdf->prov);
42*b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(kdf->lock);
43*b077aed3SPierre Pronchery OPENSSL_free(kdf);
44*b077aed3SPierre Pronchery }
45*b077aed3SPierre Pronchery
evp_kdf_new(void)46*b077aed3SPierre Pronchery static void *evp_kdf_new(void)
47*b077aed3SPierre Pronchery {
48*b077aed3SPierre Pronchery EVP_KDF *kdf = NULL;
49*b077aed3SPierre Pronchery
50*b077aed3SPierre Pronchery if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL
51*b077aed3SPierre Pronchery || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) {
52*b077aed3SPierre Pronchery OPENSSL_free(kdf);
53*b077aed3SPierre Pronchery return NULL;
54*b077aed3SPierre Pronchery }
55*b077aed3SPierre Pronchery kdf->refcnt = 1;
56*b077aed3SPierre Pronchery return kdf;
57*b077aed3SPierre Pronchery }
58*b077aed3SPierre Pronchery
evp_kdf_from_algorithm(int name_id,const OSSL_ALGORITHM * algodef,OSSL_PROVIDER * prov)59*b077aed3SPierre Pronchery static void *evp_kdf_from_algorithm(int name_id,
60*b077aed3SPierre Pronchery const OSSL_ALGORITHM *algodef,
61*b077aed3SPierre Pronchery OSSL_PROVIDER *prov)
62*b077aed3SPierre Pronchery {
63*b077aed3SPierre Pronchery const OSSL_DISPATCH *fns = algodef->implementation;
64*b077aed3SPierre Pronchery EVP_KDF *kdf = NULL;
65*b077aed3SPierre Pronchery int fnkdfcnt = 0, fnctxcnt = 0;
66*b077aed3SPierre Pronchery
67*b077aed3SPierre Pronchery if ((kdf = evp_kdf_new()) == NULL) {
68*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
69*b077aed3SPierre Pronchery return NULL;
70*b077aed3SPierre Pronchery }
71*b077aed3SPierre Pronchery kdf->name_id = name_id;
72*b077aed3SPierre Pronchery if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
73*b077aed3SPierre Pronchery evp_kdf_free(kdf);
74*b077aed3SPierre Pronchery return NULL;
75*b077aed3SPierre Pronchery }
76*b077aed3SPierre Pronchery kdf->description = algodef->algorithm_description;
77*b077aed3SPierre Pronchery
78*b077aed3SPierre Pronchery for (; fns->function_id != 0; fns++) {
79*b077aed3SPierre Pronchery switch (fns->function_id) {
80*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_NEWCTX:
81*b077aed3SPierre Pronchery if (kdf->newctx != NULL)
82*b077aed3SPierre Pronchery break;
83*b077aed3SPierre Pronchery kdf->newctx = OSSL_FUNC_kdf_newctx(fns);
84*b077aed3SPierre Pronchery fnctxcnt++;
85*b077aed3SPierre Pronchery break;
86*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_DUPCTX:
87*b077aed3SPierre Pronchery if (kdf->dupctx != NULL)
88*b077aed3SPierre Pronchery break;
89*b077aed3SPierre Pronchery kdf->dupctx = OSSL_FUNC_kdf_dupctx(fns);
90*b077aed3SPierre Pronchery break;
91*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_FREECTX:
92*b077aed3SPierre Pronchery if (kdf->freectx != NULL)
93*b077aed3SPierre Pronchery break;
94*b077aed3SPierre Pronchery kdf->freectx = OSSL_FUNC_kdf_freectx(fns);
95*b077aed3SPierre Pronchery fnctxcnt++;
96*b077aed3SPierre Pronchery break;
97*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_RESET:
98*b077aed3SPierre Pronchery if (kdf->reset != NULL)
99*b077aed3SPierre Pronchery break;
100*b077aed3SPierre Pronchery kdf->reset = OSSL_FUNC_kdf_reset(fns);
101*b077aed3SPierre Pronchery break;
102*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_DERIVE:
103*b077aed3SPierre Pronchery if (kdf->derive != NULL)
104*b077aed3SPierre Pronchery break;
105*b077aed3SPierre Pronchery kdf->derive = OSSL_FUNC_kdf_derive(fns);
106*b077aed3SPierre Pronchery fnkdfcnt++;
107*b077aed3SPierre Pronchery break;
108*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_GETTABLE_PARAMS:
109*b077aed3SPierre Pronchery if (kdf->gettable_params != NULL)
110*b077aed3SPierre Pronchery break;
111*b077aed3SPierre Pronchery kdf->gettable_params =
112*b077aed3SPierre Pronchery OSSL_FUNC_kdf_gettable_params(fns);
113*b077aed3SPierre Pronchery break;
114*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS:
115*b077aed3SPierre Pronchery if (kdf->gettable_ctx_params != NULL)
116*b077aed3SPierre Pronchery break;
117*b077aed3SPierre Pronchery kdf->gettable_ctx_params =
118*b077aed3SPierre Pronchery OSSL_FUNC_kdf_gettable_ctx_params(fns);
119*b077aed3SPierre Pronchery break;
120*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS:
121*b077aed3SPierre Pronchery if (kdf->settable_ctx_params != NULL)
122*b077aed3SPierre Pronchery break;
123*b077aed3SPierre Pronchery kdf->settable_ctx_params =
124*b077aed3SPierre Pronchery OSSL_FUNC_kdf_settable_ctx_params(fns);
125*b077aed3SPierre Pronchery break;
126*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_GET_PARAMS:
127*b077aed3SPierre Pronchery if (kdf->get_params != NULL)
128*b077aed3SPierre Pronchery break;
129*b077aed3SPierre Pronchery kdf->get_params = OSSL_FUNC_kdf_get_params(fns);
130*b077aed3SPierre Pronchery break;
131*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_GET_CTX_PARAMS:
132*b077aed3SPierre Pronchery if (kdf->get_ctx_params != NULL)
133*b077aed3SPierre Pronchery break;
134*b077aed3SPierre Pronchery kdf->get_ctx_params = OSSL_FUNC_kdf_get_ctx_params(fns);
135*b077aed3SPierre Pronchery break;
136*b077aed3SPierre Pronchery case OSSL_FUNC_KDF_SET_CTX_PARAMS:
137*b077aed3SPierre Pronchery if (kdf->set_ctx_params != NULL)
138*b077aed3SPierre Pronchery break;
139*b077aed3SPierre Pronchery kdf->set_ctx_params = OSSL_FUNC_kdf_set_ctx_params(fns);
140*b077aed3SPierre Pronchery break;
141*b077aed3SPierre Pronchery }
142*b077aed3SPierre Pronchery }
143*b077aed3SPierre Pronchery if (fnkdfcnt != 1 || fnctxcnt != 2) {
144*b077aed3SPierre Pronchery /*
145*b077aed3SPierre Pronchery * In order to be a consistent set of functions we must have at least
146*b077aed3SPierre Pronchery * a derive function, and a complete set of context management
147*b077aed3SPierre Pronchery * functions.
148*b077aed3SPierre Pronchery */
149*b077aed3SPierre Pronchery evp_kdf_free(kdf);
150*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
151*b077aed3SPierre Pronchery return NULL;
152*b077aed3SPierre Pronchery }
153*b077aed3SPierre Pronchery kdf->prov = prov;
154*b077aed3SPierre Pronchery if (prov != NULL)
155*b077aed3SPierre Pronchery ossl_provider_up_ref(prov);
156*b077aed3SPierre Pronchery
157*b077aed3SPierre Pronchery return kdf;
158*b077aed3SPierre Pronchery }
159*b077aed3SPierre Pronchery
EVP_KDF_fetch(OSSL_LIB_CTX * libctx,const char * algorithm,const char * properties)160*b077aed3SPierre Pronchery EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
161*b077aed3SPierre Pronchery const char *properties)
162*b077aed3SPierre Pronchery {
163*b077aed3SPierre Pronchery return evp_generic_fetch(libctx, OSSL_OP_KDF, algorithm, properties,
164*b077aed3SPierre Pronchery evp_kdf_from_algorithm, evp_kdf_up_ref,
165*b077aed3SPierre Pronchery evp_kdf_free);
166*b077aed3SPierre Pronchery }
167*b077aed3SPierre Pronchery
EVP_KDF_up_ref(EVP_KDF * kdf)168*b077aed3SPierre Pronchery int EVP_KDF_up_ref(EVP_KDF *kdf)
169*b077aed3SPierre Pronchery {
170*b077aed3SPierre Pronchery return evp_kdf_up_ref(kdf);
171*b077aed3SPierre Pronchery }
172*b077aed3SPierre Pronchery
EVP_KDF_free(EVP_KDF * kdf)173*b077aed3SPierre Pronchery void EVP_KDF_free(EVP_KDF *kdf)
174*b077aed3SPierre Pronchery {
175*b077aed3SPierre Pronchery evp_kdf_free(kdf);
176*b077aed3SPierre Pronchery }
177*b077aed3SPierre Pronchery
EVP_KDF_gettable_params(const EVP_KDF * kdf)178*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf)
179*b077aed3SPierre Pronchery {
180*b077aed3SPierre Pronchery if (kdf->gettable_params == NULL)
181*b077aed3SPierre Pronchery return NULL;
182*b077aed3SPierre Pronchery return kdf->gettable_params(ossl_provider_ctx(EVP_KDF_get0_provider(kdf)));
183*b077aed3SPierre Pronchery }
184*b077aed3SPierre Pronchery
EVP_KDF_gettable_ctx_params(const EVP_KDF * kdf)185*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf)
186*b077aed3SPierre Pronchery {
187*b077aed3SPierre Pronchery void *alg;
188*b077aed3SPierre Pronchery
189*b077aed3SPierre Pronchery if (kdf->gettable_ctx_params == NULL)
190*b077aed3SPierre Pronchery return NULL;
191*b077aed3SPierre Pronchery alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf));
192*b077aed3SPierre Pronchery return kdf->gettable_ctx_params(NULL, alg);
193*b077aed3SPierre Pronchery }
194*b077aed3SPierre Pronchery
EVP_KDF_settable_ctx_params(const EVP_KDF * kdf)195*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf)
196*b077aed3SPierre Pronchery {
197*b077aed3SPierre Pronchery void *alg;
198*b077aed3SPierre Pronchery
199*b077aed3SPierre Pronchery if (kdf->settable_ctx_params == NULL)
200*b077aed3SPierre Pronchery return NULL;
201*b077aed3SPierre Pronchery alg = ossl_provider_ctx(EVP_KDF_get0_provider(kdf));
202*b077aed3SPierre Pronchery return kdf->settable_ctx_params(NULL, alg);
203*b077aed3SPierre Pronchery }
204*b077aed3SPierre Pronchery
EVP_KDF_CTX_gettable_params(EVP_KDF_CTX * ctx)205*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KDF_CTX_gettable_params(EVP_KDF_CTX *ctx)
206*b077aed3SPierre Pronchery {
207*b077aed3SPierre Pronchery void *alg;
208*b077aed3SPierre Pronchery
209*b077aed3SPierre Pronchery if (ctx->meth->gettable_ctx_params == NULL)
210*b077aed3SPierre Pronchery return NULL;
211*b077aed3SPierre Pronchery alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth));
212*b077aed3SPierre Pronchery return ctx->meth->gettable_ctx_params(ctx->algctx, alg);
213*b077aed3SPierre Pronchery }
214*b077aed3SPierre Pronchery
EVP_KDF_CTX_settable_params(EVP_KDF_CTX * ctx)215*b077aed3SPierre Pronchery const OSSL_PARAM *EVP_KDF_CTX_settable_params(EVP_KDF_CTX *ctx)
216*b077aed3SPierre Pronchery {
217*b077aed3SPierre Pronchery void *alg;
218*b077aed3SPierre Pronchery
219*b077aed3SPierre Pronchery if (ctx->meth->settable_ctx_params == NULL)
220*b077aed3SPierre Pronchery return NULL;
221*b077aed3SPierre Pronchery alg = ossl_provider_ctx(EVP_KDF_get0_provider(ctx->meth));
222*b077aed3SPierre Pronchery return ctx->meth->settable_ctx_params(ctx->algctx, alg);
223*b077aed3SPierre Pronchery }
224*b077aed3SPierre Pronchery
EVP_KDF_do_all_provided(OSSL_LIB_CTX * libctx,void (* fn)(EVP_KDF * kdf,void * arg),void * arg)225*b077aed3SPierre Pronchery void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
226*b077aed3SPierre Pronchery void (*fn)(EVP_KDF *kdf, void *arg),
227*b077aed3SPierre Pronchery void *arg)
228*b077aed3SPierre Pronchery {
229*b077aed3SPierre Pronchery evp_generic_do_all(libctx, OSSL_OP_KDF,
230*b077aed3SPierre Pronchery (void (*)(void *, void *))fn, arg,
231*b077aed3SPierre Pronchery evp_kdf_from_algorithm, evp_kdf_up_ref, evp_kdf_free);
232*b077aed3SPierre Pronchery }
233