1*e0c4386eSCy Schubert /*
2*e0c4386eSCy Schubert  * Copyright 2018-2023 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 "../testutil.h"
11*e0c4386eSCy Schubert #include <ctype.h>
12*e0c4386eSCy Schubert #include <openssl/provider.h>
13*e0c4386eSCy Schubert #include <openssl/core_names.h>
14*e0c4386eSCy Schubert #include <string.h>
15*e0c4386eSCy Schubert 
test_get_libctx(OSSL_LIB_CTX ** libctx,OSSL_PROVIDER ** default_null_prov,const char * config_file,OSSL_PROVIDER ** provider,const char * module_name)16*e0c4386eSCy Schubert int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
17*e0c4386eSCy Schubert                     const char *config_file,
18*e0c4386eSCy Schubert                     OSSL_PROVIDER **provider, const char *module_name)
19*e0c4386eSCy Schubert {
20*e0c4386eSCy Schubert     OSSL_LIB_CTX *new_libctx = NULL;
21*e0c4386eSCy Schubert 
22*e0c4386eSCy Schubert     if (libctx != NULL) {
23*e0c4386eSCy Schubert         if ((new_libctx = *libctx = OSSL_LIB_CTX_new()) == NULL) {
24*e0c4386eSCy Schubert             opt_printf_stderr("Failed to create libctx\n");
25*e0c4386eSCy Schubert             goto err;
26*e0c4386eSCy Schubert         }
27*e0c4386eSCy Schubert     }
28*e0c4386eSCy Schubert 
29*e0c4386eSCy Schubert     if (default_null_prov != NULL
30*e0c4386eSCy Schubert         && (*default_null_prov = OSSL_PROVIDER_load(NULL, "null")) == NULL) {
31*e0c4386eSCy Schubert         opt_printf_stderr("Failed to load null provider into default libctx\n");
32*e0c4386eSCy Schubert         goto err;
33*e0c4386eSCy Schubert     }
34*e0c4386eSCy Schubert 
35*e0c4386eSCy Schubert     if (config_file != NULL
36*e0c4386eSCy Schubert             && !OSSL_LIB_CTX_load_config(new_libctx, config_file)) {
37*e0c4386eSCy Schubert         opt_printf_stderr("Error loading config from file %s\n", config_file);
38*e0c4386eSCy Schubert         goto err;
39*e0c4386eSCy Schubert     }
40*e0c4386eSCy Schubert 
41*e0c4386eSCy Schubert     if (provider != NULL && module_name != NULL
42*e0c4386eSCy Schubert             && (*provider = OSSL_PROVIDER_load(new_libctx, module_name)) == NULL) {
43*e0c4386eSCy Schubert         opt_printf_stderr("Failed to load provider %s\n", module_name);
44*e0c4386eSCy Schubert         goto err;
45*e0c4386eSCy Schubert     }
46*e0c4386eSCy Schubert     return 1;
47*e0c4386eSCy Schubert 
48*e0c4386eSCy Schubert  err:
49*e0c4386eSCy Schubert     ERR_print_errors_fp(stderr);
50*e0c4386eSCy Schubert     return 0;
51*e0c4386eSCy Schubert }
52*e0c4386eSCy Schubert 
test_arg_libctx(OSSL_LIB_CTX ** libctx,OSSL_PROVIDER ** default_null_prov,OSSL_PROVIDER ** provider,int argn,const char * usage)53*e0c4386eSCy Schubert int test_arg_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
54*e0c4386eSCy Schubert                     OSSL_PROVIDER **provider, int argn, const char *usage)
55*e0c4386eSCy Schubert {
56*e0c4386eSCy Schubert     const char *module_name;
57*e0c4386eSCy Schubert 
58*e0c4386eSCy Schubert     if (!TEST_ptr(module_name = test_get_argument(argn))) {
59*e0c4386eSCy Schubert         TEST_error("usage: <prog> %s", usage);
60*e0c4386eSCy Schubert         return 0;
61*e0c4386eSCy Schubert     }
62*e0c4386eSCy Schubert     if (strcmp(module_name, "none") == 0)
63*e0c4386eSCy Schubert         return 1;
64*e0c4386eSCy Schubert     return test_get_libctx(libctx, default_null_prov,
65*e0c4386eSCy Schubert                            test_get_argument(argn + 1), provider, module_name);
66*e0c4386eSCy Schubert }
67*e0c4386eSCy Schubert 
68*e0c4386eSCy Schubert typedef struct {
69*e0c4386eSCy Schubert     int major, minor, patch;
70*e0c4386eSCy Schubert } FIPS_VERSION;
71*e0c4386eSCy Schubert 
72*e0c4386eSCy Schubert /*
73*e0c4386eSCy Schubert  * Query the FIPS provider to determine it's version number.
74*e0c4386eSCy Schubert  * Returns 1 if the version is retrieved correctly, 0 if the FIPS provider isn't
75*e0c4386eSCy Schubert  * loaded and -1 on error.
76*e0c4386eSCy Schubert  */
fips_provider_version(OSSL_LIB_CTX * libctx,FIPS_VERSION * vers)77*e0c4386eSCy Schubert static int fips_provider_version(OSSL_LIB_CTX *libctx, FIPS_VERSION *vers)
78*e0c4386eSCy Schubert {
79*e0c4386eSCy Schubert     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
80*e0c4386eSCy Schubert     OSSL_PROVIDER *fips_prov;
81*e0c4386eSCy Schubert     char *vs;
82*e0c4386eSCy Schubert 
83*e0c4386eSCy Schubert     if (!OSSL_PROVIDER_available(libctx, "fips"))
84*e0c4386eSCy Schubert         return 0;
85*e0c4386eSCy Schubert     *params = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, &vs, 0);
86*e0c4386eSCy Schubert     if ((fips_prov = OSSL_PROVIDER_load(libctx, "fips")) == NULL)
87*e0c4386eSCy Schubert         return -1;
88*e0c4386eSCy Schubert     if (!OSSL_PROVIDER_get_params(fips_prov, params)
89*e0c4386eSCy Schubert             || sscanf(vs, "%d.%d.%d", &vers->major, &vers->minor, &vers->patch) != 3)
90*e0c4386eSCy Schubert         goto err;
91*e0c4386eSCy Schubert     if (!OSSL_PROVIDER_unload(fips_prov))
92*e0c4386eSCy Schubert         return -1;
93*e0c4386eSCy Schubert     return 1;
94*e0c4386eSCy Schubert  err:
95*e0c4386eSCy Schubert     OSSL_PROVIDER_unload(fips_prov);
96*e0c4386eSCy Schubert     return -1;
97*e0c4386eSCy Schubert }
98*e0c4386eSCy Schubert 
fips_provider_version_eq(OSSL_LIB_CTX * libctx,int major,int minor,int patch)99*e0c4386eSCy Schubert int fips_provider_version_eq(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
100*e0c4386eSCy Schubert {
101*e0c4386eSCy Schubert     FIPS_VERSION prov;
102*e0c4386eSCy Schubert     int res;
103*e0c4386eSCy Schubert 
104*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
105*e0c4386eSCy Schubert         return res == 0;
106*e0c4386eSCy Schubert     return major == prov.major && minor == prov.minor && patch == prov.patch;
107*e0c4386eSCy Schubert }
108*e0c4386eSCy Schubert 
fips_provider_version_ne(OSSL_LIB_CTX * libctx,int major,int minor,int patch)109*e0c4386eSCy Schubert int fips_provider_version_ne(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
110*e0c4386eSCy Schubert {
111*e0c4386eSCy Schubert     FIPS_VERSION prov;
112*e0c4386eSCy Schubert     int res;
113*e0c4386eSCy Schubert 
114*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
115*e0c4386eSCy Schubert         return res == 0;
116*e0c4386eSCy Schubert     return major != prov.major || minor != prov.minor || patch != prov.patch;
117*e0c4386eSCy Schubert }
118*e0c4386eSCy Schubert 
fips_provider_version_le(OSSL_LIB_CTX * libctx,int major,int minor,int patch)119*e0c4386eSCy Schubert int fips_provider_version_le(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
120*e0c4386eSCy Schubert {
121*e0c4386eSCy Schubert     FIPS_VERSION prov;
122*e0c4386eSCy Schubert     int res;
123*e0c4386eSCy Schubert 
124*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
125*e0c4386eSCy Schubert         return res == 0;
126*e0c4386eSCy Schubert     return prov.major < major
127*e0c4386eSCy Schubert            || (prov.major == major
128*e0c4386eSCy Schubert                && (prov.minor < minor
129*e0c4386eSCy Schubert                    || (prov.minor == minor && prov.patch <= patch)));
130*e0c4386eSCy Schubert }
131*e0c4386eSCy Schubert 
fips_provider_version_lt(OSSL_LIB_CTX * libctx,int major,int minor,int patch)132*e0c4386eSCy Schubert int fips_provider_version_lt(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
133*e0c4386eSCy Schubert {
134*e0c4386eSCy Schubert     FIPS_VERSION prov;
135*e0c4386eSCy Schubert     int res;
136*e0c4386eSCy Schubert 
137*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
138*e0c4386eSCy Schubert         return res == 0;
139*e0c4386eSCy Schubert     return prov.major < major
140*e0c4386eSCy Schubert            || (prov.major == major
141*e0c4386eSCy Schubert                && (prov.minor < minor
142*e0c4386eSCy Schubert                    || (prov.minor == minor && prov.patch < patch)));
143*e0c4386eSCy Schubert }
144*e0c4386eSCy Schubert 
fips_provider_version_gt(OSSL_LIB_CTX * libctx,int major,int minor,int patch)145*e0c4386eSCy Schubert int fips_provider_version_gt(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
146*e0c4386eSCy Schubert {
147*e0c4386eSCy Schubert     FIPS_VERSION prov;
148*e0c4386eSCy Schubert     int res;
149*e0c4386eSCy Schubert 
150*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
151*e0c4386eSCy Schubert         return res == 0;
152*e0c4386eSCy Schubert     return prov.major > major
153*e0c4386eSCy Schubert            || (prov.major == major
154*e0c4386eSCy Schubert                && (prov.minor > minor
155*e0c4386eSCy Schubert                    || (prov.minor == minor && prov.patch > patch)));
156*e0c4386eSCy Schubert }
157*e0c4386eSCy Schubert 
fips_provider_version_ge(OSSL_LIB_CTX * libctx,int major,int minor,int patch)158*e0c4386eSCy Schubert int fips_provider_version_ge(OSSL_LIB_CTX *libctx, int major, int minor, int patch)
159*e0c4386eSCy Schubert {
160*e0c4386eSCy Schubert     FIPS_VERSION prov;
161*e0c4386eSCy Schubert     int res;
162*e0c4386eSCy Schubert 
163*e0c4386eSCy Schubert     if ((res = fips_provider_version(libctx, &prov)) <= 0)
164*e0c4386eSCy Schubert         return res == 0;
165*e0c4386eSCy Schubert     return prov.major > major
166*e0c4386eSCy Schubert            || (prov.major == major
167*e0c4386eSCy Schubert                && (prov.minor > minor
168*e0c4386eSCy Schubert                    || (prov.minor == minor && prov.patch >= patch)));
169*e0c4386eSCy Schubert }
170*e0c4386eSCy Schubert 
fips_provider_version_match(OSSL_LIB_CTX * libctx,const char * versions)171*e0c4386eSCy Schubert int fips_provider_version_match(OSSL_LIB_CTX *libctx, const char *versions)
172*e0c4386eSCy Schubert {
173*e0c4386eSCy Schubert     const char *p;
174*e0c4386eSCy Schubert     int major, minor, patch, r;
175*e0c4386eSCy Schubert     enum {
176*e0c4386eSCy Schubert         MODE_EQ, MODE_NE, MODE_LE, MODE_LT, MODE_GT, MODE_GE
177*e0c4386eSCy Schubert     } mode;
178*e0c4386eSCy Schubert 
179*e0c4386eSCy Schubert     while (*versions != '\0') {
180*e0c4386eSCy Schubert         for (; isspace((unsigned char)(*versions)); versions++)
181*e0c4386eSCy Schubert             continue;
182*e0c4386eSCy Schubert         if (*versions == '\0')
183*e0c4386eSCy Schubert             break;
184*e0c4386eSCy Schubert         for (p = versions; *versions != '\0' && !isspace((unsigned char)(*versions)); versions++)
185*e0c4386eSCy Schubert             continue;
186*e0c4386eSCy Schubert         if (*p == '!') {
187*e0c4386eSCy Schubert             mode = MODE_NE;
188*e0c4386eSCy Schubert             p++;
189*e0c4386eSCy Schubert         } else if (*p == '=') {
190*e0c4386eSCy Schubert             mode = MODE_EQ;
191*e0c4386eSCy Schubert             p++;
192*e0c4386eSCy Schubert         } else if (*p == '<' && p[1] == '=') {
193*e0c4386eSCy Schubert             mode = MODE_LE;
194*e0c4386eSCy Schubert             p += 2;
195*e0c4386eSCy Schubert         } else if (*p == '>' && p[1] == '=') {
196*e0c4386eSCy Schubert             mode = MODE_GE;
197*e0c4386eSCy Schubert             p += 2;
198*e0c4386eSCy Schubert         } else if (*p == '<') {
199*e0c4386eSCy Schubert             mode = MODE_LT;
200*e0c4386eSCy Schubert             p++;
201*e0c4386eSCy Schubert         } else if (*p == '>') {
202*e0c4386eSCy Schubert             mode = MODE_GT;
203*e0c4386eSCy Schubert             p++;
204*e0c4386eSCy Schubert         } else if (isdigit((unsigned char)*p)) {
205*e0c4386eSCy Schubert             mode = MODE_EQ;
206*e0c4386eSCy Schubert         } else {
207*e0c4386eSCy Schubert             TEST_info("Error matching FIPS version: mode %s\n", p);
208*e0c4386eSCy Schubert             return -1;
209*e0c4386eSCy Schubert         }
210*e0c4386eSCy Schubert         if (sscanf(p, "%d.%d.%d", &major, &minor, &patch) != 3) {
211*e0c4386eSCy Schubert             TEST_info("Error matching FIPS version: version %s\n", p);
212*e0c4386eSCy Schubert             return -1;
213*e0c4386eSCy Schubert         }
214*e0c4386eSCy Schubert         switch (mode) {
215*e0c4386eSCy Schubert         case MODE_EQ:
216*e0c4386eSCy Schubert             r = fips_provider_version_eq(libctx, major, minor, patch);
217*e0c4386eSCy Schubert             break;
218*e0c4386eSCy Schubert         case MODE_NE:
219*e0c4386eSCy Schubert             r = fips_provider_version_ne(libctx, major, minor, patch);
220*e0c4386eSCy Schubert             break;
221*e0c4386eSCy Schubert         case MODE_LE:
222*e0c4386eSCy Schubert             r = fips_provider_version_le(libctx, major, minor, patch);
223*e0c4386eSCy Schubert             break;
224*e0c4386eSCy Schubert         case MODE_LT:
225*e0c4386eSCy Schubert             r = fips_provider_version_lt(libctx, major, minor, patch);
226*e0c4386eSCy Schubert             break;
227*e0c4386eSCy Schubert         case MODE_GT:
228*e0c4386eSCy Schubert             r = fips_provider_version_gt(libctx, major, minor, patch);
229*e0c4386eSCy Schubert             break;
230*e0c4386eSCy Schubert         case MODE_GE:
231*e0c4386eSCy Schubert             r = fips_provider_version_ge(libctx, major, minor, patch);
232*e0c4386eSCy Schubert             break;
233*e0c4386eSCy Schubert         }
234*e0c4386eSCy Schubert         if (r < 0) {
235*e0c4386eSCy Schubert             TEST_info("Error matching FIPS version: internal error\n");
236*e0c4386eSCy Schubert             return -1;
237*e0c4386eSCy Schubert         }
238*e0c4386eSCy Schubert         if (r == 0)
239*e0c4386eSCy Schubert             return 0;
240*e0c4386eSCy Schubert     }
241*e0c4386eSCy Schubert     return 1;
242*e0c4386eSCy Schubert }
243