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