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