]>
Commit | Line | Data |
---|---|---|
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 <string.h> | |
11 | #include <stdio.h> | |
12 | #include <openssl/core.h> | |
13 | #include <openssl/core_dispatch.h> | |
14 | #include <openssl/core_names.h> | |
15 | #include <openssl/err.h> | |
16 | #include <openssl/params.h> | |
17 | #include "prov/provider_ctx.h" | |
18 | #include "prov/implementations.h" | |
19 | #include "prov/names.h" | |
20 | #include "prov/providercommon.h" | |
21 | ||
22 | /* | |
23 | * Forward declarations to ensure that interface functions are correctly | |
24 | * defined. | |
25 | */ | |
26 | static OSSL_FUNC_provider_gettable_params_fn legacy_gettable_params; | |
27 | static OSSL_FUNC_provider_get_params_fn legacy_get_params; | |
28 | static OSSL_FUNC_provider_query_operation_fn legacy_query; | |
29 | ||
30 | #define ALG(NAMES, FUNC) { NAMES, "provider=legacy", FUNC } | |
31 | ||
32 | #ifdef STATIC_LEGACY | |
33 | OSSL_provider_init_fn ossl_legacy_provider_init; | |
34 | # define OSSL_provider_init ossl_legacy_provider_init | |
35 | #endif | |
36 | ||
37 | #ifndef STATIC_LEGACY | |
38 | /* | |
39 | * Should these function pointers be stored in the provider side provctx? | |
40 | * Could they ever be different from one init to the next? We assume not for | |
41 | * now. | |
42 | */ | |
43 | ||
44 | /* Functions provided by the core */ | |
45 | static OSSL_FUNC_core_new_error_fn *c_new_error; | |
46 | static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug; | |
47 | static OSSL_FUNC_core_vset_error_fn *c_vset_error; | |
48 | static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark; | |
49 | static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark; | |
50 | static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark; | |
51 | #endif | |
52 | ||
53 | /* Parameters we provide to the core */ | |
54 | static const OSSL_PARAM legacy_param_types[] = { | |
55 | OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), | |
56 | OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0), | |
57 | OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0), | |
58 | OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0), | |
59 | OSSL_PARAM_END | |
60 | }; | |
61 | ||
62 | static const OSSL_PARAM *legacy_gettable_params(void *provctx) | |
63 | { | |
64 | return legacy_param_types; | |
65 | } | |
66 | ||
67 | static int legacy_get_params(void *provctx, OSSL_PARAM params[]) | |
68 | { | |
69 | OSSL_PARAM *p; | |
70 | ||
71 | p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME); | |
72 | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Legacy Provider")) | |
73 | return 0; | |
74 | p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION); | |
75 | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR)) | |
76 | return 0; | |
77 | p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO); | |
78 | if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR)) | |
79 | return 0; | |
80 | p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS); | |
81 | if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running())) | |
82 | return 0; | |
83 | return 1; | |
84 | } | |
85 | ||
86 | static const OSSL_ALGORITHM legacy_digests[] = { | |
87 | #ifndef OPENSSL_NO_MD2 | |
88 | ALG(PROV_NAMES_MD2, ossl_md2_functions), | |
89 | #endif | |
90 | #ifndef OPENSSL_NO_MD4 | |
91 | ALG(PROV_NAMES_MD4, ossl_md4_functions), | |
92 | #endif | |
93 | #ifndef OPENSSL_NO_MDC2 | |
94 | ALG(PROV_NAMES_MDC2, ossl_mdc2_functions), | |
95 | #endif /* OPENSSL_NO_MDC2 */ | |
96 | #ifndef OPENSSL_NO_WHIRLPOOL | |
97 | ALG(PROV_NAMES_WHIRLPOOL, ossl_wp_functions), | |
98 | #endif /* OPENSSL_NO_WHIRLPOOL */ | |
99 | #ifndef OPENSSL_NO_RMD160 | |
100 | ALG(PROV_NAMES_RIPEMD_160, ossl_ripemd160_functions), | |
101 | #endif /* OPENSSL_NO_RMD160 */ | |
102 | { NULL, NULL, NULL } | |
103 | }; | |
104 | ||
105 | static const OSSL_ALGORITHM legacy_ciphers[] = { | |
106 | #ifndef OPENSSL_NO_CAST | |
107 | ALG(PROV_NAMES_CAST5_ECB, ossl_cast5128ecb_functions), | |
108 | ALG(PROV_NAMES_CAST5_CBC, ossl_cast5128cbc_functions), | |
109 | ALG(PROV_NAMES_CAST5_OFB, ossl_cast5128ofb64_functions), | |
110 | ALG(PROV_NAMES_CAST5_CFB, ossl_cast5128cfb64_functions), | |
111 | #endif /* OPENSSL_NO_CAST */ | |
112 | #ifndef OPENSSL_NO_BF | |
113 | ALG(PROV_NAMES_BF_ECB, ossl_blowfish128ecb_functions), | |
114 | ALG(PROV_NAMES_BF_CBC, ossl_blowfish128cbc_functions), | |
115 | ALG(PROV_NAMES_BF_OFB, ossl_blowfish128ofb64_functions), | |
116 | ALG(PROV_NAMES_BF_CFB, ossl_blowfish128cfb64_functions), | |
117 | #endif /* OPENSSL_NO_BF */ | |
118 | #ifndef OPENSSL_NO_IDEA | |
119 | ALG(PROV_NAMES_IDEA_ECB, ossl_idea128ecb_functions), | |
120 | ALG(PROV_NAMES_IDEA_CBC, ossl_idea128cbc_functions), | |
121 | ALG(PROV_NAMES_IDEA_OFB, ossl_idea128ofb64_functions), | |
122 | ALG(PROV_NAMES_IDEA_CFB, ossl_idea128cfb64_functions), | |
123 | #endif /* OPENSSL_NO_IDEA */ | |
124 | #ifndef OPENSSL_NO_SEED | |
125 | ALG(PROV_NAMES_SEED_ECB, ossl_seed128ecb_functions), | |
126 | ALG(PROV_NAMES_SEED_CBC, ossl_seed128cbc_functions), | |
127 | ALG(PROV_NAMES_SEED_OFB, ossl_seed128ofb128_functions), | |
128 | ALG(PROV_NAMES_SEED_CFB, ossl_seed128cfb128_functions), | |
129 | #endif /* OPENSSL_NO_SEED */ | |
130 | #ifndef OPENSSL_NO_RC2 | |
131 | ALG(PROV_NAMES_RC2_ECB, ossl_rc2128ecb_functions), | |
132 | ALG(PROV_NAMES_RC2_CBC, ossl_rc2128cbc_functions), | |
133 | ALG(PROV_NAMES_RC2_40_CBC, ossl_rc240cbc_functions), | |
134 | ALG(PROV_NAMES_RC2_64_CBC, ossl_rc264cbc_functions), | |
135 | ALG(PROV_NAMES_RC2_CFB, ossl_rc2128cfb128_functions), | |
136 | ALG(PROV_NAMES_RC2_OFB, ossl_rc2128ofb128_functions), | |
137 | #endif /* OPENSSL_NO_RC2 */ | |
138 | #ifndef OPENSSL_NO_RC4 | |
139 | ALG(PROV_NAMES_RC4, ossl_rc4128_functions), | |
140 | ALG(PROV_NAMES_RC4_40, ossl_rc440_functions), | |
141 | # ifndef OPENSSL_NO_MD5 | |
142 | ALG(PROV_NAMES_RC4_HMAC_MD5, ossl_rc4_hmac_ossl_md5_functions), | |
143 | # endif /* OPENSSL_NO_MD5 */ | |
144 | #endif /* OPENSSL_NO_RC4 */ | |
145 | #ifndef OPENSSL_NO_RC5 | |
146 | ALG(PROV_NAMES_RC5_ECB, ossl_rc5128ecb_functions), | |
147 | ALG(PROV_NAMES_RC5_CBC, ossl_rc5128cbc_functions), | |
148 | ALG(PROV_NAMES_RC5_OFB, ossl_rc5128ofb64_functions), | |
149 | ALG(PROV_NAMES_RC5_CFB, ossl_rc5128cfb64_functions), | |
150 | #endif /* OPENSSL_NO_RC5 */ | |
151 | #ifndef OPENSSL_NO_DES | |
152 | ALG(PROV_NAMES_DESX_CBC, ossl_tdes_desx_cbc_functions), | |
153 | ALG(PROV_NAMES_DES_ECB, ossl_des_ecb_functions), | |
154 | ALG(PROV_NAMES_DES_CBC, ossl_des_cbc_functions), | |
155 | ALG(PROV_NAMES_DES_OFB, ossl_des_ofb64_functions), | |
156 | ALG(PROV_NAMES_DES_CFB, ossl_des_cfb64_functions), | |
157 | ALG(PROV_NAMES_DES_CFB1, ossl_des_cfb1_functions), | |
158 | ALG(PROV_NAMES_DES_CFB8, ossl_des_cfb8_functions), | |
159 | #endif /* OPENSSL_NO_DES */ | |
160 | { NULL, NULL, NULL } | |
161 | }; | |
162 | ||
163 | static const OSSL_ALGORITHM legacy_kdfs[] = { | |
164 | ALG(PROV_NAMES_PBKDF1, ossl_kdf_pbkdf1_functions), | |
165 | ALG(PROV_NAMES_PVKKDF, ossl_kdf_pvk_functions), | |
166 | { NULL, NULL, NULL } | |
167 | }; | |
168 | ||
169 | static const OSSL_ALGORITHM *legacy_query(void *provctx, int operation_id, | |
170 | int *no_cache) | |
171 | { | |
172 | *no_cache = 0; | |
173 | switch (operation_id) { | |
174 | case OSSL_OP_DIGEST: | |
175 | return legacy_digests; | |
176 | case OSSL_OP_CIPHER: | |
177 | return legacy_ciphers; | |
178 | case OSSL_OP_KDF: | |
179 | return legacy_kdfs; | |
180 | } | |
181 | return NULL; | |
182 | } | |
183 | ||
184 | static void legacy_teardown(void *provctx) | |
185 | { | |
186 | OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx)); | |
187 | ossl_prov_ctx_free(provctx); | |
188 | } | |
189 | ||
190 | /* Functions we provide to the core */ | |
191 | static const OSSL_DISPATCH legacy_dispatch_table[] = { | |
192 | { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))legacy_teardown }, | |
193 | { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))legacy_gettable_params }, | |
194 | { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))legacy_get_params }, | |
195 | { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))legacy_query }, | |
196 | OSSL_DISPATCH_END | |
197 | }; | |
198 | ||
199 | int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, | |
200 | const OSSL_DISPATCH *in, | |
201 | const OSSL_DISPATCH **out, | |
202 | void **provctx) | |
203 | { | |
204 | OSSL_LIB_CTX *libctx = NULL; | |
205 | #ifndef STATIC_LEGACY | |
206 | const OSSL_DISPATCH *tmp; | |
207 | #endif | |
208 | ||
209 | #ifndef STATIC_LEGACY | |
210 | for (tmp = in; tmp->function_id != 0; tmp++) { | |
211 | /* | |
212 | * We do not support the scenario of an application linked against | |
213 | * multiple versions of libcrypto (e.g. one static and one dynamic), | |
214 | * but sharing a single legacy.so. We do a simple sanity check here. | |
215 | */ | |
216 | #define set_func(c, f) if (c == NULL) c = f; else if (c != f) return 0; | |
217 | switch (tmp->function_id) { | |
218 | case OSSL_FUNC_CORE_NEW_ERROR: | |
219 | set_func(c_new_error, OSSL_FUNC_core_new_error(tmp)); | |
220 | break; | |
221 | case OSSL_FUNC_CORE_SET_ERROR_DEBUG: | |
222 | set_func(c_set_error_debug, OSSL_FUNC_core_set_error_debug(tmp)); | |
223 | break; | |
224 | case OSSL_FUNC_CORE_VSET_ERROR: | |
225 | set_func(c_vset_error, OSSL_FUNC_core_vset_error(tmp)); | |
226 | break; | |
227 | case OSSL_FUNC_CORE_SET_ERROR_MARK: | |
228 | set_func(c_set_error_mark, OSSL_FUNC_core_set_error_mark(tmp)); | |
229 | break; | |
230 | case OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK: | |
231 | set_func(c_clear_last_error_mark, | |
232 | OSSL_FUNC_core_clear_last_error_mark(tmp)); | |
233 | break; | |
234 | case OSSL_FUNC_CORE_POP_ERROR_TO_MARK: | |
235 | set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(tmp)); | |
236 | break; | |
237 | } | |
238 | } | |
239 | #endif | |
240 | ||
241 | if ((*provctx = ossl_prov_ctx_new()) == NULL | |
242 | || (libctx = OSSL_LIB_CTX_new_child(handle, in)) == NULL) { | |
243 | OSSL_LIB_CTX_free(libctx); | |
244 | legacy_teardown(*provctx); | |
245 | *provctx = NULL; | |
246 | return 0; | |
247 | } | |
248 | ossl_prov_ctx_set0_libctx(*provctx, libctx); | |
249 | ossl_prov_ctx_set0_handle(*provctx, handle); | |
250 | ||
251 | *out = legacy_dispatch_table; | |
252 | ||
253 | return 1; | |
254 | } | |
255 | ||
256 | #ifndef STATIC_LEGACY | |
257 | /* | |
258 | * Provider specific implementation of libcrypto functions in terms of | |
259 | * upcalls. | |
260 | */ | |
261 | ||
262 | /* | |
263 | * For ERR functions, we pass a NULL context. This is valid to do as long | |
264 | * as only error codes that the calling libcrypto supports are used. | |
265 | */ | |
266 | void ERR_new(void) | |
267 | { | |
268 | c_new_error(NULL); | |
269 | } | |
270 | ||
271 | void ERR_set_debug(const char *file, int line, const char *func) | |
272 | { | |
273 | c_set_error_debug(NULL, file, line, func); | |
274 | } | |
275 | ||
276 | void ERR_set_error(int lib, int reason, const char *fmt, ...) | |
277 | { | |
278 | va_list args; | |
279 | ||
280 | va_start(args, fmt); | |
281 | c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args); | |
282 | va_end(args); | |
283 | } | |
284 | ||
285 | void ERR_vset_error(int lib, int reason, const char *fmt, va_list args) | |
286 | { | |
287 | c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args); | |
288 | } | |
289 | ||
290 | int ERR_set_mark(void) | |
291 | { | |
292 | return c_set_error_mark(NULL); | |
293 | } | |
294 | ||
295 | int ERR_clear_last_mark(void) | |
296 | { | |
297 | return c_clear_last_error_mark(NULL); | |
298 | } | |
299 | ||
300 | int ERR_pop_to_mark(void) | |
301 | { | |
302 | return c_pop_error_to_mark(NULL); | |
303 | } | |
304 | #endif |