xref: /freebsd-src/crypto/openssl/test/provider_test.c (revision a7148ab39c03abd4d1a84997c70bf96f15dd2a09)
1e0c4386eSCy Schubert /*
2*a7148ab3SEnji Cooper  * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
3e0c4386eSCy Schubert  *
4e0c4386eSCy Schubert  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e0c4386eSCy Schubert  * this file except in compliance with the License.  You can obtain a copy
6e0c4386eSCy Schubert  * in the file LICENSE in the source distribution or at
7e0c4386eSCy Schubert  * https://www.openssl.org/source/license.html
8e0c4386eSCy Schubert  */
9e0c4386eSCy Schubert 
10e0c4386eSCy Schubert #include <stddef.h>
11e0c4386eSCy Schubert #include <openssl/provider.h>
12e0c4386eSCy Schubert #include "testutil.h"
13e0c4386eSCy Schubert 
14e0c4386eSCy Schubert extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
15e0c4386eSCy Schubert 
16e0c4386eSCy Schubert static char buf[256];
17e0c4386eSCy Schubert static OSSL_PARAM greeting_request[] = {
18e0c4386eSCy Schubert     { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
19e0c4386eSCy Schubert     { NULL, 0, NULL, 0, 0 }
20e0c4386eSCy Schubert };
21e0c4386eSCy Schubert 
22e0c4386eSCy Schubert static unsigned int digestsuccess = 0;
23e0c4386eSCy Schubert static OSSL_PARAM digest_check[] = {
24e0c4386eSCy Schubert     { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess,
25e0c4386eSCy Schubert       sizeof(digestsuccess) },
26e0c4386eSCy Schubert     { NULL, 0, NULL, 0, 0 }
27e0c4386eSCy Schubert };
28e0c4386eSCy Schubert 
29e0c4386eSCy Schubert static unsigned int stopsuccess = 0;
30e0c4386eSCy Schubert static OSSL_PARAM stop_property_mirror[] = {
31e0c4386eSCy Schubert     { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
32e0c4386eSCy Schubert       sizeof(stopsuccess) },
33e0c4386eSCy Schubert     { NULL, 0, NULL, 0, 0 }
34e0c4386eSCy Schubert };
35e0c4386eSCy Schubert 
36e0c4386eSCy Schubert static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
37e0c4386eSCy Schubert                          OSSL_PROVIDER *legacy)
38e0c4386eSCy Schubert {
39e0c4386eSCy Schubert     OSSL_PROVIDER *prov = NULL;
40e0c4386eSCy Schubert     const char *greeting = NULL;
41e0c4386eSCy Schubert     char expected_greeting[256];
42e0c4386eSCy Schubert     int ok = 0;
43e0c4386eSCy Schubert     long err;
44e0c4386eSCy Schubert     int dolegacycheck = (legacy != NULL);
45e0c4386eSCy Schubert     OSSL_PROVIDER *deflt = NULL, *base = NULL;
46e0c4386eSCy Schubert 
47e0c4386eSCy Schubert     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
48e0c4386eSCy Schubert                  "Hello OpenSSL %.20s, greetings from %s!",
49e0c4386eSCy Schubert                  OPENSSL_VERSION_STR, name);
50e0c4386eSCy Schubert 
51e0c4386eSCy Schubert 
52e0c4386eSCy Schubert     /*
53e0c4386eSCy Schubert      * We set properties that we know the providers we are using don't have.
54e0c4386eSCy Schubert      * This should mean that the p_test provider will fail any fetches - which
55e0c4386eSCy Schubert      * is something we test inside the provider.
56e0c4386eSCy Schubert      */
57e0c4386eSCy Schubert     EVP_set_default_properties(*libctx, "fips=yes");
58e0c4386eSCy Schubert     /*
59e0c4386eSCy Schubert      * Check that it is possible to have a built-in provider mirrored in
60e0c4386eSCy Schubert      * a child lib ctx.
61e0c4386eSCy Schubert      */
62e0c4386eSCy Schubert     if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
63e0c4386eSCy Schubert         goto err;
64e0c4386eSCy Schubert     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
65e0c4386eSCy Schubert         goto err;
66e0c4386eSCy Schubert 
67e0c4386eSCy Schubert     /*
68e0c4386eSCy Schubert      * Once the provider is loaded we clear the default properties and fetches
69e0c4386eSCy Schubert      * should start working again.
70e0c4386eSCy Schubert      */
71e0c4386eSCy Schubert     EVP_set_default_properties(*libctx, "");
72e0c4386eSCy Schubert     if (dolegacycheck) {
73e0c4386eSCy Schubert         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
74e0c4386eSCy Schubert                 || !TEST_true(digestsuccess))
75e0c4386eSCy Schubert             goto err;
76e0c4386eSCy Schubert 
77e0c4386eSCy Schubert         /*
78e0c4386eSCy Schubert          * Check that a provider can prevent property mirroring if it sets its
79e0c4386eSCy Schubert          * own properties explicitly
80e0c4386eSCy Schubert          */
81e0c4386eSCy Schubert         if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
82e0c4386eSCy Schubert                 || !TEST_true(stopsuccess))
83e0c4386eSCy Schubert             goto err;
84e0c4386eSCy Schubert         EVP_set_default_properties(*libctx, "fips=yes");
85e0c4386eSCy Schubert         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
86e0c4386eSCy Schubert                 || !TEST_true(digestsuccess))
87e0c4386eSCy Schubert             goto err;
88e0c4386eSCy Schubert         EVP_set_default_properties(*libctx, "");
89e0c4386eSCy Schubert     }
90e0c4386eSCy Schubert     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
91e0c4386eSCy Schubert             || !TEST_ptr(greeting = greeting_request[0].data)
92e0c4386eSCy Schubert             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
93e0c4386eSCy Schubert             || !TEST_str_eq(greeting, expected_greeting))
94e0c4386eSCy Schubert         goto err;
95e0c4386eSCy Schubert 
96e0c4386eSCy Schubert     /* Make sure we got the error we were expecting */
97e0c4386eSCy Schubert     err = ERR_peek_last_error();
98e0c4386eSCy Schubert     if (!TEST_int_gt(err, 0)
99e0c4386eSCy Schubert             || !TEST_int_eq(ERR_GET_REASON(err), 1))
100e0c4386eSCy Schubert         goto err;
101e0c4386eSCy Schubert 
102e0c4386eSCy Schubert     OSSL_PROVIDER_unload(legacy);
103e0c4386eSCy Schubert     legacy = NULL;
104e0c4386eSCy Schubert 
105e0c4386eSCy Schubert     if (dolegacycheck) {
106e0c4386eSCy Schubert         /* Legacy provider should also be unloaded from child libctx */
107e0c4386eSCy Schubert         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
108e0c4386eSCy Schubert                 || !TEST_false(digestsuccess))
109e0c4386eSCy Schubert             goto err;
110e0c4386eSCy Schubert         /*
111e0c4386eSCy Schubert          * Loading the legacy provider again should make it available again in
112e0c4386eSCy Schubert          * the child libctx. Loading and unloading the default provider should
113e0c4386eSCy Schubert          * have no impact on the child because the child loads it explicitly
114e0c4386eSCy Schubert          * before this point.
115e0c4386eSCy Schubert          */
116e0c4386eSCy Schubert         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
117e0c4386eSCy Schubert         deflt = OSSL_PROVIDER_load(*libctx, "default");
118e0c4386eSCy Schubert         if (!TEST_ptr(deflt)
119e0c4386eSCy Schubert                 || !TEST_true(OSSL_PROVIDER_available(*libctx, "default")))
120e0c4386eSCy Schubert             goto err;
121e0c4386eSCy Schubert         OSSL_PROVIDER_unload(deflt);
122e0c4386eSCy Schubert         deflt = NULL;
123e0c4386eSCy Schubert         if (!TEST_ptr(legacy)
124e0c4386eSCy Schubert                 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
125e0c4386eSCy Schubert                 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
126e0c4386eSCy Schubert                 || !TEST_true(digestsuccess))
127e0c4386eSCy Schubert         goto err;
128e0c4386eSCy Schubert         OSSL_PROVIDER_unload(legacy);
129e0c4386eSCy Schubert         legacy = NULL;
130e0c4386eSCy Schubert     }
131e0c4386eSCy Schubert 
132e0c4386eSCy Schubert     if (!TEST_true(OSSL_PROVIDER_unload(base)))
133e0c4386eSCy Schubert         goto err;
134e0c4386eSCy Schubert     base = NULL;
135e0c4386eSCy Schubert     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
136e0c4386eSCy Schubert         goto err;
137e0c4386eSCy Schubert     prov = NULL;
138e0c4386eSCy Schubert 
139e0c4386eSCy Schubert     /*
140e0c4386eSCy Schubert      * We must free the libctx to force the provider to really be unloaded from
141e0c4386eSCy Schubert      * memory
142e0c4386eSCy Schubert      */
143e0c4386eSCy Schubert     OSSL_LIB_CTX_free(*libctx);
144e0c4386eSCy Schubert     *libctx = NULL;
145e0c4386eSCy Schubert 
146e0c4386eSCy Schubert     /* We print out all the data to make sure it can still be accessed */
147e0c4386eSCy Schubert     ERR_print_errors_fp(stderr);
148e0c4386eSCy Schubert     ok = 1;
149e0c4386eSCy Schubert  err:
150e0c4386eSCy Schubert     OSSL_PROVIDER_unload(base);
151e0c4386eSCy Schubert     OSSL_PROVIDER_unload(deflt);
152e0c4386eSCy Schubert     OSSL_PROVIDER_unload(legacy);
153e0c4386eSCy Schubert     legacy = NULL;
154e0c4386eSCy Schubert     OSSL_PROVIDER_unload(prov);
155e0c4386eSCy Schubert     OSSL_LIB_CTX_free(*libctx);
156e0c4386eSCy Schubert     *libctx = NULL;
157e0c4386eSCy Schubert     return ok;
158e0c4386eSCy Schubert }
159e0c4386eSCy Schubert 
160e0c4386eSCy Schubert static int test_builtin_provider(void)
161e0c4386eSCy Schubert {
162e0c4386eSCy Schubert     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
163e0c4386eSCy Schubert     const char *name = "p_test_builtin";
164e0c4386eSCy Schubert     int ok;
165e0c4386eSCy Schubert 
166e0c4386eSCy Schubert     ok =
167e0c4386eSCy Schubert         TEST_ptr(libctx)
168e0c4386eSCy Schubert         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
169e0c4386eSCy Schubert                                                PROVIDER_INIT_FUNCTION_NAME))
170e0c4386eSCy Schubert         && test_provider(&libctx, name, NULL);
171e0c4386eSCy Schubert 
172e0c4386eSCy Schubert     OSSL_LIB_CTX_free(libctx);
173e0c4386eSCy Schubert 
174e0c4386eSCy Schubert     return ok;
175e0c4386eSCy Schubert }
176e0c4386eSCy Schubert 
177e0c4386eSCy Schubert /* Test relies on fetching the MD4 digest from the legacy provider */
178e0c4386eSCy Schubert #ifndef OPENSSL_NO_MD4
179e0c4386eSCy Schubert static int test_builtin_provider_with_child(void)
180e0c4386eSCy Schubert {
181e0c4386eSCy Schubert     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
182e0c4386eSCy Schubert     const char *name = "p_test";
183e0c4386eSCy Schubert     OSSL_PROVIDER *legacy;
184e0c4386eSCy Schubert 
185e0c4386eSCy Schubert     if (!TEST_ptr(libctx))
186e0c4386eSCy Schubert         return 0;
187e0c4386eSCy Schubert 
188e0c4386eSCy Schubert     legacy = OSSL_PROVIDER_load(libctx, "legacy");
189e0c4386eSCy Schubert     if (legacy == NULL) {
190e0c4386eSCy Schubert         /*
191e0c4386eSCy Schubert          * In this case we assume we've been built with "no-legacy" and skip
192e0c4386eSCy Schubert          * this test (there is no OPENSSL_NO_LEGACY)
193e0c4386eSCy Schubert          */
194e0c4386eSCy Schubert         OSSL_LIB_CTX_free(libctx);
195e0c4386eSCy Schubert         return 1;
196e0c4386eSCy Schubert     }
197e0c4386eSCy Schubert 
198e0c4386eSCy Schubert     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
199e0c4386eSCy Schubert                                              PROVIDER_INIT_FUNCTION_NAME))) {
200*a7148ab3SEnji Cooper         OSSL_PROVIDER_unload(legacy);
201e0c4386eSCy Schubert         OSSL_LIB_CTX_free(libctx);
202e0c4386eSCy Schubert         return 0;
203e0c4386eSCy Schubert     }
204e0c4386eSCy Schubert 
205e0c4386eSCy Schubert     /* test_provider will free libctx and unload legacy as part of the test */
206e0c4386eSCy Schubert     return test_provider(&libctx, name, legacy);
207e0c4386eSCy Schubert }
208e0c4386eSCy Schubert #endif
209e0c4386eSCy Schubert 
210e0c4386eSCy Schubert #ifndef NO_PROVIDER_MODULE
211e0c4386eSCy Schubert static int test_loaded_provider(void)
212e0c4386eSCy Schubert {
213e0c4386eSCy Schubert     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
214e0c4386eSCy Schubert     const char *name = "p_test";
215e0c4386eSCy Schubert 
216e0c4386eSCy Schubert     if (!TEST_ptr(libctx))
217e0c4386eSCy Schubert         return 0;
218e0c4386eSCy Schubert 
219e0c4386eSCy Schubert     /* test_provider will free libctx as part of the test */
220e0c4386eSCy Schubert     return test_provider(&libctx, name, NULL);
221e0c4386eSCy Schubert }
222e0c4386eSCy Schubert #endif
223e0c4386eSCy Schubert 
224e0c4386eSCy Schubert typedef enum OPTION_choice {
225e0c4386eSCy Schubert     OPT_ERR = -1,
226e0c4386eSCy Schubert     OPT_EOF = 0,
227e0c4386eSCy Schubert     OPT_LOADED,
228e0c4386eSCy Schubert     OPT_TEST_ENUM
229e0c4386eSCy Schubert } OPTION_CHOICE;
230e0c4386eSCy Schubert 
231e0c4386eSCy Schubert const OPTIONS *test_get_options(void)
232e0c4386eSCy Schubert {
233e0c4386eSCy Schubert     static const OPTIONS test_options[] = {
234e0c4386eSCy Schubert         OPT_TEST_OPTIONS_DEFAULT_USAGE,
235e0c4386eSCy Schubert         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
236e0c4386eSCy Schubert         { NULL }
237e0c4386eSCy Schubert     };
238e0c4386eSCy Schubert     return test_options;
239e0c4386eSCy Schubert }
240e0c4386eSCy Schubert 
241e0c4386eSCy Schubert int setup_tests(void)
242e0c4386eSCy Schubert {
243e0c4386eSCy Schubert     OPTION_CHOICE o;
244e0c4386eSCy Schubert     int loaded = 0;
245e0c4386eSCy Schubert 
246e0c4386eSCy Schubert     while ((o = opt_next()) != OPT_EOF) {
247e0c4386eSCy Schubert         switch (o) {
248e0c4386eSCy Schubert         case OPT_TEST_CASES:
249e0c4386eSCy Schubert             break;
250e0c4386eSCy Schubert         case OPT_LOADED:
251e0c4386eSCy Schubert             loaded = 1;
252e0c4386eSCy Schubert             break;
253e0c4386eSCy Schubert         default:
254e0c4386eSCy Schubert             return 0;
255e0c4386eSCy Schubert         }
256e0c4386eSCy Schubert     }
257e0c4386eSCy Schubert 
258e0c4386eSCy Schubert     if (!loaded) {
259e0c4386eSCy Schubert         ADD_TEST(test_builtin_provider);
260e0c4386eSCy Schubert #ifndef OPENSSL_NO_MD4
261e0c4386eSCy Schubert         ADD_TEST(test_builtin_provider_with_child);
262e0c4386eSCy Schubert #endif
263e0c4386eSCy Schubert     }
264e0c4386eSCy Schubert #ifndef NO_PROVIDER_MODULE
265e0c4386eSCy Schubert     else {
266e0c4386eSCy Schubert         ADD_TEST(test_loaded_provider);
267e0c4386eSCy Schubert     }
268e0c4386eSCy Schubert #endif
269e0c4386eSCy Schubert     return 1;
270e0c4386eSCy Schubert }
271e0c4386eSCy Schubert 
272