1 /* 2 * Copyright 2019-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 <openssl/provider.h> 12 #include <openssl/param_build.h> 13 #include "testutil.h" 14 15 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME; 16 17 static char buf[256]; 18 static OSSL_PARAM greeting_request[] = { 19 { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) }, 20 { NULL, 0, NULL, 0, 0 } 21 }; 22 23 static unsigned int digestsuccess = 0; 24 static OSSL_PARAM digest_check[] = { 25 { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess, 26 sizeof(digestsuccess) }, 27 { NULL, 0, NULL, 0, 0 } 28 }; 29 30 static unsigned int stopsuccess = 0; 31 static OSSL_PARAM stop_property_mirror[] = { 32 { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess, 33 sizeof(stopsuccess) }, 34 { NULL, 0, NULL, 0, 0 } 35 }; 36 37 static int test_provider(OSSL_LIB_CTX **libctx, const char *name, 38 OSSL_PROVIDER *legacy) 39 { 40 OSSL_PROVIDER *prov = NULL; 41 const char *greeting = NULL; 42 char expected_greeting[256]; 43 int ok = 0; 44 long err; 45 int dolegacycheck = (legacy != NULL); 46 OSSL_PROVIDER *deflt = NULL, *base = NULL; 47 48 BIO_snprintf(expected_greeting, sizeof(expected_greeting), 49 "Hello OpenSSL %.20s, greetings from %s!", 50 OPENSSL_VERSION_STR, name); 51 52 53 /* 54 * We set properties that we know the providers we are using don't have. 55 * This should mean that the p_test provider will fail any fetches - which 56 * is something we test inside the provider. 57 */ 58 EVP_set_default_properties(*libctx, "fips=yes"); 59 /* 60 * Check that it is possible to have a built-in provider mirrored in 61 * a child lib ctx. 62 */ 63 if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base"))) 64 goto err; 65 if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name))) 66 goto err; 67 68 /* 69 * Once the provider is loaded we clear the default properties and fetches 70 * should start working again. 71 */ 72 EVP_set_default_properties(*libctx, ""); 73 if (dolegacycheck) { 74 if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) 75 || !TEST_true(digestsuccess)) 76 goto err; 77 78 /* 79 * Check that a provider can prevent property mirroring if it sets its 80 * own properties explicitly 81 */ 82 if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror)) 83 || !TEST_true(stopsuccess)) 84 goto err; 85 EVP_set_default_properties(*libctx, "fips=yes"); 86 if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) 87 || !TEST_true(digestsuccess)) 88 goto err; 89 EVP_set_default_properties(*libctx, ""); 90 } 91 if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request)) 92 || !TEST_ptr(greeting = greeting_request[0].data) 93 || !TEST_size_t_gt(greeting_request[0].data_size, 0) 94 || !TEST_str_eq(greeting, expected_greeting)) 95 goto err; 96 97 /* Make sure we got the error we were expecting */ 98 err = ERR_peek_last_error(); 99 if (!TEST_int_gt(err, 0) 100 || !TEST_int_eq(ERR_GET_REASON(err), 1)) 101 goto err; 102 103 OSSL_PROVIDER_unload(legacy); 104 legacy = NULL; 105 106 if (dolegacycheck) { 107 /* Legacy provider should also be unloaded from child libctx */ 108 if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) 109 || !TEST_false(digestsuccess)) 110 goto err; 111 /* 112 * Loading the legacy provider again should make it available again in 113 * the child libctx. Loading and unloading the default provider should 114 * have no impact on the child because the child loads it explicitly 115 * before this point. 116 */ 117 legacy = OSSL_PROVIDER_load(*libctx, "legacy"); 118 deflt = OSSL_PROVIDER_load(*libctx, "default"); 119 if (!TEST_ptr(deflt) 120 || !TEST_true(OSSL_PROVIDER_available(*libctx, "default"))) 121 goto err; 122 OSSL_PROVIDER_unload(deflt); 123 deflt = NULL; 124 if (!TEST_ptr(legacy) 125 || !TEST_false(OSSL_PROVIDER_available(*libctx, "default")) 126 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check)) 127 || !TEST_true(digestsuccess)) 128 goto err; 129 OSSL_PROVIDER_unload(legacy); 130 legacy = NULL; 131 } 132 133 if (!TEST_true(OSSL_PROVIDER_unload(base))) 134 goto err; 135 base = NULL; 136 if (!TEST_true(OSSL_PROVIDER_unload(prov))) 137 goto err; 138 prov = NULL; 139 140 /* 141 * We must free the libctx to force the provider to really be unloaded from 142 * memory 143 */ 144 OSSL_LIB_CTX_free(*libctx); 145 *libctx = NULL; 146 147 /* We print out all the data to make sure it can still be accessed */ 148 ERR_print_errors_fp(stderr); 149 ok = 1; 150 err: 151 OSSL_PROVIDER_unload(base); 152 OSSL_PROVIDER_unload(deflt); 153 OSSL_PROVIDER_unload(legacy); 154 legacy = NULL; 155 OSSL_PROVIDER_unload(prov); 156 OSSL_LIB_CTX_free(*libctx); 157 *libctx = NULL; 158 return ok; 159 } 160 161 #ifndef NO_PROVIDER_MODULE 162 static int test_provider_ex(OSSL_LIB_CTX **libctx, const char *name) 163 { 164 OSSL_PROVIDER *prov = NULL; 165 const char *greeting = NULL; 166 int ok = 0; 167 long err; 168 const char custom_buf[] = "Custom greeting"; 169 OSSL_PARAM_BLD *bld = NULL; 170 OSSL_PARAM *params = NULL; 171 172 if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) 173 || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, "greeting", custom_buf, 174 strlen(custom_buf))) 175 || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) { 176 goto err; 177 } 178 179 if (!TEST_ptr(prov = OSSL_PROVIDER_load_ex(*libctx, name, params))) 180 goto err; 181 182 if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request)) 183 || !TEST_ptr(greeting = greeting_request[0].data) 184 || !TEST_size_t_gt(greeting_request[0].data_size, 0) 185 || !TEST_str_eq(greeting, custom_buf)) 186 goto err; 187 188 /* Make sure we got the error we were expecting */ 189 err = ERR_peek_last_error(); 190 if (!TEST_int_gt(err, 0) 191 || !TEST_int_eq(ERR_GET_REASON(err), 1)) 192 goto err; 193 194 if (!TEST_true(OSSL_PROVIDER_unload(prov))) 195 goto err; 196 prov = NULL; 197 198 /* 199 * We must free the libctx to force the provider to really be unloaded from 200 * memory 201 */ 202 OSSL_LIB_CTX_free(*libctx); 203 *libctx = NULL; 204 205 /* We print out all the data to make sure it can still be accessed */ 206 ERR_print_errors_fp(stderr); 207 ok = 1; 208 err: 209 OSSL_PARAM_BLD_free(bld); 210 OSSL_PARAM_free(params); 211 OSSL_PROVIDER_unload(prov); 212 OSSL_LIB_CTX_free(*libctx); 213 *libctx = NULL; 214 return ok; 215 } 216 #endif 217 218 static int test_builtin_provider(void) 219 { 220 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 221 const char *name = "p_test_builtin"; 222 int ok; 223 224 ok = 225 TEST_ptr(libctx) 226 && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, 227 PROVIDER_INIT_FUNCTION_NAME)) 228 && test_provider(&libctx, name, NULL); 229 230 OSSL_LIB_CTX_free(libctx); 231 232 return ok; 233 } 234 235 /* Test relies on fetching the MD4 digest from the legacy provider */ 236 #ifndef OPENSSL_NO_MD4 237 static int test_builtin_provider_with_child(void) 238 { 239 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 240 const char *name = "p_test"; 241 OSSL_PROVIDER *legacy; 242 243 if (!TEST_ptr(libctx)) 244 return 0; 245 246 legacy = OSSL_PROVIDER_load(libctx, "legacy"); 247 if (legacy == NULL) { 248 /* 249 * In this case we assume we've been built with "no-legacy" and skip 250 * this test (there is no OPENSSL_NO_LEGACY) 251 */ 252 OSSL_LIB_CTX_free(libctx); 253 return 1; 254 } 255 256 if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, 257 PROVIDER_INIT_FUNCTION_NAME))) { 258 OSSL_PROVIDER_unload(legacy); 259 OSSL_LIB_CTX_free(libctx); 260 return 0; 261 } 262 263 /* test_provider will free libctx and unload legacy as part of the test */ 264 return test_provider(&libctx, name, legacy); 265 } 266 #endif 267 268 #ifndef NO_PROVIDER_MODULE 269 static int test_loaded_provider(void) 270 { 271 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 272 const char *name = "p_test"; 273 int res = 0; 274 275 if (!TEST_ptr(libctx)) 276 return 0; 277 278 /* test_provider will free libctx as part of the test */ 279 res = test_provider(&libctx, name, NULL); 280 281 libctx = OSSL_LIB_CTX_new(); 282 if (!TEST_ptr(libctx)) 283 return 0; 284 285 /* test_provider_ex will free libctx as part of the test */ 286 res = res && test_provider_ex(&libctx, name); 287 288 return res; 289 } 290 #endif 291 292 typedef enum OPTION_choice { 293 OPT_ERR = -1, 294 OPT_EOF = 0, 295 OPT_LOADED, 296 OPT_TEST_ENUM 297 } OPTION_CHOICE; 298 299 const OPTIONS *test_get_options(void) 300 { 301 static const OPTIONS test_options[] = { 302 OPT_TEST_OPTIONS_DEFAULT_USAGE, 303 { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" }, 304 { NULL } 305 }; 306 return test_options; 307 } 308 309 int setup_tests(void) 310 { 311 OPTION_CHOICE o; 312 int loaded = 0; 313 314 while ((o = opt_next()) != OPT_EOF) { 315 switch (o) { 316 case OPT_TEST_CASES: 317 break; 318 case OPT_LOADED: 319 loaded = 1; 320 break; 321 default: 322 return 0; 323 } 324 } 325 326 if (!loaded) { 327 ADD_TEST(test_builtin_provider); 328 #ifndef OPENSSL_NO_MD4 329 ADD_TEST(test_builtin_provider_with_child); 330 #endif 331 } 332 #ifndef NO_PROVIDER_MODULE 333 else { 334 ADD_TEST(test_loaded_provider); 335 } 336 #endif 337 return 1; 338 } 339 340