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