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