The self tests for the fips module are triggered on startup and they need to know the
core's libctx in order to function correctly. As the provider can be autoloaded via configuration
it then needs to propagate the callers libctx down to the provider via the config load.
Note that OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, ..) is still called, but will only load the default
configuration if the OPENSSL_CONF environment variable is set.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11240)
* the "CONF classic" functions, for consistency.
*/
-CONF *NCONF_new(CONF_METHOD *meth)
+CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth)
{
CONF *ret;
ret = meth->create(meth);
if (ret == NULL) {
- CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE);
+ CONFerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
+ ret->libctx = libctx;
return ret;
}
+CONF *NCONF_new(CONF_METHOD *meth)
+{
+ return NCONF_new_with_libctx(NULL, meth);
+}
+
void NCONF_free(CONF *conf)
{
if (conf == NULL)
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 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
#include <openssl/crypto.h>
#include "internal/conf.h"
#include "internal/dso.h"
+#include "internal/thread_once.h"
#include <openssl/x509.h>
#include <openssl/trace.h>
+#include <openssl/engine.h>
#define DSO_mod_init_name "OPENSSL_init"
#define DSO_mod_finish_name "OPENSSL_finish"
static STACK_OF(CONF_MODULE) *supported_modules = NULL;
static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
+static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT;
+
static void module_free(CONF_MODULE *md);
static void module_finish(CONF_IMODULE *imod);
static int module_run(const CONF *cnf, const char *name, const char *value,
}
-int CONF_modules_load_file(const char *filename, const char *appname,
- unsigned long flags)
+int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx,
+ const char *filename,
+ const char *appname, unsigned long flags)
{
char *file = NULL;
CONF *conf = NULL;
int ret = 0;
- conf = NCONF_new(NULL);
+
+ conf = NCONF_new_with_libctx(libctx, NULL);
if (conf == NULL)
goto err;
if (filename == NULL) {
file = CONF_get1_default_config_file();
- if (!file)
+ if (file == NULL)
goto err;
- } else
+ } else {
file = (char *)filename;
+ }
if (NCONF_load(conf, file, NULL) <= 0) {
if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
return ret;
}
+int CONF_modules_load_file(const char *filename,
+ const char *appname, unsigned long flags)
+{
+ return CONF_modules_load_file_with_libctx(NULL, filename, appname, flags);
+}
+
+DEFINE_RUN_ONCE_STATIC(do_load_builtin_modules)
+{
+ OPENSSL_load_builtin_modules();
+#ifndef OPENSSL_NO_ENGINE
+ /* Need to load ENGINEs */
+ ENGINE_load_builtin_engines();
+#endif
+ ERR_clear_error();
+ return 1;
+}
+
static int module_run(const CONF *cnf, const char *name, const char *value,
unsigned long flags)
{
CONF_MODULE *md;
int ret;
+ if (!RUN_ONCE(&load_builtin_modules, do_load_builtin_modules))
+ return -1;
+
md = module_find(name);
/* Module not found: try to load DSO */
filename, appname, flags);
#endif
- OPENSSL_load_builtin_modules();
-#ifndef OPENSSL_NO_ENGINE
- /* Need to load ENGINEs */
- ENGINE_load_builtin_engines();
-#endif
- ERR_clear_error();
#ifndef OPENSSL_SYS_UEFI
ret = CONF_modules_load_file(filename, appname, flags);
#endif
*/
#include "crypto/cryptlib.h"
+#include <openssl/conf.h>
#include "internal/thread_once.h"
#include "internal/property.h"
return ctx;
}
+#ifndef FIPS_MODE
+int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file)
+{
+ return CONF_modules_load_file_with_libctx(ctx, config_file, NULL, 0) > 0;
+}
+#endif
+
void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
{
if (ctx != NULL)
for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
cval = sk_CONF_VALUE_value(elist, i);
- if (!provider_conf_load(NULL, cval->name, cval->value, cnf))
+ if (!provider_conf_load(cnf->libctx, cval->name, cval->value, cnf))
return 0;
}
=head1 SEE ALSO
L<config(5)>, L<OPENSSL_config(3)>,
-L<CONF_modules_load_file(3)>
+L<CONF_modules_load_file_with_libctx(3)>
=head1 HISTORY
=head1 NAME
-CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions
+CONF_modules_load_file_with_libctx, CONF_modules_load_file, CONF_modules_load
+- OpenSSL configuration functions
=head1 SYNOPSIS
#include <openssl/conf.h>
+ int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx,
+ const char *filename,
+ const char *appname, unsigned long flags);
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags);
int CONF_modules_load(const CONF *cnf, const char *appname,
=head1 DESCRIPTION
-The function CONF_modules_load_file() configures OpenSSL using file
-B<filename> and application name B<appname>. If B<filename> is NULL
-the standard OpenSSL configuration file is used. If B<appname> is
-NULL the standard OpenSSL application name B<openssl_conf> is used.
+The function CONF_modules_load_file_with_libctx() configures OpenSSL using
+library context B<libctx> file B<filename> and application name B<appname>.
+If B<filename> is NULL the standard OpenSSL configuration file is used.
+If B<appname> is NULL the standard OpenSSL application name B<openssl_conf> is
+used.
The behaviour can be customized using B<flags>.
+CONF_modules_load_file() is the same as CONF_modules_load_file_with_libctx() but
+has a NULL library context.
+
CONF_modules_load() is identical to CONF_modules_load_file() except it
reads configuration information from B<cnf>.
This is used by default in L<OPENSSL_init_crypto(3)> to ignore any errors in
the default system-wide configuration file, as having all OpenSSL applications
fail to start when there are potentially minor issues in the file is too risky.
-Applications calling B<CONF_modules_load_file> explicitly should not generally
-set this flag.
+Applications calling B<CONF_modules_load_file_with_libctx> explicitly should not
+generally set this flag.
If B<CONF_MFLAGS_NO_DSO> is set configuration module loading from DSOs is
disabled.
B<CONF_MFLAGS_DEFAULT_SECTION> if set and B<appname> is not NULL will use the
default section pointed to by B<openssl_conf> if B<appname> does not exist.
-By using CONF_modules_load_file() with appropriate flags an application can
-customise application configuration to best suit its needs. In some cases the
-use of a configuration file is optional and its absence is not an error: in
-this case B<CONF_MFLAGS_IGNORE_MISSING_FILE> would be set.
+By using CONF_modules_load_file_with_libctx() with appropriate flags an
+application can customise application configuration to best suit its needs.
+In some cases the use of a configuration file is optional and its absence is not
+an error: in this case B<CONF_MFLAGS_IGNORE_MISSING_FILE> would be set.
Errors during configuration may also be handled differently by different
applications. For example in some cases an error may simply print out a warning
Load a configuration file and print out any errors and exit (missing file
considered fatal):
- if (CONF_modules_load_file(NULL, NULL, 0) <= 0) {
+ if (CONF_modules_load_file_with_libctx(libctx, NULL, NULL, 0) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
Load default configuration file using the section indicated by "myapp",
tolerate missing files, but exit on other errors:
- if (CONF_modules_load_file(NULL, "myapp",
- CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
+ if (CONF_modules_load_file_with_libctx(NULL, NULL, "myapp",
+ CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
Load custom configuration file and section, only print warnings on error,
missing configuration file ignored:
- if (CONF_modules_load_file("/something/app.cnf", "myapp",
- CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
+ if (CONF_modules_load_file_with_libctx(NULL, "/something/app.cnf", "myapp",
+ CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "WARNING: error loading configuration file\n");
ERR_print_errors_fp(stderr);
}
fprintf(stderr, "Error opening configuration file\n");
/* Other missing configuration file behaviour */
} else {
- cnf = NCONF_new(NULL);
+ cnf = NCONF_new_with_libctx(libctx, NULL);
if (NCONF_load_fp(cnf, fp, &eline) == 0) {
fprintf(stderr, "Error on line %ld of configuration file\n", eline);
ERR_print_errors_fp(stderr);
=head1 SEE ALSO
-L<config(5)>, L<OPENSSL_config(3)>
+L<config(5)>,
+L<OPENSSL_config(3)>,
+L<NCONF_new_with_libctx(3)>
=head1 COPYRIGHT
-Copyright 2004-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2020 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
--- /dev/null
+=pod
+
+=head1 NAME
+
+NCONF_new_with_libctx, NCONF_new, NCONF_free, NCONF_default, NCONF_load
+- functionality to Load and parse configuration files manually
+
+=head1 SYNOPSIS
+
+ #include <openssl/conf.h>
+
+ CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth);
+ CONF *NCONF_new(CONF_METHOD *meth);
+ void NCONF_free(CONF *conf);
+ CONF_METHOD *NCONF_default(void);
+ int NCONF_load(CONF *conf, const char *file, long *eline);
+
+=head1 DESCRIPTION
+
+NCONF_new_with_libctx() creates a new CONF object in heap memory and assigns to
+it a context I<libctx> that can be used during loading. If the method table
+I<meth> is set to NULL then the default value of NCONF_default() is used.
+
+NCONF_new() is similar to NCONF_new_with_libctx() but sets the I<libctx> to NULL.
+
+NCONF_free() frees the data associated with I<conf> and then frees the I<conf>
+object.
+
+NCONF_load() parses the file named I<filename> and adds the values found to
+I<conf>. If an error occurs I<file> and I<eline> list the file and line that
+the load failed on if they are not NULL.
+
+NCONF_default() gets the default method table for processing a configuration file.
+
+=head1 RETURN VALUES
+
+NCONF_load() returns 1 on success or 0 on error.
+
+NCONF_new_with_libctx() and NCONF_new() return a newly created I<CONF> object
+or NULL if an error occurs.
+
+=head1 SEE ALSO
+
+L<CONF_modules_load_file(3)>,
+
+=head1 HISTORY
+
+NCONF_new_with_libctx() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 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
=head1 NAME
-OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free - OpenSSL library context
+OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free, OPENSSL_CTX_load_config
+- OpenSSL library context
=head1 SYNOPSIS
typedef struct openssl_ctx_st OPENSSL_CTX;
OPENSSL_CTX *OPENSSL_CTX_new(void);
+ int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file);
void OPENSSL_CTX_free(OPENSSL_CTX *ctx);
=head1 DESCRIPTION
the OPENSSL_CTX is freed.
See L<OPENSSL_thread_stop_ex(3)> for more information.
+OPENSSL_CTX_load_config() loads a configuration file using the given C<ctx>.
+This can be used to associate a libctx with providers that are loaded from
+a configuration.
+
OPENSSL_CTX_free() frees the given C<ctx>.
=head1 RETURN VALUES
=head1 HISTORY
-OPENSSL_CTX, OPENSSL_CTX_new() and OPENSSL_CTX_free()
+OPENSSL_CTX, OPENSSL_CTX_new(), OPENSSL_CTX_load_config() and OPENSSL_CTX_free()
were added in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2020 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
Simple OpenSSL library configuration example to enter FIPS mode:
# Default appname: should match "appname" parameter (if any)
- # supplied to CONF_modules_load_file et al.
+ # supplied to CONF_modules_load_file_with_libctx et al.
openssl_conf = openssl_conf_section
[openssl_conf_section]
More complex OpenSSL library configuration. Add OID and don't enter FIPS mode:
# Default appname: should match "appname" parameter (if any)
- # supplied to CONF_modules_load_file et al.
+ # supplied to CONF_modules_load_file_with_libctx et al.
openssl_conf = openssl_conf_section
[openssl_conf_section]
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2020 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
void *meth_data;
LHASH_OF(CONF_VALUE) *data;
unsigned int flag_dollarid:1;
+ OPENSSL_CTX *libctx;
};
+CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth);
CONF *NCONF_new(CONF_METHOD *meth);
CONF_METHOD *NCONF_default(void);
DEPRECATEDIN_3_0(CONF_METHOD *NCONF_WIN32(void))
int CONF_modules_load(const CONF *cnf, const char *appname,
unsigned long flags);
+int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx, const char *filename,
+ const char *appname, unsigned long flags);
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags);
void CONF_modules_unload(int all);
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b);
OPENSSL_CTX *OPENSSL_CTX_new(void);
+int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file);
void OPENSSL_CTX_free(OPENSSL_CTX *);
# ifdef __cplusplus
#include <openssl/provider.h>
#include "testutil.h"
+static char *config_file = NULL;
static char *alg = "digest";
static int use_default_ctx = 0;
static char *fetch_property = NULL;
OPT_FETCH_PROPERTY,
OPT_FETCH_FAILURE,
OPT_USE_DEFAULTCTX,
+ OPT_CONFIG_FILE,
OPT_TEST_ENUM
} OPTION_CHOICE;
{
static const OPTIONS test_options[] = {
OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[provname...]\n"),
+ { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" },
{ "type", OPT_ALG_FETCH_TYPE, 's', "The fetch type to test" },
{ "property", OPT_FETCH_PROPERTY, 's', "The fetch property e.g. provider=fips" },
{ "fetchfail", OPT_FETCH_FAILURE, '-', "fetch is expected to fail" },
static int load_providers(OPENSSL_CTX **libctx, OSSL_PROVIDER *prov[])
{
- OPENSSL_CTX *ctx;
+ OPENSSL_CTX *ctx = NULL;
int ret = 0;
size_t i;
if (!TEST_ptr(ctx))
goto err;
+ if (!TEST_true(OPENSSL_CTX_load_config(ctx, config_file)))
+ goto err;
if (test_get_argument_count() > 2)
goto err;
if (!TEST_ptr(prov[i]))
goto err;
}
+
ret = 1;
*libctx = ctx;
err:
+ if (ret == 0)
+ OPENSSL_CTX_free(ctx);
return ret;
}
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
+ case OPT_CONFIG_FILE:
+ config_file = opt_arg();
+ break;
case OPT_ALG_FETCH_TYPE:
alg = opt_arg();
break;
foreach my $alg (@types) {
foreach my $testcase (@testdata) {
- $ENV{OPENSSL_CONF} = $testcase->{config};
+ $ENV{OPENSSL_CONF} = "";
foreach my $test (@{$testcase->{tests}}) {
my @testproviders =
@{ $test->{providers} // $testcase->{providers} };
"running evp_fetch_prov_test with $alg$testprovstr$testmsg";
ok(run(test(["evp_fetch_prov_test", "-type", "$alg",
+ "-config", "$testcase->{config}",
@testargs, @testproviders])),
$message);
}
EVP_PKEY_CTX_set_rsa_keygen_bits ? 3_0_0 EXIST::FUNCTION:RSA
EVP_PKEY_CTX_set_rsa_keygen_pubexp ? 3_0_0 EXIST::FUNCTION:RSA
EVP_PKEY_CTX_set_rsa_keygen_primes ? 3_0_0 EXIST::FUNCTION:RSA
+NCONF_new_with_libctx ? 3_0_0 EXIST::FUNCTION:
+CONF_modules_load_file_with_libctx ? 3_0_0 EXIST::FUNCTION:
+OPENSSL_CTX_load_config ? 3_0_0 EXIST::FUNCTION:
NAME_CONSTRAINTS_it(3)
NAMING_AUTHORITY_it(3)
NCONF_WIN32(3)
-NCONF_default(3)
NCONF_dump_bio(3)
NCONF_dump_fp(3)
-NCONF_free(3)
NCONF_free_data(3)
NCONF_get_number_e(3)
NCONF_get_section(3)
NCONF_get_string(3)
-NCONF_load(3)
NCONF_load_bio(3)
NCONF_load_fp(3)
-NCONF_new(3)
NETSCAPE_CERT_SEQUENCE_it(3)
NETSCAPE_SPKAC_it(3)
NETSCAPE_SPKI_b64_decode(3)