xref: /freebsd/crypto/openssl/test/provider_status_test.c (revision dece5b05f577fc4c6b89af7ad48dfbdf7cc4945c)
1 /*
2  * Copyright 2020-2026 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 <string.h>
12 #include <stdbool.h>
13 #include <openssl/provider.h>
14 #include <openssl/params.h>
15 #include <openssl/core_names.h>
16 #include <openssl/self_test.h>
17 #include <openssl/evp.h>
18 #include <openssl/rsa.h>
19 #include "testutil.h"
20 
21 typedef enum OPTION_choice {
22     OPT_ERR = -1,
23     OPT_EOF = 0,
24     OPT_PROVIDER_NAME,
25     OPT_CONFIG_FILE,
26     OPT_TEST_ENUM
27 } OPTION_CHOICE;
28 
29 struct self_test_arg {
30     int count;
31 };
32 
33 static OSSL_LIB_CTX *libctx = NULL;
34 static char *provider_name = NULL;
35 static struct self_test_arg self_test_args = { 0 };
36 
37 const OPTIONS *test_get_options(void)
38 {
39     static const OPTIONS test_options[] = {
40         OPT_TEST_OPTIONS_DEFAULT_USAGE,
41         { "provider_name", OPT_PROVIDER_NAME, 's',
42             "The name of the provider to load" },
43         { "config", OPT_CONFIG_FILE, '<',
44             "The configuration file to use for the libctx" },
45         { NULL }
46     };
47     return test_options;
48 }
49 
50 static int self_test_events(const OSSL_PARAM params[], void *arg,
51     const char *title, int corrupt)
52 {
53     struct self_test_arg *args = arg;
54     const OSSL_PARAM *p = NULL;
55     const char *phase = NULL, *type = NULL, *desc = NULL;
56     int ret = 0;
57 
58     if (args->count == 0)
59         BIO_printf(bio_out, "\n%s\n", title);
60     args->count++;
61 
62     p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
63     if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
64         goto err;
65     phase = (const char *)p->data;
66 
67     p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);
68     if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
69         goto err;
70     desc = (const char *)p->data;
71 
72     p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
73     if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
74         goto err;
75     type = (const char *)p->data;
76 
77     if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)
78         BIO_printf(bio_out, "%s : (%s) : ", desc, type);
79     else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0
80         || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)
81         BIO_printf(bio_out, "%s\n", phase);
82     /*
83      * The self test code will internally corrupt the KAT test result if an
84      * error is returned during the corrupt phase.
85      */
86     if (corrupt && strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0)
87         goto err;
88     ret = 1;
89 err:
90     return ret;
91 }
92 
93 static int self_test_on_demand_fail(const OSSL_PARAM params[], void *arg)
94 {
95     return self_test_events(params, arg, "On Demand Failure", 1);
96 }
97 
98 static int self_test_on_demand(const OSSL_PARAM params[], void *arg)
99 {
100     return self_test_events(params, arg, "On Demand", 0);
101 }
102 
103 static int self_test_on_load(const OSSL_PARAM params[], void *arg)
104 {
105     return self_test_events(params, arg, "On Loading", 0);
106 }
107 
108 static int get_provider_params(const OSSL_PROVIDER *prov)
109 {
110     int ret = 0;
111     OSSL_PARAM params[5];
112     char *name, *version, *buildinfo;
113     int status;
114     const OSSL_PARAM *gettable, *p;
115 
116     if (!TEST_ptr(gettable = OSSL_PROVIDER_gettable_params(prov))
117         || !TEST_ptr(p = OSSL_PARAM_locate_const(gettable, OSSL_PROV_PARAM_NAME))
118         || !TEST_ptr(p = OSSL_PARAM_locate_const(gettable, OSSL_PROV_PARAM_VERSION))
119         || !TEST_ptr(p = OSSL_PARAM_locate_const(gettable, OSSL_PROV_PARAM_STATUS))
120         || !TEST_ptr(p = OSSL_PARAM_locate_const(gettable, OSSL_PROV_PARAM_BUILDINFO)))
121         goto end;
122 
123     params[0] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME, &name, 0);
124     params[1] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,
125         &version, 0);
126     params[2] = OSSL_PARAM_construct_int(OSSL_PROV_PARAM_STATUS, &status);
127     params[3] = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO,
128         &buildinfo, 0);
129     params[4] = OSSL_PARAM_construct_end();
130     OSSL_PARAM_set_all_unmodified(params);
131     if (!TEST_true(OSSL_PROVIDER_get_params(prov, params)))
132         goto end;
133     if (!TEST_true(OSSL_PARAM_modified(params + 0))
134         || !TEST_true(OSSL_PARAM_modified(params + 1))
135         || !TEST_true(OSSL_PARAM_modified(params + 2))
136         || !TEST_true(OSSL_PARAM_modified(params + 3))
137         || !TEST_true(status == 1))
138         goto end;
139 
140     ret = 1;
141 end:
142     return ret;
143 }
144 
145 struct group_capability_st {
146     int num_capabilities;
147     int num_correct_type;
148 };
149 
150 static int tls_group_capability_cb(const OSSL_PARAM params[], void *arg)
151 {
152     const OSSL_PARAM *p = OSSL_PARAM_locate_const(
153         params, OSSL_CAPABILITY_TLS_GROUP_IS_KEM);
154     struct group_capability_st *gcp = (struct group_capability_st *)arg;
155 
156     gcp->num_capabilities++;
157 
158     if (!TEST_ptr(p) || !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER))
159         return 0;
160 
161     gcp->num_correct_type++;
162     return 1;
163 }
164 
165 static int test_tls_group_capability_type(void)
166 {
167     OSSL_PROVIDER *prov = NULL;
168     struct group_capability_st gc = { 0, 0 };
169     int ret = 0;
170 
171     if (!TEST_ptr(prov = OSSL_PROVIDER_load(libctx, provider_name))
172         || !TEST_true(OSSL_PROVIDER_get_capabilities(
173             prov, "TLS-GROUP", tls_group_capability_cb, &gc))
174         || !TEST_int_eq(gc.num_capabilities, gc.num_correct_type))
175         goto err;
176 
177     ret = 1;
178 err:
179     OSSL_PROVIDER_unload(prov);
180     return ret;
181 }
182 
183 static int test_provider_status(void)
184 {
185     int ret = 0;
186     unsigned int status = 0;
187     OSSL_PROVIDER *prov = NULL;
188     OSSL_PARAM params[2];
189     EVP_MD *fetch = NULL;
190     EVP_PKEY_CTX *pctx = NULL;
191     EVP_PKEY *pkey = NULL;
192 
193     if (!TEST_ptr(prov = OSSL_PROVIDER_load(libctx, provider_name)))
194         goto err;
195     if (!get_provider_params(prov))
196         goto err;
197 
198     /* Test that the provider status is ok */
199     params[0] = OSSL_PARAM_construct_uint(OSSL_PROV_PARAM_STATUS, &status);
200     params[1] = OSSL_PARAM_construct_end();
201     if (!TEST_true(OSSL_PROVIDER_get_params(prov, params))
202         || !TEST_true(status == 1))
203         goto err;
204     if (!TEST_ptr(fetch = EVP_MD_fetch(libctx, "SHA256", NULL)))
205         goto err;
206     EVP_MD_free(fetch);
207     fetch = NULL;
208     /* Use RNG before triggering on-demand self tests */
209     if (!TEST_ptr((pctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)))
210         || !TEST_int_gt(EVP_PKEY_keygen_init(pctx), 0)
211         || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048), 0)
212         || !TEST_int_gt(EVP_PKEY_keygen(pctx, &pkey), 0))
213         goto err;
214     EVP_PKEY_free(pkey);
215     EVP_PKEY_CTX_free(pctx);
216     pkey = NULL;
217     pctx = NULL;
218 
219     /* Test that the provider self test is ok */
220     self_test_args.count = 0;
221     OSSL_SELF_TEST_set_callback(libctx, self_test_on_demand, &self_test_args);
222     if (!TEST_true(OSSL_PROVIDER_self_test(prov)))
223         goto err;
224 
225     /* Setup a callback that corrupts the self tests and causes status failures */
226     self_test_args.count = 0;
227     OSSL_SELF_TEST_set_callback(libctx, self_test_on_demand_fail, &self_test_args);
228     if (!TEST_false(OSSL_PROVIDER_self_test(prov)))
229         goto err;
230     if (!TEST_true(OSSL_PROVIDER_get_params(prov, params))
231         || !TEST_uint_eq(status, 0))
232         goto err;
233     if (!TEST_ptr_null(fetch = EVP_MD_fetch(libctx, "SHA256", NULL)))
234         goto err;
235 
236     ret = 1;
237 err:
238     EVP_MD_free(fetch);
239     OSSL_PROVIDER_unload(prov);
240     return ret;
241 }
242 
243 static int test_provider_gettable_params(void)
244 {
245     OSSL_PROVIDER *prov;
246     int ret;
247 
248     if (!TEST_ptr(prov = OSSL_PROVIDER_load(libctx, provider_name)))
249         return 0;
250     ret = get_provider_params(prov);
251     OSSL_PROVIDER_unload(prov);
252     return ret;
253 }
254 
255 int setup_tests(void)
256 {
257     OPTION_CHOICE o;
258     char *config_file = NULL;
259     bool is_fips, is_default;
260 
261     while ((o = opt_next()) != OPT_EOF) {
262         switch (o) {
263         case OPT_CONFIG_FILE:
264             config_file = opt_arg();
265             break;
266         case OPT_PROVIDER_NAME:
267             provider_name = opt_arg();
268             break;
269         case OPT_TEST_CASES:
270             break;
271         default:
272         case OPT_ERR:
273             return 0;
274         }
275     }
276 
277     if (!TEST_ptr(libctx = OSSL_LIB_CTX_new()))
278         return 0;
279     if (!TEST_ptr(provider_name))
280         return 0;
281 
282     is_fips = strcmp(provider_name, "fips") == 0;
283     is_default = strcmp(provider_name, "default") == 0;
284 
285     if (is_fips) {
286         if (!TEST_ptr(config_file))
287             return 0;
288         self_test_args.count = 0;
289         OSSL_SELF_TEST_set_callback(libctx, self_test_on_load, &self_test_args);
290         if (!OSSL_LIB_CTX_load_config(libctx, config_file)) {
291             opt_printf_stderr("Failed to load config\n");
292             return 0;
293         }
294         ADD_TEST(test_provider_status);
295     } else {
296         ADD_TEST(test_provider_gettable_params);
297     }
298 
299     if (is_default || (is_fips && fips_provider_version_ge(libctx, 4, 1, 0)))
300         ADD_TEST(test_tls_group_capability_type);
301 
302     return 1;
303 }
304 
305 void cleanup_tests(void)
306 {
307     OSSL_LIB_CTX_free(libctx);
308 }
309