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