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