Latest update.

This commit is contained in:
2019-09-21 00:43:47 +09:00
parent 2e57f602ae
commit 62515c7d8d
1131 changed files with 47556 additions and 24957 deletions
+63 -47
View File
@@ -25,6 +25,7 @@
#define IMPL_CACHE_FLUSH_THRESHOLD 500
typedef struct {
const OSSL_PROVIDER *provider;
OSSL_PROPERTY_LIST *properties;
void *method;
void (*method_destruct)(void *);
@@ -58,9 +59,9 @@ struct ossl_method_store_st {
};
typedef struct {
OSSL_METHOD_STORE *store;
LHASH_OF(QUERY) *cache;
size_t nelem;
uint32_t seed;
} IMPL_CACHE_FLUSH;
DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
@@ -83,12 +84,6 @@ int ossl_property_unlock(OSSL_METHOD_STORE *p)
return p != 0 ? CRYPTO_THREAD_unlock(p->lock) : 0;
}
static openssl_ctx_run_once_fn do_method_store_init;
int do_method_store_init(OPENSSL_CTX *ctx)
{
return ossl_property_parse_init(ctx);
}
static unsigned long query_hash(const QUERY *a)
{
return OPENSSL_LH_strhash(a->query);
@@ -131,11 +126,6 @@ OSSL_METHOD_STORE *ossl_method_store_new(OPENSSL_CTX *ctx)
{
OSSL_METHOD_STORE *res;
if (!openssl_ctx_run_once(ctx,
OPENSSL_CTX_METHOD_STORE_RUN_ONCE_INDEX,
do_method_store_init))
return NULL;
res = OPENSSL_zalloc(sizeof(*res));
if (res != NULL) {
res->ctx = ctx;
@@ -173,13 +163,15 @@ static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg)
return ossl_sa_ALGORITHM_set(store->algs, alg->nid, alg);
}
int ossl_method_store_add(OSSL_METHOD_STORE *store,
int nid, const char *properties,
void *method, void (*method_destruct)(void *))
int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
int nid, const char *properties, void *method,
int (*method_up_ref)(void *),
void (*method_destruct)(void *))
{
ALGORITHM *alg = NULL;
IMPLEMENTATION *impl;
int ret = 0;
int i;
if (nid <= 0 || method == NULL || store == NULL)
return 0;
@@ -190,6 +182,11 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store,
impl = OPENSSL_malloc(sizeof(*impl));
if (impl == NULL)
return 0;
if (method_up_ref != NULL && !method_up_ref(method)) {
OPENSSL_free(impl);
return 0;
}
impl->provider = prov;
impl->method = method;
impl->method_destruct = method_destruct;
@@ -219,8 +216,16 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store,
goto err;
}
/* Push onto stack */
if (sk_IMPLEMENTATION_push(alg->impls, impl))
/* Push onto stack if there isn't one there already */
for (i = 0; i < sk_IMPLEMENTATION_num(alg->impls); i++) {
const IMPLEMENTATION *tmpimpl = sk_IMPLEMENTATION_value(alg->impls, i);
if (tmpimpl->provider == impl->provider
&& tmpimpl->properties == impl->properties)
break;
}
if (i == sk_IMPLEMENTATION_num(alg->impls)
&& sk_IMPLEMENTATION_push(alg->impls, impl))
ret = 1;
ossl_property_unlock(store);
if (ret == 0)
@@ -279,6 +284,10 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
int ret = 0;
int j, best = -1, score, optional;
#ifndef FIPS_MODE
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
if (nid <= 0 || method == NULL || store == NULL)
return 0;
@@ -376,37 +385,40 @@ IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
/*
* Flush an element from the query cache (perhaps).
*
* In order to avoid taking a write lock to keep accurate LRU information or
* using atomic operations to approximate similar, the procedure used here
* is to stochastically flush approximately half the cache. Since generating
* random numbers is relatively expensive, we produce them in blocks and
* consume them as we go, saving generated bits between generations of flushes.
* In order to avoid taking a write lock or using atomic operations
* to keep accurate least recently used (LRU) or least frequently used
* (LFU) information, the procedure used here is to stochastically
* flush approximately half the cache.
*
* This procedure isn't ideal, LRU would be better. However, in normal
* operation, reaching a full cache would be quite unexpected. It means
* that no steady state of algorithm queries has been reached. I.e. it is most
* likely an attack of some form. A suboptimal clearance strategy that doesn't
* degrade performance of the normal case is preferable to a more refined
* approach that imposes a performance impact.
* This procedure isn't ideal, LRU or LFU would be better. However,
* in normal operation, reaching a full cache would be unexpected.
* It means that no steady state of algorithm queries has been reached.
* That is, it is most likely an attack of some form. A suboptimal clearance
* strategy that doesn't degrade performance of the normal case is
* preferable to a more refined approach that imposes a performance
* impact.
*/
static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
{
#if !defined(FIPS_MODE)
/* TODO(3.0): No RAND_bytes yet in FIPS module. Add this back when available */
OSSL_METHOD_STORE *store = state->store;
unsigned int n;
uint32_t n;
if (store->nbits == 0) {
if (!RAND_bytes(store->rand_bits, sizeof(store->rand_bits)))
return;
store->nbits = sizeof(store->rand_bits) * 8;
}
n = --store->nbits;
if ((store->rand_bits[n >> 3] & (1 << (n & 7))) != 0)
/*
* Implement the 32 bit xorshift as suggested by George Marsaglia in:
* https://doi.org/10.18637/jss.v008.i14
*
* This is a very fast PRNG so there is no need to extract bits one at a
* time and use the entire value each time.
*/
n = state->seed;
n ^= n << 13;
n ^= n >> 17;
n ^= n << 5;
state->seed = n;
if ((n & 1) != 0)
OPENSSL_free(lh_QUERY_delete(state->cache, c));
else
state->nelem++;
#endif /* !defined(FIPS_MODE) */
}
static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg,
@@ -424,9 +436,10 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
IMPL_CACHE_FLUSH state;
state.nelem = 0;
state.store = store;
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
if ((state.seed = OPENSSL_rdtsc()) == 0)
state.seed = 1;
store->need_flush = 0;
ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state);
store->nelem = state.nelem;
}
@@ -480,7 +493,8 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
if (method == NULL) {
elem.query = prop_query;
lh_QUERY_delete(alg->cache, &elem);
if (lh_QUERY_delete(alg->cache, &elem) != NULL)
store->nelem--;
ossl_property_unlock(store);
return 1;
}
@@ -489,11 +503,13 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
p->query = p->body;
p->method = method;
memcpy((char *)p->query, prop_query, len + 1);
if ((old = lh_QUERY_insert(alg->cache, p)) != NULL)
if ((old = lh_QUERY_insert(alg->cache, p)) != NULL) {
OPENSSL_free(old);
if (old != NULL || !lh_QUERY_error(alg->cache)) {
store->nelem++;
if (store->nelem >= IMPL_CACHE_FLUSH_THRESHOLD)
ossl_property_unlock(store);
return 1;
}
if (!lh_QUERY_error(alg->cache)) {
if (++store->nelem >= IMPL_CACHE_FLUSH_THRESHOLD)
store->need_flush = 1;
ossl_property_unlock(store);
return 1;