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