1 | /*
|
---|
2 | * Copyright 2019-2022 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 "internal/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 | }
|
---|