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