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