2 * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 /* This file has quite some overlap with engines/e_loader_attic.c */
14 #include <ctype.h> /* isdigit */
17 #include <openssl/core_dispatch.h>
18 #include <openssl/core_names.h>
19 #include <openssl/core_object.h>
20 #include <openssl/bio.h>
21 #include <openssl/err.h>
22 #include <openssl/params.h>
23 #include <openssl/decoder.h>
24 #include <openssl/proverr.h>
25 #include <openssl/store.h> /* The OSSL_STORE_INFO type numbers */
26 #include "internal/cryptlib.h"
27 #include "internal/o_dir.h"
28 #include "crypto/decoder.h"
29 #include "crypto/ctype.h" /* ossl_isdigit() */
30 #include "prov/implementations.h"
32 #include "file_store_local.h"
34 DEFINE_STACK_OF(OSSL_STORE_INFO
)
41 # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
44 static OSSL_FUNC_store_open_fn file_open
;
45 static OSSL_FUNC_store_attach_fn file_attach
;
46 static OSSL_FUNC_store_settable_ctx_params_fn file_settable_ctx_params
;
47 static OSSL_FUNC_store_set_ctx_params_fn file_set_ctx_params
;
48 static OSSL_FUNC_store_load_fn file_load
;
49 static OSSL_FUNC_store_eof_fn file_eof
;
50 static OSSL_FUNC_store_close_fn file_close
;
53 * This implementation makes full use of OSSL_DECODER, and then some.
54 * It uses its own internal decoder implementation that reads DER and
55 * passes that on to the data callback; this decoder is created with
56 * internal OpenSSL functions, thereby bypassing the need for a surrounding
57 * provider. This is ok, since this is a local decoder, not meant for
58 * public consumption. It also uses the libcrypto internal decoder
59 * setup function ossl_decoder_ctx_setup_for_pkey(), to allow the
60 * last resort decoder to be added first (and thereby be executed last).
61 * Finally, it sets up its own construct and cleanup functions.
63 * Essentially, that makes this implementation a kind of glorified decoder.
68 char *uri
; /* The URI we currently try to load */
70 IS_FILE
= 0, /* Read file and pass results */
71 IS_DIR
/* Pass directory entry names */
75 /* Used with |IS_FILE| */
79 OSSL_DECODER_CTX
*decoderctx
;
81 char *propq
; /* The properties we got as a parameter */
84 /* Used with |IS_DIR| */
90 * When a search expression is given, these are filled in.
91 * |search_name| contains the file basename to look for.
92 * The string is exactly 8 characters long.
97 * The directory reading utility we have combines opening with
98 * reading the first name. To make sure we can detect the end
99 * at the right time, we read early and cache the name.
101 const char *last_entry
;
106 /* Expected object type. May be unspecified */
110 static void free_file_ctx(struct file_ctx_st
*ctx
)
115 OPENSSL_free(ctx
->uri
);
116 if (ctx
->type
!= IS_DIR
) {
117 OSSL_DECODER_CTX_free(ctx
->_
.file
.decoderctx
);
118 OPENSSL_free(ctx
->_
.file
.propq
);
119 OPENSSL_free(ctx
->_
.file
.input_type
);
124 static struct file_ctx_st
*new_file_ctx(int type
, const char *uri
,
127 struct file_ctx_st
*ctx
= NULL
;
129 if ((ctx
= OPENSSL_zalloc(sizeof(*ctx
))) != NULL
130 && (uri
== NULL
|| (ctx
->uri
= OPENSSL_strdup(uri
)) != NULL
)) {
132 ctx
->provctx
= provctx
;
139 static OSSL_DECODER_CONSTRUCT file_load_construct
;
140 static OSSL_DECODER_CLEANUP file_load_cleanup
;
143 * Opening / attaching streams and directories
144 * -------------------------------------------
148 * Function to service both file_open() and file_attach()
152 static struct file_ctx_st
*file_open_stream(BIO
*source
, const char *uri
,
155 struct file_ctx_st
*ctx
;
157 if ((ctx
= new_file_ctx(IS_FILE
, uri
, provctx
)) == NULL
) {
158 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
162 ctx
->_
.file
.file
= source
;
170 static void *file_open_dir(const char *path
, const char *uri
, void *provctx
)
172 struct file_ctx_st
*ctx
;
174 if ((ctx
= new_file_ctx(IS_DIR
, uri
, provctx
)) == NULL
) {
175 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
179 ctx
->_
.dir
.last_entry
= OPENSSL_DIR_read(&ctx
->_
.dir
.ctx
, path
);
180 ctx
->_
.dir
.last_errno
= errno
;
181 if (ctx
->_
.dir
.last_entry
== NULL
) {
182 if (ctx
->_
.dir
.last_errno
!= 0) {
183 ERR_raise_data(ERR_LIB_SYS
, ctx
->_
.dir
.last_errno
,
184 "Calling OPENSSL_DIR_read(\"%s\")", path
);
187 ctx
->_
.dir
.end_reached
= 1;
195 static void *file_open(void *provctx
, const char *uri
)
197 struct file_ctx_st
*ctx
= NULL
;
201 unsigned int check_absolute
:1;
203 size_t path_data_n
= 0, i
;
204 const char *path
, *p
= uri
, *q
;
210 * First step, just take the URI as is.
212 path_data
[path_data_n
].check_absolute
= 0;
213 path_data
[path_data_n
++].path
= uri
;
216 * Second step, if the URI appears to start with the "file" scheme,
217 * extract the path and make that the second path to check.
218 * There's a special case if the URI also contains an authority, then
219 * the full URI shouldn't be used as a path anywhere.
221 if (CHECK_AND_SKIP_CASE_PREFIX(p
, "file:")) {
223 if (CHECK_AND_SKIP_CASE_PREFIX(q
, "//")) {
224 path_data_n
--; /* Invalidate using the full URI */
225 if (CHECK_AND_SKIP_CASE_PREFIX(q
, "localhost/")
226 || CHECK_AND_SKIP_CASE_PREFIX(q
, "/")) {
229 ERR_clear_last_mark();
230 ERR_raise(ERR_LIB_PROV
, PROV_R_URI_AUTHORITY_UNSUPPORTED
);
235 path_data
[path_data_n
].check_absolute
= 1;
237 /* Windows "file:" URIs with a drive letter start with a '/' */
238 if (p
[0] == '/' && p
[2] == ':' && p
[3] == '/') {
239 char c
= tolower(p
[1]);
241 if (c
>= 'a' && c
<= 'z') {
243 /* We know it's absolute, so no need to check */
244 path_data
[path_data_n
].check_absolute
= 0;
248 path_data
[path_data_n
++].path
= p
;
252 for (i
= 0, path
= NULL
; path
== NULL
&& i
< path_data_n
; i
++) {
254 * If the scheme "file" was an explicit part of the URI, the path must
255 * be absolute. So says RFC 8089
257 if (path_data
[i
].check_absolute
&& path_data
[i
].path
[0] != '/') {
258 ERR_clear_last_mark();
259 ERR_raise_data(ERR_LIB_PROV
, PROV_R_PATH_MUST_BE_ABSOLUTE
,
260 "Given path=%s", path_data
[i
].path
);
264 if (stat(path_data
[i
].path
, &st
) < 0) {
265 ERR_raise_data(ERR_LIB_SYS
, errno
,
269 path
= path_data
[i
].path
;
273 ERR_clear_last_mark();
277 /* Successfully found a working path, clear possible collected errors */
280 if (S_ISDIR(st
.st_mode
))
281 ctx
= file_open_dir(path
, uri
, provctx
);
282 else if ((bio
= BIO_new_file(path
, "rb")) == NULL
283 || (ctx
= file_open_stream(bio
, uri
, provctx
)) == NULL
)
289 void *file_attach(void *provctx
, OSSL_CORE_BIO
*cin
)
291 struct file_ctx_st
*ctx
;
292 BIO
*new_bio
= ossl_bio_new_from_core_bio(provctx
, cin
);
297 ctx
= file_open_stream(new_bio
, NULL
, provctx
);
308 static const OSSL_PARAM
*file_settable_ctx_params(void *provctx
)
310 static const OSSL_PARAM known_settable_ctx_params
[] = {
311 OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES
, NULL
, 0),
312 OSSL_PARAM_int(OSSL_STORE_PARAM_EXPECT
, NULL
),
313 OSSL_PARAM_octet_string(OSSL_STORE_PARAM_SUBJECT
, NULL
, 0),
314 OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE
, NULL
, 0),
317 return known_settable_ctx_params
;
320 static int file_set_ctx_params(void *loaderctx
, const OSSL_PARAM params
[])
322 struct file_ctx_st
*ctx
= loaderctx
;
328 if (ctx
->type
!= IS_DIR
) {
329 /* these parameters are ignored for directories */
330 p
= OSSL_PARAM_locate_const(params
, OSSL_STORE_PARAM_PROPERTIES
);
332 OPENSSL_free(ctx
->_
.file
.propq
);
333 ctx
->_
.file
.propq
= NULL
;
334 if (!OSSL_PARAM_get_utf8_string(p
, &ctx
->_
.file
.propq
, 0))
337 p
= OSSL_PARAM_locate_const(params
, OSSL_STORE_PARAM_INPUT_TYPE
);
339 OPENSSL_free(ctx
->_
.file
.input_type
);
340 ctx
->_
.file
.input_type
= NULL
;
341 if (!OSSL_PARAM_get_utf8_string(p
, &ctx
->_
.file
.input_type
, 0))
345 p
= OSSL_PARAM_locate_const(params
, OSSL_STORE_PARAM_EXPECT
);
346 if (p
!= NULL
&& !OSSL_PARAM_get_int(p
, &ctx
->expected_type
))
348 p
= OSSL_PARAM_locate_const(params
, OSSL_STORE_PARAM_SUBJECT
);
350 const unsigned char *der
= NULL
;
352 X509_NAME
*x509_name
;
356 if (ctx
->type
!= IS_DIR
) {
357 ERR_raise(ERR_LIB_PROV
,
358 PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES
);
362 if (!OSSL_PARAM_get_octet_string_ptr(p
, (const void **)&der
, &der_len
)
363 || (x509_name
= d2i_X509_NAME(NULL
, &der
, der_len
)) == NULL
)
365 hash
= X509_NAME_hash_ex(x509_name
,
366 ossl_prov_ctx_get0_libctx(ctx
->provctx
), NULL
,
368 BIO_snprintf(ctx
->_
.dir
.search_name
, sizeof(ctx
->_
.dir
.search_name
),
370 X509_NAME_free(x509_name
);
378 * Loading an object from a stream
379 * -------------------------------
382 struct file_load_data_st
{
383 OSSL_CALLBACK
*object_cb
;
387 static int file_load_construct(OSSL_DECODER_INSTANCE
*decoder_inst
,
388 const OSSL_PARAM
*params
, void *construct_data
)
390 struct file_load_data_st
*data
= construct_data
;
393 * At some point, we may find it justifiable to recognise PKCS#12 and
394 * handle it specially here, making |file_load()| return pass its
395 * contents one piece at ta time, like |e_loader_attic.c| does.
397 * However, that currently means parsing them out, which converts the
398 * DER encoded PKCS#12 into a bunch of EVP_PKEYs and X509s, just to
399 * have to re-encode them into DER to create an object abstraction for
401 * It's much simpler (less churn) to pass on the object abstraction we
402 * get to the load_result callback and leave it to that one to do the
403 * work. If that's libcrypto code, we know that it has much better
404 * possibilities to handle the EVP_PKEYs and X509s without the extra
408 return data
->object_cb(params
, data
->object_cbarg
);
411 void file_load_cleanup(void *construct_data
)
416 static int file_setup_decoders(struct file_ctx_st
*ctx
)
418 OSSL_LIB_CTX
*libctx
= ossl_prov_ctx_get0_libctx(ctx
->provctx
);
419 const OSSL_ALGORITHM
*to_algo
= NULL
;
422 /* Setup for this session, so only if not already done */
423 if (ctx
->_
.file
.decoderctx
== NULL
) {
424 if ((ctx
->_
.file
.decoderctx
= OSSL_DECODER_CTX_new()) == NULL
) {
425 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
429 /* Make sure the input type is set */
430 if (!OSSL_DECODER_CTX_set_input_type(ctx
->_
.file
.decoderctx
,
431 ctx
->_
.file
.input_type
)) {
432 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
437 * Where applicable, set the outermost structure name.
438 * The goal is to avoid the STORE object types that are
439 * potentially password protected but aren't interesting
442 switch (ctx
->expected_type
) {
443 case OSSL_STORE_INFO_CERT
:
444 if (!OSSL_DECODER_CTX_set_input_structure(ctx
->_
.file
.decoderctx
,
446 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
450 case OSSL_STORE_INFO_CRL
:
451 if (!OSSL_DECODER_CTX_set_input_structure(ctx
->_
.file
.decoderctx
,
452 "CertificateList")) {
453 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
461 for (to_algo
= ossl_any_to_obj_algorithm
;
462 to_algo
->algorithm_names
!= NULL
;
464 OSSL_DECODER
*to_obj
= NULL
;
465 OSSL_DECODER_INSTANCE
*to_obj_inst
= NULL
;
468 * Create the internal last resort decoder implementation
469 * together with a "decoder instance".
470 * The decoder doesn't need any identification or to be
471 * attached to any provider, since it's only used locally.
473 to_obj
= ossl_decoder_from_algorithm(0, to_algo
, NULL
);
475 to_obj_inst
= ossl_decoder_instance_new(to_obj
, ctx
->provctx
);
476 OSSL_DECODER_free(to_obj
);
477 if (to_obj_inst
== NULL
)
480 if (!ossl_decoder_ctx_add_decoder_inst(ctx
->_
.file
.decoderctx
,
482 ossl_decoder_instance_free(to_obj_inst
);
483 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
487 /* Add on the usual extra decoders */
488 if (!OSSL_DECODER_CTX_add_extra(ctx
->_
.file
.decoderctx
,
489 libctx
, ctx
->_
.file
.propq
)) {
490 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
495 * Then install our constructor hooks, which just passes decoded
496 * data to the load callback
498 if (!OSSL_DECODER_CTX_set_construct(ctx
->_
.file
.decoderctx
,
500 || !OSSL_DECODER_CTX_set_cleanup(ctx
->_
.file
.decoderctx
,
501 file_load_cleanup
)) {
502 ERR_raise(ERR_LIB_PROV
, ERR_R_OSSL_DECODER_LIB
);
512 static int file_load_file(struct file_ctx_st
*ctx
,
513 OSSL_CALLBACK
*object_cb
, void *object_cbarg
,
514 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
516 struct file_load_data_st data
;
519 /* Setup the decoders (one time shot per session */
521 if (!file_setup_decoders(ctx
))
524 /* Setup for this object */
526 data
.object_cb
= object_cb
;
527 data
.object_cbarg
= object_cbarg
;
528 OSSL_DECODER_CTX_set_construct_data(ctx
->_
.file
.decoderctx
, &data
);
529 OSSL_DECODER_CTX_set_passphrase_cb(ctx
->_
.file
.decoderctx
, pw_cb
, pw_cbarg
);
534 ret
= OSSL_DECODER_from_bio(ctx
->_
.file
.decoderctx
, ctx
->_
.file
.file
);
535 if (BIO_eof(ctx
->_
.file
.file
)
536 && ((err
= ERR_peek_last_error()) != 0)
537 && ERR_GET_LIB(err
) == ERR_LIB_OSSL_DECODER
538 && ERR_GET_REASON(err
) == ERR_R_UNSUPPORTED
)
541 ERR_clear_last_mark();
546 * Loading a name object from a directory
547 * --------------------------------------
550 static char *file_name_to_uri(struct file_ctx_st
*ctx
, const char *name
)
554 assert(name
!= NULL
);
556 const char *pathsep
= ossl_ends_with_dirsep(ctx
->uri
) ? "" : "/";
557 long calculated_length
= strlen(ctx
->uri
) + strlen(pathsep
)
558 + strlen(name
) + 1 /* \0 */;
560 data
= OPENSSL_zalloc(calculated_length
);
562 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
566 OPENSSL_strlcat(data
, ctx
->uri
, calculated_length
);
567 OPENSSL_strlcat(data
, pathsep
, calculated_length
);
568 OPENSSL_strlcat(data
, name
, calculated_length
);
573 static int file_name_check(struct file_ctx_st
*ctx
, const char *name
)
575 const char *p
= NULL
;
576 size_t len
= strlen(ctx
->_
.dir
.search_name
);
578 /* If there are no search criteria, all names are accepted */
579 if (ctx
->_
.dir
.search_name
[0] == '\0')
582 /* If the expected type isn't supported, no name is accepted */
583 if (ctx
->expected_type
!= 0
584 && ctx
->expected_type
!= OSSL_STORE_INFO_CERT
585 && ctx
->expected_type
!= OSSL_STORE_INFO_CRL
)
589 * First, check the basename
591 if (OPENSSL_strncasecmp(name
, ctx
->_
.dir
.search_name
, len
) != 0
597 * Then, if the expected type is a CRL, check that the extension starts
602 if (ctx
->expected_type
!= 0
603 && ctx
->expected_type
!= OSSL_STORE_INFO_CRL
)
605 } else if (ctx
->expected_type
== OSSL_STORE_INFO_CRL
) {
610 * Last, check that the rest of the extension is a decimal number, at
611 * least one digit long.
620 * One extra step here, check for a possible generation number.
623 for (p
++; *p
!= '\0'; p
++)
624 if (!ossl_isdigit(*p
))
629 * If we've reached the end of the string at this point, we've successfully
630 * found a fitting file name.
635 static int file_load_dir_entry(struct file_ctx_st
*ctx
,
636 OSSL_CALLBACK
*object_cb
, void *object_cbarg
,
637 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
639 /* Prepare as much as possible in advance */
640 static const int object_type
= OSSL_OBJECT_NAME
;
641 OSSL_PARAM object
[] = {
642 OSSL_PARAM_int(OSSL_OBJECT_PARAM_TYPE
, (int *)&object_type
),
643 OSSL_PARAM_utf8_string(OSSL_OBJECT_PARAM_DATA
, NULL
, 0),
646 char *newname
= NULL
;
649 /* Loop until we get an error or until we have a suitable name */
651 if (ctx
->_
.dir
.last_entry
== NULL
) {
652 if (!ctx
->_
.dir
.end_reached
) {
653 assert(ctx
->_
.dir
.last_errno
!= 0);
654 ERR_raise(ERR_LIB_SYS
, ctx
->_
.dir
.last_errno
);
656 /* file_eof() will tell if EOF was reached */
660 /* flag acceptable names */
661 if (ctx
->_
.dir
.last_entry
[0] != '.'
662 && file_name_check(ctx
, ctx
->_
.dir
.last_entry
)) {
664 /* If we can't allocate the new name, we fail */
666 file_name_to_uri(ctx
, ctx
->_
.dir
.last_entry
)) == NULL
)
671 * On the first call (with a NULL context), OPENSSL_DIR_read()
672 * cares about the second argument. On the following calls, it
673 * only cares that it isn't NULL. Therefore, we can safely give
676 ctx
->_
.dir
.last_entry
= OPENSSL_DIR_read(&ctx
->_
.dir
.ctx
, ctx
->uri
);
677 ctx
->_
.dir
.last_errno
= errno
;
678 if (ctx
->_
.dir
.last_entry
== NULL
&& ctx
->_
.dir
.last_errno
== 0)
679 ctx
->_
.dir
.end_reached
= 1;
680 } while (newname
== NULL
);
682 object
[1].data
= newname
;
683 object
[1].data_size
= strlen(newname
);
684 ok
= object_cb(object
, object_cbarg
);
685 OPENSSL_free(newname
);
690 * Loading, local dispatcher
691 * -------------------------
694 static int file_load(void *loaderctx
,
695 OSSL_CALLBACK
*object_cb
, void *object_cbarg
,
696 OSSL_PASSPHRASE_CALLBACK
*pw_cb
, void *pw_cbarg
)
698 struct file_ctx_st
*ctx
= loaderctx
;
702 return file_load_file(ctx
, object_cb
, object_cbarg
, pw_cb
, pw_cbarg
);
705 file_load_dir_entry(ctx
, object_cb
, object_cbarg
, pw_cb
, pw_cbarg
);
710 /* ctx->type has an unexpected value */
716 * Eof detection and closing
717 * -------------------------
720 static int file_eof(void *loaderctx
)
722 struct file_ctx_st
*ctx
= loaderctx
;
726 return ctx
->_
.dir
.end_reached
;
729 * BIO_pending() checks any filter BIO.
730 * BIO_eof() checks the source BIO.
732 return !BIO_pending(ctx
->_
.file
.file
)
733 && BIO_eof(ctx
->_
.file
.file
);
736 /* ctx->type has an unexpected value */
741 static int file_close_dir(struct file_ctx_st
*ctx
)
743 if (ctx
->_
.dir
.ctx
!= NULL
)
744 OPENSSL_DIR_end(&ctx
->_
.dir
.ctx
);
749 static int file_close_stream(struct file_ctx_st
*ctx
)
752 * This frees either the provider BIO filter (for file_attach()) OR
753 * the allocated file BIO (for file_open()).
755 BIO_free(ctx
->_
.file
.file
);
756 ctx
->_
.file
.file
= NULL
;
762 static int file_close(void *loaderctx
)
764 struct file_ctx_st
*ctx
= loaderctx
;
768 return file_close_dir(ctx
);
770 return file_close_stream(ctx
);
773 /* ctx->type has an unexpected value */
778 const OSSL_DISPATCH ossl_file_store_functions
[] = {
779 { OSSL_FUNC_STORE_OPEN
, (void (*)(void))file_open
},
780 { OSSL_FUNC_STORE_ATTACH
, (void (*)(void))file_attach
},
781 { OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS
,
782 (void (*)(void))file_settable_ctx_params
},
783 { OSSL_FUNC_STORE_SET_CTX_PARAMS
, (void (*)(void))file_set_ctx_params
},
784 { OSSL_FUNC_STORE_LOAD
, (void (*)(void))file_load
},
785 { OSSL_FUNC_STORE_EOF
, (void (*)(void))file_eof
},
786 { OSSL_FUNC_STORE_CLOSE
, (void (*)(void))file_close
},