Test that properties are mirrored as we expect
[openssl.git] / test / provider_test.c
1 /*
2  * Copyright 2019-2021 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 int test_provider(OSSL_LIB_CTX **libctx, const char *name,
30                          OSSL_PROVIDER *legacy)
31 {
32     OSSL_PROVIDER *prov = NULL;
33     const char *greeting = NULL;
34     char expected_greeting[256];
35     int ok = 0;
36     long err;
37     int dolegacycheck = (legacy != NULL);
38     OSSL_PROVIDER *deflt = NULL, *base = NULL;
39
40     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
41                  "Hello OpenSSL %.20s, greetings from %s!",
42                  OPENSSL_VERSION_STR, name);
43
44
45     /*
46      * We set properties that we know the providers we are using don't have.
47      * This should mean that the p_test provider will fail any fetches - which
48      * is something we test inside the provider.
49      */
50     EVP_set_default_properties(*libctx, "fips=yes");
51     /*
52      * Check that it is possible to have a built-in provider mirrored in
53      * a child lib ctx.
54      */
55     if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
56         goto err;
57     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
58         goto err;
59
60     /*
61      * Once the provider is loaded we clear the default properties and fetches
62      * should start working again.
63      */
64     EVP_set_default_properties(*libctx, "");
65     if (dolegacycheck) {
66         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
67                 || !TEST_true(digestsuccess))
68             goto err;
69     }
70     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
71             || !TEST_ptr(greeting = greeting_request[0].data)
72             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
73             || !TEST_str_eq(greeting, expected_greeting))
74         goto err;
75
76     /* Make sure we got the error we were expecting */
77     err = ERR_peek_last_error();
78     if (!TEST_int_gt(err, 0)
79             || !TEST_int_eq(ERR_GET_REASON(err), 1))
80         goto err;
81
82     OSSL_PROVIDER_unload(legacy);
83     legacy = NULL;
84
85     if (dolegacycheck) {
86         /* Legacy provider should also be unloaded from child libctx */
87         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
88                 || !TEST_false(digestsuccess))
89             goto err;
90         /*
91          * Loading the legacy provider again should make it available again in
92          * the child libctx. Loading and unloading the default provider should
93          * have no impact on the child because the child loads it explicitly
94          * before this point.
95          */
96         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
97         deflt = OSSL_PROVIDER_load(*libctx, "default");
98         if (!TEST_ptr(deflt)
99                 || !TEST_true(OSSL_PROVIDER_available(*libctx, "default")))
100             goto err;
101         OSSL_PROVIDER_unload(deflt);
102         deflt = NULL;
103         if (!TEST_ptr(legacy)
104                 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
105                 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
106                 || !TEST_true(digestsuccess))
107         goto err;
108         OSSL_PROVIDER_unload(legacy);
109         legacy = NULL;
110     }
111
112     if (!TEST_true(OSSL_PROVIDER_unload(base)))
113         goto err;
114     base = NULL;
115     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
116         goto err;
117     prov = NULL;
118
119     /*
120      * We must free the libctx to force the provider to really be unloaded from
121      * memory
122      */
123     OSSL_LIB_CTX_free(*libctx);
124     *libctx = NULL;
125
126     /* We print out all the data to make sure it can still be accessed */
127     ERR_print_errors_fp(stderr);
128     ok = 1;
129  err:
130     OSSL_PROVIDER_unload(base);
131     OSSL_PROVIDER_unload(deflt);
132     OSSL_PROVIDER_unload(legacy);
133     legacy = NULL;
134     OSSL_PROVIDER_unload(prov);
135     OSSL_LIB_CTX_free(*libctx);
136     *libctx = NULL;
137     return ok;
138 }
139
140 static int test_builtin_provider(void)
141 {
142     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
143     const char *name = "p_test_builtin";
144     int ok;
145
146     ok =
147         TEST_ptr(libctx)
148         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
149                                                PROVIDER_INIT_FUNCTION_NAME))
150         && test_provider(&libctx, name, NULL);
151
152     OSSL_LIB_CTX_free(libctx);
153
154     return ok;
155 }
156
157 /* Test relies on fetching the MD4 digest from the legacy provider */
158 #ifndef OPENSSL_NO_MD4
159 static int test_builtin_provider_with_child(void)
160 {
161     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
162     const char *name = "p_test";
163     OSSL_PROVIDER *legacy;
164
165     if (!TEST_ptr(libctx))
166         return 0;
167
168     legacy = OSSL_PROVIDER_load(libctx, "legacy");
169     if (legacy == NULL) {
170         /*
171          * In this case we assume we've been built with "no-legacy" and skip
172          * this test (there is no OPENSSL_NO_LEGACY)
173          */
174         return 1;
175     }
176
177     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
178                                              PROVIDER_INIT_FUNCTION_NAME)))
179         return 0;
180
181     /* test_provider will free libctx and unload legacy as part of the test */
182     return test_provider(&libctx, name, legacy);
183 }
184 #endif
185
186 #ifndef NO_PROVIDER_MODULE
187 static int test_loaded_provider(void)
188 {
189     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
190     const char *name = "p_test";
191
192     if (!TEST_ptr(libctx))
193         return 0;
194
195     /* test_provider will free libctx as part of the test */
196     return test_provider(&libctx, name, NULL);
197 }
198 #endif
199
200 typedef enum OPTION_choice {
201     OPT_ERR = -1,
202     OPT_EOF = 0,
203     OPT_LOADED,
204     OPT_TEST_ENUM
205 } OPTION_CHOICE;
206
207 const OPTIONS *test_get_options(void)
208 {
209     static const OPTIONS test_options[] = {
210         OPT_TEST_OPTIONS_DEFAULT_USAGE,
211         { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
212         { NULL }
213     };
214     return test_options;
215 }
216
217 int setup_tests(void)
218 {
219     OPTION_CHOICE o;
220     int loaded = 0;
221
222     while ((o = opt_next()) != OPT_EOF) {
223         switch (o) {
224         case OPT_TEST_CASES:
225             break;
226         case OPT_LOADED:
227             loaded = 1;
228             break;
229         default:
230             return 0;
231         }
232     }
233
234     if (!loaded) {
235         ADD_TEST(test_builtin_provider);
236 #ifndef OPENSSL_NO_MD4
237         ADD_TEST(test_builtin_provider_with_child);
238 #endif
239     }
240 #ifndef NO_PROVIDER_MODULE
241     else {
242         ADD_TEST(test_loaded_provider);
243     }
244 #endif
245     return 1;
246 }
247