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