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, MODE_NE, MODE_LE, MODE_LT, MODE_GT, MODE_GE 177 } mode; 178 179 while (*versions != '\0') { 180 for (; isspace((unsigned char)(*versions)); versions++) 181 continue; 182 if (*versions == '\0') 183 break; 184 for (p = versions; *versions != '\0' && !isspace((unsigned char)(*versions)); versions++) 185 continue; 186 if (*p == '!') { 187 mode = MODE_NE; 188 p++; 189 } else if (*p == '=') { 190 mode = MODE_EQ; 191 p++; 192 } else if (*p == '<' && p[1] == '=') { 193 mode = MODE_LE; 194 p += 2; 195 } else if (*p == '>' && p[1] == '=') { 196 mode = MODE_GE; 197 p += 2; 198 } else if (*p == '<') { 199 mode = MODE_LT; 200 p++; 201 } else if (*p == '>') { 202 mode = MODE_GT; 203 p++; 204 } else if (isdigit((unsigned char)*p)) { 205 mode = MODE_EQ; 206 } else { 207 TEST_info("Error matching FIPS version: mode %s\n", p); 208 return -1; 209 } 210 if (sscanf(p, "%d.%d.%d", &major, &minor, &patch) != 3) { 211 TEST_info("Error matching FIPS version: version %s\n", p); 212 return -1; 213 } 214 switch (mode) { 215 case MODE_EQ: 216 r = fips_provider_version_eq(libctx, major, minor, patch); 217 break; 218 case MODE_NE: 219 r = fips_provider_version_ne(libctx, major, minor, patch); 220 break; 221 case MODE_LE: 222 r = fips_provider_version_le(libctx, major, minor, patch); 223 break; 224 case MODE_LT: 225 r = fips_provider_version_lt(libctx, major, minor, patch); 226 break; 227 case MODE_GT: 228 r = fips_provider_version_gt(libctx, major, minor, patch); 229 break; 230 case MODE_GE: 231 r = fips_provider_version_ge(libctx, major, minor, patch); 232 break; 233 } 234 if (r < 0) { 235 TEST_info("Error matching FIPS version: internal error\n"); 236 return -1; 237 } 238 if (r == 0) 239 return 0; 240 } 241 return 1; 242 } 243