xref: /freebsd/crypto/openssl/test/provider_test.c (revision a7148ab3)
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 "testutil.h"
13 
14 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
15 
16 static char buf[256];
17 static OSSL_PARAM greeting_request[] = {
18     { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
19     { NULL, 0, NULL, 0, 0 }
20 };
21 
22 static unsigned int digestsuccess = 0;
23 static OSSL_PARAM digest_check[] = {
24     { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess,
25       sizeof(digestsuccess) },
26     { NULL, 0, NULL, 0, 0 }
27 };
28 
29 static unsigned int stopsuccess = 0;
30 static OSSL_PARAM stop_property_mirror[] = {
31     { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
32       sizeof(stopsuccess) },
33     { NULL, 0, NULL, 0, 0 }
34 };
35 
test_provider(OSSL_LIB_CTX ** libctx,const char * name,OSSL_PROVIDER * legacy)36 static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
37                          OSSL_PROVIDER *legacy)
38 {
39     OSSL_PROVIDER *prov = NULL;
40     const char *greeting = NULL;
41     char expected_greeting[256];
42     int ok = 0;
43     long err;
44     int dolegacycheck = (legacy != NULL);
45     OSSL_PROVIDER *deflt = NULL, *base = NULL;
46 
47     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
48                  "Hello OpenSSL %.20s, greetings from %s!",
49                  OPENSSL_VERSION_STR, name);
50 
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 
test_builtin_provider(void)160 static int test_builtin_provider(void)
161 {
162     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
163     const char *name = "p_test_builtin";
164     int ok;
165 
166     ok =
167         TEST_ptr(libctx)
168         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
169                                                PROVIDER_INIT_FUNCTION_NAME))
170         && test_provider(&libctx, name, NULL);
171 
172     OSSL_LIB_CTX_free(libctx);
173 
174     return ok;
175 }
176 
177 /* Test relies on fetching the MD4 digest from the legacy provider */
178 #ifndef OPENSSL_NO_MD4
test_builtin_provider_with_child(void)179 static int test_builtin_provider_with_child(void)
180 {
181     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
182     const char *name = "p_test";
183     OSSL_PROVIDER *legacy;
184 
185     if (!TEST_ptr(libctx))
186         return 0;
187 
188     legacy = OSSL_PROVIDER_load(libctx, "legacy");
189     if (legacy == NULL) {
190         /*
191          * In this case we assume we've been built with "no-legacy" and skip
192          * this test (there is no OPENSSL_NO_LEGACY)
193          */
194         OSSL_LIB_CTX_free(libctx);
195         return 1;
196     }
197 
198     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
199                                              PROVIDER_INIT_FUNCTION_NAME))) {
200         OSSL_PROVIDER_unload(legacy);
201         OSSL_LIB_CTX_free(libctx);
202         return 0;
203     }
204 
205     /* test_provider will free libctx and unload legacy as part of the test */
206     return test_provider(&libctx, name, legacy);
207 }
208 #endif
209 
210 #ifndef NO_PROVIDER_MODULE
test_loaded_provider(void)211 static int test_loaded_provider(void)
212 {
213     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
214     const char *name = "p_test";
215 
216     if (!TEST_ptr(libctx))
217         return 0;
218 
219     /* test_provider will free libctx as part of the test */
220     return test_provider(&libctx, name, NULL);
221 }
222 #endif
223 
224 typedef enum OPTION_choice {
225     OPT_ERR = -1,
226     OPT_EOF = 0,
227     OPT_LOADED,
228     OPT_TEST_ENUM
229 } OPTION_CHOICE;
230 
test_get_options(void)231 const OPTIONS *test_get_options(void)
232 {
233     static const OPTIONS test_options[] = {
234         OPT_TEST_OPTIONS_DEFAULT_USAGE,
235         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
236         { NULL }
237     };
238     return test_options;
239 }
240 
setup_tests(void)241 int setup_tests(void)
242 {
243     OPTION_CHOICE o;
244     int loaded = 0;
245 
246     while ((o = opt_next()) != OPT_EOF) {
247         switch (o) {
248         case OPT_TEST_CASES:
249             break;
250         case OPT_LOADED:
251             loaded = 1;
252             break;
253         default:
254             return 0;
255         }
256     }
257 
258     if (!loaded) {
259         ADD_TEST(test_builtin_provider);
260 #ifndef OPENSSL_NO_MD4
261         ADD_TEST(test_builtin_provider_with_child);
262 #endif
263     }
264 #ifndef NO_PROVIDER_MODULE
265     else {
266         ADD_TEST(test_loaded_provider);
267     }
268 #endif
269     return 1;
270 }
271 
272