]>
Commit | Line | Data |
---|---|---|
fb9e6dd6 P |
1 | /* |
2 | * Copyright 2019 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_numbers.h> | |
14 | #include <openssl/kdf.h> | |
25f2138b | 15 | #include "crypto/evp.h" |
fb9e6dd6 | 16 | #include "internal/provider.h" |
706457b7 | 17 | #include "evp_local.h" |
fb9e6dd6 P |
18 | |
19 | static int evp_kdf_up_ref(void *vkdf) | |
20 | { | |
21 | EVP_KDF *kdf = (EVP_KDF *)vkdf; | |
22 | int ref = 0; | |
23 | ||
24 | CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock); | |
25 | return 1; | |
26 | } | |
27 | ||
28 | static void evp_kdf_free(void *vkdf){ | |
29 | EVP_KDF *kdf = (EVP_KDF *)vkdf; | |
30 | int ref = 0; | |
31 | ||
32 | if (kdf != NULL) { | |
33 | CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock); | |
34 | if (ref <= 0) { | |
35 | ossl_provider_free(kdf->prov); | |
fb9e6dd6 P |
36 | CRYPTO_THREAD_lock_free(kdf->lock); |
37 | OPENSSL_free(kdf); | |
38 | } | |
39 | } | |
40 | } | |
41 | ||
42 | static void *evp_kdf_new(void) | |
43 | { | |
44 | EVP_KDF *kdf = NULL; | |
45 | ||
46 | if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL | |
47 | || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) { | |
48 | OPENSSL_free(kdf); | |
49 | return NULL; | |
50 | } | |
51 | kdf->refcnt = 1; | |
52 | return kdf; | |
53 | } | |
54 | ||
f7c16d48 RL |
55 | static void *evp_kdf_from_dispatch(int name_id, |
56 | const OSSL_DISPATCH *fns, | |
0ddf74bf | 57 | OSSL_PROVIDER *prov) |
fb9e6dd6 P |
58 | { |
59 | EVP_KDF *kdf = NULL; | |
60 | int fnkdfcnt = 0, fnctxcnt = 0; | |
61 | ||
f7c16d48 | 62 | if ((kdf = evp_kdf_new()) == NULL) { |
fb9e6dd6 P |
63 | EVPerr(0, ERR_R_MALLOC_FAILURE); |
64 | return NULL; | |
65 | } | |
f7c16d48 | 66 | kdf->name_id = name_id; |
fb9e6dd6 P |
67 | |
68 | for (; fns->function_id != 0; fns++) { | |
69 | switch (fns->function_id) { | |
70 | case OSSL_FUNC_KDF_NEWCTX: | |
71 | if (kdf->newctx != NULL) | |
72 | break; | |
73 | kdf->newctx = OSSL_get_OP_kdf_newctx(fns); | |
74 | fnctxcnt++; | |
75 | break; | |
76 | case OSSL_FUNC_KDF_DUPCTX: | |
77 | if (kdf->dupctx != NULL) | |
78 | break; | |
79 | kdf->dupctx = OSSL_get_OP_kdf_dupctx(fns); | |
80 | break; | |
81 | case OSSL_FUNC_KDF_FREECTX: | |
82 | if (kdf->freectx != NULL) | |
83 | break; | |
84 | kdf->freectx = OSSL_get_OP_kdf_freectx(fns); | |
85 | fnctxcnt++; | |
86 | break; | |
6d1c3154 RL |
87 | case OSSL_FUNC_KDF_RESET: |
88 | if (kdf->reset != NULL) | |
89 | break; | |
90 | kdf->reset = OSSL_get_OP_kdf_reset(fns); | |
91 | break; | |
fb9e6dd6 P |
92 | case OSSL_FUNC_KDF_DERIVE: |
93 | if (kdf->derive != NULL) | |
94 | break; | |
95 | kdf->derive = OSSL_get_OP_kdf_derive(fns); | |
96 | fnkdfcnt++; | |
97 | break; | |
98 | case OSSL_FUNC_KDF_GETTABLE_PARAMS: | |
99 | if (kdf->gettable_params != NULL) | |
100 | break; | |
101 | kdf->gettable_params = | |
102 | OSSL_get_OP_kdf_gettable_params(fns); | |
103 | break; | |
104 | case OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS: | |
105 | if (kdf->gettable_ctx_params != NULL) | |
106 | break; | |
107 | kdf->gettable_ctx_params = | |
108 | OSSL_get_OP_kdf_gettable_ctx_params(fns); | |
109 | break; | |
110 | case OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS: | |
111 | if (kdf->settable_ctx_params != NULL) | |
112 | break; | |
113 | kdf->settable_ctx_params = | |
114 | OSSL_get_OP_kdf_settable_ctx_params(fns); | |
115 | break; | |
116 | case OSSL_FUNC_KDF_GET_PARAMS: | |
117 | if (kdf->get_params != NULL) | |
118 | break; | |
119 | kdf->get_params = OSSL_get_OP_kdf_get_params(fns); | |
120 | break; | |
121 | case OSSL_FUNC_KDF_GET_CTX_PARAMS: | |
122 | if (kdf->get_ctx_params != NULL) | |
123 | break; | |
124 | kdf->get_ctx_params = OSSL_get_OP_kdf_get_ctx_params(fns); | |
125 | break; | |
126 | case OSSL_FUNC_KDF_SET_CTX_PARAMS: | |
127 | if (kdf->set_ctx_params != NULL) | |
128 | break; | |
129 | kdf->set_ctx_params = OSSL_get_OP_kdf_set_ctx_params(fns); | |
130 | break; | |
131 | } | |
132 | } | |
133 | if (fnkdfcnt != 1 || fnctxcnt != 2) { | |
134 | /* | |
135 | * In order to be a consistent set of functions we must have at least | |
136 | * a derive function, and a complete set of context management | |
137 | * functions. | |
138 | */ | |
139 | evp_kdf_free(kdf); | |
140 | ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); | |
141 | return NULL; | |
142 | } | |
143 | kdf->prov = prov; | |
144 | if (prov != NULL) | |
145 | ossl_provider_up_ref(prov); | |
146 | ||
147 | return kdf; | |
148 | } | |
149 | ||
150 | EVP_KDF *EVP_KDF_fetch(OPENSSL_CTX *libctx, const char *algorithm, | |
151 | const char *properties) | |
152 | { | |
153 | return evp_generic_fetch(libctx, OSSL_OP_KDF, algorithm, properties, | |
0ddf74bf | 154 | evp_kdf_from_dispatch, evp_kdf_up_ref, |
fb9e6dd6 P |
155 | evp_kdf_free); |
156 | } | |
157 | ||
158 | int EVP_KDF_up_ref(EVP_KDF *kdf) | |
159 | { | |
160 | return evp_kdf_up_ref(kdf); | |
161 | } | |
162 | ||
163 | void EVP_KDF_free(EVP_KDF *kdf) | |
164 | { | |
165 | evp_kdf_free(kdf); | |
166 | } | |
167 | ||
168 | const OSSL_PARAM *EVP_KDF_gettable_params(const EVP_KDF *kdf) | |
169 | { | |
170 | if (kdf->gettable_params == NULL) | |
171 | return NULL; | |
172 | return kdf->gettable_params(); | |
173 | } | |
174 | ||
41f7ecf3 | 175 | const OSSL_PARAM *EVP_KDF_gettable_ctx_params(const EVP_KDF *kdf) |
fb9e6dd6 P |
176 | { |
177 | if (kdf->gettable_ctx_params == NULL) | |
178 | return NULL; | |
179 | return kdf->gettable_ctx_params(); | |
180 | } | |
181 | ||
41f7ecf3 | 182 | const OSSL_PARAM *EVP_KDF_settable_ctx_params(const EVP_KDF *kdf) |
fb9e6dd6 P |
183 | { |
184 | if (kdf->settable_ctx_params == NULL) | |
185 | return NULL; | |
186 | return kdf->settable_ctx_params(); | |
187 | } | |
188 | ||
251e610c RL |
189 | void EVP_KDF_do_all_provided(OPENSSL_CTX *libctx, |
190 | void (*fn)(EVP_KDF *kdf, void *arg), | |
191 | void *arg) | |
fb9e6dd6 P |
192 | { |
193 | evp_generic_do_all(libctx, OSSL_OP_KDF, | |
194 | (void (*)(void *, void *))fn, arg, | |
0ddf74bf | 195 | evp_kdf_from_dispatch, evp_kdf_free); |
fb9e6dd6 | 196 | } |