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