summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-08-09 18:06:52 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-08-09 18:06:52 +1000
commit04cb5ec0b74896fe806625ac4d87e3396890f246 (patch)
tree558c92ddf1b1fb2421d9f3f9aae3c82595a94830 /crypto
parentdda4e259e51aeaf05a2417ef577accf778c9f6f6 (diff)
Add 'on demand self test' and status test to providers
The default and legacy providers currently return 1 for status and self test checks. Added test to show the 3 different stages the self test can be run (for installation, loading and on demand). For the fips provider: - If the on demand self test fails, then any subsequent fetches should also fail. To implement this the cached algorithms are flushed on failure. - getting the self test callback in the fips provider is a bit complicated since the callback hangs off the core libctx (as it is set by the application) not the actual fips library context. Also the callback can be set at any time not just during the OSSL_provider_init() so it is calculated each time before doing any self test. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/11752)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/evp_fetch.c11
-rw-r--r--crypto/property/property.c21
-rw-r--r--crypto/provider.c6
-rw-r--r--crypto/provider_core.c19
-rw-r--r--crypto/sparse_array.c2
5 files changed, 51 insertions, 8 deletions
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index 5cb59d98fc..4c3992ab40 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -17,6 +17,7 @@
#include "internal/core.h"
#include "internal/provider.h"
#include "internal/namemap.h"
+#include "internal/property.h"
#include "crypto/evp.h" /* evp_local.h needs it */
#include "evp_local.h"
@@ -368,6 +369,14 @@ void *evp_generic_fetch_by_number(OPENSSL_CTX *libctx, int operation_id,
return ret;
}
+void evp_method_store_flush(OPENSSL_CTX *libctx)
+{
+ OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+ if (store != NULL)
+ ossl_method_store_flush_cache(store, 1);
+}
+
static int evp_set_default_properties(OPENSSL_CTX *libctx,
OSSL_PROPERTY_LIST *def_prop)
{
@@ -378,7 +387,7 @@ static int evp_set_default_properties(OPENSSL_CTX *libctx,
ossl_property_free(*plp);
*plp = def_prop;
if (store != NULL)
- ossl_method_store_flush_cache(store);
+ ossl_method_store_flush_cache(store, 0);
return 1;
}
EVPerr(0, ERR_R_INTERNAL_ERROR);
diff --git a/crypto/property/property.c b/crypto/property/property.c
index 645e361b0a..cb82f8956b 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -394,10 +394,19 @@ fin:
return ret;
}
-static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg)
+static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
{
+ SPARSE_ARRAY_OF(ALGORITHM) *algs = arg;
+
lh_QUERY_doall(alg->cache, &impl_cache_free);
- lh_QUERY_flush(alg->cache);
+ if (algs != NULL) {
+ sk_IMPLEMENTATION_pop_free(alg->impls, &impl_free);
+ lh_QUERY_free(alg->cache);
+ OPENSSL_free(alg);
+ ossl_sa_ALGORITHM_set(algs, idx, NULL);
+ } else {
+ lh_QUERY_flush(alg->cache);
+ }
}
static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
@@ -406,14 +415,16 @@ static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid)
if (alg != NULL) {
store->nelem -= lh_QUERY_num_items(alg->cache);
- impl_cache_flush_alg(0, alg);
+ impl_cache_flush_alg(0, alg, NULL);
}
}
-void ossl_method_store_flush_cache(OSSL_METHOD_STORE *store)
+void ossl_method_store_flush_cache(OSSL_METHOD_STORE *store, int all)
{
+ void *arg = (all != 0 ? store->algs : NULL);
+
ossl_property_write_lock(store);
- ossl_sa_ALGORITHM_doall(store->algs, &impl_cache_flush_alg);
+ ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_alg, arg);
store->nelem = 0;
ossl_property_unlock(store);
}
diff --git a/crypto/provider.c b/crypto/provider.c
index 8646aef771..40c837d8c0 100644
--- a/crypto/provider.c
+++ b/crypto/provider.c
@@ -10,6 +10,7 @@
#include <openssl/err.h>
#include <openssl/cryptoerr.h>
#include <openssl/provider.h>
+#include <openssl/core_names.h>
#include "internal/provider.h"
OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *libctx, const char *name)
@@ -69,6 +70,11 @@ void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
return ossl_provider_prov_ctx(prov);
}
+int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_self_test(prov);
+}
+
int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
const char *capability,
OSSL_CALLBACK *cb,
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 79c330383c..4b5b013608 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -14,6 +14,7 @@
#include <openssl/params.h>
#include <openssl/opensslv.h>
#include "crypto/cryptlib.h"
+#include "crypto/evp.h" /* evp_method_store_flush */
#include "internal/nelem.h"
#include "internal/thread_once.h"
#include "internal/provider.h"
@@ -71,6 +72,7 @@ struct ossl_provider_st {
OSSL_FUNC_provider_gettable_params_fn *gettable_params;
OSSL_FUNC_provider_get_params_fn *get_params;
OSSL_FUNC_provider_get_capabilities_fn *get_capabilities;
+ OSSL_FUNC_provider_self_test_fn *self_test;
OSSL_FUNC_provider_query_operation_fn *query_operation;
/*
@@ -544,6 +546,10 @@ static int provider_activate(OSSL_PROVIDER *prov)
prov->get_params =
OSSL_FUNC_provider_get_params(provider_dispatch);
break;
+ case OSSL_FUNC_PROVIDER_SELF_TEST:
+ prov->self_test =
+ OSSL_FUNC_provider_self_test(provider_dispatch);
+ break;
case OSSL_FUNC_PROVIDER_GET_CAPABILITIES:
prov->get_capabilities =
OSSL_FUNC_provider_get_capabilities(provider_dispatch);
@@ -824,6 +830,18 @@ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
? 0 : prov->get_params(prov->provctx, params);
}
+int ossl_provider_self_test(const OSSL_PROVIDER *prov)
+{
+ int ret;
+
+ if (prov->self_test == NULL)
+ return 1;
+ ret = prov->self_test(prov->provctx);
+ if (ret == 0)
+ evp_method_store_flush(ossl_provider_library_context(prov));
+ return ret;
+}
+
int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov,
const char *capability,
OSSL_CALLBACK *cb,
@@ -833,7 +851,6 @@ int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov,
? 1 : prov->get_capabilities(prov->provctx, capability, cb, arg);
}
-
const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
int operation_id,
int *no_cache)
diff --git a/crypto/sparse_array.c b/crypto/sparse_array.c
index 9d444739f5..69a56db01c 100644
--- a/crypto/sparse_array.c
+++ b/crypto/sparse_array.c
@@ -162,7 +162,7 @@ void *OPENSSL_SA_get(const OPENSSL_SA *sa, ossl_uintmax_t n)
int level;
void **p, *r = NULL;
- if (sa == NULL)
+ if (sa == NULL || sa->nelem == 0)
return NULL;
if (n <= sa->top) {