]>
Commit | Line | Data |
---|---|---|
021a6552 | 1 | /* |
da1c088f | 2 | * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. |
021a6552 RL |
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 <stddef.h> | |
11 | #include <openssl/provider.h> | |
4f3e3d9d | 12 | #include <openssl/param_build.h> |
021a6552 RL |
13 | #include "testutil.h" |
14 | ||
15 | extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME; | |
16 | ||
17 | static char buf[256]; | |
021a6552 | 18 | static OSSL_PARAM greeting_request[] = { |
4e7991b4 P |
19 | { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) }, |
20 | { NULL, 0, NULL, 0, 0 } | |
021a6552 RL |
21 | }; |
22 | ||
5442611d MC |
23 | static unsigned int digestsuccess = 0; |
24 | static OSSL_PARAM digest_check[] = { | |
25 | { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess, | |
26 | sizeof(digestsuccess) }, | |
27 | { NULL, 0, NULL, 0, 0 } | |
28 | }; | |
29 | ||
b1c053ac MC |
30 | static unsigned int stopsuccess = 0; |
31 | static OSSL_PARAM stop_property_mirror[] = { | |
32 | { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess, | |
33 | sizeof(stopsuccess) }, | |
34 | { NULL, 0, NULL, 0, 0 } | |
35 | }; | |
36 | ||
5442611d MC |
37 | static int test_provider(OSSL_LIB_CTX **libctx, const char *name, |
38 | OSSL_PROVIDER *legacy) | |
021a6552 RL |
39 | { |
40 | OSSL_PROVIDER *prov = NULL; | |
41 | const char *greeting = NULL; | |
42 | char expected_greeting[256]; | |
81c15ed0 MC |
43 | int ok = 0; |
44 | long err; | |
3b85bcfa | 45 | int dolegacycheck = (legacy != NULL); |
fb9b3a7b | 46 | OSSL_PROVIDER *deflt = NULL, *base = NULL; |
021a6552 | 47 | |
f4b4574f | 48 | BIO_snprintf(expected_greeting, sizeof(expected_greeting), |
866cc233 SL |
49 | "Hello OpenSSL %.20s, greetings from %s!", |
50 | OPENSSL_VERSION_STR, name); | |
021a6552 | 51 | |
18cb5c31 MC |
52 | |
53 | /* | |
54 | * We set properties that we know the providers we are using don't have. | |
55 | * This should mean that the p_test provider will fail any fetches - which | |
56 | * is something we test inside the provider. | |
57 | */ | |
58 | EVP_set_default_properties(*libctx, "fips=yes"); | |
fb9b3a7b | 59 | /* |
18cb5c31 MC |
60 | * Check that it is possible to have a built-in provider mirrored in |
61 | * a child lib ctx. | |
62 | */ | |
fb9b3a7b MC |
63 | if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base"))) |
64 | goto err; | |
5442611d MC |
65 | if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name))) |
66 | goto err; | |
18cb5c31 MC |
67 | |
68 | /* | |
69 | * Once the provider is loaded we clear the default properties and fetches | |
70 | * should start working again. | |
71 | */ | |
72 | EVP_set_default_properties(*libctx, ""); | |
3b85bcfa | 73 | if (dolegacycheck) { |
5442611d MC |
74 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) |
75 | || !TEST_true(digestsuccess)) | |
76 | goto err; | |
b1c053ac MC |
77 | |
78 | /* | |
79 | * Check that a provider can prevent property mirroring if it sets its | |
80 | * own properties explicitly | |
81 | */ | |
82 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror)) | |
83 | || !TEST_true(stopsuccess)) | |
84 | goto err; | |
85 | EVP_set_default_properties(*libctx, "fips=yes"); | |
86 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) | |
87 | || !TEST_true(digestsuccess)) | |
88 | goto err; | |
89 | EVP_set_default_properties(*libctx, ""); | |
5442611d MC |
90 | } |
91 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request)) | |
81c15ed0 MC |
92 | || !TEST_ptr(greeting = greeting_request[0].data) |
93 | || !TEST_size_t_gt(greeting_request[0].data_size, 0) | |
3b85bcfa MC |
94 | || !TEST_str_eq(greeting, expected_greeting)) |
95 | goto err; | |
96 | ||
97 | /* Make sure we got the error we were expecting */ | |
98 | err = ERR_peek_last_error(); | |
99 | if (!TEST_int_gt(err, 0) | |
100 | || !TEST_int_eq(ERR_GET_REASON(err), 1)) | |
81c15ed0 MC |
101 | goto err; |
102 | ||
5442611d MC |
103 | OSSL_PROVIDER_unload(legacy); |
104 | legacy = NULL; | |
81c15ed0 | 105 | |
3b85bcfa MC |
106 | if (dolegacycheck) { |
107 | /* Legacy provider should also be unloaded from child libctx */ | |
108 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) | |
109 | || !TEST_false(digestsuccess)) | |
110 | goto err; | |
111 | /* | |
112 | * Loading the legacy provider again should make it available again in | |
fb9b3a7b MC |
113 | * the child libctx. Loading and unloading the default provider should |
114 | * have no impact on the child because the child loads it explicitly | |
115 | * before this point. | |
3b85bcfa MC |
116 | */ |
117 | legacy = OSSL_PROVIDER_load(*libctx, "legacy"); | |
fb9b3a7b MC |
118 | deflt = OSSL_PROVIDER_load(*libctx, "default"); |
119 | if (!TEST_ptr(deflt) | |
120 | || !TEST_true(OSSL_PROVIDER_available(*libctx, "default"))) | |
121 | goto err; | |
122 | OSSL_PROVIDER_unload(deflt); | |
123 | deflt = NULL; | |
3b85bcfa | 124 | if (!TEST_ptr(legacy) |
fb9b3a7b | 125 | || !TEST_false(OSSL_PROVIDER_available(*libctx, "default")) |
3b85bcfa MC |
126 | || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) |
127 | || !TEST_true(digestsuccess)) | |
128 | goto err; | |
129 | OSSL_PROVIDER_unload(legacy); | |
130 | legacy = NULL; | |
131 | } | |
132 | ||
fb9b3a7b MC |
133 | if (!TEST_true(OSSL_PROVIDER_unload(base))) |
134 | goto err; | |
135 | base = NULL; | |
3b85bcfa MC |
136 | if (!TEST_true(OSSL_PROVIDER_unload(prov))) |
137 | goto err; | |
138 | prov = NULL; | |
139 | ||
81c15ed0 MC |
140 | /* |
141 | * We must free the libctx to force the provider to really be unloaded from | |
142 | * memory | |
143 | */ | |
144 | OSSL_LIB_CTX_free(*libctx); | |
145 | *libctx = NULL; | |
146 | ||
81c15ed0 MC |
147 | /* We print out all the data to make sure it can still be accessed */ |
148 | ERR_print_errors_fp(stderr); | |
149 | ok = 1; | |
150 | err: | |
fb9b3a7b MC |
151 | OSSL_PROVIDER_unload(base); |
152 | OSSL_PROVIDER_unload(deflt); | |
5442611d MC |
153 | OSSL_PROVIDER_unload(legacy); |
154 | legacy = NULL; | |
81c15ed0 MC |
155 | OSSL_PROVIDER_unload(prov); |
156 | OSSL_LIB_CTX_free(*libctx); | |
157 | *libctx = NULL; | |
158 | return ok; | |
021a6552 RL |
159 | } |
160 | ||
4f3e3d9d DB |
161 | #ifndef NO_PROVIDER_MODULE |
162 | static int test_provider_ex(OSSL_LIB_CTX **libctx, const char *name) | |
163 | { | |
164 | OSSL_PROVIDER *prov = NULL; | |
165 | const char *greeting = NULL; | |
166 | int ok = 0; | |
167 | long err; | |
168 | const char custom_buf[] = "Custom greeting"; | |
169 | OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); | |
170 | OSSL_PARAM *params = NULL; | |
171 | ||
172 | OSSL_PARAM_BLD_push_utf8_string(bld, "greeting", custom_buf, strlen(custom_buf)); | |
173 | params = OSSL_PARAM_BLD_to_param(bld); | |
174 | ||
175 | OSSL_PARAM_BLD_free(bld); | |
176 | ||
177 | if (!TEST_ptr(prov = OSSL_PROVIDER_load_ex(*libctx, name, params))) | |
178 | goto err; | |
179 | ||
180 | if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request)) | |
181 | || !TEST_ptr(greeting = greeting_request[0].data) | |
182 | || !TEST_size_t_gt(greeting_request[0].data_size, 0) | |
183 | || !TEST_str_eq(greeting, custom_buf)) | |
184 | goto err; | |
185 | ||
186 | /* Make sure we got the error we were expecting */ | |
187 | err = ERR_peek_last_error(); | |
188 | if (!TEST_int_gt(err, 0) | |
189 | || !TEST_int_eq(ERR_GET_REASON(err), 1)) | |
190 | goto err; | |
191 | ||
192 | if (!TEST_true(OSSL_PROVIDER_unload(prov))) | |
193 | goto err; | |
194 | prov = NULL; | |
195 | ||
196 | /* | |
197 | * We must free the libctx to force the provider to really be unloaded from | |
198 | * memory | |
199 | */ | |
200 | OSSL_LIB_CTX_free(*libctx); | |
201 | *libctx = NULL; | |
202 | ||
203 | /* We print out all the data to make sure it can still be accessed */ | |
204 | ERR_print_errors_fp(stderr); | |
205 | ok = 1; | |
206 | err: | |
207 | OSSL_PARAM_free(params); | |
208 | OSSL_PROVIDER_unload(prov); | |
209 | OSSL_LIB_CTX_free(*libctx); | |
210 | *libctx = NULL; | |
211 | return ok; | |
212 | } | |
213 | #endif | |
214 | ||
021a6552 RL |
215 | static int test_builtin_provider(void) |
216 | { | |
81c15ed0 | 217 | OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); |
021a6552 | 218 | const char *name = "p_test_builtin"; |
81c15ed0 | 219 | int ok; |
021a6552 | 220 | |
81c15ed0 MC |
221 | ok = |
222 | TEST_ptr(libctx) | |
223 | && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, | |
224 | PROVIDER_INIT_FUNCTION_NAME)) | |
5442611d | 225 | && test_provider(&libctx, name, NULL); |
81c15ed0 MC |
226 | |
227 | OSSL_LIB_CTX_free(libctx); | |
228 | ||
229 | return ok; | |
021a6552 RL |
230 | } |
231 | ||
fb9b3a7b MC |
232 | /* Test relies on fetching the MD4 digest from the legacy provider */ |
233 | #ifndef OPENSSL_NO_MD4 | |
5442611d MC |
234 | static int test_builtin_provider_with_child(void) |
235 | { | |
236 | OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); | |
237 | const char *name = "p_test"; | |
238 | OSSL_PROVIDER *legacy; | |
239 | ||
240 | if (!TEST_ptr(libctx)) | |
241 | return 0; | |
242 | ||
243 | legacy = OSSL_PROVIDER_load(libctx, "legacy"); | |
244 | if (legacy == NULL) { | |
245 | /* | |
246 | * In this case we assume we've been built with "no-legacy" and skip | |
247 | * this test (there is no OPENSSL_NO_LEGACY) | |
248 | */ | |
49d874e0 | 249 | OSSL_LIB_CTX_free(libctx); |
5442611d MC |
250 | return 1; |
251 | } | |
252 | ||
253 | if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, | |
49d874e0 RL |
254 | PROVIDER_INIT_FUNCTION_NAME))) { |
255 | OSSL_LIB_CTX_free(libctx); | |
5442611d | 256 | return 0; |
49d874e0 | 257 | } |
5442611d MC |
258 | |
259 | /* test_provider will free libctx and unload legacy as part of the test */ | |
260 | return test_provider(&libctx, name, legacy); | |
261 | } | |
fb9b3a7b | 262 | #endif |
5442611d | 263 | |
2a2bc6fc | 264 | #ifndef NO_PROVIDER_MODULE |
021a6552 RL |
265 | static int test_loaded_provider(void) |
266 | { | |
81c15ed0 | 267 | OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); |
021a6552 | 268 | const char *name = "p_test"; |
4f3e3d9d | 269 | int res = 0; |
021a6552 | 270 | |
81c15ed0 MC |
271 | if (!TEST_ptr(libctx)) |
272 | return 0; | |
273 | ||
274 | /* test_provider will free libctx as part of the test */ | |
4f3e3d9d DB |
275 | res = test_provider(&libctx, name, NULL); |
276 | ||
277 | libctx = OSSL_LIB_CTX_new(); | |
278 | if (!TEST_ptr(libctx)) | |
279 | return 0; | |
280 | ||
281 | /* test_provider_ex will free libctx as part of the test */ | |
282 | res = res && test_provider_ex(&libctx, name); | |
283 | ||
284 | return res; | |
021a6552 RL |
285 | } |
286 | #endif | |
287 | ||
5442611d MC |
288 | typedef enum OPTION_choice { |
289 | OPT_ERR = -1, | |
290 | OPT_EOF = 0, | |
291 | OPT_LOADED, | |
292 | OPT_TEST_ENUM | |
293 | } OPTION_CHOICE; | |
294 | ||
295 | const OPTIONS *test_get_options(void) | |
296 | { | |
297 | static const OPTIONS test_options[] = { | |
298 | OPT_TEST_OPTIONS_DEFAULT_USAGE, | |
299 | { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" }, | |
300 | { NULL } | |
301 | }; | |
302 | return test_options; | |
303 | } | |
304 | ||
021a6552 RL |
305 | int setup_tests(void) |
306 | { | |
5442611d MC |
307 | OPTION_CHOICE o; |
308 | int loaded = 0; | |
309 | ||
310 | while ((o = opt_next()) != OPT_EOF) { | |
311 | switch (o) { | |
312 | case OPT_TEST_CASES: | |
313 | break; | |
314 | case OPT_LOADED: | |
315 | loaded = 1; | |
316 | break; | |
317 | default: | |
318 | return 0; | |
319 | } | |
320 | } | |
321 | ||
322 | if (!loaded) { | |
323 | ADD_TEST(test_builtin_provider); | |
fb9b3a7b | 324 | #ifndef OPENSSL_NO_MD4 |
5442611d | 325 | ADD_TEST(test_builtin_provider_with_child); |
fb9b3a7b | 326 | #endif |
5442611d | 327 | } |
2a2bc6fc | 328 | #ifndef NO_PROVIDER_MODULE |
5442611d MC |
329 | else { |
330 | ADD_TEST(test_loaded_provider); | |
331 | } | |
021a6552 RL |
332 | #endif |
333 | return 1; | |
334 | } | |
335 |