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