mirror of
https://github.com/openssl/openssl.git
synced 2024-11-23 10:03:32 +08:00
Add support for loading root CAs from Windows crypto API
Fixes #18020. Reviewed-by: Richard Levitte <levitte@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18070)
This commit is contained in:
parent
021859bf81
commit
606e0426a1
24
CHANGES.md
24
CHANGES.md
@ -179,12 +179,24 @@ OpenSSL 3.1
|
|||||||
|
|
||||||
*Hugo Landau*
|
*Hugo Landau*
|
||||||
|
|
||||||
* The `SSL_CERT_URI` environment variable has been added, which can be used
|
* The `SSL_CERT_PATH` and `SSL_CERT_URI` environment variables are introduced.
|
||||||
to specify a default URI for certificate stores. Previously, the
|
`SSL_CERT_URI` can be used to specify a URI for a root certificate store. The
|
||||||
`SSL_CERT_DIR` environment variable was used for this purpose, and could
|
`SSL_CERT_PATH` environment variable specifies a delimiter-separated list of
|
||||||
accept either a URI or a delimiter-separated list of paths. This usage is now
|
paths which are searched for root certificates.
|
||||||
deprecated; to specify a delimiter-separated list of paths, use
|
|
||||||
`SSL_CERT_DIR`, and to specify a URI, use `SSL_CERT_URI`.
|
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*
|
*Hugo Landau*
|
||||||
|
|
||||||
|
@ -417,6 +417,7 @@ my @disablables = (
|
|||||||
"cached-fetch",
|
"cached-fetch",
|
||||||
"camellia",
|
"camellia",
|
||||||
"capieng",
|
"capieng",
|
||||||
|
"winstore",
|
||||||
"cast",
|
"cast",
|
||||||
"chacha",
|
"chacha",
|
||||||
"cmac",
|
"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});
|
push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
|
||||||
|
|
||||||
# Get the extra flags used when building shared libraries and modules. We
|
# Get the extra flags used when building shared libraries and modules. We
|
||||||
|
@ -88,15 +88,14 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
|
|||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case X509_L_ADD_DIR:
|
case X509_L_ADD_DIR:
|
||||||
if (argl == X509_FILETYPE_DEFAULT) {
|
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());
|
||||||
|
|
||||||
/*
|
/* Fallback to SSL_CERT_DIR. */
|
||||||
* If SSL_CERT_DIR seems to specify a URI, don't process it as a
|
if (dir == NULL)
|
||||||
* directory.
|
dir = ossl_safe_getenv(X509_get_default_cert_dir_env());
|
||||||
*/
|
|
||||||
if (dir != NULL && ossl_is_uri(dir))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
/* Fallback to built-in default. */
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
dir = X509_get_default_cert_dir();
|
dir = X509_get_default_cert_dir();
|
||||||
|
|
||||||
|
@ -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());
|
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 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());
|
argp = ossl_safe_getenv(X509_get_default_cert_dir_env());
|
||||||
if (argp != NULL && !ossl_is_uri(argp))
|
|
||||||
argp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fallback to default store URI. */
|
/* Fallback to default store URI. */
|
||||||
if (argp == NULL)
|
if (argp == NULL)
|
||||||
|
@ -42,6 +42,11 @@ const char *X509_get_default_cert_uri_env(void)
|
|||||||
return X509_CERT_URI_EVP;
|
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)
|
const char *X509_get_default_cert_dir_env(void)
|
||||||
{
|
{
|
||||||
return X509_CERT_DIR_EVP;
|
return X509_CERT_DIR_EVP;
|
||||||
|
@ -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
|
GENERATE[html/man3/X509_get0_uids.html]=man3/X509_get0_uids.pod
|
||||||
DEPEND[man/man3/X509_get0_uids.3]=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
|
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
|
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
|
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
|
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_notBefore.html \
|
||||||
html/man3/X509_get0_signature.html \
|
html/man3/X509_get0_signature.html \
|
||||||
html/man3/X509_get0_uids.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_extension_flags.html \
|
||||||
html/man3/X509_get_pubkey.html \
|
html/man3/X509_get_pubkey.html \
|
||||||
html/man3/X509_get_serialNumber.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_notBefore.3 \
|
||||||
man/man3/X509_get0_signature.3 \
|
man/man3/X509_get0_signature.3 \
|
||||||
man/man3/X509_get0_uids.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_extension_flags.3 \
|
||||||
man/man3/X509_get_pubkey.3 \
|
man/man3/X509_get_pubkey.3 \
|
||||||
man/man3/X509_get_serialNumber.3 \
|
man/man3/X509_get_serialNumber.3 \
|
||||||
|
113
doc/man3/X509_get_default_cert_file.pod
Normal file
113
doc/man3/X509_get_default_cert_file.pod
Normal file
@ -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 <openssl/x509.h>
|
||||||
|
|
||||||
|
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<X509_LOOKUP(3)>,
|
||||||
|
L<SSL_CTX_set_default_verify_file(3)>,
|
||||||
|
L<SSL_CTX_set_default_verify_dir(3)>,
|
||||||
|
L<SSL_CTX_set_default_verify_store(3)>,
|
||||||
|
L<SSL_CTX_load_verify_file(3)>,
|
||||||
|
L<SSL_CTX_load_verify_dir(3)>,
|
||||||
|
L<SSL_CTX_load_verify_store(3)>,
|
||||||
|
L<SSL_CTX_load_verify_locations(3)>
|
||||||
|
|
||||||
|
=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<https://www.openssl.org/source/license.html>.
|
||||||
|
|
||||||
|
=cut
|
@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# 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"
|
# include "internal/nelem.h"
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#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"
|
# define CTLOG_FILE "OSSL$DATAROOT:[000000]ct_log_list.cnf"
|
||||||
# endif
|
# 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_URI_EVP "SSL_CERT_URI"
|
||||||
|
# define X509_CERT_PATH_EVP "SSL_CERT_PATH"
|
||||||
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
|
# define X509_CERT_DIR_EVP "SSL_CERT_DIR"
|
||||||
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
|
# define X509_CERT_FILE_EVP "SSL_CERT_FILE"
|
||||||
# define CTLOG_FILE_EVP "CTLOG_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] == '/';
|
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
|
#endif
|
||||||
|
@ -249,7 +249,7 @@ FILE *__iob_func();
|
|||||||
/***********************************************/
|
/***********************************************/
|
||||||
|
|
||||||
# if defined(OPENSSL_SYS_WINDOWS)
|
# 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 open _open
|
||||||
# define fdopen _fdopen
|
# define fdopen _fdopen
|
||||||
# define close _close
|
# define close _close
|
||||||
|
@ -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_dir(void);
|
||||||
const char *X509_get_default_cert_file(void);
|
const char *X509_get_default_cert_file(void);
|
||||||
const char *X509_get_default_cert_uri_env(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_dir_env(void);
|
||||||
const char *X509_get_default_cert_file_env(void);
|
const char *X509_get_default_cert_file_env(void);
|
||||||
const char *X509_get_default_private_dir(void);
|
const char *X509_get_default_private_dir(void);
|
||||||
|
@ -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_pem_to_der_decoder_functions[];
|
||||||
|
|
||||||
extern const OSSL_DISPATCH ossl_file_store_functions[];
|
extern const OSSL_DISPATCH ossl_file_store_functions[];
|
||||||
|
extern const OSSL_DISPATCH ossl_winstore_store_functions[];
|
||||||
|
@ -4,3 +4,6 @@
|
|||||||
$STORE_GOAL=../../libdefault.a
|
$STORE_GOAL=../../libdefault.a
|
||||||
|
|
||||||
SOURCE[$STORE_GOAL]=file_store.c file_store_any2obj.c
|
SOURCE[$STORE_GOAL]=file_store.c file_store_any2obj.c
|
||||||
|
IF[{- !$disabled{winstore} -}]
|
||||||
|
SOURCE[$STORE_GOAL]=winstore_store.c
|
||||||
|
ENDIF
|
||||||
|
327
providers/implementations/storemgmt/winstore_store.c
Normal file
327
providers/implementations/storemgmt/winstore_store.c
Normal file
@ -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 <openssl/store.h>
|
||||||
|
#include <openssl/core_dispatch.h>
|
||||||
|
#include <openssl/core_names.h>
|
||||||
|
#include <openssl/core_object.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/params.h>
|
||||||
|
#include <openssl/decoder.h>
|
||||||
|
#include <openssl/proverr.h>
|
||||||
|
#include <openssl/store.h> /* 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 <wincrypt.h>
|
||||||
|
|
||||||
|
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 },
|
||||||
|
};
|
@ -12,3 +12,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
STORE("file", "yes", ossl_file_store_functions)
|
STORE("file", "yes", ossl_file_store_functions)
|
||||||
|
#ifndef OPENSSL_NO_WINSTORE
|
||||||
|
STORE("org.openssl.winstore", "yes", ossl_winstore_store_functions)
|
||||||
|
#endif
|
||||||
|
@ -5456,3 +5456,6 @@ BIO_meth_get_sendmmsg ? 3_1_0 EXIST::FUNCTION:
|
|||||||
BIO_meth_set_recvmmsg ? 3_1_0 EXIST::FUNCTION:
|
BIO_meth_set_recvmmsg ? 3_1_0 EXIST::FUNCTION:
|
||||||
BIO_meth_get_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
|
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:
|
||||||
|
@ -1312,10 +1312,6 @@ X509_get0_trust_objects(3)
|
|||||||
X509_get1_email(3)
|
X509_get1_email(3)
|
||||||
X509_get1_ocsp(3)
|
X509_get1_ocsp(3)
|
||||||
X509_get_default_cert_area(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_default_private_dir(3)
|
||||||
X509_get_pubkey_parameters(3)
|
X509_get_pubkey_parameters(3)
|
||||||
X509_get_signature_type(3)
|
X509_get_signature_type(3)
|
||||||
|
Loading…
Reference in New Issue
Block a user