xref: /openssl/test/provider_test.c (revision 7ed6de99)
1 /*
2  * Copyright 2019-2024 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 <stddef.h>
11 #include <openssl/provider.h>
12 #include <openssl/param_build.h>
13 #include "testutil.h"
14 
15 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
16 
17 static char buf[256];
18 static OSSL_PARAM greeting_request[] = {
19     { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
20     { NULL, 0, NULL, 0, 0 }
21 };
22 
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 
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 
test_provider(OSSL_LIB_CTX ** libctx,const char * name,OSSL_PROVIDER * legacy)37 static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
38                          OSSL_PROVIDER *legacy)
39 {
40     OSSL_PROVIDER *prov = NULL;
41     const char *greeting = NULL;
42     char expected_greeting[256];
43     int ok = 0;
44     long err;
45     int dolegacycheck = (legacy != NULL);
46     OSSL_PROVIDER *deflt = NULL, *base = NULL;
47 
48     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
49                  "Hello OpenSSL %.20s, greetings from %s!",
50                  OPENSSL_VERSION_STR, name);
51 
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");
59     /*
60      * Check that it is possible to have a built-in provider mirrored in
61      * a child lib ctx.
62      */
63     if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
64         goto err;
65     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
66         goto err;
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, "");
73     if (dolegacycheck) {
74         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
75                 || !TEST_true(digestsuccess))
76             goto err;
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, "");
90     }
91     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
92             || !TEST_ptr(greeting = greeting_request[0].data)
93             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
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))
101         goto err;
102 
103     OSSL_PROVIDER_unload(legacy);
104     legacy = NULL;
105 
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
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.
116          */
117         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
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;
124         if (!TEST_ptr(legacy)
125                 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
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 
133     if (!TEST_true(OSSL_PROVIDER_unload(base)))
134         goto err;
135     base = NULL;
136     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
137         goto err;
138     prov = NULL;
139 
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 
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:
151     OSSL_PROVIDER_unload(base);
152     OSSL_PROVIDER_unload(deflt);
153     OSSL_PROVIDER_unload(legacy);
154     legacy = NULL;
155     OSSL_PROVIDER_unload(prov);
156     OSSL_LIB_CTX_free(*libctx);
157     *libctx = NULL;
158     return ok;
159 }
160 
161 #ifndef NO_PROVIDER_MODULE
test_provider_ex(OSSL_LIB_CTX ** libctx,const char * name)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 = NULL;
170     OSSL_PARAM *params = NULL;
171 
172     if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
173         || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, "greeting", custom_buf,
174                                                       strlen(custom_buf)))
175         || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) {
176         goto err;
177     }
178 
179     if (!TEST_ptr(prov = OSSL_PROVIDER_load_ex(*libctx, name, params)))
180         goto err;
181 
182     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
183             || !TEST_ptr(greeting = greeting_request[0].data)
184             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
185             || !TEST_str_eq(greeting, custom_buf))
186         goto err;
187 
188     /* Make sure we got the error we were expecting */
189     err = ERR_peek_last_error();
190     if (!TEST_int_gt(err, 0)
191             || !TEST_int_eq(ERR_GET_REASON(err), 1))
192         goto err;
193 
194     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
195         goto err;
196     prov = NULL;
197 
198     /*
199      * We must free the libctx to force the provider to really be unloaded from
200      * memory
201      */
202     OSSL_LIB_CTX_free(*libctx);
203     *libctx = NULL;
204 
205     /* We print out all the data to make sure it can still be accessed */
206     ERR_print_errors_fp(stderr);
207     ok = 1;
208  err:
209     OSSL_PARAM_BLD_free(bld);
210     OSSL_PARAM_free(params);
211     OSSL_PROVIDER_unload(prov);
212     OSSL_LIB_CTX_free(*libctx);
213     *libctx = NULL;
214     return ok;
215 }
216 #endif
217 
test_builtin_provider(void)218 static int test_builtin_provider(void)
219 {
220     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
221     const char *name = "p_test_builtin";
222     int ok;
223 
224     ok =
225         TEST_ptr(libctx)
226         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
227                                                PROVIDER_INIT_FUNCTION_NAME))
228         && test_provider(&libctx, name, NULL);
229 
230     OSSL_LIB_CTX_free(libctx);
231 
232     return ok;
233 }
234 
235 /* Test relies on fetching the MD4 digest from the legacy provider */
236 #ifndef OPENSSL_NO_MD4
test_builtin_provider_with_child(void)237 static int test_builtin_provider_with_child(void)
238 {
239     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
240     const char *name = "p_test";
241     OSSL_PROVIDER *legacy;
242 
243     if (!TEST_ptr(libctx))
244         return 0;
245 
246     legacy = OSSL_PROVIDER_load(libctx, "legacy");
247     if (legacy == NULL) {
248         /*
249          * In this case we assume we've been built with "no-legacy" and skip
250          * this test (there is no OPENSSL_NO_LEGACY)
251          */
252         OSSL_LIB_CTX_free(libctx);
253         return 1;
254     }
255 
256     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
257                                              PROVIDER_INIT_FUNCTION_NAME))) {
258         OSSL_PROVIDER_unload(legacy);
259         OSSL_LIB_CTX_free(libctx);
260         return 0;
261     }
262 
263     /* test_provider will free libctx and unload legacy as part of the test */
264     return test_provider(&libctx, name, legacy);
265 }
266 #endif
267 
268 #ifndef NO_PROVIDER_MODULE
test_loaded_provider(void)269 static int test_loaded_provider(void)
270 {
271     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
272     const char *name = "p_test";
273     int res = 0;
274 
275     if (!TEST_ptr(libctx))
276         return 0;
277 
278     /* test_provider will free libctx as part of the test */
279     res = test_provider(&libctx, name, NULL);
280 
281     libctx = OSSL_LIB_CTX_new();
282     if (!TEST_ptr(libctx))
283         return 0;
284 
285     /* test_provider_ex will free libctx as part of the test */
286     res = res && test_provider_ex(&libctx, name);
287 
288     return res;
289 }
290 #endif
291 
292 typedef enum OPTION_choice {
293     OPT_ERR = -1,
294     OPT_EOF = 0,
295     OPT_LOADED,
296     OPT_TEST_ENUM
297 } OPTION_CHOICE;
298 
test_get_options(void)299 const OPTIONS *test_get_options(void)
300 {
301     static const OPTIONS test_options[] = {
302         OPT_TEST_OPTIONS_DEFAULT_USAGE,
303         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
304         { NULL }
305     };
306     return test_options;
307 }
308 
setup_tests(void)309 int setup_tests(void)
310 {
311     OPTION_CHOICE o;
312     int loaded = 0;
313 
314     while ((o = opt_next()) != OPT_EOF) {
315         switch (o) {
316         case OPT_TEST_CASES:
317             break;
318         case OPT_LOADED:
319             loaded = 1;
320             break;
321         default:
322             return 0;
323         }
324     }
325 
326     if (!loaded) {
327         ADD_TEST(test_builtin_provider);
328 #ifndef OPENSSL_NO_MD4
329         ADD_TEST(test_builtin_provider_with_child);
330 #endif
331     }
332 #ifndef NO_PROVIDER_MODULE
333     else {
334         ADD_TEST(test_loaded_provider);
335     }
336 #endif
337     return 1;
338 }
339 
340