1 1.1 christos /* 2 1.1 christos * Copyright 2019-2023 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 /* 11 1.1 christos * This is a very simple provider that does absolutely nothing except respond 12 1.1 christos * to provider global parameter requests. It does this by simply echoing back 13 1.1 christos * a parameter request it makes to the loading library. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <string.h> 17 1.1 christos #include <stdio.h> 18 1.1 christos 19 1.1 christos #include <stdarg.h> 20 1.1 christos 21 1.1 christos /* 22 1.1 christos * When built as an object file to link the application with, we get the 23 1.1 christos * init function name through the macro PROVIDER_INIT_FUNCTION_NAME. If 24 1.1 christos * not defined, we use the standard init function name for the shared 25 1.1 christos * object form. 26 1.1 christos */ 27 1.1 christos #ifdef PROVIDER_INIT_FUNCTION_NAME 28 1.1.1.2 christos #define OSSL_provider_init PROVIDER_INIT_FUNCTION_NAME 29 1.1 christos #endif 30 1.1 christos 31 1.1 christos #include "internal/e_os.h" 32 1.1 christos #include <openssl/core.h> 33 1.1 christos #include <openssl/core_dispatch.h> 34 1.1 christos #include <openssl/err.h> 35 1.1 christos #include <openssl/evp.h> 36 1.1 christos #include <openssl/crypto.h> 37 1.1 christos #include <openssl/provider.h> 38 1.1 christos 39 1.1 christos typedef struct p_test_ctx { 40 1.1 christos char *thisfile; 41 1.1 christos char *thisfunc; 42 1.1 christos const OSSL_CORE_HANDLE *handle; 43 1.1 christos OSSL_LIB_CTX *libctx; 44 1.1 christos } P_TEST_CTX; 45 1.1 christos 46 1.1 christos static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; 47 1.1 christos static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; 48 1.1 christos static OSSL_FUNC_core_new_error_fn *c_new_error; 49 1.1 christos static OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug; 50 1.1 christos static OSSL_FUNC_core_vset_error_fn *c_vset_error; 51 1.1 christos static OSSL_FUNC_BIO_vsnprintf_fn *c_BIO_vsnprintf; 52 1.1 christos 53 1.1 christos /* Tell the core what params we provide and what type they are */ 54 1.1 christos static const OSSL_PARAM p_param_types[] = { 55 1.1 christos { "greeting", OSSL_PARAM_UTF8_STRING, NULL, 0, 0 }, 56 1.1.1.2 christos { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0 }, 57 1.1 christos { NULL, 0, NULL, 0, 0 } 58 1.1 christos }; 59 1.1 christos 60 1.1 christos /* This is a trick to ensure we define the provider functions correctly */ 61 1.1 christos static OSSL_FUNC_provider_gettable_params_fn p_gettable_params; 62 1.1 christos static OSSL_FUNC_provider_get_params_fn p_get_params; 63 1.1 christos static OSSL_FUNC_provider_get_reason_strings_fn p_get_reason_strings; 64 1.1 christos static OSSL_FUNC_provider_teardown_fn p_teardown; 65 1.1 christos 66 1.1 christos static int local_snprintf(char *buf, size_t n, const char *format, ...) 67 1.1 christos { 68 1.1 christos va_list args; 69 1.1 christos int ret; 70 1.1 christos 71 1.1 christos va_start(args, format); 72 1.1 christos ret = (*c_BIO_vsnprintf)(buf, n, format, args); 73 1.1 christos va_end(args); 74 1.1 christos return ret; 75 1.1 christos } 76 1.1 christos 77 1.1 christos static void p_set_error(int lib, int reason, const char *file, int line, 78 1.1.1.2 christos const char *func, const char *fmt, ...) 79 1.1 christos { 80 1.1 christos va_list ap; 81 1.1 christos 82 1.1 christos va_start(ap, fmt); 83 1.1 christos c_new_error(NULL); 84 1.1 christos c_set_error_debug(NULL, file, line, func); 85 1.1 christos c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, ap); 86 1.1 christos va_end(ap); 87 1.1 christos } 88 1.1 christos 89 1.1 christos static const OSSL_PARAM *p_gettable_params(void *_) 90 1.1 christos { 91 1.1 christos return p_param_types; 92 1.1 christos } 93 1.1 christos 94 1.1 christos static int p_get_params(void *provctx, OSSL_PARAM params[]) 95 1.1 christos { 96 1.1 christos P_TEST_CTX *ctx = (P_TEST_CTX *)provctx; 97 1.1 christos const OSSL_CORE_HANDLE *hand = ctx->handle; 98 1.1 christos OSSL_PARAM *p = params; 99 1.1 christos int ok = 1; 100 1.1 christos 101 1.1 christos for (; ok && p->key != NULL; p++) { 102 1.1 christos if (strcmp(p->key, "greeting") == 0) { 103 1.1 christos static char *opensslv; 104 1.1 christos static char *provname; 105 1.1 christos static char *greeting; 106 1.1 christos static OSSL_PARAM counter_request[] = { 107 1.1 christos /* Known libcrypto provided parameters */ 108 1.1 christos { "openssl-version", OSSL_PARAM_UTF8_PTR, 109 1.1.1.2 christos &opensslv, sizeof(&opensslv), 0 }, 110 1.1 christos { "provider-name", OSSL_PARAM_UTF8_PTR, 111 1.1.1.2 christos &provname, sizeof(&provname), 0 }, 112 1.1 christos 113 1.1 christos /* This might be present, if there's such a configuration */ 114 1.1 christos { "greeting", OSSL_PARAM_UTF8_PTR, 115 1.1.1.2 christos &greeting, sizeof(&greeting), 0 }, 116 1.1 christos 117 1.1 christos { NULL, 0, NULL, 0, 0 } 118 1.1 christos }; 119 1.1 christos char buf[256]; 120 1.1 christos size_t buf_l; 121 1.1 christos 122 1.1 christos opensslv = provname = greeting = NULL; 123 1.1 christos 124 1.1 christos if (c_get_params(hand, counter_request)) { 125 1.1 christos if (greeting) { 126 1.1 christos strcpy(buf, greeting); 127 1.1 christos } else { 128 1.1 christos const char *versionp = *(void **)counter_request[0].data; 129 1.1 christos const char *namep = *(void **)counter_request[1].data; 130 1.1 christos 131 1.1 christos local_snprintf(buf, sizeof(buf), "Hello OpenSSL %.20s, greetings from %s!", 132 1.1.1.2 christos versionp, namep); 133 1.1 christos } 134 1.1 christos } else { 135 1.1 christos local_snprintf(buf, sizeof(buf), "Howdy stranger..."); 136 1.1 christos } 137 1.1 christos 138 1.1 christos p->return_size = buf_l = strlen(buf) + 1; 139 1.1 christos if (p->data_size >= buf_l) 140 1.1 christos strcpy(p->data, buf); 141 1.1 christos else 142 1.1 christos ok = 0; 143 1.1 christos } else if (strcmp(p->key, "digest-check") == 0) { 144 1.1 christos unsigned int digestsuccess = 0; 145 1.1 christos 146 1.1 christos /* 147 1.1 christos * Test we can use an algorithm from another provider. We're using 148 1.1 christos * legacy to check that legacy is actually available and we haven't 149 1.1 christos * just fallen back to default. 150 1.1 christos */ 151 1.1 christos #ifdef PROVIDER_INIT_FUNCTION_NAME 152 1.1 christos EVP_MD *md4 = EVP_MD_fetch(ctx->libctx, "MD4", NULL); 153 1.1 christos EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); 154 1.1 christos const char *msg = "Hello world"; 155 1.1 christos unsigned char out[16]; 156 1.1 christos OSSL_PROVIDER *deflt; 157 1.1 christos 158 1.1 christos /* 159 1.1.1.2 christos * "default" has not been loaded into the parent libctx. We should be able 160 1.1.1.2 christos * to explicitly load it as a non-child provider. 161 1.1.1.2 christos */ 162 1.1 christos deflt = OSSL_PROVIDER_load(ctx->libctx, "default"); 163 1.1 christos if (deflt == NULL 164 1.1.1.2 christos || !OSSL_PROVIDER_available(ctx->libctx, "default")) { 165 1.1 christos /* We set error "3" for a failure to load the default provider */ 166 1.1 christos p_set_error(ERR_LIB_PROV, 3, ctx->thisfile, OPENSSL_LINE, 167 1.1.1.2 christos ctx->thisfunc, NULL); 168 1.1 christos ok = 0; 169 1.1 christos } 170 1.1 christos 171 1.1 christos /* 172 1.1 christos * We should have the default provider available that we loaded 173 1.1 christos * ourselves, and the base and legacy providers which we inherit 174 1.1 christos * from the parent libctx. We should also have "this" provider 175 1.1 christos * available. 176 1.1 christos */ 177 1.1 christos if (ok 178 1.1.1.2 christos && OSSL_PROVIDER_available(ctx->libctx, "default") 179 1.1.1.2 christos && OSSL_PROVIDER_available(ctx->libctx, "base") 180 1.1.1.2 christos && OSSL_PROVIDER_available(ctx->libctx, "legacy") 181 1.1.1.2 christos && OSSL_PROVIDER_available(ctx->libctx, "p_test") 182 1.1.1.2 christos && md4 != NULL 183 1.1.1.2 christos && mdctx != NULL) { 184 1.1 christos if (EVP_DigestInit_ex(mdctx, md4, NULL) 185 1.1.1.2 christos && EVP_DigestUpdate(mdctx, (const unsigned char *)msg, 186 1.1.1.2 christos strlen(msg)) 187 1.1.1.2 christos && EVP_DigestFinal(mdctx, out, NULL)) 188 1.1 christos digestsuccess = 1; 189 1.1 christos } 190 1.1 christos EVP_MD_CTX_free(mdctx); 191 1.1 christos EVP_MD_free(md4); 192 1.1 christos OSSL_PROVIDER_unload(deflt); 193 1.1 christos #endif 194 1.1 christos if (p->data_size >= sizeof(digestsuccess)) { 195 1.1 christos *(unsigned int *)p->data = digestsuccess; 196 1.1 christos p->return_size = sizeof(digestsuccess); 197 1.1 christos } else { 198 1.1 christos ok = 0; 199 1.1 christos } 200 1.1 christos } else if (strcmp(p->key, "stop-property-mirror") == 0) { 201 1.1 christos /* 202 1.1 christos * Setting the default properties explicitly should stop mirroring 203 1.1 christos * of properties from the parent libctx. 204 1.1 christos */ 205 1.1 christos unsigned int stopsuccess = 0; 206 1.1 christos 207 1.1 christos #ifdef PROVIDER_INIT_FUNCTION_NAME 208 1.1 christos stopsuccess = EVP_set_default_properties(ctx->libctx, NULL); 209 1.1 christos #endif 210 1.1 christos if (p->data_size >= sizeof(stopsuccess)) { 211 1.1 christos *(unsigned int *)p->data = stopsuccess; 212 1.1 christos p->return_size = sizeof(stopsuccess); 213 1.1 christos } else { 214 1.1 christos ok = 0; 215 1.1 christos } 216 1.1 christos } 217 1.1 christos } 218 1.1 christos return ok; 219 1.1 christos } 220 1.1 christos 221 1.1 christos static const OSSL_ITEM *p_get_reason_strings(void *_) 222 1.1 christos { 223 1.1 christos static const OSSL_ITEM reason_strings[] = { 224 1.1.1.2 christos { 1, "dummy reason string" }, 225 1.1.1.2 christos { 2, "Can't create child library context" }, 226 1.1.1.2 christos { 3, "Can't load default provider" }, 227 1.1.1.2 christos { 0, NULL } 228 1.1 christos }; 229 1.1 christos 230 1.1 christos return reason_strings; 231 1.1 christos } 232 1.1 christos 233 1.1 christos static const OSSL_ALGORITHM *p_query(OSSL_PROVIDER *prov, 234 1.1.1.2 christos int operation_id, 235 1.1.1.2 christos int *no_cache) 236 1.1 christos { 237 1.1 christos *no_cache = 1; 238 1.1 christos return NULL; 239 1.1 christos } 240 1.1 christos 241 1.1 christos static const OSSL_DISPATCH p_test_table[] = { 242 1.1 christos { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))p_gettable_params }, 243 1.1 christos { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))p_get_params }, 244 1.1 christos { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, 245 1.1.1.2 christos (void (*)(void))p_get_reason_strings }, 246 1.1 christos { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown }, 247 1.1 christos { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_query }, 248 1.1 christos OSSL_DISPATCH_END 249 1.1 christos }; 250 1.1 christos 251 1.1 christos int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, 252 1.1.1.2 christos const OSSL_DISPATCH *oin, 253 1.1.1.2 christos const OSSL_DISPATCH **out, 254 1.1.1.2 christos void **provctx) 255 1.1 christos { 256 1.1 christos P_TEST_CTX *ctx; 257 1.1 christos const OSSL_DISPATCH *in = oin; 258 1.1 christos 259 1.1 christos for (; in->function_id != 0; in++) { 260 1.1 christos switch (in->function_id) { 261 1.1 christos case OSSL_FUNC_CORE_GETTABLE_PARAMS: 262 1.1 christos c_gettable_params = OSSL_FUNC_core_gettable_params(in); 263 1.1 christos break; 264 1.1 christos case OSSL_FUNC_CORE_GET_PARAMS: 265 1.1 christos c_get_params = OSSL_FUNC_core_get_params(in); 266 1.1 christos break; 267 1.1 christos case OSSL_FUNC_CORE_NEW_ERROR: 268 1.1 christos c_new_error = OSSL_FUNC_core_new_error(in); 269 1.1 christos break; 270 1.1 christos case OSSL_FUNC_CORE_SET_ERROR_DEBUG: 271 1.1 christos c_set_error_debug = OSSL_FUNC_core_set_error_debug(in); 272 1.1 christos break; 273 1.1 christos case OSSL_FUNC_CORE_VSET_ERROR: 274 1.1 christos c_vset_error = OSSL_FUNC_core_vset_error(in); 275 1.1 christos break; 276 1.1 christos case OSSL_FUNC_BIO_VSNPRINTF: 277 1.1 christos c_BIO_vsnprintf = OSSL_FUNC_BIO_vsnprintf(in); 278 1.1 christos break; 279 1.1 christos default: 280 1.1 christos /* Just ignore anything we don't understand */ 281 1.1 christos break; 282 1.1 christos } 283 1.1 christos } 284 1.1 christos 285 1.1 christos /* 286 1.1 christos * We want to test that libcrypto doesn't use the file and func pointers 287 1.1 christos * that we provide to it via c_set_error_debug beyond the time that they 288 1.1 christos * are valid for. Therefore we dynamically allocate these strings now and 289 1.1 christos * free them again when the provider is torn down. If anything tries to 290 1.1 christos * use those strings after that point there will be a use-after-free and 291 1.1 christos * asan will complain (and hence the tests will fail). 292 1.1 christos * This file isn't linked against libcrypto, so we use malloc and strdup 293 1.1 christos * instead of OPENSSL_malloc and OPENSSL_strdup 294 1.1 christos */ 295 1.1 christos ctx = malloc(sizeof(*ctx)); 296 1.1 christos if (ctx == NULL) 297 1.1 christos return 0; 298 1.1 christos ctx->thisfile = strdup(OPENSSL_FILE); 299 1.1 christos ctx->thisfunc = strdup(OPENSSL_FUNC); 300 1.1 christos ctx->handle = handle; 301 1.1 christos #ifdef PROVIDER_INIT_FUNCTION_NAME 302 1.1 christos /* We only do this if we are linked with libcrypto */ 303 1.1 christos ctx->libctx = OSSL_LIB_CTX_new_child(handle, oin); 304 1.1 christos if (ctx->libctx == NULL) { 305 1.1 christos /* We set error "2" for a failure to create the child libctx*/ 306 1.1 christos p_set_error(ERR_LIB_PROV, 2, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc, 307 1.1.1.2 christos NULL); 308 1.1 christos p_teardown(ctx); 309 1.1 christos return 0; 310 1.1 christos } 311 1.1 christos /* 312 1.1 christos * The default provider is loaded - but the default properties should not 313 1.1 christos * allow its use. 314 1.1 christos */ 315 1.1 christos { 316 1.1 christos EVP_MD *sha256 = EVP_MD_fetch(ctx->libctx, "SHA2-256", NULL); 317 1.1 christos if (sha256 != NULL) { 318 1.1 christos EVP_MD_free(sha256); 319 1.1 christos p_teardown(ctx); 320 1.1 christos return 0; 321 1.1 christos } 322 1.1 christos } 323 1.1 christos #endif 324 1.1 christos 325 1.1 christos /* 326 1.1 christos * Set a spurious error to check error handling works correctly. This will 327 1.1 christos * be ignored 328 1.1 christos */ 329 1.1 christos p_set_error(ERR_LIB_PROV, 1, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc, NULL); 330 1.1 christos 331 1.1 christos *provctx = (void *)ctx; 332 1.1 christos *out = p_test_table; 333 1.1 christos return 1; 334 1.1 christos } 335 1.1 christos 336 1.1 christos static void p_teardown(void *provctx) 337 1.1 christos { 338 1.1 christos P_TEST_CTX *ctx = (P_TEST_CTX *)provctx; 339 1.1 christos 340 1.1 christos #ifdef PROVIDER_INIT_FUNCTION_NAME 341 1.1 christos OSSL_LIB_CTX_free(ctx->libctx); 342 1.1 christos #endif 343 1.1 christos free(ctx->thisfile); 344 1.1 christos free(ctx->thisfunc); 345 1.1 christos free(ctx); 346 1.1 christos } 347