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