1 /*
2 * Copyright 2016-2024 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 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13
14 /* We need to use some STORE deprecated APIs */
15 #define OPENSSL_SUPPRESS_DEPRECATED
16
17 #include "internal/e_os.h"
18
19 #include <openssl/crypto.h>
20 #include <openssl/err.h>
21 #include <openssl/trace.h>
22 #include <openssl/core_names.h>
23 #include <openssl/provider.h>
24 #include <openssl/param_build.h>
25 #include <openssl/store.h>
26 #include "internal/thread_once.h"
27 #include "internal/cryptlib.h"
28 #include "internal/provider.h"
29 #include "internal/bio.h"
30 #include "crypto/store.h"
31 #include "store_local.h"
32
33 static int ossl_store_close_it(OSSL_STORE_CTX *ctx);
34
loader_set_params(OSSL_STORE_LOADER * loader,OSSL_STORE_LOADER_CTX * loader_ctx,const OSSL_PARAM params[],const char * propq)35 static int loader_set_params(OSSL_STORE_LOADER *loader,
36 OSSL_STORE_LOADER_CTX *loader_ctx,
37 const OSSL_PARAM params[], const char *propq)
38 {
39 if (params != NULL) {
40 if (!loader->p_set_ctx_params(loader_ctx, params))
41 return 0;
42 }
43
44 if (propq != NULL) {
45 OSSL_PARAM propp[2];
46
47 if (OSSL_PARAM_locate_const(params,
48 OSSL_STORE_PARAM_PROPERTIES) != NULL)
49 /* use the propq from params */
50 return 1;
51
52 propp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
53 (char *)propq, 0);
54 propp[1] = OSSL_PARAM_construct_end();
55
56 if (!loader->p_set_ctx_params(loader_ctx, propp))
57 return 0;
58 }
59 return 1;
60 }
61
62 OSSL_STORE_CTX *
OSSL_STORE_open_ex(const char * uri,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[],OSSL_STORE_post_process_info_fn post_process,void * post_process_data)63 OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
64 const UI_METHOD *ui_method, void *ui_data,
65 const OSSL_PARAM params[],
66 OSSL_STORE_post_process_info_fn post_process,
67 void *post_process_data)
68 {
69 struct ossl_passphrase_data_st pwdata = { 0 };
70 const OSSL_STORE_LOADER *loader = NULL;
71 OSSL_STORE_LOADER *fetched_loader = NULL;
72 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
73 OSSL_STORE_CTX *ctx = NULL;
74 char *propq_copy = NULL;
75 int no_loader_found = 1;
76 char scheme_copy[256], *p, *schemes[2], *scheme = NULL;
77 size_t schemes_n = 0;
78 size_t i;
79
80 /*
81 * Put the file scheme first. If the uri does represent an existing file,
82 * possible device name and all, then it should be loaded. Only a failed
83 * attempt at loading a local file should have us try something else.
84 */
85 schemes[schemes_n++] = "file";
86
87 /*
88 * Now, check if we have something that looks like a scheme, and add it
89 * as a second scheme. However, also check if there's an authority start
90 * (://), because that will invalidate the previous file scheme. Also,
91 * check that this isn't actually the file scheme, as there's no point
92 * going through that one twice!
93 */
94 OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
95 if ((p = strchr(scheme_copy, ':')) != NULL) {
96 *p++ = '\0';
97 if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
98 if (HAS_PREFIX(p, "//"))
99 schemes_n--; /* Invalidate the file scheme */
100 schemes[schemes_n++] = scheme_copy;
101 }
102 }
103
104 ERR_set_mark();
105
106 if (ui_method != NULL
107 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
108 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
109 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
110 goto err;
111 }
112
113 /*
114 * Try each scheme until we find one that could open the URI.
115 *
116 * For each scheme, we look for the engine implementation first, and
117 * failing that, we then try to fetch a provided implementation.
118 * This is consistent with how we handle legacy / engine implementations
119 * elsewhere.
120 */
121 for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
122 scheme = schemes[i];
123 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
124 #ifndef OPENSSL_NO_DEPRECATED_3_0
125 ERR_set_mark();
126 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) {
127 ERR_clear_last_mark();
128 no_loader_found = 0;
129 if (loader->open_ex != NULL)
130 loader_ctx = loader->open_ex(loader, uri, libctx, propq,
131 ui_method, ui_data);
132 else
133 loader_ctx = loader->open(loader, uri, ui_method, ui_data);
134 } else {
135 ERR_pop_to_mark();
136 }
137 #endif
138 if (loader == NULL
139 && (fetched_loader =
140 OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
141 const OSSL_PROVIDER *provider =
142 OSSL_STORE_LOADER_get0_provider(fetched_loader);
143 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
144
145 no_loader_found = 0;
146 if (fetched_loader->p_open_ex != NULL) {
147 loader_ctx =
148 fetched_loader->p_open_ex(provctx, uri, params,
149 ossl_pw_passphrase_callback_dec,
150 &pwdata);
151 } else {
152 if (fetched_loader->p_open != NULL &&
153 (loader_ctx = fetched_loader->p_open(provctx, uri)) != NULL &&
154 !loader_set_params(fetched_loader, loader_ctx,
155 params, propq)) {
156 (void)fetched_loader->p_close(loader_ctx);
157 loader_ctx = NULL;
158 }
159 }
160 if (loader_ctx == NULL) {
161 OSSL_STORE_LOADER_free(fetched_loader);
162 fetched_loader = NULL;
163 }
164 loader = fetched_loader;
165
166 /* Clear any internally cached passphrase */
167 (void)ossl_pw_clear_passphrase_cache(&pwdata);
168 }
169 }
170
171 if (no_loader_found)
172 /*
173 * It's assumed that ossl_store_get0_loader_int() and
174 * OSSL_STORE_LOADER_fetch() report their own errors
175 */
176 goto err;
177
178 OSSL_TRACE1(STORE, "Found loader for scheme %s\n", scheme);
179
180 if (loader_ctx == NULL)
181 /*
182 * It's assumed that the loader's open() method reports its own
183 * errors
184 */
185 goto err;
186
187 OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx);
188
189 if ((propq != NULL && (propq_copy = OPENSSL_strdup(propq)) == NULL)
190 || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
191 goto err;
192
193 ctx->properties = propq_copy;
194 ctx->fetched_loader = fetched_loader;
195 ctx->loader = loader;
196 ctx->loader_ctx = loader_ctx;
197 ctx->post_process = post_process;
198 ctx->post_process_data = post_process_data;
199 ctx->pwdata = pwdata;
200
201 /*
202 * If the attempt to open with the 'file' scheme loader failed and the
203 * other scheme loader succeeded, the failure to open with the 'file'
204 * scheme loader leaves an error on the error stack. Let's remove it.
205 */
206 ERR_pop_to_mark();
207
208 return ctx;
209
210 err:
211 ERR_clear_last_mark();
212 if (loader_ctx != NULL) {
213 /*
214 * Temporary structure so OSSL_STORE_close() can work even when
215 * |ctx| couldn't be allocated properly
216 */
217 OSSL_STORE_CTX tmpctx = { NULL, };
218
219 tmpctx.fetched_loader = fetched_loader;
220 tmpctx.loader = loader;
221 tmpctx.loader_ctx = loader_ctx;
222
223 /*
224 * We ignore a returned error because we will return NULL anyway in
225 * this case, so if something goes wrong when closing, that'll simply
226 * just add another entry on the error stack.
227 */
228 (void)ossl_store_close_it(&tmpctx);
229 }
230 /* Coverity false positive, the reference counting is confusing it */
231 /* coverity[pass_freed_arg] */
232 OSSL_STORE_LOADER_free(fetched_loader);
233 OPENSSL_free(propq_copy);
234 OPENSSL_free(ctx);
235 return NULL;
236 }
237
OSSL_STORE_open(const char * uri,const UI_METHOD * ui_method,void * ui_data,OSSL_STORE_post_process_info_fn post_process,void * post_process_data)238 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
239 const UI_METHOD *ui_method, void *ui_data,
240 OSSL_STORE_post_process_info_fn post_process,
241 void *post_process_data)
242 {
243 return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, NULL,
244 post_process, post_process_data);
245 }
246
247 #ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_STORE_ctrl(OSSL_STORE_CTX * ctx,int cmd,...)248 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
249 {
250 va_list args;
251 int ret;
252
253 va_start(args, cmd);
254 ret = OSSL_STORE_vctrl(ctx, cmd, args);
255 va_end(args);
256
257 return ret;
258 }
259
OSSL_STORE_vctrl(OSSL_STORE_CTX * ctx,int cmd,va_list args)260 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
261 {
262 if (ctx->fetched_loader != NULL) {
263 if (ctx->fetched_loader->p_set_ctx_params != NULL) {
264 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
265
266 switch (cmd) {
267 case OSSL_STORE_C_USE_SECMEM:
268 {
269 int on = *(va_arg(args, int *));
270
271 params[0] = OSSL_PARAM_construct_int("use_secmem", &on);
272 }
273 break;
274 default:
275 break;
276 }
277
278 return ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
279 params);
280 }
281 } else if (ctx->loader->ctrl != NULL) {
282 return ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
283 }
284
285 /*
286 * If the fetched loader doesn't have a set_ctx_params or a ctrl, it's as
287 * if there was one that ignored our params, which usually returns 1.
288 */
289 return 1;
290 }
291 #endif
292
OSSL_STORE_expect(OSSL_STORE_CTX * ctx,int expected_type)293 int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
294 {
295 int ret = 1;
296
297 if (ctx == NULL
298 || expected_type < 0 || expected_type > OSSL_STORE_INFO_CRL) {
299 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
300 return 0;
301 }
302 if (ctx->loading) {
303 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
304 return 0;
305 }
306
307 ctx->expected_type = expected_type;
308 if (ctx->fetched_loader != NULL
309 && ctx->fetched_loader->p_set_ctx_params != NULL) {
310 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
311
312 params[0] =
313 OSSL_PARAM_construct_int(OSSL_STORE_PARAM_EXPECT, &expected_type);
314 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx, params);
315 }
316 #ifndef OPENSSL_NO_DEPRECATED_3_0
317 if (ctx->fetched_loader == NULL
318 && ctx->loader->expect != NULL) {
319 ret = ctx->loader->expect(ctx->loader_ctx, expected_type);
320 }
321 #endif
322 return ret;
323 }
324
OSSL_STORE_find(OSSL_STORE_CTX * ctx,const OSSL_STORE_SEARCH * search)325 int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
326 {
327 int ret = 1;
328
329 if (ctx->loading) {
330 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
331 return 0;
332 }
333 if (search == NULL) {
334 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
335 return 0;
336 }
337
338 if (ctx->fetched_loader != NULL) {
339 OSSL_PARAM_BLD *bld;
340 OSSL_PARAM *params;
341 /* OSSL_STORE_SEARCH_BY_NAME, OSSL_STORE_SEARCH_BY_ISSUER_SERIAL*/
342 void *name_der = NULL;
343 int name_der_sz;
344 /* OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */
345 BIGNUM *number = NULL;
346
347 if (ctx->fetched_loader->p_set_ctx_params == NULL) {
348 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
349 return 0;
350 }
351
352 if ((bld = OSSL_PARAM_BLD_new()) == NULL) {
353 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
354 return 0;
355 }
356
357 ret = 0; /* Assume the worst */
358
359 switch (search->search_type) {
360 case OSSL_STORE_SEARCH_BY_NAME:
361 if ((name_der_sz = i2d_X509_NAME(search->name,
362 (unsigned char **)&name_der)) > 0
363 && OSSL_PARAM_BLD_push_octet_string(bld,
364 OSSL_STORE_PARAM_SUBJECT,
365 name_der, name_der_sz))
366 ret = 1;
367 break;
368 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
369 if ((name_der_sz = i2d_X509_NAME(search->name,
370 (unsigned char **)&name_der)) > 0
371 && (number = ASN1_INTEGER_to_BN(search->serial, NULL)) != NULL
372 && OSSL_PARAM_BLD_push_octet_string(bld,
373 OSSL_STORE_PARAM_ISSUER,
374 name_der, name_der_sz)
375 && OSSL_PARAM_BLD_push_BN(bld, OSSL_STORE_PARAM_SERIAL,
376 number))
377 ret = 1;
378 break;
379 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
380 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_DIGEST,
381 EVP_MD_get0_name(search->digest),
382 0)
383 && OSSL_PARAM_BLD_push_octet_string(bld,
384 OSSL_STORE_PARAM_FINGERPRINT,
385 search->string,
386 search->stringlength))
387 ret = 1;
388 break;
389 case OSSL_STORE_SEARCH_BY_ALIAS:
390 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_ALIAS,
391 (char *)search->string,
392 search->stringlength))
393 ret = 1;
394 break;
395 }
396 if (ret) {
397 params = OSSL_PARAM_BLD_to_param(bld);
398 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
399 params);
400 OSSL_PARAM_free(params);
401 }
402 OSSL_PARAM_BLD_free(bld);
403 OPENSSL_free(name_der);
404 BN_free(number);
405 } else {
406 #ifndef OPENSSL_NO_DEPRECATED_3_0
407 /* legacy loader section */
408 if (ctx->loader->find == NULL) {
409 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
410 return 0;
411 }
412 ret = ctx->loader->find(ctx->loader_ctx, search);
413 #endif
414 }
415
416 return ret;
417 }
418
OSSL_STORE_load(OSSL_STORE_CTX * ctx)419 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
420 {
421 OSSL_STORE_INFO *v = NULL;
422
423 ctx->loading = 1;
424 again:
425 if (OSSL_STORE_eof(ctx))
426 return NULL;
427
428 if (ctx->loader != NULL)
429 OSSL_TRACE(STORE, "Loading next object\n");
430
431 if (ctx->cached_info != NULL
432 && sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
433 sk_OSSL_STORE_INFO_free(ctx->cached_info);
434 ctx->cached_info = NULL;
435 }
436
437 if (ctx->cached_info != NULL) {
438 v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
439 } else {
440 if (ctx->fetched_loader != NULL) {
441 struct ossl_load_result_data_st load_data;
442
443 load_data.v = NULL;
444 load_data.ctx = ctx;
445 ctx->error_flag = 0;
446
447 if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
448 ossl_store_handle_load_result,
449 &load_data,
450 ossl_pw_passphrase_callback_dec,
451 &ctx->pwdata)) {
452 ctx->error_flag = 1;
453 return NULL;
454 }
455 v = load_data.v;
456 }
457 #ifndef OPENSSL_NO_DEPRECATED_3_0
458 if (ctx->fetched_loader == NULL)
459 v = ctx->loader->load(ctx->loader_ctx,
460 ctx->pwdata._.ui_method.ui_method,
461 ctx->pwdata._.ui_method.ui_method_data);
462 #endif
463 }
464
465 if (ctx->post_process != NULL && v != NULL) {
466 v = ctx->post_process(v, ctx->post_process_data);
467
468 /*
469 * By returning NULL, the callback decides that this object should
470 * be ignored.
471 */
472 if (v == NULL)
473 goto again;
474 }
475
476 /* Clear any internally cached passphrase */
477 (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
478
479 if (v != NULL && ctx->expected_type != 0) {
480 int returned_type = OSSL_STORE_INFO_get_type(v);
481
482 if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) {
483 if (ctx->expected_type != returned_type) {
484 OSSL_STORE_INFO_free(v);
485 goto again;
486 }
487 }
488 }
489
490 if (v != NULL)
491 OSSL_TRACE1(STORE, "Got a %s\n",
492 OSSL_STORE_INFO_type_string(OSSL_STORE_INFO_get_type(v)));
493
494 return v;
495 }
496
OSSL_STORE_delete(const char * uri,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[])497 int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
498 const UI_METHOD *ui_method, void *ui_data,
499 const OSSL_PARAM params[])
500 {
501 OSSL_STORE_LOADER *fetched_loader = NULL;
502 char scheme[256], *p;
503 int res = 0;
504 struct ossl_passphrase_data_st pwdata = {0};
505
506 OPENSSL_strlcpy(scheme, uri, sizeof(scheme));
507 if ((p = strchr(scheme, ':')) != NULL)
508 *p++ = '\0';
509 else /* We don't work without explicit scheme */
510 return 0;
511
512 if (ui_method != NULL
513 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
514 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
515 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
516 return 0;
517 }
518
519 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
520 fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq);
521
522 if (fetched_loader != NULL && fetched_loader->p_delete != NULL) {
523 const OSSL_PROVIDER *provider =
524 OSSL_STORE_LOADER_get0_provider(fetched_loader);
525 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
526
527 /*
528 * It's assumed that the loader's delete() method reports its own
529 * errors
530 */
531 OSSL_TRACE1(STORE, "Performing URI delete %s\n", uri);
532 res = fetched_loader->p_delete(provctx, uri, params,
533 ossl_pw_passphrase_callback_dec,
534 &pwdata);
535 }
536 /* Clear any internally cached passphrase */
537 (void)ossl_pw_clear_passphrase_cache(&pwdata);
538
539 OSSL_STORE_LOADER_free(fetched_loader);
540
541 return res;
542 }
543
OSSL_STORE_error(OSSL_STORE_CTX * ctx)544 int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
545 {
546 int ret = 1;
547
548 if (ctx->fetched_loader != NULL)
549 ret = ctx->error_flag;
550 #ifndef OPENSSL_NO_DEPRECATED_3_0
551 if (ctx->fetched_loader == NULL)
552 ret = ctx->loader->error(ctx->loader_ctx);
553 #endif
554 return ret;
555 }
556
OSSL_STORE_eof(OSSL_STORE_CTX * ctx)557 int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
558 {
559 int ret = 1;
560
561 if (ctx->fetched_loader != NULL)
562 ret = ctx->loader->p_eof(ctx->loader_ctx);
563 #ifndef OPENSSL_NO_DEPRECATED_3_0
564 if (ctx->fetched_loader == NULL)
565 ret = ctx->loader->eof(ctx->loader_ctx);
566 #endif
567 return ret != 0;
568 }
569
ossl_store_close_it(OSSL_STORE_CTX * ctx)570 static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
571 {
572 int ret = 0;
573
574 if (ctx == NULL)
575 return 1;
576 OSSL_TRACE1(STORE, "Closing %p\n", (void *)ctx->loader_ctx);
577
578 if (ctx->fetched_loader != NULL)
579 ret = ctx->loader->p_close(ctx->loader_ctx);
580 #ifndef OPENSSL_NO_DEPRECATED_3_0
581 if (ctx->fetched_loader == NULL)
582 ret = ctx->loader->closefn(ctx->loader_ctx);
583 #endif
584
585 sk_OSSL_STORE_INFO_pop_free(ctx->cached_info, OSSL_STORE_INFO_free);
586 OSSL_STORE_LOADER_free(ctx->fetched_loader);
587 OPENSSL_free(ctx->properties);
588 ossl_pw_clear_passphrase_data(&ctx->pwdata);
589 return ret;
590 }
591
OSSL_STORE_close(OSSL_STORE_CTX * ctx)592 int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
593 {
594 int ret = ossl_store_close_it(ctx);
595
596 OPENSSL_free(ctx);
597 return ret;
598 }
599
600 /*
601 * Functions to generate OSSL_STORE_INFOs, one function for each type we
602 * support having in them as well as a generic constructor.
603 *
604 * In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
605 * and will therefore be freed when the OSSL_STORE_INFO is freed.
606 */
OSSL_STORE_INFO_new(int type,void * data)607 OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data)
608 {
609 OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
610
611 if (info == NULL)
612 return NULL;
613
614 info->type = type;
615 info->_.data = data;
616 return info;
617 }
618
OSSL_STORE_INFO_new_NAME(char * name)619 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
620 {
621 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL);
622
623 if (info == NULL) {
624 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
625 return NULL;
626 }
627
628 info->_.name.name = name;
629 info->_.name.desc = NULL;
630
631 return info;
632 }
633
OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO * info,char * desc)634 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
635 {
636 if (info->type != OSSL_STORE_INFO_NAME) {
637 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
638 return 0;
639 }
640
641 info->_.name.desc = desc;
642
643 return 1;
644 }
OSSL_STORE_INFO_new_PARAMS(EVP_PKEY * params)645 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
646 {
647 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params);
648
649 if (info == NULL)
650 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
651 return info;
652 }
653
OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY * pkey)654 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
655 {
656 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey);
657
658 if (info == NULL)
659 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
660 return info;
661 }
662
OSSL_STORE_INFO_new_PKEY(EVP_PKEY * pkey)663 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
664 {
665 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey);
666
667 if (info == NULL)
668 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
669 return info;
670 }
671
OSSL_STORE_INFO_new_CERT(X509 * x509)672 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
673 {
674 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509);
675
676 if (info == NULL)
677 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
678 return info;
679 }
680
OSSL_STORE_INFO_new_CRL(X509_CRL * crl)681 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
682 {
683 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl);
684
685 if (info == NULL)
686 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
687 return info;
688 }
689
690 /*
691 * Functions to try to extract data from an OSSL_STORE_INFO.
692 */
OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO * info)693 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
694 {
695 return info->type;
696 }
697
OSSL_STORE_INFO_get0_data(int type,const OSSL_STORE_INFO * info)698 void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info)
699 {
700 if (info->type == type)
701 return info->_.data;
702 return NULL;
703 }
704
OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO * info)705 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
706 {
707 if (info->type == OSSL_STORE_INFO_NAME)
708 return info->_.name.name;
709 return NULL;
710 }
711
OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO * info)712 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
713 {
714 if (info->type == OSSL_STORE_INFO_NAME)
715 return OPENSSL_strdup(info->_.name.name);
716 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
717 return NULL;
718 }
719
OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO * info)720 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
721 {
722 if (info->type == OSSL_STORE_INFO_NAME)
723 return info->_.name.desc;
724 return NULL;
725 }
726
OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO * info)727 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
728 {
729 if (info->type == OSSL_STORE_INFO_NAME)
730 return OPENSSL_strdup(info->_.name.desc ? info->_.name.desc : "");
731 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
732 return NULL;
733 }
734
OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO * info)735 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
736 {
737 if (info->type == OSSL_STORE_INFO_PARAMS)
738 return info->_.params;
739 return NULL;
740 }
741
OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO * info)742 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
743 {
744 if (info->type == OSSL_STORE_INFO_PARAMS) {
745 EVP_PKEY_up_ref(info->_.params);
746 return info->_.params;
747 }
748 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS);
749 return NULL;
750 }
751
OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO * info)752 EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info)
753 {
754 if (info->type == OSSL_STORE_INFO_PUBKEY)
755 return info->_.pubkey;
756 return NULL;
757 }
758
OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO * info)759 EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info)
760 {
761 if (info->type == OSSL_STORE_INFO_PUBKEY) {
762 EVP_PKEY_up_ref(info->_.pubkey);
763 return info->_.pubkey;
764 }
765 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY);
766 return NULL;
767 }
768
OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO * info)769 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
770 {
771 if (info->type == OSSL_STORE_INFO_PKEY)
772 return info->_.pkey;
773 return NULL;
774 }
775
OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO * info)776 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
777 {
778 if (info->type == OSSL_STORE_INFO_PKEY) {
779 EVP_PKEY_up_ref(info->_.pkey);
780 return info->_.pkey;
781 }
782 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY);
783 return NULL;
784 }
785
OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO * info)786 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
787 {
788 if (info->type == OSSL_STORE_INFO_CERT)
789 return info->_.x509;
790 return NULL;
791 }
792
OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO * info)793 X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
794 {
795 if (info->type == OSSL_STORE_INFO_CERT) {
796 X509_up_ref(info->_.x509);
797 return info->_.x509;
798 }
799 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE);
800 return NULL;
801 }
802
OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO * info)803 X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
804 {
805 if (info->type == OSSL_STORE_INFO_CRL)
806 return info->_.crl;
807 return NULL;
808 }
809
OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO * info)810 X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
811 {
812 if (info->type == OSSL_STORE_INFO_CRL) {
813 X509_CRL_up_ref(info->_.crl);
814 return info->_.crl;
815 }
816 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL);
817 return NULL;
818 }
819
820 /*
821 * Free the OSSL_STORE_INFO
822 */
OSSL_STORE_INFO_free(OSSL_STORE_INFO * info)823 void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
824 {
825 if (info != NULL) {
826 switch (info->type) {
827 case OSSL_STORE_INFO_NAME:
828 OPENSSL_free(info->_.name.name);
829 OPENSSL_free(info->_.name.desc);
830 break;
831 case OSSL_STORE_INFO_PARAMS:
832 EVP_PKEY_free(info->_.params);
833 break;
834 case OSSL_STORE_INFO_PUBKEY:
835 EVP_PKEY_free(info->_.pubkey);
836 break;
837 case OSSL_STORE_INFO_PKEY:
838 EVP_PKEY_free(info->_.pkey);
839 break;
840 case OSSL_STORE_INFO_CERT:
841 X509_free(info->_.x509);
842 break;
843 case OSSL_STORE_INFO_CRL:
844 X509_CRL_free(info->_.crl);
845 break;
846 }
847 OPENSSL_free(info);
848 }
849 }
850
OSSL_STORE_supports_search(OSSL_STORE_CTX * ctx,int search_type)851 int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
852 {
853 int ret = 0;
854
855 if (ctx->fetched_loader != NULL) {
856 void *provctx =
857 ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
858 const OSSL_PARAM *params;
859 const OSSL_PARAM *p_subject = NULL;
860 const OSSL_PARAM *p_issuer = NULL;
861 const OSSL_PARAM *p_serial = NULL;
862 const OSSL_PARAM *p_fingerprint = NULL;
863 const OSSL_PARAM *p_alias = NULL;
864
865 if (ctx->fetched_loader->p_settable_ctx_params == NULL)
866 return 0;
867
868 params = ctx->fetched_loader->p_settable_ctx_params(provctx);
869 p_subject = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
870 p_issuer = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ISSUER);
871 p_serial = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SERIAL);
872 p_fingerprint =
873 OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_FINGERPRINT);
874 p_alias = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ALIAS);
875
876 switch (search_type) {
877 case OSSL_STORE_SEARCH_BY_NAME:
878 ret = (p_subject != NULL);
879 break;
880 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
881 ret = (p_issuer != NULL && p_serial != NULL);
882 break;
883 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
884 ret = (p_fingerprint != NULL);
885 break;
886 case OSSL_STORE_SEARCH_BY_ALIAS:
887 ret = (p_alias != NULL);
888 break;
889 }
890 }
891 #ifndef OPENSSL_NO_DEPRECATED_3_0
892 if (ctx->fetched_loader == NULL) {
893 OSSL_STORE_SEARCH tmp_search;
894
895 if (ctx->loader->find == NULL)
896 return 0;
897 tmp_search.search_type = search_type;
898 ret = ctx->loader->find(NULL, &tmp_search);
899 }
900 #endif
901 return ret;
902 }
903
904 /* Search term constructors */
OSSL_STORE_SEARCH_by_name(X509_NAME * name)905 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
906 {
907 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
908
909 if (search == NULL)
910 return NULL;
911
912 search->search_type = OSSL_STORE_SEARCH_BY_NAME;
913 search->name = name;
914 return search;
915 }
916
OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME * name,const ASN1_INTEGER * serial)917 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
918 const ASN1_INTEGER *serial)
919 {
920 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
921
922 if (search == NULL)
923 return NULL;
924
925 search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
926 search->name = name;
927 search->serial = serial;
928 return search;
929 }
930
OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD * digest,const unsigned char * bytes,size_t len)931 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
932 const unsigned char
933 *bytes, size_t len)
934 {
935 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
936 int md_size;
937
938 if (search == NULL)
939 return NULL;
940
941 md_size = EVP_MD_get_size(digest);
942 if (md_size <= 0) {
943 OPENSSL_free(search);
944 return NULL;
945 }
946
947 if (digest != NULL && len != (size_t)md_size) {
948 ERR_raise_data(ERR_LIB_OSSL_STORE,
949 OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
950 "%s size is %d, fingerprint size is %zu",
951 EVP_MD_get0_name(digest), md_size, len);
952 OPENSSL_free(search);
953 return NULL;
954 }
955
956 search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
957 search->digest = digest;
958 search->string = bytes;
959 search->stringlength = len;
960 return search;
961 }
962
OSSL_STORE_SEARCH_by_alias(const char * alias)963 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
964 {
965 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
966
967 if (search == NULL)
968 return NULL;
969
970 search->search_type = OSSL_STORE_SEARCH_BY_ALIAS;
971 search->string = (const unsigned char *)alias;
972 search->stringlength = strlen(alias);
973 return search;
974 }
975
976 /* Search term destructor */
OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH * search)977 void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search)
978 {
979 OPENSSL_free(search);
980 }
981
982 /* Search term accessors */
OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH * criterion)983 int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
984 {
985 return criterion->search_type;
986 }
987
OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH * criterion)988 X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion)
989 {
990 return criterion->name;
991 }
992
OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH * criterion)993 const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
994 *criterion)
995 {
996 return criterion->serial;
997 }
998
OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH * criterion,size_t * length)999 const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
1000 *criterion, size_t *length)
1001 {
1002 *length = criterion->stringlength;
1003 return criterion->string;
1004 }
1005
OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH * criterion)1006 const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion)
1007 {
1008 return (const char *)criterion->string;
1009 }
1010
OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH * criterion)1011 const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
1012 {
1013 return criterion->digest;
1014 }
1015
OSSL_STORE_attach(BIO * bp,const char * scheme,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[],OSSL_STORE_post_process_info_fn post_process,void * post_process_data)1016 OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
1017 OSSL_LIB_CTX *libctx, const char *propq,
1018 const UI_METHOD *ui_method, void *ui_data,
1019 const OSSL_PARAM params[],
1020 OSSL_STORE_post_process_info_fn post_process,
1021 void *post_process_data)
1022 {
1023 const OSSL_STORE_LOADER *loader = NULL;
1024 OSSL_STORE_LOADER *fetched_loader = NULL;
1025 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
1026 OSSL_STORE_CTX *ctx = NULL;
1027
1028 if (scheme == NULL)
1029 scheme = "file";
1030
1031 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
1032 ERR_set_mark();
1033 #ifndef OPENSSL_NO_DEPRECATED_3_0
1034 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL)
1035 loader_ctx = loader->attach(loader, bp, libctx, propq,
1036 ui_method, ui_data);
1037 #endif
1038 if (loader == NULL
1039 && (fetched_loader =
1040 OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
1041 const OSSL_PROVIDER *provider =
1042 OSSL_STORE_LOADER_get0_provider(fetched_loader);
1043 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
1044 OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
1045
1046 if (cbio == NULL
1047 || fetched_loader->p_attach == NULL
1048 || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
1049 OSSL_STORE_LOADER_free(fetched_loader);
1050 fetched_loader = NULL;
1051 } else if (!loader_set_params(fetched_loader, loader_ctx,
1052 params, propq)) {
1053 (void)fetched_loader->p_close(loader_ctx);
1054 OSSL_STORE_LOADER_free(fetched_loader);
1055 fetched_loader = NULL;
1056 }
1057 loader = fetched_loader;
1058 ossl_core_bio_free(cbio);
1059 }
1060
1061 if (loader_ctx == NULL) {
1062 ERR_clear_last_mark();
1063 return NULL;
1064 }
1065
1066 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
1067 ERR_clear_last_mark();
1068 return NULL;
1069 }
1070
1071 if (ui_method != NULL
1072 && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
1073 ERR_clear_last_mark();
1074 OPENSSL_free(ctx);
1075 return NULL;
1076 }
1077
1078 ctx->fetched_loader = fetched_loader;
1079 ctx->loader = loader;
1080 ctx->loader_ctx = loader_ctx;
1081 ctx->post_process = post_process;
1082 ctx->post_process_data = post_process_data;
1083
1084 /*
1085 * ossl_store_get0_loader_int will raise an error if the loader for
1086 * the scheme cannot be retrieved. But if a loader was successfully
1087 * fetched then we remove this error from the error stack.
1088 */
1089 ERR_pop_to_mark();
1090
1091 return ctx;
1092 }
1093