diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index e65f4610085823aed1b3bcf3bfb386128f9dfa3c..fdf9a7e1eab5569dc4128ec7784a21ad961df6d6 100644 --- a/crypto/provider_predefined.c +++ b/crypto/provider_predefined.c @@ -11,6 +11,7 @@ #include "provider_local.h" OSSL_provider_init_fn ossl_default_provider_init; +OSSL_provider_init_fn ossl_null_provider_init; OSSL_provider_init_fn fips_intern_provider_init; #ifdef STATIC_LEGACY OSSL_provider_init_fn ossl_legacy_provider_init; @@ -23,6 +24,7 @@ const struct predefined_providers_st predefined_providers[] = { # ifdef STATIC_LEGACY { "legacy", ossl_legacy_provider_init, 0 }, # endif + { "null", ossl_null_provider_init, 0 }, #endif { NULL, NULL, 0 } }; diff --git a/doc/man7/OSSL_PROVIDER-null.pod b/doc/man7/OSSL_PROVIDER-null.pod new file mode 100644 index 0000000000000000000000000000000000000000..10ce5844f1d38f0f9eb62bf1d366ee4f5721446a --- /dev/null +++ b/doc/man7/OSSL_PROVIDER-null.pod @@ -0,0 +1,35 @@ +=pod + +=head1 NAME + +OSSL_PROVIDER-null - OpenSSL null provider + +=head1 DESCRIPTION + +The OpenSSL null provider supplies no algorithms. + +It can used to guarantee that the default library context and a fallback +provider will not be accidentally accessed. + +=head2 Properties + +The null provider defines no properties. + +=head1 OPERATIONS AND ALGORITHMS + +The OpenSSL null provider supports no operations and algorithms. + +=head1 SEE ALSO + +L + +=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. + +=cut diff --git a/providers/build.info b/providers/build.info index 54c3381bca96ab204d1fb6f89409a547a7c0961a..45faecf6e923f47cf870acfb39ef25a46a82fed4 100644 --- a/providers/build.info +++ b/providers/build.info @@ -151,3 +151,13 @@ IF[{- !$disabled{legacy} -}] SOURCE[$LEGACYGOAL]=legacyprov.c INCLUDE[$LEGACYGOAL]=../include implementations/include ENDIF + +# +# Null provider stuff +# +# Because the null provider is built in, it means that libcrypto must +# include all the object files that are needed. +$NULLGOAL=../libcrypto +SOURCE[$NULLGOAL]=nullprov.c + + diff --git a/providers/nullprov.c b/providers/nullprov.c new file mode 100644 index 0000000000000000000000000000000000000000..a1a26811738febc93477fd680ee2c53ef6189e13 --- /dev/null +++ b/providers/nullprov.c @@ -0,0 +1,106 @@ +/* + * 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 + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "prov/implementations.h" + +OSSL_provider_init_fn ossl_null_provider_init; + +/* Functions provided by the core */ +static OSSL_core_gettable_params_fn *c_gettable_params = NULL; +static OSSL_core_get_params_fn *c_get_params = NULL; + +/* Parameters we provide to the core */ +static const OSSL_ITEM null_param_types[] = { + { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_NAME }, + { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_VERSION }, + { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_BUILDINFO }, + { 0, NULL } +}; + +static const OSSL_ITEM *null_gettable_params(const OSSL_PROVIDER *prov) +{ + return null_param_types; +} + +static int null_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME); + if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Null Provider")) + return 0; + p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION); + if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR)) + return 0; + p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO); + if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR)) + return 0; + + return 1; +} + +static const OSSL_ALGORITHM *null_query(OSSL_PROVIDER *prov, + int operation_id, + int *no_cache) +{ + *no_cache = 0; + return NULL; +} + +/* Functions we provide to the core */ +static const OSSL_DISPATCH null_dispatch_table[] = { + { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))null_gettable_params }, + { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))null_get_params }, + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))null_query }, + { 0, NULL } +}; + +int ossl_null_provider_init(const OSSL_PROVIDER *provider, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, + void **provctx) +{ + OSSL_core_get_library_context_fn *c_get_libctx = NULL; + + for (; in->function_id != 0; in++) { + switch (in->function_id) { + case OSSL_FUNC_CORE_GETTABLE_PARAMS: + c_gettable_params = OSSL_get_core_gettable_params(in); + break; + case OSSL_FUNC_CORE_GET_PARAMS: + c_get_params = OSSL_get_core_get_params(in); + break; + case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT: + c_get_libctx = OSSL_get_core_get_library_context(in); + break; + /* Just ignore anything we don't understand */ + default: + break; + } + } + + if (c_get_libctx == NULL) + return 0; + + *out = null_dispatch_table; + + /* + * We want to make sure that all calls from this provider that requires + * a library context use the same context as the one used to call our + * functions. We do that by passing it along as the provider context. + */ + *provctx = c_get_libctx(provider); + return 1; +} diff --git a/test/recipes/20-test_provider.t b/test/recipes/20-test_provider.t index 0cfd81d09b8d0c052eaed03a7158e8af6d1a5c94..d7a0821441ec987646b00569dbf1d76ae64eedbe 100644 --- a/test/recipes/20-test_provider.t +++ b/test/recipes/20-test_provider.t @@ -14,7 +14,7 @@ use OpenSSL::Test; setup("test_provider"); -plan tests => 7; +plan tests => 9; SKIP: { skip "No default provider?", 6 @@ -45,3 +45,18 @@ plan tests => 7; } } + SKIP: { + skip "No null provider?", 1 + unless ok(run(app([qw(openssl provider null)])), + "try running 'openssl provider null'"); + + my @cmd = ('openssl', 'provider', '-vvv', 'null'); + my @lines = ( map { (my $x = $_) =~ s|\R$||; $x } + run(app([@cmd]), capture => 1) ); + + my $curr = scalar @lines; + my $cmp = "$curr == 1"; + ok(eval $cmp, + "'openssl provider $_ default' line count == 1"); +} +