]>
Commit | Line | Data |
---|---|---|
021a6552 | 1 | /* |
da1c088f | 2 | * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. |
021a6552 RL |
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 | ||
d5f9166b | 29 | #include "internal/e_os.h" |
021a6552 | 30 | #include <openssl/core.h> |
23c48d94 | 31 | #include <openssl/core_dispatch.h> |
81c15ed0 | 32 | #include <openssl/err.h> |
5442611d MC |
33 | #include <openssl/evp.h> |
34 | #include <openssl/crypto.h> | |
fb9b3a7b | 35 | #include <openssl/provider.h> |
81c15ed0 MC |
36 | |
37 | typedef struct p_test_ctx { | |
38 | char *thisfile; | |
39 | char *thisfunc; | |
40 | const OSSL_CORE_HANDLE *handle; | |
5442611d | 41 | OSSL_LIB_CTX *libctx; |
81c15ed0 | 42 | } P_TEST_CTX; |
021a6552 | 43 | |
363b1e5d DMSP |
44 | static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; |
45 | static OSSL_FUNC_core_get_params_fn *c_get_params = NULL; | |
81c15ed0 MC |
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; | |
021a6552 RL |
49 | |
50 | /* Tell the core what params we provide and what type they are */ | |
26175013 RL |
51 | static const OSSL_PARAM p_param_types[] = { |
52 | { "greeting", OSSL_PARAM_UTF8_STRING, NULL, 0, 0 }, | |
5442611d | 53 | { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, |
26175013 | 54 | { NULL, 0, NULL, 0, 0 } |
021a6552 RL |
55 | }; |
56 | ||
a39eb840 | 57 | /* This is a trick to ensure we define the provider functions correctly */ |
363b1e5d DMSP |
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; | |
81c15ed0 | 61 | static OSSL_FUNC_provider_teardown_fn p_teardown; |
a39eb840 | 62 | |
52282716 MC |
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 | ||
dca97d00 | 75 | static const OSSL_PARAM *p_gettable_params(void *_) |
021a6552 RL |
76 | { |
77 | return p_param_types; | |
78 | } | |
79 | ||
81c15ed0 | 80 | static int p_get_params(void *provctx, OSSL_PARAM params[]) |
021a6552 | 81 | { |
81c15ed0 MC |
82 | P_TEST_CTX *ctx = (P_TEST_CTX *)provctx; |
83 | const OSSL_CORE_HANDLE *hand = ctx->handle; | |
4e7991b4 | 84 | OSSL_PARAM *p = params; |
021a6552 RL |
85 | int ok = 1; |
86 | ||
87 | for (; ok && p->key != NULL; p++) { | |
88 | if (strcmp(p->key, "greeting") == 0) { | |
1ccf4973 RL |
89 | static char *opensslv; |
90 | static char *provname; | |
91 | static char *greeting; | |
4e7991b4 | 92 | static OSSL_PARAM counter_request[] = { |
6d872a83 | 93 | /* Known libcrypto provided parameters */ |
e2146e12 | 94 | { "openssl-version", OSSL_PARAM_UTF8_PTR, |
4e7991b4 | 95 | &opensslv, sizeof(&opensslv), 0 }, |
e2146e12 | 96 | { "provider-name", OSSL_PARAM_UTF8_PTR, |
4e7991b4 | 97 | &provname, sizeof(&provname), 0}, |
6d872a83 RL |
98 | |
99 | /* This might be present, if there's such a configuration */ | |
100 | { "greeting", OSSL_PARAM_UTF8_PTR, | |
4e7991b4 | 101 | &greeting, sizeof(&greeting), 0 }, |
6d872a83 | 102 | |
4e7991b4 | 103 | { NULL, 0, NULL, 0, 0 } |
021a6552 RL |
104 | }; |
105 | char buf[256]; | |
106 | size_t buf_l; | |
107 | ||
1ccf4973 RL |
108 | opensslv = provname = greeting = NULL; |
109 | ||
d40b42ab | 110 | if (c_get_params(hand, counter_request)) { |
6d872a83 RL |
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 | } | |
021a6552 RL |
120 | } else { |
121 | sprintf(buf, "Howdy stranger..."); | |
122 | } | |
123 | ||
4e7991b4 | 124 | p->return_size = buf_l = strlen(buf) + 1; |
8c4412ed | 125 | if (p->data_size >= buf_l) |
f663ddc7 | 126 | strcpy(p->data, buf); |
021a6552 RL |
127 | else |
128 | ok = 0; | |
5442611d MC |
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]; | |
52282716 MC |
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 | } | |
5442611d | 156 | |
fb9b3a7b MC |
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 | */ | |
52282716 MC |
163 | if (ok |
164 | && OSSL_PROVIDER_available(ctx->libctx, "default") | |
fb9b3a7b MC |
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) { | |
5442611d MC |
170 | if (EVP_DigestInit_ex(mdctx, md4, NULL) |
171 | && EVP_DigestUpdate(mdctx, (const unsigned char *)msg, | |
172 | strlen(msg)) | |
52282716 | 173 | && EVP_DigestFinal(mdctx, out, NULL)) |
5442611d MC |
174 | digestsuccess = 1; |
175 | } | |
176 | EVP_MD_CTX_free(mdctx); | |
177 | EVP_MD_free(md4); | |
52282716 | 178 | OSSL_PROVIDER_unload(deflt); |
5442611d MC |
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 | } | |
b1c053ac MC |
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 | } | |
021a6552 RL |
202 | } |
203 | } | |
204 | return ok; | |
205 | } | |
206 | ||
551543e5 NT |
207 | static const OSSL_ITEM *p_get_reason_strings(void *_) |
208 | { | |
209 | static const OSSL_ITEM reason_strings[] = { | |
210 | {1, "dummy reason string"}, | |
fb9b3a7b MC |
211 | {2, "Can't create child library context"}, |
212 | {3, "Can't load default provider"}, | |
551543e5 NT |
213 | {0, NULL} |
214 | }; | |
215 | ||
216 | return reason_strings; | |
217 | } | |
218 | ||
021a6552 | 219 | static const OSSL_DISPATCH p_test_table[] = { |
dca97d00 | 220 | { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))p_gettable_params }, |
021a6552 | 221 | { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))p_get_params }, |
551543e5 NT |
222 | { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, |
223 | (void (*)(void))p_get_reason_strings}, | |
81c15ed0 | 224 | { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown }, |
1e6bd31e | 225 | OSSL_DISPATCH_END |
021a6552 RL |
226 | }; |
227 | ||
d40b42ab | 228 | int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, |
5442611d | 229 | const OSSL_DISPATCH *oin, |
a39eb840 RL |
230 | const OSSL_DISPATCH **out, |
231 | void **provctx) | |
021a6552 | 232 | { |
81c15ed0 | 233 | P_TEST_CTX *ctx; |
5442611d | 234 | const OSSL_DISPATCH *in = oin; |
81c15ed0 | 235 | |
021a6552 RL |
236 | for (; in->function_id != 0; in++) { |
237 | switch (in->function_id) { | |
dca97d00 | 238 | case OSSL_FUNC_CORE_GETTABLE_PARAMS: |
363b1e5d | 239 | c_gettable_params = OSSL_FUNC_core_gettable_params(in); |
021a6552 RL |
240 | break; |
241 | case OSSL_FUNC_CORE_GET_PARAMS: | |
363b1e5d | 242 | c_get_params = OSSL_FUNC_core_get_params(in); |
021a6552 | 243 | break; |
81c15ed0 MC |
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; | |
021a6552 RL |
253 | default: |
254 | /* Just ignore anything we don't understand */ | |
255 | break; | |
256 | } | |
257 | } | |
258 | ||
81c15ed0 MC |
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; | |
5442611d MC |
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) { | |
fb9b3a7b MC |
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 | } | |
18cb5c31 MC |
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 | } | |
5442611d | 297 | #endif |
81c15ed0 MC |
298 | |
299 | /* | |
300 | * Set a spurious error to check error handling works correctly. This will | |
301 | * be ignored | |
302 | */ | |
d7d8e2c8 | 303 | p_set_error(ERR_LIB_PROV, 1, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc, NULL); |
81c15ed0 MC |
304 | |
305 | *provctx = (void *)ctx; | |
021a6552 RL |
306 | *out = p_test_table; |
307 | return 1; | |
308 | } | |
81c15ed0 MC |
309 | |
310 | static void p_teardown(void *provctx) | |
311 | { | |
312 | P_TEST_CTX *ctx = (P_TEST_CTX *)provctx; | |
313 | ||
5442611d MC |
314 | #ifdef PROVIDER_INIT_FUNCTION_NAME |
315 | OSSL_LIB_CTX_free(ctx->libctx); | |
316 | #endif | |
81c15ed0 MC |
317 | free(ctx->thisfile); |
318 | free(ctx->thisfunc); | |
319 | free(ctx); | |
320 | } |