From 606e0426a148034c8c131de9f31f7d3e38be99ea Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 8 Apr 2022 13:20:44 +0100 Subject: [PATCH] Add support for loading root CAs from Windows crypto API Fixes #18020. Reviewed-by: Richard Levitte Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/18070) --- CHANGES.md | 24 +- Configure | 7 + crypto/x509/by_dir.c | 13 +- crypto/x509/by_store.c | 5 +- crypto/x509/x509_def.c | 5 + doc/build.info | 6 + doc/man3/X509_get_default_cert_file.pod | 113 ++++++ include/internal/common.h | 22 +- include/internal/e_os.h | 2 +- include/openssl/x509.h.in | 1 + .../include/prov/implementations.h | 1 + .../implementations/storemgmt/build.info | 3 + .../storemgmt/winstore_store.c | 327 ++++++++++++++++++ providers/stores.inc | 3 + util/libcrypto.num | 3 + util/missingcrypto.txt | 4 - 16 files changed, 504 insertions(+), 35 deletions(-) create mode 100644 doc/man3/X509_get_default_cert_file.pod create mode 100644 providers/implementations/storemgmt/winstore_store.c diff --git a/CHANGES.md b/CHANGES.md index 5a5bc9d91f..9bc1a91c94 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -179,12 +179,24 @@ OpenSSL 3.1 *Hugo Landau* - * The `SSL_CERT_URI` environment variable has been added, which can be used - to specify a default URI for certificate stores. Previously, the - `SSL_CERT_DIR` environment variable was used for this purpose, and could - accept either a URI or a delimiter-separated list of paths. This usage is now - deprecated; to specify a delimiter-separated list of paths, use - `SSL_CERT_DIR`, and to specify a URI, use `SSL_CERT_URI`. + * The `SSL_CERT_PATH` and `SSL_CERT_URI` environment variables are introduced. + `SSL_CERT_URI` can be used to specify a URI for a root certificate store. The + `SSL_CERT_PATH` environment variable specifies a delimiter-separated list of + paths which are searched for root certificates. + + The existing `SSL_CERT_DIR` environment variable is deprecated. + `SSL_CERT_DIR` was previously used to specify either a delimiter-separated + list of paths or an URI, which is ambiguous. Setting `SSL_CERT_PATH` causes + `SSL_CERT_DIR` to be ignored for the purposes of determining root certificate + directories, and setting `SSL_CERT_URI` causes `SSL_CERT_DIR` to be ignored + for the purposes of determining root certificate stores. + + *Hugo Landau* + + * Support for loading root certificates from the Windows certificate store + has been added. The support is in the form of a store which recognises the + URI string of `org.openssl.winstore://`. This store is enabled by default and + can be disabled using the new compile-time option `no-winstore`. *Hugo Landau* diff --git a/Configure b/Configure index b5ee68d54d..066ff1833e 100755 --- a/Configure +++ b/Configure @@ -417,6 +417,7 @@ my @disablables = ( "cached-fetch", "camellia", "capieng", + "winstore", "cast", "chacha", "cmac", @@ -1731,6 +1732,12 @@ unless ($disabled{ktls}) { } } +unless ($disabled{winstore}) { + unless ($target =~ /^(?:Cygwin|mingw|VC-|BC-)/) { + disable('not-windows', 'winstore'); + } +} + push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); # Get the extra flags used when building shared libraries and modules. We diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index e63686784d..8d61c27d70 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -88,15 +88,14 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, switch (cmd) { case X509_L_ADD_DIR: if (argl == X509_FILETYPE_DEFAULT) { - const char *dir = ossl_safe_getenv(X509_get_default_cert_dir_env()); + /* If SSL_CERT_PATH is provided and non-empty, use that. */ + const char *dir = ossl_safe_getenv(X509_get_default_cert_path_env()); - /* - * If SSL_CERT_DIR seems to specify a URI, don't process it as a - * directory. - */ - if (dir != NULL && ossl_is_uri(dir)) - return 0; + /* Fallback to SSL_CERT_DIR. */ + if (dir == NULL) + dir = ossl_safe_getenv(X509_get_default_cert_dir_env()); + /* Fallback to built-in default. */ if (dir == NULL) dir = X509_get_default_cert_dir(); diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c index 8c7ae83fae..96bd46d602 100644 --- a/crypto/x509/by_store.c +++ b/crypto/x509/by_store.c @@ -116,11 +116,8 @@ static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp, argp = ossl_safe_getenv(X509_get_default_cert_uri_env()); /* If not set, see if we have a URI in the older cert dir envvar. */ - if (argp == NULL) { + if (argp == NULL) argp = ossl_safe_getenv(X509_get_default_cert_dir_env()); - if (argp != NULL && !ossl_is_uri(argp)) - argp = NULL; - } /* Fallback to default store URI. */ if (argp == NULL) diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c index a199cc8655..f32e28115d 100644 --- a/crypto/x509/x509_def.c +++ b/crypto/x509/x509_def.c @@ -42,6 +42,11 @@ const char *X509_get_default_cert_uri_env(void) return X509_CERT_URI_EVP; } +const char *X509_get_default_cert_path_env(void) +{ + return X509_CERT_PATH_EVP; +} + const char *X509_get_default_cert_dir_env(void) { return X509_CERT_DIR_EVP; diff --git a/doc/build.info b/doc/build.info index f6d9355ef8..6b6e837838 100644 --- a/doc/build.info +++ b/doc/build.info @@ -2775,6 +2775,10 @@ DEPEND[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod GENERATE[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod DEPEND[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod GENERATE[man/man3/X509_get0_uids.3]=man3/X509_get0_uids.pod +DEPEND[html/man3/X509_get_default_cert_file.html]=man3/X509_get_default_cert_file.pod +GENERATE[html/man3/X509_get_default_cert_file.html]=man3/X509_get_default_cert_file.pod +DEPEND[man/man3/X509_get_default_cert_file.3]=man3/X509_get_default_cert_file.pod +GENERATE[man/man3/X509_get_default_cert_file.3]=man3/X509_get_default_cert_file.pod DEPEND[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod GENERATE[html/man3/X509_get_extension_flags.html]=man3/X509_get_extension_flags.pod DEPEND[man/man3/X509_get_extension_flags.3]=man3/X509_get_extension_flags.pod @@ -3441,6 +3445,7 @@ html/man3/X509_get0_distinguishing_id.html \ html/man3/X509_get0_notBefore.html \ html/man3/X509_get0_signature.html \ html/man3/X509_get0_uids.html \ +html/man3/X509_get_default_cert_file.html \ html/man3/X509_get_extension_flags.html \ html/man3/X509_get_pubkey.html \ html/man3/X509_get_serialNumber.html \ @@ -4040,6 +4045,7 @@ man/man3/X509_get0_distinguishing_id.3 \ man/man3/X509_get0_notBefore.3 \ man/man3/X509_get0_signature.3 \ man/man3/X509_get0_uids.3 \ +man/man3/X509_get_default_cert_file.3 \ man/man3/X509_get_extension_flags.3 \ man/man3/X509_get_pubkey.3 \ man/man3/X509_get_serialNumber.3 \ diff --git a/doc/man3/X509_get_default_cert_file.pod b/doc/man3/X509_get_default_cert_file.pod new file mode 100644 index 0000000000..22e6f836cc --- /dev/null +++ b/doc/man3/X509_get_default_cert_file.pod @@ -0,0 +1,113 @@ +=pod + +=head1 NAME + +X509_get_default_cert_file, X509_get_default_cert_file_env, +X509_get_default_cert_path_env, +X509_get_default_cert_dir, X509_get_default_cert_dir_env, +X509_get_default_cert_uri, X509_get_default_cert_uri_env - +retrieve default locations for trusted CA certificates + +=head1 SYNOPSIS + + #include + + const char *X509_get_default_cert_file(void); + const char *X509_get_default_cert_dir(void); + const char *X509_get_default_cert_uri(void); + + const char *X509_get_default_cert_file_env(void); + const char *X509_get_default_cert_path_env(void); + const char *X509_get_default_cert_dir_env(void); + const char *X509_get_default_cert_uri_env(void); + +=head1 DESCRIPTION + +The X509_get_default_cert_file() function returns the default path +to a file containing trusted CA certificates. OpenSSL will use this as +the default path when it is asked to load trusted CA certificates +from a file and no other path is specified. If the file exists, CA certificates +are loaded from the file. + +The X509_get_default_cert_dir() function returns a default delimeter-separated +list of paths to a directories containing trusted CA certificates named in the +hashed format. OpenSSL will use this as the default list of paths when it is +asked to load trusted CA certificates from a directory and no other path is +specified. If a given directory in the list exists, OpenSSL attempts to lookup +CA certificates in this directory by calculating a filename based on a hash of +the certificate's subject name. + +The X509_get_default_cert_uri() function returns the default URI for a +certificate store accessed programmatically via an OpenSSL provider. If there is +no default store applicable to the system for which OpenSSL was compiled, this +returns an empty string. + +X509_get_default_cert_file_env() and X509_get_default_cert_uri_env() return +environment variable names which are recommended to specify nondefault values to +be used instead of the values returned by X509_get_default_cert_file() and +X509_get_default_cert_uri() respectively. The values returned by the latter +functions are not affected by these environment variables; you must check for +these environment variables yourself, using these functions to retrieve the +correct environment variable names. If an environment variable is not set, the +value returned by the corresponding function above should be used. + +X509_get_default_cert_path_env() returns the environment variable name which is +recommended to specify a nondefault value to be used instead of the value +returned by X509_get_default_cert_dir(). This environment variable supercedes +the deprecated environment variable whose name is returned by +X509_get_default_cert_dir_env(). This environment variable was deprecated as its +contents can be interpreted ambiguously; see NOTES. + +By default, OpenSSL uses the path list specified in the environment variable +whose name is returned by X509_get_default_cert_path_env() if it is set; +otherwise, it uses the path list specified in the environment variable whose +name is returned by X509_get_default_cert_dir_env() if it is set; otherwise, it +uses the value returned by X509_get_default_cert_dir()). + +=head1 NOTES + +X509_get_default_cert_uri(), X509_get_default_cert_uri_env() and +X509_get_default_cert_path_env() were introduced in OpenSSL 3.1. Prior to this +release, store URIs were expressed via the environment variable returned by +X509_get_default_cert_dir_env(); this environment variable could be used to +specify either a list of directories or a store URI. This creates an ambiguity +in which the environment variable returned by X509_get_default_cert_dir_env() is +interpreted both as a list of directories and as a store URI. + +This usage and the environment variable returned by +X509_get_default_cert_dir_env() are now deprecated; to specify a store URI, use +the environment variable returned by X509_get_default_cert_uri_env(), and to +specify a list of directories, use the environment variable returned by +X509_get_default_cert_path_env(). + +=head1 RETURN VALUES + +These functions return pointers to constant strings with static storage +duration. + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L, +L + +=head1 HISTORY + +X509_get_default_cert_uri(), X509_get_default_cert_path_env() and +X509_get_default_cert_uri_env() were introduced in OpenSSL 3.1. + +=head1 COPYRIGHT + +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/include/internal/common.h b/include/internal/common.h index d820f3e00d..83549737ed 100644 --- a/include/internal/common.h +++ b/include/internal/common.h @@ -13,7 +13,9 @@ # include # include -# include "internal/e_os.h" /* To get strncasecmp() on Windows */ +# include "openssl/configuration.h" + +# include "internal/e_os.h" /* ossl_inline in many files */ # include "internal/nelem.h" #ifdef NDEBUG @@ -73,9 +75,14 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, # define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf" # endif -#define X509_CERT_URI "" +#ifndef OPENSSL_NO_WINSTORE +# define X509_CERT_URI "org.openssl.winstore://" +#else +# define X509_CERT_URI "" +#endif # define X509_CERT_URI_EVP "SSL_CERT_URI" +# define X509_CERT_PATH_EVP "SSL_CERT_PATH" # define X509_CERT_DIR_EVP "SSL_CERT_DIR" # define X509_CERT_FILE_EVP "SSL_CERT_FILE" # define CTLOG_FILE_EVP "CTLOG_FILE" @@ -114,15 +121,4 @@ static ossl_inline int ossl_is_absolute_path(const char *path) return path[0] == '/'; } -static ossl_inline int ossl_is_uri(const char *s) -{ - const char *x; - for (x=s; ossl_isalnum(*x); ++x); -#ifdef _WIN32 - if (x-s <= 1) - return 0; -#endif - return x > s && HAS_PREFIX(x, "://"); -} - #endif diff --git a/include/internal/e_os.h b/include/internal/e_os.h index 1be20f61f9..8b0c3a933c 100644 --- a/include/internal/e_os.h +++ b/include/internal/e_os.h @@ -249,7 +249,7 @@ FILE *__iob_func(); /***********************************************/ # if defined(OPENSSL_SYS_WINDOWS) -# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE) +# if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(_WIN32_WCE) # define open _open # define fdopen _fdopen # define close _close diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in index b7fcf91281..204938748e 100644 --- a/include/openssl/x509.h.in +++ b/include/openssl/x509.h.in @@ -495,6 +495,7 @@ const char *X509_get_default_cert_uri(void); const char *X509_get_default_cert_dir(void); const char *X509_get_default_cert_file(void); const char *X509_get_default_cert_uri_env(void); +const char *X509_get_default_cert_path_env(void); const char *X509_get_default_cert_dir_env(void); const char *X509_get_default_cert_file_env(void); const char *X509_get_default_private_dir(void); diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 288808bb6f..a6ac602d41 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -526,3 +526,4 @@ extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_der_decoder_function extern const OSSL_DISPATCH ossl_pem_to_der_decoder_functions[]; extern const OSSL_DISPATCH ossl_file_store_functions[]; +extern const OSSL_DISPATCH ossl_winstore_store_functions[]; diff --git a/providers/implementations/storemgmt/build.info b/providers/implementations/storemgmt/build.info index 8e6445a4e7..d0b1174926 100644 --- a/providers/implementations/storemgmt/build.info +++ b/providers/implementations/storemgmt/build.info @@ -4,3 +4,6 @@ $STORE_GOAL=../../libdefault.a SOURCE[$STORE_GOAL]=file_store.c file_store_any2obj.c +IF[{- !$disabled{winstore} -}] + SOURCE[$STORE_GOAL]=winstore_store.c +ENDIF diff --git a/providers/implementations/storemgmt/winstore_store.c b/providers/implementations/storemgmt/winstore_store.c new file mode 100644 index 0000000000..f686517f74 --- /dev/null +++ b/providers/implementations/storemgmt/winstore_store.c @@ -0,0 +1,327 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* The OSSL_STORE_INFO type numbers */ +#include "internal/cryptlib.h" +#include "internal/o_dir.h" +#include "crypto/decoder.h" +#include "crypto/ctype.h" /* ossl_isdigit() */ +#include "prov/implementations.h" +#include "prov/bio.h" +#include "file_store_local.h" + +#include + +enum { + STATE_IDLE, + STATE_READ, + STATE_EOF, +}; + +struct winstore_ctx_st { + void *provctx; + char *propq; + unsigned char *subject; + size_t subject_len; + + HCERTSTORE win_store; + const CERT_CONTEXT *win_ctx; + int state; + + OSSL_DECODER_CTX *dctx; +}; + +static void winstore_win_reset(struct winstore_ctx_st *ctx) +{ + if (ctx->win_ctx != NULL) { + CertFreeCertificateContext(ctx->win_ctx); + ctx->win_ctx = NULL; + } + + ctx->state = STATE_IDLE; +} + +static void winstore_win_advance(struct winstore_ctx_st *ctx) +{ + CERT_NAME_BLOB name = {0}; + + if (ctx->state == STATE_EOF) + return; + + name.cbData = ctx->subject_len; + name.pbData = ctx->subject; + + ctx->win_ctx = (name.cbData == 0 ? NULL : + CertFindCertificateInStore(ctx->win_store, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, CERT_FIND_SUBJECT_NAME, + &name, ctx->win_ctx)); + + ctx->state = (ctx->win_ctx == NULL) ? STATE_EOF : STATE_READ; +} + +static void *winstore_open(void *provctx, const char *uri) +{ + struct winstore_ctx_st *ctx = NULL; + + if (!HAS_CASE_PREFIX(uri, "org.openssl.winstore:")) + return NULL; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->provctx = provctx; + ctx->win_store = CertOpenSystemStoreW(0, L"ROOT"); + if (ctx->win_store == NULL) { + OPENSSL_free(ctx); + return NULL; + } + + winstore_win_reset(ctx); + return ctx; +} + +static void *winstore_attach(void *provctx, OSSL_CORE_BIO *cin) +{ + return NULL; /* not supported */ +} + +static const OSSL_PARAM *winstore_settable_ctx_params(void *loaderctx, const OSSL_PARAM params[]) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_STORE_PARAM_SUBJECT, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int winstore_set_ctx_params(void *loaderctx, const OSSL_PARAM params[]) +{ + struct winstore_ctx_st *ctx = loaderctx; + const OSSL_PARAM *p; + int do_reset = 0; + + if (params == NULL) + return 1; + + p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_PROPERTIES); + if (p != NULL) { + do_reset = 1; + OPENSSL_free(ctx->propq); + ctx->propq = NULL; + if (!OSSL_PARAM_get_utf8_string(p, &ctx->propq, 0)) + return 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT); + if (p != NULL) { + const unsigned char *der = NULL; + size_t der_len = 0; + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &der_len)) + return 0; + + do_reset = 1; + + OPENSSL_free(ctx->subject); + + ctx->subject = OPENSSL_malloc(der_len); + if (ctx->subject == NULL) { + ctx->subject_len = 0; + return 0; + } + + ctx->subject_len = der_len; + memcpy(ctx->subject, der, der_len); + } + + if (do_reset) { + winstore_win_reset(ctx); + winstore_win_advance(ctx); + } + + return 1; +} + +struct load_data_st { + OSSL_CALLBACK *object_cb; + void *object_cbarg; +}; + +static int load_construct(OSSL_DECODER_INSTANCE *decoder_inst, + const OSSL_PARAM *params, void *construct_data) +{ + struct load_data_st *data = construct_data; + return data->object_cb(params, data->object_cbarg); +} + +static void load_cleanup(void *construct_data) +{ + /* No-op. */ +} + +static int setup_decoder(struct winstore_ctx_st *ctx) +{ + OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(ctx->provctx); + const OSSL_ALGORITHM *to_algo = NULL; + + if (ctx->dctx != NULL) + return 1; + + ctx->dctx = OSSL_DECODER_CTX_new(); + if (ctx->dctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!OSSL_DECODER_CTX_set_input_type(ctx->dctx, "DER")) { + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + if (!OSSL_DECODER_CTX_set_input_structure(ctx->dctx, "Certificate")) { + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + for (to_algo = ossl_any_to_obj_algorithm; + to_algo->algorithm_names != NULL; + to_algo++) { + OSSL_DECODER *to_obj = NULL; + OSSL_DECODER_INSTANCE *to_obj_inst = NULL; + + /* + * Create the internal last resort decoder implementation + * together with a "decoder instance". + * The decoder doesn't need any identification or to be + * attached to any provider, since it's only used locally. + */ + to_obj = ossl_decoder_from_algorithm(0, to_algo, NULL); + if (to_obj != NULL) + to_obj_inst = ossl_decoder_instance_new(to_obj, ctx->provctx); + + OSSL_DECODER_free(to_obj); + if (to_obj_inst == NULL) + goto err; + + if (!ossl_decoder_ctx_add_decoder_inst(ctx->dctx, + to_obj_inst)) { + ossl_decoder_instance_free(to_obj_inst); + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + } + + if (!OSSL_DECODER_CTX_add_extra(ctx->dctx, libctx, ctx->propq)) { + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + if (!OSSL_DECODER_CTX_set_construct(ctx->dctx, load_construct)) { + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + if (!OSSL_DECODER_CTX_set_cleanup(ctx->dctx, load_cleanup)) { + ERR_raise(ERR_LIB_PROV, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + return 1; + +err: + OSSL_DECODER_CTX_free(ctx->dctx); + ctx->dctx = NULL; + return 0; +} + +static int winstore_load_using(struct winstore_ctx_st *ctx, + OSSL_CALLBACK *object_cb, void *object_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg, + const void *der, size_t der_len) +{ + struct load_data_st data; + const unsigned char *der_ = der; + size_t der_len_ = der_len; + + if (setup_decoder(ctx) == 0) + return 0; + + data.object_cb = object_cb; + data.object_cbarg = object_cbarg; + + OSSL_DECODER_CTX_set_construct_data(ctx->dctx, &data); + OSSL_DECODER_CTX_set_passphrase_cb(ctx->dctx, pw_cb, pw_cbarg); + + if (OSSL_DECODER_from_data(ctx->dctx, &der_, &der_len_) == 0) + return 0; + + return 1; +} + +static int winstore_load(void *loaderctx, + OSSL_CALLBACK *object_cb, void *object_cbarg, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + int ret = 0; + struct winstore_ctx_st *ctx = loaderctx; + + if (ctx->state != STATE_READ) + return 0; + + ret = winstore_load_using(ctx, object_cb, object_cbarg, pw_cb, pw_cbarg, + ctx->win_ctx->pbCertEncoded, + ctx->win_ctx->cbCertEncoded); + + if (ret == 1) + winstore_win_advance(ctx); + + return ret; +} + +static int winstore_eof(void *loaderctx) +{ + struct winstore_ctx_st *ctx = loaderctx; + + return ctx->state != STATE_READ; +} + +static int winstore_close(void *loaderctx) +{ + struct winstore_ctx_st *ctx = loaderctx; + + winstore_win_reset(ctx); + CertCloseStore(ctx->win_store, 0); + OSSL_DECODER_CTX_free(ctx->dctx); + OPENSSL_free(ctx->propq); + OPENSSL_free(ctx->subject); + OPENSSL_free(ctx); + return 1; +} + +const OSSL_DISPATCH ossl_winstore_store_functions[] = { + { OSSL_FUNC_STORE_OPEN, (void (*)(void))winstore_open }, + { OSSL_FUNC_STORE_ATTACH, (void (*)(void))winstore_attach }, + { OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS, (void (*)(void))winstore_settable_ctx_params }, + { OSSL_FUNC_STORE_SET_CTX_PARAMS, (void (*)(void))winstore_set_ctx_params }, + { OSSL_FUNC_STORE_LOAD, (void (*)(void))winstore_load }, + { OSSL_FUNC_STORE_EOF, (void (*)(void))winstore_eof }, + { OSSL_FUNC_STORE_CLOSE, (void (*)(void))winstore_close }, + { 0, NULL }, +}; diff --git a/providers/stores.inc b/providers/stores.inc index 4c1ec8f287..526532759e 100644 --- a/providers/stores.inc +++ b/providers/stores.inc @@ -12,3 +12,6 @@ #endif STORE("file", "yes", ossl_file_store_functions) +#ifndef OPENSSL_NO_WINSTORE +STORE("org.openssl.winstore", "yes", ossl_winstore_store_functions) +#endif diff --git a/util/libcrypto.num b/util/libcrypto.num index c5d2e9a07e..82e937f60a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5456,3 +5456,6 @@ BIO_meth_get_sendmmsg ? 3_1_0 EXIST::FUNCTION: BIO_meth_set_recvmmsg ? 3_1_0 EXIST::FUNCTION: BIO_meth_get_recvmmsg ? 3_1_0 EXIST::FUNCTION: BIO_err_is_non_fatal ? 3_1_0 EXIST::FUNCTION:SOCK +X509_get_default_cert_uri ? 3_1_0 EXIST::FUNCTION: +X509_get_default_cert_uri_env ? 3_1_0 EXIST::FUNCTION: +X509_get_default_cert_path_env ? 3_1_0 EXIST::FUNCTION: diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 6a677f7aa0..be42f59aff 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -1312,10 +1312,6 @@ X509_get0_trust_objects(3) X509_get1_email(3) X509_get1_ocsp(3) X509_get_default_cert_area(3) -X509_get_default_cert_dir(3) -X509_get_default_cert_dir_env(3) -X509_get_default_cert_file(3) -X509_get_default_cert_file_env(3) X509_get_default_private_dir(3) X509_get_pubkey_parameters(3) X509_get_signature_type(3)