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 "testutil.h" 13 14 extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME; 15 16 static char buf[256]; 17 static OSSL_PARAM greeting_request[] = { 18 { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) }, 19 { NULL, 0, NULL, 0, 0 } 20 }; 21 22 static unsigned int digestsuccess = 0; 23 static OSSL_PARAM digest_check[] = { 24 { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess, 25 sizeof(digestsuccess) }, 26 { NULL, 0, NULL, 0, 0 } 27 }; 28 29 static unsigned int stopsuccess = 0; 30 static OSSL_PARAM stop_property_mirror[] = { 31 { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess, 32 sizeof(stopsuccess) }, 33 { NULL, 0, NULL, 0, 0 } 34 }; 35 36 static int test_provider(OSSL_LIB_CTX **libctx, const char *name, 37 OSSL_PROVIDER *legacy) 38 { 39 OSSL_PROVIDER *prov = NULL; 40 const char *greeting = NULL; 41 char expected_greeting[256]; 42 int ok = 0; 43 long err; 44 int dolegacycheck = (legacy != NULL); 45 OSSL_PROVIDER *deflt = NULL, *base = NULL; 46 47 BIO_snprintf(expected_greeting, sizeof(expected_greeting), 48 "Hello OpenSSL %.20s, greetings from %s!", 49 OPENSSL_VERSION_STR, name); 50 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 static int test_builtin_provider(void) 161 { 162 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 163 const char *name = "p_test_builtin"; 164 int ok; 165 166 ok = 167 TEST_ptr(libctx) 168 && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, 169 PROVIDER_INIT_FUNCTION_NAME)) 170 && test_provider(&libctx, name, NULL); 171 172 OSSL_LIB_CTX_free(libctx); 173 174 return ok; 175 } 176 177 /* Test relies on fetching the MD4 digest from the legacy provider */ 178 #ifndef OPENSSL_NO_MD4 179 static int test_builtin_provider_with_child(void) 180 { 181 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 182 const char *name = "p_test"; 183 OSSL_PROVIDER *legacy; 184 185 if (!TEST_ptr(libctx)) 186 return 0; 187 188 legacy = OSSL_PROVIDER_load(libctx, "legacy"); 189 if (legacy == NULL) { 190 /* 191 * In this case we assume we've been built with "no-legacy" and skip 192 * this test (there is no OPENSSL_NO_LEGACY) 193 */ 194 OSSL_LIB_CTX_free(libctx); 195 return 1; 196 } 197 198 if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name, 199 PROVIDER_INIT_FUNCTION_NAME))) { 200 OSSL_PROVIDER_unload(legacy); 201 OSSL_LIB_CTX_free(libctx); 202 return 0; 203 } 204 205 /* test_provider will free libctx and unload legacy as part of the test */ 206 return test_provider(&libctx, name, legacy); 207 } 208 #endif 209 210 #ifndef NO_PROVIDER_MODULE 211 static int test_loaded_provider(void) 212 { 213 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); 214 const char *name = "p_test"; 215 216 if (!TEST_ptr(libctx)) 217 return 0; 218 219 /* test_provider will free libctx as part of the test */ 220 return test_provider(&libctx, name, NULL); 221 } 222 #endif 223 224 typedef enum OPTION_choice { 225 OPT_ERR = -1, 226 OPT_EOF = 0, 227 OPT_LOADED, 228 OPT_TEST_ENUM 229 } OPTION_CHOICE; 230 231 const OPTIONS *test_get_options(void) 232 { 233 static const OPTIONS test_options[] = { 234 OPT_TEST_OPTIONS_DEFAULT_USAGE, 235 { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" }, 236 { NULL } 237 }; 238 return test_options; 239 } 240 241 int setup_tests(void) 242 { 243 OPTION_CHOICE o; 244 int loaded = 0; 245 246 while ((o = opt_next()) != OPT_EOF) { 247 switch (o) { 248 case OPT_TEST_CASES: 249 break; 250 case OPT_LOADED: 251 loaded = 1; 252 break; 253 default: 254 return 0; 255 } 256 } 257 258 if (!loaded) { 259 ADD_TEST(test_builtin_provider); 260 #ifndef OPENSSL_NO_MD4 261 ADD_TEST(test_builtin_provider_with_child); 262 #endif 263 } 264 #ifndef NO_PROVIDER_MODULE 265 else { 266 ADD_TEST(test_loaded_provider); 267 } 268 #endif 269 return 1; 270 } 271 272