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