Latest update.
This commit is contained in:
+63
-47
@@ -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;
|
||||
|
||||
@@ -13,19 +13,6 @@
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA PROP_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_OSSL_PARSE_PROPERTY, 0),
|
||||
"ossl_parse_property"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_OSSL_PARSE_QUERY, 0), "ossl_parse_query"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_HEX, 0), "parse_hex"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_NAME, 0), "parse_name"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_NUMBER, 0), "parse_number"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_OCT, 0), "parse_oct"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_STRING, 0), "parse_string"},
|
||||
{ERR_PACK(ERR_LIB_PROP, PROP_F_PARSE_UNQUOTED, 0), "parse_unquoted"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA PROP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NAME_TOO_LONG), "name too long"},
|
||||
{ERR_PACK(ERR_LIB_PROP, 0, PROP_R_NOT_AN_ASCII_CHARACTER),
|
||||
@@ -52,10 +39,8 @@ static const ERR_STRING_DATA PROP_str_reasons[] = {
|
||||
int ERR_load_PROP_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(PROP_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(PROP_str_functs);
|
||||
if (ERR_reason_error_string(PROP_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(PROP_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
@@ -21,7 +21,6 @@ OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s,
|
||||
int create);
|
||||
|
||||
/* Property list functions */
|
||||
int ossl_property_parse_init(OPENSSL_CTX *ctx);
|
||||
void ossl_property_free(OSSL_PROPERTY_LIST *p);
|
||||
int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query);
|
||||
int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
|
||||
|
||||
@@ -91,8 +91,8 @@ static int parse_name(OPENSSL_CTX *ctx, const char *t[], int create,
|
||||
|
||||
for (;;) {
|
||||
if (!ossl_isalpha(*s)) {
|
||||
PROPerr(PROP_F_PARSE_NAME, PROP_R_NOT_AN_IDENTIFIER);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
|
||||
"HERE-->%s", *t);
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
@@ -112,8 +112,7 @@ static int parse_name(OPENSSL_CTX *ctx, const char *t[], int create,
|
||||
}
|
||||
name[i] = '\0';
|
||||
if (err) {
|
||||
PROPerr(PROP_F_PARSE_NAME, PROP_R_NAME_TOO_LONG);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
|
||||
return 0;
|
||||
}
|
||||
*t = skip_space(s);
|
||||
@@ -132,8 +131,8 @@ static int parse_number(const char *t[], PROPERTY_DEFINITION *res)
|
||||
v = v * 10 + (*s++ - '0');
|
||||
} while (ossl_isdigit(*s));
|
||||
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
|
||||
PROPerr(PROP_F_PARSE_NUMBER, PROP_R_NOT_A_DECIMAL_DIGIT);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
|
||||
"HERE-->%s", *t);
|
||||
return 0;
|
||||
}
|
||||
*t = skip_space(s);
|
||||
@@ -157,8 +156,8 @@ static int parse_hex(const char *t[], PROPERTY_DEFINITION *res)
|
||||
v += ossl_tolower(*s) - 'a';
|
||||
} while (ossl_isxdigit(*++s));
|
||||
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
|
||||
PROPerr(PROP_F_PARSE_HEX, PROP_R_NOT_AN_HEXADECIMAL_DIGIT);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
|
||||
"HERE-->%s", *t);
|
||||
return 0;
|
||||
}
|
||||
*t = skip_space(s);
|
||||
@@ -178,8 +177,8 @@ static int parse_oct(const char *t[], PROPERTY_DEFINITION *res)
|
||||
v = (v << 3) + (*s - '0');
|
||||
} while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
|
||||
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
|
||||
PROPerr(PROP_F_PARSE_OCT, PROP_R_NOT_AN_OCTAL_DIGIT);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
|
||||
"HERE-->%s", *t);
|
||||
return 0;
|
||||
}
|
||||
*t = skip_space(s);
|
||||
@@ -204,18 +203,13 @@ static int parse_string(OPENSSL_CTX *ctx, const char *t[], char delim,
|
||||
s++;
|
||||
}
|
||||
if (*s == '\0') {
|
||||
char buf[2] = { 0, 0 };
|
||||
|
||||
PROPerr(PROP_F_PARSE_STRING,
|
||||
PROP_R_NO_MATCHING_STRING_DELIMETER);
|
||||
buf[0] = delim;
|
||||
ERR_add_error_data(3, "HERE-->", buf, *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMETER,
|
||||
"HERE-->%c%s", delim, *t);
|
||||
return 0;
|
||||
}
|
||||
v[i] = '\0';
|
||||
if (err) {
|
||||
PROPerr(PROP_F_PARSE_STRING, PROP_R_STRING_TOO_LONG);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
|
||||
} else {
|
||||
res->v.str_val = ossl_property_value(ctx, v, create);
|
||||
}
|
||||
@@ -242,14 +236,13 @@ static int parse_unquoted(OPENSSL_CTX *ctx, const char *t[],
|
||||
s++;
|
||||
}
|
||||
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
|
||||
PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_NOT_AN_ASCII_CHARACTER);
|
||||
ERR_add_error_data(2, "HERE-->", s);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
|
||||
"HERE-->%s", s);
|
||||
return 0;
|
||||
}
|
||||
v[i] = 0;
|
||||
if (err) {
|
||||
PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_STRING_TOO_LONG);
|
||||
ERR_add_error_data(2, "HERE-->", *t);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
|
||||
} else {
|
||||
res->v.str_val = ossl_property_value(ctx, v, create);
|
||||
}
|
||||
@@ -358,14 +351,14 @@ OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
|
||||
goto err;
|
||||
prop->oper = PROPERTY_OPER_EQ;
|
||||
if (prop->name_idx == 0) {
|
||||
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_PARSE_FAILED);
|
||||
ERR_add_error_data(2, "Unknown name HERE-->", start);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
|
||||
"Unknown name HERE-->%s", start);
|
||||
goto err;
|
||||
}
|
||||
if (match_ch(&s, '=')) {
|
||||
if (!parse_value(ctx, &s, prop, 1)) {
|
||||
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_NO_VALUE);
|
||||
ERR_add_error_data(2, "HERE-->", start);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
|
||||
"HERE-->%s", start);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
@@ -380,8 +373,8 @@ OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
|
||||
done = !match_ch(&s, ',');
|
||||
}
|
||||
if (*s != '\0') {
|
||||
PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_TRAILING_CHARACTERS);
|
||||
ERR_add_error_data(2, "HERE-->", s);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
|
||||
"HERE-->%s", s);
|
||||
goto err;
|
||||
}
|
||||
res = stack_to_property_list(sk);
|
||||
@@ -442,8 +435,8 @@ skip_value:
|
||||
done = !match_ch(&s, ',');
|
||||
}
|
||||
if (*s != '\0') {
|
||||
PROPerr(PROP_F_OSSL_PARSE_QUERY, PROP_R_TRAILING_CHARACTERS);
|
||||
ERR_add_error_data(2, "HERE-->", s);
|
||||
ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
|
||||
"HERE-->%s", s);
|
||||
goto err;
|
||||
}
|
||||
res = stack_to_property_list(sk);
|
||||
|
||||
Reference in New Issue
Block a user