diff --git a/backport-Avoid-calling-into-provider-with-the-same-iv_len-or-.patch b/backport-Avoid-calling-into-provider-with-the-same-iv_len-or-.patch new file mode 100644 index 0000000000000000000000000000000000000000..85a08ffdbb6063c4f5d471df4427d8442386d807 --- /dev/null +++ b/backport-Avoid-calling-into-provider-with-the-same-iv_len-or-.patch @@ -0,0 +1,46 @@ +From 6f8002014dda3f45aa864b38b92c2df7611af52e Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Fri, 31 Mar 2023 15:46:15 +0200 +Subject: [PATCH] Avoid calling into provider with the same iv_len or key_len + +Fixes #20625 + +Reviewed-by: Matt Caswell +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20664) + +(cherry picked from commit eb52450f5151e8e78743ab05de21a344823316f5) +--- + crypto/evp/evp_enc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c +index e6af8b1c7b..231be1adf4 100644 +--- a/crypto/evp/evp_enc.c ++++ b/crypto/evp/evp_enc.c +@@ -1078,6 +1078,11 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) + + switch (type) { + case EVP_CTRL_SET_KEY_LENGTH: ++ if (arg < 0) ++ return 0; ++ if (ctx->key_len == arg) ++ /* Skip calling into provider if unchanged. */ ++ return 1; + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz); + ctx->key_len = -1; + break; +@@ -1103,6 +1108,9 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg < 0) + return 0; ++ if (ctx->iv_len == arg) ++ /* Skip calling into provider if unchanged. */ ++ return 1; + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); + ctx->iv_len = -1; + break; +-- +2.33.0 + diff --git a/backport-Don-t-take-a-write-lock-to-retrieve-a-value-from-a-s.patch b/backport-Don-t-take-a-write-lock-to-retrieve-a-value-from-a-s.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6508426561bc803e025d81637c510858b78d516 --- /dev/null +++ b/backport-Don-t-take-a-write-lock-to-retrieve-a-value-from-a-s.patch @@ -0,0 +1,102 @@ +From d6e07491ab2838c74e7070bd3247073cb1222e36 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Fri, 12 May 2023 16:15:21 +0100 +Subject: [PATCH] Don't take a write lock to retrieve a value from a stack + +ossl_x509_store_ctx_get_by_subject() was taking a write lock for the +store, but was only (usually) retrieving a value from the stack of +objects. We take a read lock instead. + +Partially fixes #20286 + +Reviewed-by: Tomas Mraz +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20952) + +(cherry picked from commit 80935bf5ad309bf6c03591acf1d48fe1db57b78f) +--- + crypto/x509/x509_lu.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c +index d8927bda07..1fb46586f0 100644 +--- a/crypto/x509/x509_lu.c ++++ b/crypto/x509/x509_lu.c +@@ -41,14 +41,19 @@ void X509_LOOKUP_free(X509_LOOKUP *ctx) + OPENSSL_free(ctx); + } + +-int X509_STORE_lock(X509_STORE *s) ++int X509_STORE_lock(X509_STORE *xs) + { +- return CRYPTO_THREAD_write_lock(s->lock); ++ return CRYPTO_THREAD_write_lock(xs->lock); + } + +-int X509_STORE_unlock(X509_STORE *s) ++static int x509_store_read_lock(X509_STORE *xs) + { +- return CRYPTO_THREAD_unlock(s->lock); ++ return CRYPTO_THREAD_read_lock(xs->lock); ++} ++ ++int X509_STORE_unlock(X509_STORE *xs) ++{ ++ return CRYPTO_THREAD_unlock(xs->lock); + } + + int X509_LOOKUP_init(X509_LOOKUP *ctx) +@@ -321,9 +326,19 @@ int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs, + stmp.type = X509_LU_NONE; + stmp.data.ptr = NULL; + +- if (!X509_STORE_lock(store)) ++ if (!x509_store_read_lock(store)) + return 0; +- ++ /* Should already be sorted...but just in case */ ++ if (!sk_X509_OBJECT_is_sorted(store->objs)) { ++ X509_STORE_unlock(store); ++ /* Take a write lock instead of a read lock */ ++ X509_STORE_lock(store); ++ /* ++ * Another thread might have sorted it in the meantime. But if so, ++ * sk_X509_OBJECT_sort() exits early. ++ */ ++ sk_X509_OBJECT_sort(store->objs); ++ } + tmp = X509_OBJECT_retrieve_by_subject(store->objs, type, name); + X509_STORE_unlock(store); + +@@ -505,7 +520,6 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_OBJECT stmp; + X509 x509_s; + X509_CRL crl_s; +- int idx; + + stmp.type = type; + switch (type) { +@@ -522,16 +536,18 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + return -1; + } + +- idx = sk_X509_OBJECT_find_all(h, &stmp, pnmatch); +- return idx; ++ /* Assumes h is locked for read if applicable */ ++ return sk_X509_OBJECT_find_all(h, &stmp, pnmatch); + } + ++/* Assumes h is locked for read if applicable */ + int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + const X509_NAME *name) + { + return x509_object_idx_cnt(h, type, name, NULL); + } + ++/* Assumes h is locked for read if applicable */ + X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, + const X509_NAME *name) +-- +2.33.0 + diff --git a/backport-Refactor-OSSL_LIB_CTX-to-avoid-using-CRYPTO_EX_DATA.patch b/backport-Refactor-OSSL_LIB_CTX-to-avoid-using-CRYPTO_EX_DATA.patch new file mode 100644 index 0000000000000000000000000000000000000000..808b60c416f2aa877cc5b9793c17b8cec62f46e4 --- /dev/null +++ b/backport-Refactor-OSSL_LIB_CTX-to-avoid-using-CRYPTO_EX_DATA.patch @@ -0,0 +1,1969 @@ +From 8436ef8bdb96c0a977a15ec707d28404d97c3a6c Mon Sep 17 00:00:00 2001 +From: Hugo Landau +Date: Mon, 14 Mar 2022 08:13:12 +0000 +Subject: [PATCH] Refactor OSSL_LIB_CTX to avoid using CRYPTO_EX_DATA + +This refactors OSSL_LIB_CTX to avoid using CRYPTO_EX_DATA. The assorted +objects to be managed by OSSL_LIB_CTX are hardcoded and are initialized +eagerly rather than lazily, which avoids the need for locking on access +in most cases. + +Fixes #17116. + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/17881) + +(cherry picked from commit 927d0566ded0dff9d6c5abc8a40bb84068446b76) +--- + crypto/bio/bss_core.c | 14 +- + crypto/context.c | 441 ++++++++++++++------ + crypto/core_namemap.c | 14 +- + crypto/encode_decode/decoder_meth.c | 23 +- + crypto/encode_decode/encoder_meth.c | 23 +- + crypto/evp/evp_fetch.c | 21 +- + crypto/initthread.c | 17 +- + crypto/property/defn_cache.c | 17 +- + crypto/property/property.c | 20 +- + crypto/property/property_string.c | 19 +- + crypto/provider_child.c | 32 +- + crypto/provider_conf.c | 15 +- + crypto/provider_core.c | 17 +- + crypto/rand/rand_lib.c | 14 +- + crypto/self_test_core.c | 14 +- + crypto/store/store_meth.c | 23 +- + doc/internal/man3/ossl_lib_ctx_get_data.pod | 81 +--- + include/crypto/context.h | 40 ++ + include/internal/cryptlib.h | 14 +- + providers/fips/fipsprov.c | 27 +- + providers/implementations/rands/crngt.c | 14 +- + providers/implementations/rands/drbg.c | 14 +- + test/context_internal_test.c | 92 +--- + 23 files changed, 445 insertions(+), 561 deletions(-) + create mode 100644 include/crypto/context.h + +diff --git a/crypto/bio/bss_core.c b/crypto/bio/bss_core.c +index 7a84b20460..b9a8eff346 100644 +--- a/crypto/bio/bss_core.c ++++ b/crypto/bio/bss_core.c +@@ -10,6 +10,7 @@ + #include + #include "bio_local.h" + #include "internal/cryptlib.h" ++#include "crypto/context.h" + + typedef struct { + OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex; +@@ -21,26 +22,19 @@ typedef struct { + OSSL_FUNC_BIO_free_fn *c_bio_free; + } BIO_CORE_GLOBALS; + +-static void bio_core_globals_free(void *vbcg) ++void ossl_bio_core_globals_free(void *vbcg) + { + OPENSSL_free(vbcg); + } + +-static void *bio_core_globals_new(OSSL_LIB_CTX *ctx) ++void *ossl_bio_core_globals_new(OSSL_LIB_CTX *ctx) + { + return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS)); + } + +-static const OSSL_LIB_CTX_METHOD bio_core_globals_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- bio_core_globals_new, +- bio_core_globals_free, +-}; +- + static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX, +- &bio_core_globals_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX); + } + + static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, +diff --git a/crypto/context.c b/crypto/context.c +index 1647371bb7..c9f976c68c 100644 +--- a/crypto/context.c ++++ b/crypto/context.c +@@ -14,7 +14,7 @@ + #include "internal/core.h" + #include "internal/bio.h" + #include "internal/provider.h" +-#include "crypto/ctype.h" ++#include "crypto/context.h" + + struct ossl_lib_ctx_onfree_list_st { + ossl_lib_ctx_onfree_fn *fn; +@@ -22,20 +22,31 @@ struct ossl_lib_ctx_onfree_list_st { + }; + + struct ossl_lib_ctx_st { +- CRYPTO_RWLOCK *lock; +- CRYPTO_EX_DATA data; +- +- /* +- * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But +- * that doesn't work for ex_data itself - so we store that directly. +- */ ++ CRYPTO_RWLOCK *lock, *rand_crngt_lock; + OSSL_EX_DATA_GLOBAL global; + +- /* Map internal static indexes to dynamically created indexes */ +- int dyn_indexes[OSSL_LIB_CTX_MAX_INDEXES]; +- +- /* Keep a separate lock for each index */ +- CRYPTO_RWLOCK *index_locks[OSSL_LIB_CTX_MAX_INDEXES]; ++ void *property_string_data; ++ void *evp_method_store; ++ void *provider_store; ++ void *namemap; ++ void *property_defns; ++ void *global_properties; ++ void *drbg; ++ void *drbg_nonce; ++#ifndef FIPS_MODULE ++ void *provider_conf; ++ void *bio_core; ++ void *child_provider; ++ OSSL_METHOD_STORE *decoder_store; ++ OSSL_METHOD_STORE *encoder_store; ++ OSSL_METHOD_STORE *store_loader_store; ++ void *self_test_cb; ++#endif ++ void *rand_crngt; ++#ifdef FIPS_MODULE ++ void *thread_event_handler; ++ void *fips_prov; ++#endif + + CRYPTO_RWLOCK *oncelock; + int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE]; +@@ -68,9 +79,10 @@ int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx) + return ctx->ischild; + } + ++static void context_deinit_objs(OSSL_LIB_CTX *ctx); ++ + static int context_init(OSSL_LIB_CTX *ctx) + { +- size_t i; + int exdata_done = 0; + + ctx->lock = CRYPTO_THREAD_lock_new(); +@@ -81,48 +93,246 @@ static int context_init(OSSL_LIB_CTX *ctx) + if (ctx->oncelock == NULL) + goto err; + +- for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) { +- ctx->index_locks[i] = CRYPTO_THREAD_lock_new(); +- ctx->dyn_indexes[i] = -1; +- if (ctx->index_locks[i] == NULL) +- goto err; +- } ++ ctx->rand_crngt_lock = CRYPTO_THREAD_lock_new(); ++ if (ctx->rand_crngt_lock == NULL) ++ goto err; + +- /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */ ++ /* Initialize ex_data. */ + if (!ossl_do_ex_data_init(ctx)) + goto err; + exdata_done = 1; + +- if (!ossl_crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, +- &ctx->data)) ++ /* P2. We want evp_method_store to be cleaned up before the provider store */ ++ ctx->evp_method_store = ossl_method_store_new(ctx); ++ if (ctx->evp_method_store == NULL) ++ goto err; ++ ++#ifndef FIPS_MODULE ++ /* P2. Must be freed before the provider store is freed */ ++ ctx->provider_conf = ossl_prov_conf_ctx_new(ctx); ++ if (ctx->provider_conf == NULL) ++ goto err; ++#endif ++ ++ /* P2. */ ++ ctx->drbg = ossl_rand_ctx_new(ctx); ++ if (ctx->drbg == NULL) ++ goto err; ++ ++#ifndef FIPS_MODULE ++ /* P2. We want decoder_store to be cleaned up before the provider store */ ++ ctx->decoder_store = ossl_method_store_new(ctx); ++ if (ctx->decoder_store == NULL) ++ goto err; ++ ++ /* P2. We want encoder_store to be cleaned up before the provider store */ ++ ctx->encoder_store = ossl_method_store_new(ctx); ++ if (ctx->encoder_store == NULL) ++ goto err; ++ ++ /* P2. We want loader_store to be cleaned up before the provider store */ ++ ctx->store_loader_store = ossl_method_store_new(ctx); ++ if (ctx->store_loader_store == NULL) ++ goto err; ++#endif ++ ++ /* P1. Needs to be freed before the child provider data is freed */ ++ ctx->provider_store = ossl_provider_store_new(ctx); ++ if (ctx->provider_store == NULL) ++ goto err; ++ ++ /* Default priority. */ ++ ctx->property_string_data = ossl_property_string_data_new(ctx); ++ if (ctx->property_string_data == NULL) + goto err; + ++ ctx->namemap = ossl_stored_namemap_new(ctx); ++ if (ctx->namemap == NULL) ++ goto err; ++ ++ ctx->property_defns = ossl_property_defns_new(ctx); ++ if (ctx->property_defns == NULL) ++ goto err; ++ ++ ctx->global_properties = ossl_ctx_global_properties_new(ctx); ++ if (ctx->global_properties == NULL) ++ goto err; ++ ++#ifndef FIPS_MODULE ++ ctx->bio_core = ossl_bio_core_globals_new(ctx); ++ if (ctx->bio_core == NULL) ++ goto err; ++#endif ++ ++ ctx->drbg_nonce = ossl_prov_drbg_nonce_ctx_new(ctx); ++ if (ctx->drbg_nonce == NULL) ++ goto err; ++ ++#ifndef FIPS_MODULE ++ ctx->self_test_cb = ossl_self_test_set_callback_new(ctx); ++ if (ctx->self_test_cb == NULL) ++ goto err; ++#endif ++ ++#ifdef FIPS_MODULE ++ ctx->thread_event_handler = ossl_thread_event_ctx_new(ctx); ++ if (ctx->thread_event_handler == NULL) ++ goto err; ++ ++ ctx->fips_prov = ossl_fips_prov_ossl_ctx_new(ctx); ++ if (ctx->fips_prov == NULL) ++ goto err; ++#endif ++ ++ /* Low priority. */ ++#ifndef FIPS_MODULE ++ ctx->child_provider = ossl_child_prov_ctx_new(ctx); ++ if (ctx->child_provider == NULL) ++ goto err; ++#endif ++ + /* Everything depends on properties, so we also pre-initialise that */ + if (!ossl_property_parse_init(ctx)) + goto err; + + return 1; ++ + err: ++ context_deinit_objs(ctx); ++ + if (exdata_done) + ossl_crypto_cleanup_all_ex_data_int(ctx); +- for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) +- CRYPTO_THREAD_lock_free(ctx->index_locks[i]); ++ ++ CRYPTO_THREAD_lock_free(ctx->rand_crngt_lock); + CRYPTO_THREAD_lock_free(ctx->oncelock); + CRYPTO_THREAD_lock_free(ctx->lock); + memset(ctx, '\0', sizeof(*ctx)); + return 0; + } + ++static void context_deinit_objs(OSSL_LIB_CTX *ctx) ++{ ++ /* P2. We want evp_method_store to be cleaned up before the provider store */ ++ if (ctx->evp_method_store != NULL) { ++ ossl_method_store_free(ctx->evp_method_store); ++ ctx->evp_method_store = NULL; ++ } ++ ++ /* P2. */ ++ if (ctx->drbg != NULL) { ++ ossl_rand_ctx_free(ctx->drbg); ++ ctx->drbg = NULL; ++ } ++ ++#ifndef FIPS_MODULE ++ /* P2. */ ++ if (ctx->provider_conf != NULL) { ++ ossl_prov_conf_ctx_free(ctx->provider_conf); ++ ctx->provider_conf = NULL; ++ } ++ ++ /* P2. We want decoder_store to be cleaned up before the provider store */ ++ if (ctx->decoder_store != NULL) { ++ ossl_method_store_free(ctx->decoder_store); ++ ctx->decoder_store = NULL; ++ } ++ ++ /* P2. We want encoder_store to be cleaned up before the provider store */ ++ if (ctx->encoder_store != NULL) { ++ ossl_method_store_free(ctx->encoder_store); ++ ctx->encoder_store = NULL; ++ } ++ ++ /* P2. We want loader_store to be cleaned up before the provider store */ ++ if (ctx->store_loader_store != NULL) { ++ ossl_method_store_free(ctx->store_loader_store); ++ ctx->store_loader_store = NULL; ++ } ++#endif ++ ++ /* P1. Needs to be freed before the child provider data is freed */ ++ if (ctx->provider_store != NULL) { ++ ossl_provider_store_free(ctx->provider_store); ++ ctx->provider_store = NULL; ++ } ++ ++ /* Default priority. */ ++ if (ctx->property_string_data != NULL) { ++ ossl_property_string_data_free(ctx->property_string_data); ++ ctx->property_string_data = NULL; ++ } ++ ++ if (ctx->namemap != NULL) { ++ ossl_stored_namemap_free(ctx->namemap); ++ ctx->namemap = NULL; ++ } ++ ++ if (ctx->property_defns != NULL) { ++ ossl_property_defns_free(ctx->property_defns); ++ ctx->property_defns = NULL; ++ } ++ ++ if (ctx->global_properties != NULL) { ++ ossl_ctx_global_properties_free(ctx->global_properties); ++ ctx->global_properties = NULL; ++ } ++ ++#ifndef FIPS_MODULE ++ if (ctx->bio_core != NULL) { ++ ossl_bio_core_globals_free(ctx->bio_core); ++ ctx->bio_core = NULL; ++ } ++#endif ++ ++ if (ctx->drbg_nonce != NULL) { ++ ossl_prov_drbg_nonce_ctx_free(ctx->drbg_nonce); ++ ctx->drbg_nonce = NULL; ++ } ++ ++#ifndef FIPS_MODULE ++ if (ctx->self_test_cb != NULL) { ++ ossl_self_test_set_callback_free(ctx->self_test_cb); ++ ctx->self_test_cb = NULL; ++ } ++#endif ++ ++ if (ctx->rand_crngt != NULL) { ++ ossl_rand_crng_ctx_free(ctx->rand_crngt); ++ ctx->rand_crngt = NULL; ++ } ++ ++#ifdef FIPS_MODULE ++ if (ctx->thread_event_handler != NULL) { ++ ossl_thread_event_ctx_free(ctx->thread_event_handler); ++ ctx->thread_event_handler = NULL; ++ } ++ ++ if (ctx->fips_prov != NULL) { ++ ossl_fips_prov_ossl_ctx_free(ctx->fips_prov); ++ ctx->fips_prov = NULL; ++ } ++#endif ++ ++ /* Low priority. */ ++#ifndef FIPS_MODULE ++ if (ctx->child_provider != NULL) { ++ ossl_child_prov_ctx_free(ctx->child_provider); ++ ctx->child_provider = NULL; ++ } ++#endif ++} ++ + static int context_deinit(OSSL_LIB_CTX *ctx) + { + struct ossl_lib_ctx_onfree_list_st *tmp, *onfree; +- int i; + + if (ctx == NULL) + return 1; + + ossl_ctx_thread_stop(ctx); + ++ context_deinit_objs(ctx); ++ + onfree = ctx->onfreelist; + while (onfree != NULL) { + onfree->fn(ctx); +@@ -130,13 +340,14 @@ static int context_deinit(OSSL_LIB_CTX *ctx) + onfree = onfree->next; + OPENSSL_free(tmp); + } +- CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, &ctx->data); ++ + ossl_crypto_cleanup_all_ex_data_int(ctx); +- for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) +- CRYPTO_THREAD_lock_free(ctx->index_locks[i]); + ++ CRYPTO_THREAD_lock_free(ctx->rand_crngt_lock); + CRYPTO_THREAD_lock_free(ctx->oncelock); + CRYPTO_THREAD_lock_free(ctx->lock); ++ ctx->rand_crngt_lock = NULL; ++ ctx->oncelock = NULL; + ctx->lock = NULL; + return 1; + } +@@ -300,127 +511,89 @@ int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx) + return 0; + } + +-static void ossl_lib_ctx_generic_new(void *parent_ign, void *ptr_ign, +- CRYPTO_EX_DATA *ad, int index, +- long argl_ign, void *argp) ++void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index) + { +- const OSSL_LIB_CTX_METHOD *meth = argp; +- OSSL_LIB_CTX *ctx = ossl_crypto_ex_data_get_ossl_lib_ctx(ad); +- void *ptr = meth->new_func(ctx); +- +- if (ptr != NULL) { +- if (!CRYPTO_THREAD_write_lock(ctx->lock)) +- /* +- * Can't return something, so best to hope that something will +- * fail later. :( +- */ +- return; +- CRYPTO_set_ex_data(ad, index, ptr); +- CRYPTO_THREAD_unlock(ctx->lock); +- } +-} +-static void ossl_lib_ctx_generic_free(void *parent_ign, void *ptr, +- CRYPTO_EX_DATA *ad, int index, +- long argl_ign, void *argp) +-{ +- const OSSL_LIB_CTX_METHOD *meth = argp; +- +- meth->free_func(ptr); +-} +- +-static int ossl_lib_ctx_init_index(OSSL_LIB_CTX *ctx, int static_index, +- const OSSL_LIB_CTX_METHOD *meth) +-{ +- int idx; ++ void *p; + + ctx = ossl_lib_ctx_get_concrete(ctx); + if (ctx == NULL) +- return 0; ++ return NULL; + +- idx = ossl_crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, 0, +- (void *)meth, +- ossl_lib_ctx_generic_new, +- NULL, ossl_lib_ctx_generic_free, +- meth->priority); +- if (idx < 0) +- return 0; ++ switch (index) { ++ case OSSL_LIB_CTX_PROPERTY_STRING_INDEX: ++ return ctx->property_string_data; ++ case OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX: ++ return ctx->evp_method_store; ++ case OSSL_LIB_CTX_PROVIDER_STORE_INDEX: ++ return ctx->provider_store; ++ case OSSL_LIB_CTX_NAMEMAP_INDEX: ++ return ctx->namemap; ++ case OSSL_LIB_CTX_PROPERTY_DEFN_INDEX: ++ return ctx->property_defns; ++ case OSSL_LIB_CTX_GLOBAL_PROPERTIES: ++ return ctx->global_properties; ++ case OSSL_LIB_CTX_DRBG_INDEX: ++ return ctx->drbg; ++ case OSSL_LIB_CTX_DRBG_NONCE_INDEX: ++ return ctx->drbg_nonce; ++#ifndef FIPS_MODULE ++ case OSSL_LIB_CTX_PROVIDER_CONF_INDEX: ++ return ctx->provider_conf; ++ case OSSL_LIB_CTX_BIO_CORE_INDEX: ++ return ctx->bio_core; ++ case OSSL_LIB_CTX_CHILD_PROVIDER_INDEX: ++ return ctx->child_provider; ++ case OSSL_LIB_CTX_DECODER_STORE_INDEX: ++ return ctx->decoder_store; ++ case OSSL_LIB_CTX_ENCODER_STORE_INDEX: ++ return ctx->encoder_store; ++ case OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX: ++ return ctx->store_loader_store; ++ case OSSL_LIB_CTX_SELF_TEST_CB_INDEX: ++ return ctx->self_test_cb; ++#endif + +- ctx->dyn_indexes[static_index] = idx; +- return 1; +-} ++ case OSSL_LIB_CTX_RAND_CRNGT_INDEX: { ++ ++ /* ++ * rand_crngt must be lazily initialized because it calls into ++ * libctx, so must not be called from context_init, else a deadlock ++ * will occur. ++ * ++ * We use a separate lock because code called by the instantiation ++ * of rand_crngt is liable to try and take the libctx lock. ++ */ ++ if (CRYPTO_THREAD_read_lock(ctx->rand_crngt_lock) != 1) ++ return NULL; + +-void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index, +- const OSSL_LIB_CTX_METHOD *meth) +-{ +- void *data = NULL; +- int dynidx; ++ if (ctx->rand_crngt == NULL) { ++ CRYPTO_THREAD_unlock(ctx->rand_crngt_lock); + +- ctx = ossl_lib_ctx_get_concrete(ctx); +- if (ctx == NULL) +- return NULL; +- +- if (!CRYPTO_THREAD_read_lock(ctx->lock)) +- return NULL; +- dynidx = ctx->dyn_indexes[index]; +- CRYPTO_THREAD_unlock(ctx->lock); ++ if (CRYPTO_THREAD_write_lock(ctx->rand_crngt_lock) != 1) ++ return NULL; + +- if (dynidx != -1) { +- if (!CRYPTO_THREAD_read_lock(ctx->index_locks[index])) +- return NULL; +- if (!CRYPTO_THREAD_read_lock(ctx->lock)) { +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return NULL; ++ if (ctx->rand_crngt == NULL) ++ ctx->rand_crngt = ossl_rand_crng_ctx_new(ctx); + } +- data = CRYPTO_get_ex_data(&ctx->data, dynidx); +- CRYPTO_THREAD_unlock(ctx->lock); +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return data; +- } + +- if (!CRYPTO_THREAD_write_lock(ctx->index_locks[index])) +- return NULL; +- if (!CRYPTO_THREAD_write_lock(ctx->lock)) { +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return NULL; +- } ++ p = ctx->rand_crngt; + +- dynidx = ctx->dyn_indexes[index]; +- if (dynidx != -1) { +- data = CRYPTO_get_ex_data(&ctx->data, dynidx); +- CRYPTO_THREAD_unlock(ctx->lock); +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return data; +- } ++ CRYPTO_THREAD_unlock(ctx->rand_crngt_lock); + +- if (!ossl_lib_ctx_init_index(ctx, index, meth)) { +- CRYPTO_THREAD_unlock(ctx->lock); +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return NULL; ++ return p; + } + +- CRYPTO_THREAD_unlock(ctx->lock); +- +- /* +- * The alloc call ensures there's a value there. We release the ctx->lock +- * for this, because the allocation itself may recursively call +- * ossl_lib_ctx_get_data for other indexes (never this one). The allocation +- * will itself aquire the ctx->lock when it actually comes to store the +- * allocated data (see ossl_lib_ctx_generic_new() above). We call +- * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data(). +- * They do the same thing except that the latter calls CRYPTO_get_ex_data() +- * as well - which we must not do without holding the ctx->lock. +- */ +- if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, +- &ctx->data, ctx->dyn_indexes[index])) { +- if (!CRYPTO_THREAD_read_lock(ctx->lock)) +- goto end; +- data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]); +- CRYPTO_THREAD_unlock(ctx->lock); +- } ++#ifdef FIPS_MODULE ++ case OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX: ++ return ctx->thread_event_handler; + +-end: +- CRYPTO_THREAD_unlock(ctx->index_locks[index]); +- return data; ++ case OSSL_LIB_CTX_FIPS_PROV_INDEX: ++ return ctx->fips_prov; ++#endif ++ ++ default: ++ return NULL; ++ } + } + + OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx) +diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c +index 7e11ab1c88..554524a5c4 100644 +--- a/crypto/core_namemap.c ++++ b/crypto/core_namemap.c +@@ -12,6 +12,7 @@ + #include "crypto/lhash.h" /* ossl_lh_strcasehash */ + #include "internal/tsan_assist.h" + #include "internal/sizes.h" ++#include "crypto/context.h" + + /*- + * The namenum entry +@@ -60,7 +61,7 @@ static void namenum_free(NAMENUM_ENTRY *n) + + /* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */ + +-static void *stored_namemap_new(OSSL_LIB_CTX *libctx) ++void *ossl_stored_namemap_new(OSSL_LIB_CTX *libctx) + { + OSSL_NAMEMAP *namemap = ossl_namemap_new(); + +@@ -70,7 +71,7 @@ static void *stored_namemap_new(OSSL_LIB_CTX *libctx) + return namemap; + } + +-static void stored_namemap_free(void *vnamemap) ++void ossl_stored_namemap_free(void *vnamemap) + { + OSSL_NAMEMAP *namemap = vnamemap; + +@@ -81,12 +82,6 @@ static void stored_namemap_free(void *vnamemap) + } + } + +-static const OSSL_LIB_CTX_METHOD stored_namemap_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- stored_namemap_new, +- stored_namemap_free, +-}; +- + /*- + * API functions + * ============= +@@ -468,8 +463,7 @@ OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx) + int nms; + #endif + OSSL_NAMEMAP *namemap = +- ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX, +- &stored_namemap_method); ++ ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX); + + if (namemap == NULL) + return NULL; +diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c +index 496fbe3320..62e30ccb1a 100644 +--- a/crypto/encode_decode/decoder_meth.c ++++ b/crypto/encode_decode/decoder_meth.c +@@ -17,6 +17,7 @@ + #include "internal/provider.h" + #include "crypto/decoder.h" + #include "encoder_local.h" ++#include "crypto/context.h" + + /* + * Decoder can have multiple names, separated with colons in a name string +@@ -65,25 +66,6 @@ void OSSL_DECODER_free(OSSL_DECODER *decoder) + OPENSSL_free(decoder); + } + +-/* Permanent decoder method store, constructor and destructor */ +-static void decoder_store_free(void *vstore) +-{ +- ossl_method_store_free(vstore); +-} +- +-static void *decoder_store_new(OSSL_LIB_CTX *ctx) +-{ +- return ossl_method_store_new(ctx); +-} +- +- +-static const OSSL_LIB_CTX_METHOD decoder_store_method = { +- /* We want decoder_store to be cleaned up before the provider store */ +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- decoder_store_new, +- decoder_store_free, +-}; +- + /* Data to be passed through ossl_method_construct() */ + struct decoder_data_st { + OSSL_LIB_CTX *libctx; +@@ -120,8 +102,7 @@ static void dealloc_tmp_decoder_store(void *store) + /* Get the permanent decoder store */ + static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX, +- &decoder_store_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX); + } + + static int reserve_decoder_store(void *store, void *data) +diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c +index 89e7b6abf8..f91d349587 100644 +--- a/crypto/encode_decode/encoder_meth.c ++++ b/crypto/encode_decode/encoder_meth.c +@@ -17,6 +17,7 @@ + #include "internal/provider.h" + #include "crypto/encoder.h" + #include "encoder_local.h" ++#include "crypto/context.h" + + /* + * Encoder can have multiple names, separated with colons in a name string +@@ -65,25 +66,6 @@ void OSSL_ENCODER_free(OSSL_ENCODER *encoder) + OPENSSL_free(encoder); + } + +-/* Permanent encoder method store, constructor and destructor */ +-static void encoder_store_free(void *vstore) +-{ +- ossl_method_store_free(vstore); +-} +- +-static void *encoder_store_new(OSSL_LIB_CTX *ctx) +-{ +- return ossl_method_store_new(ctx); +-} +- +- +-static const OSSL_LIB_CTX_METHOD encoder_store_method = { +- /* We want encoder_store to be cleaned up before the provider store */ +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- encoder_store_new, +- encoder_store_free, +-}; +- + /* Data to be passed through ossl_method_construct() */ + struct encoder_data_st { + OSSL_LIB_CTX *libctx; +@@ -120,8 +102,7 @@ static void dealloc_tmp_encoder_store(void *store) + /* Get the permanent encoder store */ + static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX, +- &encoder_store_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX); + } + + static int reserve_encoder_store(void *store, void *data) +diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c +index aafd927e63..b9ef0200bb 100644 +--- a/crypto/evp/evp_fetch.c ++++ b/crypto/evp/evp_fetch.c +@@ -23,24 +23,6 @@ + + #define NAME_SEPARATOR ':' + +-static void evp_method_store_free(void *vstore) +-{ +- ossl_method_store_free(vstore); +-} +- +-static void *evp_method_store_new(OSSL_LIB_CTX *ctx) +-{ +- return ossl_method_store_new(ctx); +-} +- +- +-static const OSSL_LIB_CTX_METHOD evp_method_store_method = { +- /* We want evp_method_store to be cleaned up before the provider store */ +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- evp_method_store_new, +- evp_method_store_free, +-}; +- + /* Data to be passed through ossl_method_construct() */ + struct evp_method_data_st { + OSSL_LIB_CTX *libctx; +@@ -79,8 +61,7 @@ static void *get_tmp_evp_method_store(void *data) + + static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX, +- &evp_method_store_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX); + } + + static int reserve_evp_method_store(void *store, void *data) +diff --git a/crypto/initthread.c b/crypto/initthread.c +index 1bdaeda9fc..ee57d14466 100644 +--- a/crypto/initthread.c ++++ b/crypto/initthread.c +@@ -12,6 +12,7 @@ + #include "crypto/cryptlib.h" + #include "prov/providercommon.h" + #include "internal/thread_once.h" ++#include "crypto/context.h" + + #ifdef FIPS_MODULE + #include "prov/provider_ctx.h" +@@ -248,7 +249,7 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) + + #else + +-static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) + { + THREAD_EVENT_HANDLER **hands = NULL; + CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal)); +@@ -274,17 +275,11 @@ static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return NULL; + } + +-static void thread_event_ossl_ctx_free(void *tlocal) ++void ossl_thread_event_ctx_free(void *tlocal) + { + OPENSSL_free(tlocal); + } + +-static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- thread_event_ossl_ctx_new, +- thread_event_ossl_ctx_free, +-}; +- + static void ossl_arg_thread_stop(void *arg) + { + ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg); +@@ -294,8 +289,7 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) + { + THREAD_EVENT_HANDLER **hands; + CRYPTO_THREAD_LOCAL *local +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, +- &thread_event_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX); + + if (local == NULL) + return; +@@ -363,8 +357,7 @@ int ossl_init_thread_start(const void *index, void *arg, + * OSSL_LIB_CTX gets informed about thread stop events individually. + */ + CRYPTO_THREAD_LOCAL *local +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, +- &thread_event_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX); + #else + /* + * Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per +diff --git a/crypto/property/defn_cache.c b/crypto/property/defn_cache.c +index b4cd67c990..c697e6f474 100644 +--- a/crypto/property/defn_cache.c ++++ b/crypto/property/defn_cache.c +@@ -15,6 +15,7 @@ + #include "internal/property.h" + #include "internal/core.h" + #include "property_local.h" ++#include "crypto/context.h" + + /* + * Implement a property definition cache. +@@ -47,7 +48,7 @@ static void property_defn_free(PROPERTY_DEFN_ELEM *elem) + OPENSSL_free(elem); + } + +-static void property_defns_free(void *vproperty_defns) ++void ossl_property_defns_free(void *vproperty_defns) + { + LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns; + +@@ -58,24 +59,17 @@ static void property_defns_free(void *vproperty_defns) + } + } + +-static void *property_defns_new(OSSL_LIB_CTX *ctx) { ++void *ossl_property_defns_new(OSSL_LIB_CTX *ctx) { + return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp); + } + +-static const OSSL_LIB_CTX_METHOD property_defns_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- property_defns_new, +- property_defns_free, +-}; +- + OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop) + { + PROPERTY_DEFN_ELEM elem, *r; + LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; + + property_defns = ossl_lib_ctx_get_data(ctx, +- OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, +- &property_defns_method); ++ OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); + if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx)) + return NULL; + +@@ -99,8 +93,7 @@ int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop, + int res = 1; + + property_defns = ossl_lib_ctx_get_data(ctx, +- OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, +- &property_defns_method); ++ OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); + if (property_defns == NULL) + return 0; + +diff --git a/crypto/property/property.c b/crypto/property/property.c +index 2c92cb5e50..fe00815cbe 100644 +--- a/crypto/property/property.c ++++ b/crypto/property/property.c +@@ -23,6 +23,7 @@ + #include "crypto/lhash.h" + #include "crypto/sparse_array.h" + #include "property_local.h" ++#include "crypto/context.h" + + /* + * The number of elements in the query cache before we initiate a flush. +@@ -107,7 +108,7 @@ static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store, + static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid); + + /* Global properties are stored per library context */ +-static void ossl_ctx_global_properties_free(void *vglobp) ++void ossl_ctx_global_properties_free(void *vglobp) + { + OSSL_GLOBAL_PROPERTIES *globp = vglobp; + +@@ -117,17 +118,11 @@ static void ossl_ctx_global_properties_free(void *vglobp) + } + } + +-static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx) ++void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx) + { + return OPENSSL_zalloc(sizeof(OSSL_GLOBAL_PROPERTIES)); + } + +-static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- ossl_ctx_global_properties_new, +- ossl_ctx_global_properties_free, +-}; +- + OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx, + ossl_unused int loadconfig) + { +@@ -137,8 +132,7 @@ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx, + if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL)) + return NULL; + #endif +- globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES, +- &ossl_ctx_global_properties_method); ++ globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); + + return globp != NULL ? &globp->list : NULL; + } +@@ -147,8 +141,7 @@ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx, + int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx) + { + OSSL_GLOBAL_PROPERTIES *globp +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES, +- &ossl_ctx_global_properties_method); ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); + + return globp != NULL && globp->no_mirrored ? 1 : 0; + } +@@ -156,8 +149,7 @@ int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx) + void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx) + { + OSSL_GLOBAL_PROPERTIES *globp +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES, +- &ossl_ctx_global_properties_method); ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); + + if (globp != NULL) + globp->no_mirrored = 1; +diff --git a/crypto/property/property_string.c b/crypto/property/property_string.c +index 5a1f5cd2dc..3f978c06a3 100644 +--- a/crypto/property/property_string.c ++++ b/crypto/property/property_string.c +@@ -13,6 +13,7 @@ + #include + #include "crypto/lhash.h" + #include "property_local.h" ++#include "crypto/context.h" + + /* + * Property strings are a consolidation of all strings seen by the property +@@ -72,7 +73,7 @@ static void property_table_free(PROP_TABLE **pt) + } + } + +-static void property_string_data_free(void *vpropdata) ++void ossl_property_string_data_free(void *vpropdata) + { + PROPERTY_STRING_DATA *propdata = vpropdata; + +@@ -92,7 +93,7 @@ static void property_string_data_free(void *vpropdata) + OPENSSL_free(propdata); + } + +-static void *property_string_data_new(OSSL_LIB_CTX *ctx) { ++void *ossl_property_string_data_new(OSSL_LIB_CTX *ctx) { + PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata)); + + if (propdata == NULL) +@@ -114,18 +115,12 @@ static void *property_string_data_new(OSSL_LIB_CTX *ctx) { + || propdata->prop_values == NULL + || propdata->prop_namelist == NULL + || propdata->prop_valuelist == NULL) { +- property_string_data_free(propdata); ++ ossl_property_string_data_free(propdata); + return NULL; + } + return propdata; + } + +-static const OSSL_LIB_CTX_METHOD property_string_data_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- property_string_data_new, +- property_string_data_free, +-}; +- + static PROPERTY_STRING *new_property_string(const char *s, + OSSL_PROPERTY_IDX *pidx) + { +@@ -151,8 +146,7 @@ static OSSL_PROPERTY_IDX ossl_property_string(OSSL_LIB_CTX *ctx, int name, + STACK_OF(OPENSSL_CSTRING) *slist; + OSSL_PROPERTY_IDX *pidx; + PROPERTY_STRING_DATA *propdata +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, +- &property_string_data_method); ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX); + + if (propdata == NULL) + return 0; +@@ -224,8 +218,7 @@ static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx, + { + const char *r; + PROPERTY_STRING_DATA *propdata +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, +- &property_string_data_method); ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX); + + if (propdata == NULL) + return NULL; +diff --git a/crypto/provider_child.c b/crypto/provider_child.c +index 16728f9c12..b1eadd5b19 100644 +--- a/crypto/provider_child.c ++++ b/crypto/provider_child.c +@@ -16,6 +16,7 @@ + #include "internal/provider.h" + #include "internal/cryptlib.h" + #include "crypto/evp.h" ++#include "crypto/context.h" + + DEFINE_STACK_OF(OSSL_PROVIDER) + +@@ -33,12 +34,12 @@ struct child_prov_globals { + OSSL_FUNC_provider_free_fn *c_prov_free; + }; + +-static void *child_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *libctx) + { + return OPENSSL_zalloc(sizeof(struct child_prov_globals)); + } + +-static void child_prov_ossl_ctx_free(void *vgbl) ++void ossl_child_prov_ctx_free(void *vgbl) + { + struct child_prov_globals *gbl = vgbl; + +@@ -46,12 +47,6 @@ static void child_prov_ossl_ctx_free(void *vgbl) + OPENSSL_free(gbl); + } + +-static const OSSL_LIB_CTX_METHOD child_prov_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_LOW_PRIORITY, +- child_prov_ossl_ctx_new, +- child_prov_ossl_ctx_free, +-}; +- + static OSSL_provider_init_fn ossl_child_provider_init; + + static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle, +@@ -84,8 +79,7 @@ static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle, + */ + ctx = (OSSL_LIB_CTX *)c_get_libctx(handle); + +- gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +@@ -103,8 +97,7 @@ static int provider_create_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata) + OSSL_PROVIDER *cprov; + int ret = 0; + +- gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +@@ -166,8 +159,7 @@ static int provider_remove_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata) + const char *provname; + OSSL_PROVIDER *cprov; + +- gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +@@ -203,8 +195,7 @@ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx, + if (ctx == NULL) + return 0; + +- gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +@@ -271,8 +262,7 @@ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx, + void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx) + { + struct child_prov_globals *gbl +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return; + +@@ -297,8 +287,7 @@ int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate) + const OSSL_CORE_HANDLE *parent_handle; + + gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov), +- OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +@@ -314,8 +303,7 @@ int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate) + const OSSL_CORE_HANDLE *parent_handle; + + gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov), +- OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, +- &child_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); + if (gbl == NULL) + return 0; + +diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c +index 6a62f0df60..e3b576d6c2 100644 +--- a/crypto/provider_conf.c ++++ b/crypto/provider_conf.c +@@ -16,6 +16,7 @@ + #include "internal/provider.h" + #include "internal/cryptlib.h" + #include "provider_local.h" ++#include "crypto/context.h" + + DEFINE_STACK_OF(OSSL_PROVIDER) + +@@ -26,7 +27,7 @@ typedef struct { + STACK_OF(OSSL_PROVIDER) *activated_providers; + } PROVIDER_CONF_GLOBAL; + +-static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_prov_conf_ctx_new(OSSL_LIB_CTX *libctx) + { + PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl)); + +@@ -42,7 +43,7 @@ static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return pcgbl; + } + +-static void prov_conf_ossl_ctx_free(void *vpcgbl) ++void ossl_prov_conf_ctx_free(void *vpcgbl) + { + PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl; + +@@ -54,13 +55,6 @@ static void prov_conf_ossl_ctx_free(void *vpcgbl) + OPENSSL_free(pcgbl); + } + +-static const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = { +- /* Must be freed before the provider store is freed */ +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- prov_conf_ossl_ctx_new, +- prov_conf_ossl_ctx_free, +-}; +- + static const char *skip_dot(const char *name) + { + const char *p = strchr(name, '.'); +@@ -141,8 +135,7 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, + int soft, const CONF *cnf) + { + PROVIDER_CONF_GLOBAL *pcgbl +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX, +- &provider_conf_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX); + OSSL_PROVIDER *prov = NULL, *actual = NULL; + int ok = 0; + +diff --git a/crypto/provider_core.c b/crypto/provider_core.c +index 25583868db..c6925b4028 100644 +--- a/crypto/provider_core.c ++++ b/crypto/provider_core.c +@@ -29,6 +29,7 @@ + #include "internal/bio.h" + #include "internal/core.h" + #include "provider_local.h" ++#include "crypto/context.h" + #ifndef FIPS_MODULE + # include + #endif +@@ -282,7 +283,7 @@ void ossl_provider_info_clear(OSSL_PROVIDER_INFO *info) + sk_INFOPAIR_pop_free(info->parameters, infopair_free); + } + +-static void provider_store_free(void *vstore) ++void ossl_provider_store_free(void *vstore) + { + struct provider_store_st *store = vstore; + size_t i; +@@ -304,7 +305,7 @@ static void provider_store_free(void *vstore) + OPENSSL_free(store); + } + +-static void *provider_store_new(OSSL_LIB_CTX *ctx) ++void *ossl_provider_store_new(OSSL_LIB_CTX *ctx) + { + struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store)); + +@@ -315,7 +316,7 @@ static void *provider_store_new(OSSL_LIB_CTX *ctx) + || (store->child_cbs = sk_OSSL_PROVIDER_CHILD_CB_new_null()) == NULL + #endif + || (store->lock = CRYPTO_THREAD_lock_new()) == NULL) { +- provider_store_free(store); ++ ossl_provider_store_free(store); + return NULL; + } + store->libctx = ctx; +@@ -324,19 +325,11 @@ static void *provider_store_new(OSSL_LIB_CTX *ctx) + return store; + } + +-static const OSSL_LIB_CTX_METHOD provider_store_method = { +- /* Needs to be freed before the child provider data is freed */ +- OSSL_LIB_CTX_METHOD_PRIORITY_1, +- provider_store_new, +- provider_store_free, +-}; +- + static struct provider_store_st *get_provider_store(OSSL_LIB_CTX *libctx) + { + struct provider_store_st *store = NULL; + +- store = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_STORE_INDEX, +- &provider_store_method); ++ store = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_STORE_INDEX); + if (store == NULL) + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + return store; +diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c +index caedbca204..3f04ec171e 100644 +--- a/crypto/rand/rand_lib.c ++++ b/crypto/rand/rand_lib.c +@@ -18,6 +18,7 @@ + #include "crypto/rand.h" + #include "crypto/cryptlib.h" + #include "rand_local.h" ++#include "crypto/context.h" + + #ifndef FIPS_MODULE + # include +@@ -434,7 +435,7 @@ typedef struct rand_global_st { + * Initialize the OSSL_LIB_CTX global DRBGs on first use. + * Returns the allocated global data on success or NULL on failure. + */ +-static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_rand_ctx_new(OSSL_LIB_CTX *libctx) + { + RAND_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl)); + +@@ -469,7 +470,7 @@ static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return NULL; + } + +-static void rand_ossl_ctx_free(void *vdgbl) ++void ossl_rand_ctx_free(void *vdgbl) + { + RAND_GLOBAL *dgbl = vdgbl; + +@@ -491,16 +492,9 @@ static void rand_ossl_ctx_free(void *vdgbl) + OPENSSL_free(dgbl); + } + +-static const OSSL_LIB_CTX_METHOD rand_drbg_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- rand_ossl_ctx_new, +- rand_ossl_ctx_free, +-}; +- + static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX, +- &rand_drbg_ossl_ctx_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX); + } + + static void rand_delete_thread_state(void *arg) +diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c +index dad4be208a..e0999fb05f 100644 +--- a/crypto/self_test_core.c ++++ b/crypto/self_test_core.c +@@ -11,6 +11,7 @@ + #include + #include + #include "internal/cryptlib.h" ++#include "crypto/context.h" + + typedef struct self_test_cb_st + { +@@ -32,7 +33,7 @@ struct ossl_self_test_st + }; + + #ifndef FIPS_MODULE +-static void *self_test_set_callback_new(OSSL_LIB_CTX *ctx) ++void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *ctx) + { + SELF_TEST_CB *stcb; + +@@ -40,21 +41,14 @@ static void *self_test_set_callback_new(OSSL_LIB_CTX *ctx) + return stcb; + } + +-static void self_test_set_callback_free(void *stcb) ++void ossl_self_test_set_callback_free(void *stcb) + { + OPENSSL_free(stcb); + } + +-static const OSSL_LIB_CTX_METHOD self_test_set_callback_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- self_test_set_callback_new, +- self_test_set_callback_free, +-}; +- + static SELF_TEST_CB *get_self_test_callback(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX, +- &self_test_set_callback_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX); + } + + void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb, +diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c +index a5b0d1b095..42848b799a 100644 +--- a/crypto/store/store_meth.c ++++ b/crypto/store/store_meth.c +@@ -14,6 +14,7 @@ + #include "internal/property.h" + #include "internal/provider.h" + #include "store_local.h" ++#include "crypto/context.h" + + int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader) + { +@@ -68,25 +69,6 @@ static void free_loader(void *method) + OSSL_STORE_LOADER_free(method); + } + +-/* Permanent loader method store, constructor and destructor */ +-static void loader_store_free(void *vstore) +-{ +- ossl_method_store_free(vstore); +-} +- +-static void *loader_store_new(OSSL_LIB_CTX *ctx) +-{ +- return ossl_method_store_new(ctx); +-} +- +- +-static const OSSL_LIB_CTX_METHOD loader_store_method = { +- /* We want loader_store to be cleaned up before the provider store */ +- OSSL_LIB_CTX_METHOD_PRIORITY_2, +- loader_store_new, +- loader_store_free, +-}; +- + /* Data to be passed through ossl_method_construct() */ + struct loader_data_st { + OSSL_LIB_CTX *libctx; +@@ -123,8 +105,7 @@ static void *get_tmp_loader_store(void *data) + /* Get the permanent loader store */ + static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx) + { +- return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX, +- &loader_store_method); ++ return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX); + } + + static int reserve_loader_store(void *store, void *data) +diff --git a/doc/internal/man3/ossl_lib_ctx_get_data.pod b/doc/internal/man3/ossl_lib_ctx_get_data.pod +index faedf7275f..2ffd000da1 100644 +--- a/doc/internal/man3/ossl_lib_ctx_get_data.pod ++++ b/doc/internal/man3/ossl_lib_ctx_get_data.pod +@@ -11,14 +11,7 @@ ossl_lib_ctx_is_child + #include + #include "internal/cryptlib.h" + +- typedef struct ossl_lib_ctx_method { +- int priority; +- void *(*new_func)(OSSL_LIB_CTX *ctx); +- void (*free_func)(void *); +- } OSSL_LIB_CTX_METHOD; +- +- void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index, +- const OSSL_LIB_CTX_METHOD *meth); ++ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index); + + int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, + ossl_lib_ctx_run_once_fn run_once_fn); +@@ -28,38 +21,24 @@ ossl_lib_ctx_is_child + + =head1 DESCRIPTION + +-Internally, the OpenSSL library context B is implemented +-as a B, which allows data from diverse parts of the +-library to be added and removed dynamically. +-Each such data item must have a corresponding CRYPTO_EX_DATA index +-associated with it. Unlike normal CRYPTO_EX_DATA objects we use static indexes +-to identify data items. These are mapped transparently to CRYPTO_EX_DATA dynamic +-indexes internally to the implementation. +-See the example further down to see how that's done. +- +-ossl_lib_ctx_get_data() is used to retrieve a pointer to the data in +-the library context I associated with the given I. An +-OSSL_LIB_CTX_METHOD must be defined and given in the I parameter. The index +-for it should be defined in cryptlib.h. The functions through the method are +-used to create or free items that are stored at that index whenever a library +-context is created or freed, meaning that the code that use a data item of that +-index doesn't have to worry about that, just use the data available. +- +-Deallocation of an index happens automatically when the library +-context is freed. +- +-ossl_lib_ctx_run_once is used to run some initialisation routine I ++ossl_lib_ctx_run_once() is used to run some initialisation routine I + exactly once per library context I object. Each initialisation routine + should be allocate a unique run once index in cryptlib.h. + + Any resources allocated via a run once initialisation routine can be cleaned up +-using ossl_lib_ctx_onfree. This associates an "on free" routine I with ++using ossl_lib_ctx_onfree(). This associates an "on free" routine I with + the library context I. When I is freed all associated "on free" + routines are called. + + ossl_lib_ctx_is_child() returns 1 if this library context is a child and 0 + otherwise. + ++ossl_lib_ctx_get_data() allows different parts of the library to retrieve ++pointers to structures used in diverse parts of the library. The lifetime of ++these structures is managed by B. The different objects which can ++be retrieved are specified with the given argument I. The valid values of ++I are specified in cryptlib.h. ++ + =head1 RETURN VALUES + + ossl_lib_ctx_get_data() returns a pointer on success, or NULL on +@@ -67,51 +46,15 @@ failure. + + =head1 EXAMPLES + +-=head2 Initialization +- +-For a type C that should end up in the OpenSSL library context, a +-small bit of initialization is needed, i.e. to associate a constructor +-and a destructor to an index. +- +- typedef struct foo_st { +- int i; +- void *data; +- } FOO; +- +- static void *foo_new(OSSL_LIB_CTX *ctx) +- { +- FOO *ptr = OPENSSL_zalloc(sizeof(*foo)); +- if (ptr != NULL) +- ptr->i = 42; +- return ptr; +- } +- static void foo_free(void *ptr) +- { +- OPENSSL_free(ptr); +- } +- +- /* +- * Include a reference to this in the methods table in context.c +- * OSSL_LIB_CTX_FOO_INDEX should be added to internal/cryptlib.h +- * Priorities can be OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- * OSSL_LIB_CTX_METHOD_PRIORITY_1, OSSL_LIB_CTX_METHOD_PRIORITY_2, etc. +- * Default priority is low (0). The higher the priority the earlier the +- * method's destructor will be called when the library context is cleaned up. +- */ +- const OSSL_LIB_CTX_METHOD foo_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- foo_new, +- foo_free +- }; +- + =head2 Usage + +-To get and use the data stored in the library context, simply do this: ++To obtain a pointer for an object managed by the library context, simply do ++this: + + /* + * ctx is received from a caller, + */ +- FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX, &foo_method); ++ FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX); + + =head2 Run Once + +diff --git a/include/crypto/context.h b/include/crypto/context.h +new file mode 100644 +index 0000000000..143f6d6b6d +--- /dev/null ++++ b/include/crypto/context.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright 2022 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 ++ ++void *ossl_provider_store_new(OSSL_LIB_CTX *); ++void *ossl_property_string_data_new(OSSL_LIB_CTX *); ++void *ossl_stored_namemap_new(OSSL_LIB_CTX *); ++void *ossl_property_defns_new(OSSL_LIB_CTX *); ++void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *); ++void *ossl_rand_ctx_new(OSSL_LIB_CTX *); ++void *ossl_prov_conf_ctx_new(OSSL_LIB_CTX *); ++void *ossl_bio_core_globals_new(OSSL_LIB_CTX *); ++void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *); ++void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *); ++void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *); ++void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *); ++void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *); ++void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *); ++ ++void ossl_provider_store_free(void *); ++void ossl_property_string_data_free(void *); ++void ossl_stored_namemap_free(void *); ++void ossl_property_defns_free(void *); ++void ossl_ctx_global_properties_free(void *); ++void ossl_rand_ctx_free(void *); ++void ossl_prov_conf_ctx_free(void *); ++void ossl_bio_core_globals_free(void *); ++void ossl_child_prov_ctx_free(void *); ++void ossl_prov_drbg_nonce_ctx_free(void *); ++void ossl_self_test_set_callback_free(void *); ++void ossl_rand_crng_ctx_free(void *); ++void ossl_thread_event_ctx_free(void *); ++void ossl_fips_prov_ossl_ctx_free(void *); +diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h +index 1291299b6e..ce1a5093ac 100644 +--- a/include/internal/cryptlib.h ++++ b/include/internal/cryptlib.h +@@ -170,24 +170,12 @@ typedef struct ossl_ex_data_global_st { + # define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18 + # define OSSL_LIB_CTX_MAX_INDEXES 19 + +-# define OSSL_LIB_CTX_METHOD_LOW_PRIORITY -1 +-# define OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY 0 +-# define OSSL_LIB_CTX_METHOD_PRIORITY_1 1 +-# define OSSL_LIB_CTX_METHOD_PRIORITY_2 2 +- +-typedef struct ossl_lib_ctx_method { +- int priority; +- void *(*new_func)(OSSL_LIB_CTX *ctx); +- void (*free_func)(void *); +-} OSSL_LIB_CTX_METHOD; +- + OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx); + int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx); + int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx); + + /* Functions to retrieve pointers to data by index */ +-void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *, int /* index */, +- const OSSL_LIB_CTX_METHOD * ctx); ++void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *, int /* index */); + + void ossl_lib_ctx_default_deinit(void); + OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx); +diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c +index 9e0fcf084d..533d9d1598 100644 +--- a/providers/fips/fipsprov.c ++++ b/providers/fips/fipsprov.c +@@ -22,6 +22,7 @@ + #include "prov/provider_util.h" + #include "prov/seeding.h" + #include "self_test.h" ++#include "crypto/context.h" + #include "internal/core.h" + + static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes"; +@@ -83,7 +84,7 @@ typedef struct fips_global_st { + const char *fips_security_check_option; + } FIPS_GLOBAL; + +-static void *fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) + { + FIPS_GLOBAL *fgbl = OPENSSL_zalloc(sizeof(*fgbl)); + +@@ -95,18 +96,11 @@ static void *fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return fgbl; + } + +-static void fips_prov_ossl_ctx_free(void *fgbl) ++void ossl_fips_prov_ossl_ctx_free(void *fgbl) + { + OPENSSL_free(fgbl); + } + +-static const OSSL_LIB_CTX_METHOD fips_prov_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- fips_prov_ossl_ctx_new, +- fips_prov_ossl_ctx_free, +-}; +- +- + /* Parameters we provide to the core */ + static const OSSL_PARAM fips_param_types[] = { + OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0), +@@ -175,8 +169,7 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[]) + { + OSSL_PARAM *p; + FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), +- OSSL_LIB_CTX_FIPS_PROV_INDEX, +- &fips_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_FIPS_PROV_INDEX); + + p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME); + if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL FIPS Provider")) +@@ -213,8 +206,7 @@ static void set_self_test_cb(FIPS_GLOBAL *fgbl) + static int fips_self_test(void *provctx) + { + FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), +- OSSL_LIB_CTX_FIPS_PROV_INDEX, +- &fips_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_FIPS_PROV_INDEX); + + set_self_test_cb(fgbl); + return SELF_TEST_post(&fgbl->selftest_params, 1) ? 1 : 0; +@@ -671,8 +663,7 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, + goto err; + } + +- if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX, +- &fips_prov_ossl_ctx_method)) == NULL) ++ if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX)) == NULL) + goto err; + + fgbl->handle = handle; +@@ -817,8 +808,7 @@ int ERR_pop_to_mark(void) + const OSSL_CORE_HANDLE *FIPS_get_core_handle(OSSL_LIB_CTX *libctx) + { + FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx, +- OSSL_LIB_CTX_FIPS_PROV_INDEX, +- &fips_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_FIPS_PROV_INDEX); + + if (fgbl == NULL) + return NULL; +@@ -896,8 +886,7 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...) + int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx) + { + FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx, +- OSSL_LIB_CTX_FIPS_PROV_INDEX, +- &fips_prov_ossl_ctx_method); ++ OSSL_LIB_CTX_FIPS_PROV_INDEX); + + return fgbl->fips_security_checks; + } +diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c +index 4095994bda..50d4a429da 100644 +--- a/providers/implementations/rands/crngt.c ++++ b/providers/implementations/rands/crngt.c +@@ -23,6 +23,7 @@ + #include "crypto/rand_pool.h" + #include "drbg_local.h" + #include "prov/seeding.h" ++#include "crypto/context.h" + + typedef struct crng_test_global_st { + unsigned char crngt_prev[EVP_MAX_MD_SIZE]; +@@ -52,7 +53,7 @@ static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest, + return 0; + } + +-static void rand_crng_ossl_ctx_free(void *vcrngt_glob) ++void ossl_rand_crng_ctx_free(void *vcrngt_glob) + { + CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; + +@@ -61,7 +62,7 @@ static void rand_crng_ossl_ctx_free(void *vcrngt_glob) + OPENSSL_free(crngt_glob); + } + +-static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) ++void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *ctx) + { + CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); + +@@ -82,12 +83,6 @@ static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) + return crngt_glob; + } + +-static const OSSL_LIB_CTX_METHOD rand_crng_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- rand_crng_ossl_ctx_new, +- rand_crng_ossl_ctx_free, +-}; +- + static int prov_crngt_compare_previous(const unsigned char *prev, + const unsigned char *cur, + size_t sz) +@@ -113,8 +108,7 @@ size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, + int crng_test_pass = 1; + OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); + CRNG_TEST_GLOBAL *crngt_glob +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX, +- &rand_crng_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX); + OSSL_CALLBACK *stcb = NULL; + void *stcbarg = NULL; + OSSL_SELF_TEST *st = NULL; +diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c +index c8fe66aa57..007a181c89 100644 +--- a/providers/implementations/rands/drbg.c ++++ b/providers/implementations/rands/drbg.c +@@ -21,6 +21,7 @@ + #include "crypto/rand_pool.h" + #include "prov/provider_ctx.h" + #include "prov/providercommon.h" ++#include "crypto/context.h" + + /* + * Support framework for NIST SP 800-90A DRBG +@@ -274,7 +275,7 @@ typedef struct prov_drbg_nonce_global_st { + * to be in a different global data object. Otherwise we will go into an + * infinite recursion loop. + */ +-static void *prov_drbg_nonce_ossl_ctx_new(OSSL_LIB_CTX *libctx) ++void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *libctx) + { + PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl)); + +@@ -290,7 +291,7 @@ static void *prov_drbg_nonce_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return dngbl; + } + +-static void prov_drbg_nonce_ossl_ctx_free(void *vdngbl) ++void ossl_prov_drbg_nonce_ctx_free(void *vdngbl) + { + PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl; + +@@ -302,12 +303,6 @@ static void prov_drbg_nonce_ossl_ctx_free(void *vdngbl) + OPENSSL_free(dngbl); + } + +-static const OSSL_LIB_CTX_METHOD drbg_nonce_ossl_ctx_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- prov_drbg_nonce_ossl_ctx_new, +- prov_drbg_nonce_ossl_ctx_free, +-}; +- + /* Get a nonce from the operating system */ + static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout, + size_t min_len, size_t max_len) +@@ -316,8 +311,7 @@ static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout, + unsigned char *buf = NULL; + OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); + PROV_DRBG_NONCE_GLOBAL *dngbl +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX, +- &drbg_nonce_ossl_ctx_method); ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX); + struct { + void *drbg; + int count; +diff --git a/test/context_internal_test.c b/test/context_internal_test.c +index 4c02f601cc..fd7518c020 100644 +--- a/test/context_internal_test.c ++++ b/test/context_internal_test.c +@@ -12,103 +12,25 @@ + #include "internal/cryptlib.h" + #include "testutil.h" + +-/* +- * Everything between BEGIN EXAMPLE and END EXAMPLE is copied from +- * doc/internal/man3/ossl_lib_ctx_get_data.pod +- */ +- +-/* +- * ====================================================================== +- * BEGIN EXAMPLE +- */ +- +-typedef struct foo_st { +- int i; +- void *data; +-} FOO; +- +-static void *foo_new(OSSL_LIB_CTX *ctx) +-{ +- FOO *ptr = OPENSSL_zalloc(sizeof(*ptr)); +- if (ptr != NULL) +- ptr->i = 42; +- return ptr; +-} +-static void foo_free(void *ptr) +-{ +- OPENSSL_free(ptr); +-} +-static const OSSL_LIB_CTX_METHOD foo_method = { +- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, +- foo_new, +- foo_free +-}; +- +-/* +- * END EXAMPLE +- * ====================================================================== +- */ +- +-static int test_context(OSSL_LIB_CTX *ctx) +-{ +- FOO *data = NULL; +- +- return TEST_ptr(data = ossl_lib_ctx_get_data(ctx, 0, &foo_method)) +- /* OPENSSL_zalloc in foo_new() initialized it to zero */ +- && TEST_int_eq(data->i, 42); +-} +- +-static int test_app_context(void) +-{ +- OSSL_LIB_CTX *ctx = NULL; +- int result = +- TEST_ptr(ctx = OSSL_LIB_CTX_new()) +- && test_context(ctx); +- +- OSSL_LIB_CTX_free(ctx); +- return result; +-} +- +-static int test_def_context(void) +-{ +- return test_context(NULL); +-} +- + static int test_set0_default(void) + { + OSSL_LIB_CTX *global = OSSL_LIB_CTX_get0_global_default(); + OSSL_LIB_CTX *local = OSSL_LIB_CTX_new(); + OSSL_LIB_CTX *prev; + int testresult = 0; +- FOO *data = NULL; + + if (!TEST_ptr(global) + || !TEST_ptr(local) +- || !TEST_ptr_eq(global, OSSL_LIB_CTX_set0_default(NULL)) +- || !TEST_ptr(data = ossl_lib_ctx_get_data(local, 0, &foo_method))) +- goto err; +- +- /* Set local "i" value to 43. Global "i" should be 42 */ +- data->i++; +- if (!TEST_int_eq(data->i, 43)) +- goto err; +- +- /* The default context should still be the "global" default */ +- if (!TEST_ptr(data = ossl_lib_ctx_get_data(NULL, 0, &foo_method)) +- || !TEST_int_eq(data->i, 42)) ++ || !TEST_ptr_eq(global, OSSL_LIB_CTX_set0_default(NULL))) + goto err; + + /* Check we can change the local default context */ + if (!TEST_ptr(prev = OSSL_LIB_CTX_set0_default(local)) +- || !TEST_ptr_eq(global, prev) +- || !TEST_ptr(data = ossl_lib_ctx_get_data(NULL, 0, &foo_method)) +- || !TEST_int_eq(data->i, 43)) ++ || !TEST_ptr_eq(global, prev)) + goto err; + + /* Calling OSSL_LIB_CTX_set0_default() with a NULL should be a no-op */ +- if (!TEST_ptr_eq(local, OSSL_LIB_CTX_set0_default(NULL)) +- || !TEST_ptr(data = ossl_lib_ctx_get_data(NULL, 0, &foo_method)) +- || !TEST_int_eq(data->i, 43)) ++ if (!TEST_ptr_eq(local, OSSL_LIB_CTX_set0_default(NULL))) + goto err; + + /* Global default should be unchanged */ +@@ -116,10 +38,8 @@ static int test_set0_default(void) + goto err; + + /* Check we can swap back to the global default */ +- if (!TEST_ptr(prev = OSSL_LIB_CTX_set0_default(global)) +- || !TEST_ptr_eq(local, prev) +- || !TEST_ptr(data = ossl_lib_ctx_get_data(NULL, 0, &foo_method)) +- || !TEST_int_eq(data->i, 42)) ++ if (!TEST_ptr(prev = OSSL_LIB_CTX_set0_default(global)) ++ || !TEST_ptr_eq(local, prev)) + goto err; + + testresult = 1; +@@ -130,8 +50,6 @@ static int test_set0_default(void) + + int setup_tests(void) + { +- ADD_TEST(test_app_context); +- ADD_TEST(test_def_context); + ADD_TEST(test_set0_default); + return 1; + } +-- +2.33.0 + diff --git a/backport-Refactor-a-separate-func-for-provider-activation-fro.patch b/backport-Refactor-a-separate-func-for-provider-activation-fro.patch new file mode 100644 index 0000000000000000000000000000000000000000..3cbd4f3c9f6162524a662e02c3d77a9ac1abf658 --- /dev/null +++ b/backport-Refactor-a-separate-func-for-provider-activation-fro.patch @@ -0,0 +1,181 @@ +From ee246234bf591cd2a9779a4ad3a2ee3c53848213 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Mon, 22 Nov 2021 10:14:27 +0100 +Subject: [PATCH] Refactor: a separate func for provider activation from config + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/17099) + +(cherry picked from commit 07ba69483a7d8005a53284cbde55b9dac8c5c554) +--- + crypto/provider_conf.c | 140 ++++++++++++++++++++++------------------- + 1 file changed, 75 insertions(+), 65 deletions(-) + +diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c +index c13c887c3d..6a62f0df60 100644 +--- a/crypto/provider_conf.c ++++ b/crypto/provider_conf.c +@@ -136,13 +136,86 @@ static int prov_already_activated(const char *name, + return 0; + } + ++static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, ++ const char *value, const char *path, ++ int soft, const CONF *cnf) ++{ ++ PROVIDER_CONF_GLOBAL *pcgbl ++ = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX, ++ &provider_conf_ossl_ctx_method); ++ OSSL_PROVIDER *prov = NULL, *actual = NULL; ++ int ok = 0; ++ ++ if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) { ++ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ if (!prov_already_activated(name, pcgbl->activated_providers)) { ++ /* ++ * There is an attempt to activate a provider, so we should disable ++ * loading of fallbacks. Otherwise a misconfiguration could mean the ++ * intended provider does not get loaded. Subsequent fetches could ++ * then fallback to the default provider - which may be the wrong ++ * thing. ++ */ ++ if (!ossl_provider_disable_fallback_loading(libctx)) { ++ CRYPTO_THREAD_unlock(pcgbl->lock); ++ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ prov = ossl_provider_find(libctx, name, 1); ++ if (prov == NULL) ++ prov = ossl_provider_new(libctx, name, NULL, 1); ++ if (prov == NULL) { ++ CRYPTO_THREAD_unlock(pcgbl->lock); ++ if (soft) ++ ERR_clear_error(); ++ return 0; ++ } ++ ++ if (path != NULL) ++ ossl_provider_set_module_path(prov, path); ++ ++ ok = provider_conf_params(prov, NULL, NULL, value, cnf); ++ ++ if (ok) { ++ if (!ossl_provider_activate(prov, 1, 0)) { ++ ok = 0; ++ } else if (!ossl_provider_add_to_store(prov, &actual, 0)) { ++ ossl_provider_deactivate(prov, 1); ++ ok = 0; ++ } else if (actual != prov ++ && !ossl_provider_activate(actual, 1, 0)) { ++ ossl_provider_free(actual); ++ ok = 0; ++ } else { ++ if (pcgbl->activated_providers == NULL) ++ pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); ++ if (pcgbl->activated_providers == NULL ++ || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers, ++ actual)) { ++ ossl_provider_deactivate(actual, 1); ++ ossl_provider_free(actual); ++ ok = 0; ++ } else { ++ ok = 1; ++ } ++ } ++ } ++ if (!ok) ++ ossl_provider_free(prov); ++ } ++ CRYPTO_THREAD_unlock(pcgbl->lock); ++ ++ return ok; ++} ++ + static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, + const char *value, const CONF *cnf) + { + int i; + STACK_OF(CONF_VALUE) *ecmds; + int soft = 0; +- OSSL_PROVIDER *prov = NULL, *actual = NULL; + const char *path = NULL; + long activate = 0; + int ok = 0; +@@ -182,70 +255,7 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, + } + + if (activate) { +- PROVIDER_CONF_GLOBAL *pcgbl +- = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX, +- &provider_conf_ossl_ctx_method); +- +- if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) { +- ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); +- return 0; +- } +- if (!prov_already_activated(name, pcgbl->activated_providers)) { +- /* +- * There is an attempt to activate a provider, so we should disable +- * loading of fallbacks. Otherwise a misconfiguration could mean the +- * intended provider does not get loaded. Subsequent fetches could +- * then fallback to the default provider - which may be the wrong +- * thing. +- */ +- if (!ossl_provider_disable_fallback_loading(libctx)) { +- CRYPTO_THREAD_unlock(pcgbl->lock); +- ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); +- return 0; +- } +- prov = ossl_provider_find(libctx, name, 1); +- if (prov == NULL) +- prov = ossl_provider_new(libctx, name, NULL, 1); +- if (prov == NULL) { +- CRYPTO_THREAD_unlock(pcgbl->lock); +- if (soft) +- ERR_clear_error(); +- return 0; +- } +- +- if (path != NULL) +- ossl_provider_set_module_path(prov, path); +- +- ok = provider_conf_params(prov, NULL, NULL, value, cnf); +- +- if (ok) { +- if (!ossl_provider_activate(prov, 1, 0)) { +- ok = 0; +- } else if (!ossl_provider_add_to_store(prov, &actual, 0)) { +- ossl_provider_deactivate(prov, 1); +- ok = 0; +- } else if (actual != prov +- && !ossl_provider_activate(actual, 1, 0)) { +- ossl_provider_free(actual); +- ok = 0; +- } else { +- if (pcgbl->activated_providers == NULL) +- pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); +- if (pcgbl->activated_providers == NULL +- || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers, +- actual)) { +- ossl_provider_deactivate(actual, 1); +- ossl_provider_free(actual); +- ok = 0; +- } else { +- ok = 1; +- } +- } +- } +- if (!ok) +- ossl_provider_free(prov); +- } +- CRYPTO_THREAD_unlock(pcgbl->lock); ++ ok = provider_conf_activate(libctx, name, value, path, soft, cnf); + } else { + OSSL_PROVIDER_INFO entry; + +-- +2.33.0 + diff --git a/backport-Release-the-drbg-in-the-global-default-context-befor.patch b/backport-Release-the-drbg-in-the-global-default-context-befor.patch new file mode 100644 index 0000000000000000000000000000000000000000..b11cc234dbaf42e1f392219ea79d9a0324fc18b0 --- /dev/null +++ b/backport-Release-the-drbg-in-the-global-default-context-befor.patch @@ -0,0 +1,63 @@ +From d5c02e2de86a28ab2c06e866f0db858c43d00355 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Tue, 11 Oct 2022 17:26:23 +0200 +Subject: [PATCH] Release the drbg in the global default context before engines + +Fixes #17995 +Fixes #18578 + +Reviewed-by: Paul Dale +Reviewed-by: Bernd Edlinger +(Merged from https://github.com/openssl/openssl/pull/19386) + +(cherry picked from commit a88e97fcace01ecf557b207f04328a72df5110df) +--- + crypto/context.c | 9 +++++++++ + crypto/rand/rand_lib.c | 1 + + include/crypto/context.h | 1 + + 3 files changed, 11 insertions(+) + +diff --git a/crypto/context.c b/crypto/context.c +index aec9ecd4ac..c6358afc81 100644 +--- a/crypto/context.c ++++ b/crypto/context.c +@@ -456,6 +456,15 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx) + + return NULL; + } ++ ++void ossl_release_default_drbg_ctx(void) ++{ ++ /* early release of the DRBG in global default libctx */ ++ if (default_context_int.drbg != NULL) { ++ ossl_rand_ctx_free(default_context_int.drbg); ++ default_context_int.drbg = NULL; ++ } ++} + #endif + + OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx) +diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c +index 3f04ec171e..b186ec7f27 100644 +--- a/crypto/rand/rand_lib.c ++++ b/crypto/rand/rand_lib.c +@@ -97,6 +97,7 @@ void ossl_rand_cleanup_int(void) + CRYPTO_THREAD_lock_free(rand_meth_lock); + rand_meth_lock = NULL; + # endif ++ ossl_release_default_drbg_ctx(); + rand_inited = 0; + } + +diff --git a/include/crypto/context.h b/include/crypto/context.h +index 143f6d6b6d..cc06c71be8 100644 +--- a/include/crypto/context.h ++++ b/include/crypto/context.h +@@ -38,3 +38,4 @@ void ossl_self_test_set_callback_free(void *); + void ossl_rand_crng_ctx_free(void *); + void ossl_thread_event_ctx_free(void *); + void ossl_fips_prov_ossl_ctx_free(void *); ++void ossl_release_default_drbg_ctx(void); +-- +2.33.0 + diff --git a/backport-Revert-Release-the-drbg-in-the-global-default-contex.patch b/backport-Revert-Release-the-drbg-in-the-global-default-contex.patch new file mode 100644 index 0000000000000000000000000000000000000000..d579ab65b82af123cb74828c70c38fa2a2dae6b4 --- /dev/null +++ b/backport-Revert-Release-the-drbg-in-the-global-default-contex.patch @@ -0,0 +1,106 @@ +From 9a12f01f6e784c8cf714442014573d010266182d Mon Sep 17 00:00:00 2001 +From: hzero1996 +Date: Fri, 31 May 2024 16:55:10 +0800 +Subject: [PATCH] Revert "Release the drbg in the global default context before + engines" + +This reverts commit d0f8056c47f7aea40a34815fe459404f14501e81. + + +The fix patch for 3.1 will be merged later: d5c02e2de86a28ab2c06e866f0db858c43d00355 +--- + crypto/context.c | 15 --------------- + crypto/rand/rand_lib.c | 5 ++--- + include/crypto/rand.h | 1 - + include/internal/cryptlib.h | 2 -- + 4 files changed, 2 insertions(+), 21 deletions(-) + +diff --git a/crypto/context.c b/crypto/context.c +index 548665fba2..bdfc4d02a3 100644 +--- a/crypto/context.c ++++ b/crypto/context.c +@@ -15,7 +15,6 @@ + #include "internal/bio.h" + #include "internal/provider.h" + #include "crypto/ctype.h" +-#include "crypto/rand.h" + + struct ossl_lib_ctx_onfree_list_st { + ossl_lib_ctx_onfree_fn *fn; +@@ -272,20 +271,6 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx) + + return NULL; + } +- +-void ossl_release_default_drbg_ctx(void) +-{ +- int dynidx = default_context_int.dyn_indexes[OSSL_LIB_CTX_DRBG_INDEX]; +- +- /* early release of the DRBG in global default libctx, no locking */ +- if (dynidx != -1) { +- void *data; +- +- data = CRYPTO_get_ex_data(&default_context_int.data, dynidx); +- ossl_rand_ctx_free(data); +- CRYPTO_set_ex_data(&default_context_int.data, dynidx, NULL); +- } +-} + #endif + + OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx) +diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c +index 5fde214448..edfae865b6 100644 +--- a/crypto/rand/rand_lib.c ++++ b/crypto/rand/rand_lib.c +@@ -96,7 +96,6 @@ void ossl_rand_cleanup_int(void) + CRYPTO_THREAD_lock_free(rand_meth_lock); + rand_meth_lock = NULL; + # endif +- ossl_release_default_drbg_ctx(); + rand_inited = 0; + } + +@@ -476,7 +475,7 @@ static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx) + return NULL; + } + +-void ossl_rand_ctx_free(void *vdgbl) ++static void rand_ossl_ctx_free(void *vdgbl) + { + RAND_GLOBAL *dgbl = vdgbl; + +@@ -501,7 +500,7 @@ void ossl_rand_ctx_free(void *vdgbl) + static const OSSL_LIB_CTX_METHOD rand_drbg_ossl_ctx_method = { + OSSL_LIB_CTX_METHOD_PRIORITY_2, + rand_ossl_ctx_new, +- ossl_rand_ctx_free, ++ rand_ossl_ctx_free, + }; + + static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx) +diff --git a/include/crypto/rand.h b/include/crypto/rand.h +index 165deaf95c..6a71a339c8 100644 +--- a/include/crypto/rand.h ++++ b/include/crypto/rand.h +@@ -125,5 +125,4 @@ void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, + size_t ossl_pool_acquire_entropy(RAND_POOL *pool); + int ossl_pool_add_nonce_data(RAND_POOL *pool); + +-void ossl_rand_ctx_free(void *vdgbl); + #endif +diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h +index 934d4b089c..1291299b6e 100644 +--- a/include/internal/cryptlib.h ++++ b/include/internal/cryptlib.h +@@ -199,8 +199,6 @@ int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, + int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn); + const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx); + +-void ossl_release_default_drbg_ctx(void); +- + OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad); + int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj, + CRYPTO_EX_DATA *ad); +-- +2.33.0 + diff --git a/backport-aes-avoid-accessing-key-length-field-directly.patch b/backport-aes-avoid-accessing-key-length-field-directly.patch new file mode 100644 index 0000000000000000000000000000000000000000..e4e2eca64df2805dbe000f10f399a26860315360 --- /dev/null +++ b/backport-aes-avoid-accessing-key-length-field-directly.patch @@ -0,0 +1,711 @@ +From 071f5f874bb4cd7f04cf9d75be8b094b0bbc9179 Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Thu, 27 Jan 2022 12:51:13 +1100 +Subject: [PATCH] aes: avoid accessing key length field directly + +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/17543) + +(cherry picked from commit 80ce874a093087b919e1c722427df30f81f5dad5) +Reviewed-by: Hugo Landau +--- + crypto/evp/e_aes.c | 305 +++++++++++++++++++++---------- + crypto/evp/e_aes_cbc_hmac_sha1.c | 23 ++- + 2 files changed, 224 insertions(+), 104 deletions(-) + +diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c +index 52b9e87c1e..d8aca6e525 100644 +--- a/crypto/evp/e_aes.c ++++ b/crypto/evp/e_aes.c +@@ -146,20 +146,21 @@ static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + { + int ret, mode; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + mode = EVP_CIPHER_CTX_get_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { +- ret = aesni_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = aesni_set_decrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) aesni_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aesni_cbc_encrypt : NULL; + } else { +- ret = aesni_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = aesni_set_encrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) aesni_encrypt; + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; +@@ -223,12 +224,19 @@ static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { +- EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +- if (!iv && !key) ++ EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX, ctx); ++ ++ if (iv == NULL && key == NULL) + return 1; ++ + if (key) { +- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &gctx->ks.ks); ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ aesni_set_encrypt_key(key, keylen, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt); + gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; + /* +@@ -262,14 +270,19 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + { + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + +- if (!iv && !key) ++ if (iv == NULL && key == NULL) + return 1; + + if (key) { + /* The key is two half length keys in reality */ +- const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ const int bytes = keylen / 2; + const int bits = bytes * 8; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + /* + * Verify that the two keys are different. + * +@@ -315,11 +328,18 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { +- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &cctx->ks.ks); ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ aesni_set_encrypt_key(key, keylen, &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) aesni_encrypt); + cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks : +@@ -342,19 +362,25 @@ static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ +- aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksenc.ks); +- aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksdec.ks); ++ aesni_set_encrypt_key(key, keylen, &octx->ksenc.ks); ++ aesni_set_decrypt_key(key, keylen, &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) aesni_encrypt, +@@ -452,6 +478,10 @@ static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + + mode = EVP_CIPHER_CTX_get_mode(ctx); + bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ if (bits <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + ret = 0; +@@ -547,10 +577,16 @@ static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; + if (key) { +- int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (bits <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) aes_t4_encrypt); +@@ -603,9 +639,14 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + + if (key) { + /* The key is two half length keys in reality */ +- const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ const int bytes = keylen / 2; + const int bits = bytes * 8; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + /* + * Verify that the two keys are different. + * +@@ -670,10 +711,17 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { +- int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (key != NULL) { ++ const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (bits <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) aes_t4_encrypt); +@@ -696,19 +744,25 @@ static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ +- aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksenc.ks); +- aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksdec.ks); ++ aes_t4_set_encrypt_key(key, keylen, &octx->ksenc.ks); ++ aes_t4_set_decrypt_key(key, keylen, &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) aes_t4_encrypt, +@@ -973,6 +1027,10 @@ static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx, + S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + cctx->fc = S390X_AES_FC(keylen); + if (!enc) + cctx->fc |= S390X_DECRYPT; +@@ -999,6 +1057,14 @@ static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx, + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ if (ivlen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); ++ return 0; ++ } + memcpy(cctx->kmo.param.cv, iv, ivlen); + memcpy(cctx->kmo.param.k, key, keylen); + cctx->fc = S390X_AES_FC(keylen); +@@ -1058,6 +1124,14 @@ static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx, + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ if (ivlen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); ++ return 0; ++ } + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */ + if (!enc) +@@ -1081,6 +1155,14 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + int rem; + unsigned char tmp; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ if (ivlen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); ++ return 0; ++ } + memcpy(cctx->kmf.param.cv, iv, ivlen); + while (n && len) { + tmp = *in; +@@ -1128,6 +1210,14 @@ static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ if (ivlen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); ++ return 0; ++ } + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 1 << 24; /* 1 byte cipher feedback */ + if (!enc) +@@ -1533,6 +1623,11 @@ static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, + + if (key != NULL) { + keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ + memcpy(&gctx->kma.param.k, key, keylen); + + gctx->fc = S390X_AES_FC(keylen); +@@ -1939,6 +2034,11 @@ static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx, + + if (key != NULL) { + keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } ++ + cctx->aes.ccm.fc = S390X_AES_FC(keylen); + memcpy(cctx->aes.ccm.kmac_param.k, key, keylen); + +@@ -2315,15 +2415,19 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + { + int ret, mode; + EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + + mode = EVP_CIPHER_CTX_get_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { + #ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +- ret = HWAES_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = HWAES_set_decrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) HWAES_decrypt; + dat->stream.cbc = NULL; + # ifdef HWAES_cbc_encrypt +@@ -2334,27 +2438,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + #ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) { +- ret = AES_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) AES_decrypt; + dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt; + } else + #endif + #ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { +- ret = vpaes_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = vpaes_set_decrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) vpaes_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) vpaes_cbc_encrypt : NULL; + } else + #endif + { +- ret = AES_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) AES_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) AES_cbc_encrypt : NULL; +@@ -2362,9 +2460,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + } else + #ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +- ret = HWAES_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = HWAES_set_encrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) HWAES_encrypt; + dat->stream.cbc = NULL; + # ifdef HWAES_cbc_encrypt +@@ -2382,25 +2478,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + #ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) { +- ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) AES_encrypt; + dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; + } else + #endif + #ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { +- ret = vpaes_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = vpaes_set_encrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) vpaes_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) vpaes_cbc_encrypt : NULL; + } else + #endif + { +- ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &dat->ks.ks); ++ ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); + dat->block = (block128_f) AES_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) AES_cbc_encrypt : NULL; +@@ -2711,13 +2803,21 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + do { + #ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +- HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); ++ HWAES_set_encrypt_key(key, keylen, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) HWAES_encrypt); + # ifdef HWAES_ctr32_encrypt_blocks +@@ -2730,7 +2830,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + #ifdef BSAES_CAPABLE + if (BSAES_CAPABLE) { +- AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); ++ AES_set_encrypt_key(key, keylen, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) AES_encrypt); + gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; +@@ -2739,7 +2839,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + #ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { +- vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); ++ vpaes_set_encrypt_key(key, keylen, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) vpaes_encrypt); + gctx->ctr = NULL; +@@ -2748,7 +2848,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + (void)0; /* terminate potentially open 'else' */ + +- AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); ++ AES_set_encrypt_key(key, keylen, &gctx->ks.ks); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f) AES_encrypt); + #ifdef AES_CTR_ASM +@@ -3128,15 +3228,20 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + { + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + +- if (!iv && !key) ++ if (iv == NULL && key == NULL) + return 1; + +- if (key) { ++ if (key != NULL) { + do { + /* The key is two half length keys in reality */ +- const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ const int bytes = keylen / 2; + const int bits = bytes * 8; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + /* + * Verify that the two keys are different. + * +@@ -3382,15 +3487,21 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + do { + #ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +- HWAES_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &cctx->ks.ks); ++ HWAES_set_encrypt_key(key, keylen, &cctx->ks.ks); + + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) HWAES_encrypt); +@@ -3401,9 +3512,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + #endif + #ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { +- vpaes_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &cctx->ks.ks); ++ vpaes_set_encrypt_key(key, keylen, &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) vpaes_encrypt); + cctx->str = NULL; +@@ -3411,14 +3520,14 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + break; + } + #endif +- AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &cctx->ks.ks); ++ AES_set_encrypt_key(key, keylen, &cctx->ks.ks); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) AES_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + } while (0); +- if (iv) { ++ } ++ if (iv != NULL) { + memcpy(ctx->iv, iv, 15 - cctx->L); + cctx->iv_set = 1; + } +@@ -3573,12 +3682,16 @@ static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + if (iv == NULL && key == NULL) + return 1; + if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + if (EVP_CIPHER_CTX_is_encrypting(ctx)) +- AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &wctx->ks.ks); ++ AES_set_encrypt_key(key, keylen, &wctx->ks.ks); + else +- AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &wctx->ks.ks); ++ AES_set_decrypt_key(key, keylen, &wctx->ks.ks); + if (iv == NULL) + wctx->iv = NULL; + } +@@ -3806,9 +3919,17 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +- if (!iv && !key) ++ ++ if (iv == NULL && key == NULL) + return 1; +- if (key) { ++ ++ if (key != NULL) { ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + do { + /* + * We set both the encrypt and decrypt key here because decrypt +@@ -3817,10 +3938,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + */ + # ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +- HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksenc.ks); +- HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksdec.ks); ++ HWAES_set_encrypt_key(key, keylen, &octx->ksenc.ks); ++ HWAES_set_decrypt_key(key, keylen, &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) HWAES_encrypt, +@@ -3833,12 +3952,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + # endif + # ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { +- vpaes_set_encrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksenc.ks); +- vpaes_set_decrypt_key(key, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksdec.ks); ++ vpaes_set_encrypt_key(key, keylen, &octx->ksenc.ks); ++ vpaes_set_decrypt_key(key, keylen, &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) vpaes_encrypt, +@@ -3848,10 +3963,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + break; + } + # endif +- AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksenc.ks); +- AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &octx->ksdec.ks); ++ AES_set_encrypt_key(key, keylen, &octx->ksenc.ks); ++ AES_set_decrypt_key(key, keylen, &octx->ksdec.ks); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f) AES_encrypt, +diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c +index 4941f98e64..5f25cda0ec 100644 +--- a/crypto/evp/e_aes_cbc_hmac_sha1.c ++++ b/crypto/evp/e_aes_cbc_hmac_sha1.c +@@ -72,15 +72,16 @@ static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, + { + EVP_AES_HMAC_SHA1 *key = data(ctx); + int ret; ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + if (enc) +- ret = aesni_set_encrypt_key(inkey, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &key->ks); ++ ret = aesni_set_encrypt_key(inkey, keylen, &key->ks); + else +- ret = aesni_set_decrypt_key(inkey, +- EVP_CIPHER_CTX_get_key_length(ctx) * 8, +- &key->ks); ++ ret = aesni_set_decrypt_key(inkey, keylen, &key->ks); + + SHA1_Init(&key->head); /* handy when benchmarking */ + key->tail = key->head; +@@ -496,6 +497,12 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + # if defined(STITCHED_DECRYPT_CALL) + unsigned char tail_iv[AES_BLOCK_SIZE]; + int stitch = 0; ++ const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); ++ ++ if (keylen <= 0) { ++ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); ++ return 0; ++ } + # endif + + if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) +@@ -513,7 +520,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + return 0; + + # if defined(STITCHED_DECRYPT_CALL) +- if (len >= 1024 && ctx->key_len == 32) { ++ if (len >= 1024 && keylen == 32) { + /* decrypt last block */ + memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE, + AES_BLOCK_SIZE); +@@ -734,7 +741,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + return ret; + } else { + # if defined(STITCHED_DECRYPT_CALL) +- if (len >= 1024 && ctx->key_len == 32) { ++ if (len >= 1024 && keylen == 32) { + if (sha_off %= SHA_CBLOCK) + blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK; + else +-- +2.33.0 + diff --git a/backport-evp-enc-cache-cipher-key-length.patch b/backport-evp-enc-cache-cipher-key-length.patch new file mode 100644 index 0000000000000000000000000000000000000000..d0619ede2dec34b645e3a7190b1bc74448ff2b2c --- /dev/null +++ b/backport-evp-enc-cache-cipher-key-length.patch @@ -0,0 +1,136 @@ +From bbbccd795940114cb18722fc6fffe2b25ce3c436 Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Thu, 27 Jan 2022 13:33:36 +1100 +Subject: [PATCH] evp enc: cache cipher key length + +Instead of doing a heavy params based query every time a context is +asked for its key length, this value is cached in the context and only +queried if it could have been modified. + +Fixes #17064 + +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/17543) + +(cherry picked from commit 70f39a487d3f7d976a01e0ee7ae98a82ceeea7a0) +Reviewed-by: Hugo Landau +--- + crypto/evp/evp_enc.c | 31 ++++++++++++++++++++++++------- + crypto/evp/evp_lib.c | 26 ++++++++++++++++++++------ + 2 files changed, 44 insertions(+), 13 deletions(-) + +diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c +index 921d24dd3d..a6468f6767 100644 +--- a/crypto/evp/evp_enc.c ++++ b/crypto/evp/evp_enc.c +@@ -62,7 +62,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) + ENGINE_finish(ctx->engine); + #endif + memset(ctx, 0, sizeof(*ctx)); +- ctx->iv_len = -1; ++ ctx->iv_len = 0; + return 1; + } + +@@ -994,7 +994,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) + if (c->cipher->prov != NULL) { + int ok; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; +- size_t len = keylen; ++ size_t len; + + if (EVP_CIPHER_CTX_get_key_length(c) == keylen) + return 1; +@@ -1007,9 +1007,13 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) + } + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); ++ if (!OSSL_PARAM_set_int(params, keylen)) ++ return 0; + ok = evp_do_ciph_ctx_setparams(c->cipher, c->algctx, params); +- +- return ok > 0 ? 1 : 0; ++ if (ok <= 0) ++ return 0; ++ c->key_len = keylen; ++ return 1; + } + + /* Code below to be removed when legacy support is dropped. */ +@@ -1070,6 +1074,7 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) + switch (type) { + case EVP_CTRL_SET_KEY_LENGTH: + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz); ++ ctx->key_len = -1; + break; + case EVP_CTRL_RAND_KEY: /* Used by DES */ + set_params = 0; +@@ -1265,11 +1270,23 @@ int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]) + + int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]) + { ++ int r = 0; ++ const OSSL_PARAM *p; ++ + if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) { +- ctx->iv_len = -1; +- return ctx->cipher->set_ctx_params(ctx->algctx, params); ++ r = ctx->cipher->set_ctx_params(ctx->algctx, params); ++ if (r > 0) { ++ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); ++ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->key_len)) ++ r = 0; ++ } ++ if (r > 0) { ++ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); ++ if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->iv_len)) ++ r = 0; ++ } + } +- return 0; ++ return r; + } + + int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]) +diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c +index d88066d0a2..98bb25655d 100644 +--- a/crypto/evp/evp_lib.c ++++ b/crypto/evp/evp_lib.c +@@ -652,14 +652,28 @@ int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher) + + int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx) + { +- int ok; +- size_t v = ctx->key_len; +- OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; ++ if (ctx->key_len <= 0 && ctx->cipher->prov != NULL) { ++ int ok; ++ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; ++ size_t len; + +- params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &v); +- ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); ++ params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); ++ ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); ++ if (ok <= 0) ++ return EVP_CTRL_RET_UNSUPPORTED; + +- return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED; ++ /*- ++ * The if branch should never be taken since EVP_MAX_KEY_LENGTH is ++ * less than INT_MAX but best to be safe. ++ * ++ * Casting away the const is annoying but required here. We need to ++ * cache the result for performance reasons. ++ */ ++ if (!OSSL_PARAM_get_int(params, &((EVP_CIPHER_CTX *)ctx)->key_len)) ++ return -1; ++ ((EVP_CIPHER_CTX *)ctx)->key_len = (int)len; ++ } ++ return ctx->key_len; + } + + int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher) +-- +2.33.0 + diff --git a/backport-params-provide-a-faster-TRIE-based-param-lookup.patch b/backport-params-provide-a-faster-TRIE-based-param-lookup.patch new file mode 100644 index 0000000000000000000000000000000000000000..4940c36ed59bb319c4ad5d2b7ecf2e44ec2e8b4e --- /dev/null +++ b/backport-params-provide-a-faster-TRIE-based-param-lookup.patch @@ -0,0 +1,1686 @@ +From ed34eddc7e458dd013f7a7228f707ee2095909c5 Mon Sep 17 00:00:00 2001 +From: wangcheng +Date: Wed, 25 Sep 2024 16:52:03 +0800 +Subject: [PATCH] 2 + +--- + build.info | 11 +- + crypto/build.info | 2 +- + crypto/params_idx.c.in | 21 + + include/internal/e_os.h | 432 +++++++++++ + include/internal/param_names.h.in | 18 + + include/openssl/core_names.h.in | 118 +++ + .../ciphers/ciphercommon_gcm.c | 288 ++++---- + util/perl/OpenSSL/paramnames.pm | 673 ++++++++++++++++++ + 8 files changed, 1426 insertions(+), 137 deletions(-) + create mode 100644 crypto/params_idx.c.in + create mode 100644 include/internal/e_os.h + create mode 100644 include/internal/param_names.h.in + create mode 100644 include/openssl/core_names.h.in + create mode 100644 util/perl/OpenSSL/paramnames.pm + +diff --git a/build.info b/build.info +index 5a84216..630696c 100644 +--- a/build.info ++++ b/build.info +@@ -22,6 +22,7 @@ DEPEND[]=include/openssl/asn1.h \ + include/openssl/cmp.h \ + include/openssl/cms.h \ + include/openssl/conf.h \ ++ include/openssl/core_names.h \ + include/openssl/crmf.h \ + include/openssl/crypto.h \ + include/openssl/ct.h \ +@@ -40,7 +41,8 @@ DEPEND[]=include/openssl/asn1.h \ + include/openssl/x509.h \ + include/openssl/x509v3.h \ + include/openssl/x509_vfy.h \ +- include/crypto/bn_conf.h include/crypto/dso_conf.h ++ include/crypto/bn_conf.h include/crypto/dso_conf.h \ ++ include/internal/param_names.h crypto/params_idx.c + + GENERATE[include/openssl/asn1.h]=include/openssl/asn1.h.in + GENERATE[include/openssl/asn1t.h]=include/openssl/asn1t.h.in +@@ -73,6 +75,13 @@ GENERATE[include/openssl/x509_vfy.h]=include/openssl/x509_vfy.h.in + GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in + GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in + ++DEPEND[crypto/params_idx.c \ ++ include/internal/param_names.h \ ++ include/openssl/core_names.h]=util/perl/OpenSSL/paramnames.pm ++GENERATE[crypto/params_idx.c]=crypto/params_idx.c.in ++GENERATE[include/internal/param_names.h]=include/internal/param_names.h.in ++GENERATE[include/openssl/core_names.h]=include/openssl/core_names.h.in ++ + IF[{- defined $target{shared_defflag} -}] + SHARED_SOURCE[libcrypto]=libcrypto.ld + SHARED_SOURCE[libssl]=libssl.ld +diff --git a/crypto/build.info b/crypto/build.info +index c04db55..d7afe47 100644 +--- a/crypto/build.info ++++ b/crypto/build.info +@@ -95,7 +95,7 @@ $UTIL_COMMON=\ + cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \ + threads_pthread.c threads_win.c threads_none.c initthread.c \ + context.c sparse_array.c asn1_dsa.c packet.c param_build.c \ +- param_build_set.c der_writer.c threads_lib.c params_dup.c ++ param_build_set.c der_writer.c threads_lib.c params_dup.c params_idx.c + + SOURCE[../libcrypto]=$UTIL_COMMON \ + mem.c mem_sec.c \ +diff --git a/crypto/params_idx.c.in b/crypto/params_idx.c.in +new file mode 100644 +index 0000000..f04939b +--- /dev/null ++++ b/crypto/params_idx.c.in +@@ -0,0 +1,21 @@ ++/* ++ * {- join("\n * ", @autowarntext) -} ++ * ++ * Copyright 2023 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 ++ */ ++{- ++use OpenSSL::paramnames qw(produce_decoder); ++-} ++ ++#include "internal/e_os.h" ++#include "internal/param_names.h" ++#include ++ ++/* Machine generated TRIE -- generated by util/perl/OpenSSL/paramnames.pm */ ++{- produce_decoder(); -} ++/* End of TRIE */ +diff --git a/include/internal/e_os.h b/include/internal/e_os.h +new file mode 100644 +index 0000000..db05b7f +--- /dev/null ++++ b/include/internal/e_os.h +@@ -0,0 +1,432 @@ ++/* ++ * Copyright 1995-2022 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 ++ */ ++ ++#ifndef OSSL_E_OS_H ++# define OSSL_E_OS_H ++ ++# include ++# include ++ ++# include ++# include ++# include "internal/nelem.h" ++ ++/* ++ * contains what we can justify to make visible to the ++ * outside; this file e_os.h is not part of the exported interface. ++ */ ++ ++# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) ++# define NO_CHMOD ++# define NO_SYSLOG ++# endif ++ ++# define get_last_sys_error() errno ++# define clear_sys_error() errno=0 ++# define set_sys_error(e) errno=(e) ++ ++/******************************************************************** ++ The Microsoft section ++ ********************************************************************/ ++# if defined(OPENSSL_SYS_WIN32) && !defined(WIN32) ++# define WIN32 ++# endif ++# if defined(OPENSSL_SYS_WINDOWS) && !defined(WINDOWS) ++# define WINDOWS ++# endif ++# if defined(OPENSSL_SYS_MSDOS) && !defined(MSDOS) ++# define MSDOS ++# endif ++ ++# ifdef WIN32 ++# undef get_last_sys_error ++# undef clear_sys_error ++# undef set_sys_error ++# define get_last_sys_error() GetLastError() ++# define clear_sys_error() SetLastError(0) ++# define set_sys_error(e) SetLastError(e) ++# if !defined(WINNT) ++# define WIN_CONSOLE_BUG ++# endif ++# else ++# endif ++ ++# if (defined(WINDOWS) || defined(MSDOS)) ++ ++# ifdef __DJGPP__ ++# include ++# include ++# define _setmode setmode ++# define _O_TEXT O_TEXT ++# define _O_BINARY O_BINARY ++# undef DEVRANDOM_EGD /* Neither MS-DOS nor FreeDOS provide 'egd' sockets. */ ++# undef DEVRANDOM ++# define DEVRANDOM "/dev/urandom\x24" ++# endif /* __DJGPP__ */ ++ ++# ifndef S_IFDIR ++# define S_IFDIR _S_IFDIR ++# endif ++ ++# ifndef S_IFMT ++# define S_IFMT _S_IFMT ++# endif ++ ++# if !defined(WINNT) && !defined(__DJGPP__) ++# define NO_SYSLOG ++# endif ++ ++# ifdef WINDOWS ++# if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT) ++ /* ++ * Defining _WIN32_WINNT here in e_os.h implies certain "discipline." ++ * Most notably we ought to check for availability of each specific ++ * routine that was introduced after denoted _WIN32_WINNT with ++ * GetProcAddress(). Normally newer functions are masked with higher ++ * _WIN32_WINNT in SDK headers. So that if you wish to use them in ++ * some module, you'd need to override _WIN32_WINNT definition in ++ * the target module in order to "reach for" prototypes, but replace ++ * calls to new functions with indirect calls. Alternatively it ++ * might be possible to achieve the goal by /DELAYLOAD-ing .DLLs ++ * and check for current OS version instead. ++ */ ++# define _WIN32_WINNT 0x0501 ++# endif ++# if defined(_WIN32_WINNT) || defined(_WIN32_WCE) ++ /* ++ * Just like defining _WIN32_WINNT including winsock2.h implies ++ * certain "discipline" for maintaining [broad] binary compatibility. ++ * As long as structures are invariant among Winsock versions, ++ * it's sufficient to check for specific Winsock2 API availability ++ * at run-time [DSO_global_lookup is recommended]... ++ */ ++# include ++# include ++ /* ++ * Clang-based C++Builder 10.3.3 toolchains cannot find C inline ++ * definitions at link-time. This header defines WspiapiLoad() as an ++ * __inline function. https://quality.embarcadero.com/browse/RSP-33806 ++ */ ++# if !defined(__BORLANDC__) || !defined(__clang__) ++# include ++# endif ++ /* yes, they have to be #included prior to */ ++# endif ++# include ++# include ++# include ++# include ++# if defined(_WIN32_WCE) && !defined(EACCES) ++# define EACCES 13 ++# endif ++# include ++# ifdef _WIN64 ++# define strlen(s) _strlen31(s) ++/* cut strings to 2GB */ ++static __inline unsigned int _strlen31(const char *str) ++{ ++ unsigned int len = 0; ++ while (*str && len < 0x80000000U) ++ str++, len++; ++ return len & 0x7FFFFFFF; ++} ++# endif ++# include ++# if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(_DLL) && defined(stdin) ++# if _MSC_VER>=1300 && _MSC_VER<1600 ++# undef stdin ++# undef stdout ++# undef stderr ++FILE *__iob_func(); ++# define stdin (&__iob_func()[0]) ++# define stdout (&__iob_func()[1]) ++# define stderr (&__iob_func()[2]) ++# endif ++# endif ++# endif ++# include ++# include ++ ++# ifdef OPENSSL_SYS_WINCE ++# define OPENSSL_NO_POSIX_IO ++# endif ++ ++# define EXIT(n) exit(n) ++# define LIST_SEPARATOR_CHAR ';' ++# ifndef W_OK ++# define W_OK 2 ++# endif ++# ifndef R_OK ++# define R_OK 4 ++# endif ++# ifdef OPENSSL_SYS_WINCE ++# define DEFAULT_HOME "" ++# else ++# define DEFAULT_HOME "C:" ++# endif ++ ++/* Avoid Visual Studio 13 GetVersion deprecated problems */ ++# if defined(_MSC_VER) && _MSC_VER>=1800 ++# define check_winnt() (1) ++# define check_win_minplat(x) (1) ++# else ++# define check_winnt() (GetVersion() < 0x80000000) ++# define check_win_minplat(x) (LOBYTE(LOWORD(GetVersion())) >= (x)) ++# endif ++ ++# else /* The non-microsoft world */ ++ ++# if defined(OPENSSL_SYS_VXWORKS) ++# include ++# else ++# include ++# endif ++ ++# ifdef OPENSSL_SYS_VMS ++# define VMS 1 ++ /* ++ * some programs don't include stdlib, so exit() and others give implicit ++ * function warnings ++ */ ++# include ++# if defined(__DECC) ++# include ++# else ++# include ++# endif ++# define LIST_SEPARATOR_CHAR ',' ++ /* We don't have any well-defined random devices on VMS, yet... */ ++# undef DEVRANDOM ++ /*- ++ We need to do this since VMS has the following coding on status codes: ++ ++ Bits 0-2: status type: 0 = warning, 1 = success, 2 = error, 3 = info ... ++ The important thing to know is that odd numbers are considered ++ good, while even ones are considered errors. ++ Bits 3-15: actual status number ++ Bits 16-27: facility number. 0 is considered "unknown" ++ Bits 28-31: control bits. If bit 28 is set, the shell won't try to ++ output the message (which, for random codes, just looks ugly) ++ ++ So, what we do here is to change 0 to 1 to get the default success status, ++ and everything else is shifted up to fit into the status number field, and ++ the status is tagged as an error, which is what is wanted here. ++ ++ Finally, we add the VMS C facility code 0x35a000, because there are some ++ programs, such as Perl, that will reinterpret the code back to something ++ POSIX. 'man perlvms' explains it further. ++ ++ NOTE: the perlvms manual wants to turn all codes 2 to 255 into success ++ codes (status type = 1). I couldn't disagree more. Fortunately, the ++ status type doesn't seem to bother Perl. ++ -- Richard Levitte ++ */ ++# define EXIT(n) exit((n) ? (((n) << 3) | 2 | 0x10000000 | 0x35a000) : 1) ++ ++# define DEFAULT_HOME "SYS$LOGIN:" ++ ++# else ++ /* !defined VMS */ ++# include ++# include ++# ifdef OPENSSL_SYS_WIN32_CYGWIN ++# include ++# include ++# endif ++ ++# define LIST_SEPARATOR_CHAR ':' ++# define EXIT(n) exit(n) ++# endif ++ ++# endif ++ ++/***********************************************/ ++ ++# if defined(OPENSSL_SYS_WINDOWS) ++# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE) ++# define open _open ++# define fdopen _fdopen ++# define close _close ++# ifndef strdup ++# define strdup _strdup ++# endif ++# define unlink _unlink ++# define fileno _fileno ++# endif ++# else ++# include ++# endif ++ ++/* vxworks */ ++# if defined(OPENSSL_SYS_VXWORKS) ++# include ++# include ++# include ++# include ++# include ++# include ++ ++# define TTY_STRUCT int ++# define sleep(a) taskDelay((a) * sysClkRateGet()) ++ ++/* ++ * NOTE: these are implemented by helpers in database app! if the database is ++ * not linked, we need to implement them elsewhere ++ */ ++struct hostent *gethostbyname(const char *name); ++struct hostent *gethostbyaddr(const char *addr, int length, int type); ++struct servent *getservbyname(const char *name, const char *proto); ++ ++# endif ++/* end vxworks */ ++ ++/* system-specific variants defining ossl_sleep() */ ++#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) ++# include ++static ossl_inline void ossl_sleep(unsigned long millis) ++{ ++# ifdef OPENSSL_SYS_VXWORKS ++ struct timespec ts; ++ ts.tv_sec = (long int) (millis / 1000); ++ ts.tv_nsec = (long int) (millis % 1000) * 1000000ul; ++ nanosleep(&ts, NULL); ++# elif defined(__TANDEM) ++# if !defined(_REENTRANT) ++# include ++ /* HPNS does not support usleep for non threaded apps */ ++ PROCESS_DELAY_(millis * 1000); ++# elif defined(_SPT_MODEL_) ++# include ++# include ++ usleep(millis * 1000); ++# else ++ usleep(millis * 1000); ++# endif ++# else ++ usleep(millis * 1000); ++# endif ++} ++#elif defined(_WIN32) ++# include ++static ossl_inline void ossl_sleep(unsigned long millis) ++{ ++ Sleep(millis); ++} ++#else ++/* Fallback to a busy wait */ ++static ossl_inline void ossl_sleep(unsigned long millis) ++{ ++ struct timeval start, now; ++ unsigned long elapsedms; ++ ++ gettimeofday(&start, NULL); ++ do { ++ gettimeofday(&now, NULL); ++ elapsedms = (((now.tv_sec - start.tv_sec) * 1000000) ++ + now.tv_usec - start.tv_usec) / 1000; ++ } while (elapsedms < millis); ++} ++#endif /* defined OPENSSL_SYS_UNIX */ ++ ++/* ----------------------------- HP NonStop -------------------------------- */ ++/* Required to support platform variant without getpid() and pid_t. */ ++# if defined(__TANDEM) && defined(_GUARDIAN_TARGET) ++# include ++# include ++# define getservbyname(name,proto) getservbyname((char*)name,proto) ++# define gethostbyname(name) gethostbyname((char*)name) ++# define ioctlsocket(a,b,c) ioctl(a,b,c) ++# ifdef NO_GETPID ++inline int nssgetpid(); ++# ifndef NSSGETPID_MACRO ++# define NSSGETPID_MACRO ++# include ++# include ++ inline int nssgetpid() ++ { ++ short phandle[10]={0}; ++ union pseudo_pid { ++ struct { ++ short cpu; ++ short pin; ++ } cpu_pin ; ++ int ppid; ++ } ppid = { 0 }; ++ PROCESSHANDLE_GETMINE_(phandle); ++ PROCESSHANDLE_DECOMPOSE_(phandle, &ppid.cpu_pin.cpu, &ppid.cpu_pin.pin); ++ return ppid.ppid; ++ } ++# define getpid(a) nssgetpid(a) ++# endif /* NSSGETPID_MACRO */ ++# endif /* NO_GETPID */ ++/*# define setsockopt(a,b,c,d,f) setsockopt(a,b,c,(char*)d,f)*/ ++/*# define getsockopt(a,b,c,d,f) getsockopt(a,b,c,(char*)d,f)*/ ++/*# define connect(a,b,c) connect(a,(struct sockaddr *)b,c)*/ ++/*# define bind(a,b,c) bind(a,(struct sockaddr *)b,c)*/ ++/*# define sendto(a,b,c,d,e,f) sendto(a,(char*)b,c,d,(struct sockaddr *)e,f)*/ ++# if defined(OPENSSL_THREADS) && !defined(_PUT_MODEL_) ++ /* ++ * HPNS SPT threads ++ */ ++# define SPT_THREAD_SIGNAL 1 ++# define SPT_THREAD_AWARE 1 ++# include ++# undef close ++# define close spt_close ++/* ++# define get_last_socket_error() errno ++# define clear_socket_error() errno=0 ++# define ioctlsocket(a,b,c) ioctl(a,b,c) ++# define closesocket(s) close(s) ++# define readsocket(s,b,n) read((s),(char*)(b),(n)) ++# define writesocket(s,b,n) write((s),(char*)(b),(n) ++*/ ++# define accept(a,b,c) accept(a,(struct sockaddr *)b,c) ++# define recvfrom(a,b,c,d,e,f) recvfrom(a,b,(socklen_t)c,d,e,f) ++# endif ++# endif ++ ++# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++# define CRYPTO_memcmp memcmp ++# endif ++ ++# ifndef OPENSSL_NO_SECURE_MEMORY ++ /* unistd.h defines _POSIX_VERSION */ ++# if (defined(OPENSSL_SYS_UNIX) \ ++ && ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \ ++ || defined(__sun) || defined(__hpux) || defined(__sgi) \ ++ || defined(__osf__) )) \ ++ || defined(_WIN32) ++ /* secure memory is implemented */ ++# else ++# define OPENSSL_NO_SECURE_MEMORY ++# endif ++# endif ++ ++/* ++ * str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly ++ * https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html ++ * There are also equivalent functions on Windows. ++ * There is no locale_t on NONSTOP. ++ */ ++# if defined(OPENSSL_SYS_WINDOWS) ++# define locale_t _locale_t ++# define freelocale _free_locale ++# define strcasecmp_l _stricmp_l ++# define strncasecmp_l _strnicmp_l ++# define strcasecmp _stricmp ++# define strncasecmp _strnicmp ++# elif !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L \ ++ || defined(OPENSSL_SYS_TANDEM) ++# ifndef OPENSSL_NO_LOCALE ++# define OPENSSL_NO_LOCALE ++# endif ++# endif ++ ++#endif +diff --git a/include/internal/param_names.h.in b/include/internal/param_names.h.in +new file mode 100644 +index 0000000..f34db21 +--- /dev/null ++++ b/include/internal/param_names.h.in +@@ -0,0 +1,18 @@ ++/* ++ * {- join("\n * ", @autowarntext) -} ++ * ++ * Copyright 2023 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 ++ */ ++{- ++use OpenSSL::paramnames qw(generate_internal_macros); ++-} ++ ++int ossl_param_find_pidx(const char *s); ++ ++/* Parameter name definitions - generated by util/perl/OpenSSL/paramnames.pm */ ++{- generate_internal_macros(); -} +diff --git a/include/openssl/core_names.h.in b/include/openssl/core_names.h.in +new file mode 100644 +index 0000000..133f783 +--- /dev/null ++++ b/include/openssl/core_names.h.in +@@ -0,0 +1,118 @@ ++/* ++ * {- join("\n * ", @autowarntext) -} ++ * ++ * Copyright 2019-2021 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 ++ */ ++{- ++use OpenSSL::paramnames qw(generate_public_macros); ++-} ++ ++#ifndef OPENSSL_CORE_NAMES_H ++# define OPENSSL_CORE_NAMES_H ++# pragma once ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++/* OSSL_CIPHER_PARAM_CTS_MODE Values */ ++# define OSSL_CIPHER_CTS_MODE_CS1 "CS1" ++# define OSSL_CIPHER_CTS_MODE_CS2 "CS2" ++# define OSSL_CIPHER_CTS_MODE_CS3 "CS3" ++ ++/* Known CIPHER names (not a complete list) */ ++# define OSSL_CIPHER_NAME_AES_128_GCM_SIV "AES-128-GCM-SIV" ++# define OSSL_CIPHER_NAME_AES_192_GCM_SIV "AES-192-GCM-SIV" ++# define OSSL_CIPHER_NAME_AES_256_GCM_SIV "AES-256-GCM-SIV" ++ ++/* Known DIGEST names (not a complete list) */ ++# define OSSL_DIGEST_NAME_MD5 "MD5" ++# define OSSL_DIGEST_NAME_MD5_SHA1 "MD5-SHA1" ++# define OSSL_DIGEST_NAME_SHA1 "SHA1" ++# define OSSL_DIGEST_NAME_SHA2_224 "SHA2-224" ++# define OSSL_DIGEST_NAME_SHA2_256 "SHA2-256" ++# define OSSL_DIGEST_NAME_SHA2_384 "SHA2-384" ++# define OSSL_DIGEST_NAME_SHA2_512 "SHA2-512" ++# define OSSL_DIGEST_NAME_SHA2_512_224 "SHA2-512/224" ++# define OSSL_DIGEST_NAME_SHA2_512_256 "SHA2-512/256" ++# define OSSL_DIGEST_NAME_MD2 "MD2" ++# define OSSL_DIGEST_NAME_MD4 "MD4" ++# define OSSL_DIGEST_NAME_MDC2 "MDC2" ++# define OSSL_DIGEST_NAME_RIPEMD160 "RIPEMD160" ++# define OSSL_DIGEST_NAME_SHA3_224 "SHA3-224" ++# define OSSL_DIGEST_NAME_SHA3_256 "SHA3-256" ++# define OSSL_DIGEST_NAME_SHA3_384 "SHA3-384" ++# define OSSL_DIGEST_NAME_SHA3_512 "SHA3-512" ++# define OSSL_DIGEST_NAME_KECCAK_KMAC128 "KECCAK-KMAC-128" ++# define OSSL_DIGEST_NAME_KECCAK_KMAC256 "KECCAK-KMAC-256" ++# define OSSL_DIGEST_NAME_SM3 "SM3" ++ ++/* Known MAC names */ ++# define OSSL_MAC_NAME_BLAKE2BMAC "BLAKE2BMAC" ++# define OSSL_MAC_NAME_BLAKE2SMAC "BLAKE2SMAC" ++# define OSSL_MAC_NAME_CMAC "CMAC" ++# define OSSL_MAC_NAME_GMAC "GMAC" ++# define OSSL_MAC_NAME_HMAC "HMAC" ++# define OSSL_MAC_NAME_KMAC128 "KMAC128" ++# define OSSL_MAC_NAME_KMAC256 "KMAC256" ++# define OSSL_MAC_NAME_POLY1305 "POLY1305" ++# define OSSL_MAC_NAME_SIPHASH "SIPHASH" ++ ++/* Known KDF names */ ++# define OSSL_KDF_NAME_HKDF "HKDF" ++# define OSSL_KDF_NAME_TLS1_3_KDF "TLS13-KDF" ++# define OSSL_KDF_NAME_PBKDF1 "PBKDF1" ++# define OSSL_KDF_NAME_PBKDF2 "PBKDF2" ++# define OSSL_KDF_NAME_SCRYPT "SCRYPT" ++# define OSSL_KDF_NAME_SSHKDF "SSHKDF" ++# define OSSL_KDF_NAME_SSKDF "SSKDF" ++# define OSSL_KDF_NAME_TLS1_PRF "TLS1-PRF" ++# define OSSL_KDF_NAME_X942KDF_ASN1 "X942KDF-ASN1" ++# define OSSL_KDF_NAME_X942KDF_CONCAT "X942KDF-CONCAT" ++# define OSSL_KDF_NAME_X963KDF "X963KDF" ++# define OSSL_KDF_NAME_KBKDF "KBKDF" ++# define OSSL_KDF_NAME_KRB5KDF "KRB5KDF" ++# define OSSL_KDF_NAME_HMACDRBGKDF "HMAC-DRBG-KDF" ++ ++/* RSA padding modes */ ++# define OSSL_PKEY_RSA_PAD_MODE_NONE "none" ++# define OSSL_PKEY_RSA_PAD_MODE_PKCSV15 "pkcs1" ++# define OSSL_PKEY_RSA_PAD_MODE_OAEP "oaep" ++# define OSSL_PKEY_RSA_PAD_MODE_X931 "x931" ++# define OSSL_PKEY_RSA_PAD_MODE_PSS "pss" ++ ++/* RSA pss padding salt length */ ++# define OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST "digest" ++# define OSSL_PKEY_RSA_PSS_SALT_LEN_MAX "max" ++# define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO "auto" ++# define OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX "auto-digestmax" ++ ++/* OSSL_PKEY_PARAM_EC_ENCODING values */ ++# define OSSL_PKEY_EC_ENCODING_EXPLICIT "explicit" ++# define OSSL_PKEY_EC_ENCODING_GROUP "named_curve" ++ ++# define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED "uncompressed" ++# define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED "compressed" ++# define OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID "hybrid" ++ ++# define OSSL_PKEY_EC_GROUP_CHECK_DEFAULT "default" ++# define OSSL_PKEY_EC_GROUP_CHECK_NAMED "named" ++# define OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST "named-nist" ++ ++/* OSSL_KEM_PARAM_OPERATION values */ ++#define OSSL_KEM_PARAM_OPERATION_RSASVE "RSASVE" ++#define OSSL_KEM_PARAM_OPERATION_DHKEM "DHKEM" ++ ++/* Parameter name definitions - generated by util/perl/OpenSSL/paramnames.pm */ ++{- generate_public_macros(); -} ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif +diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c +index ed95c97..455924f 100644 +--- a/providers/implementations/ciphers/ciphercommon_gcm.c ++++ b/providers/implementations/ciphers/ciphercommon_gcm.c +@@ -15,6 +15,7 @@ + #include "prov/ciphercommon_gcm.h" + #include "prov/providercommon.h" + #include "prov/provider_ctx.h" ++#include "internal/param_names.h" + + static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len); + static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, +@@ -145,84 +146,97 @@ int ossl_gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + OSSL_PARAM *p; + size_t sz; +- +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); +- if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); +- if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); +- if (p != NULL) { +- size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen : +- GCM_TAG_MAX_SIZE; +- +- if (!OSSL_PARAM_set_size_t(p, taglen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- } +- +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); +- if (p != NULL) { +- if (ctx->iv_state == IV_STATE_UNINITIALISED) +- return 0; +- if (ctx->ivlen > p->data_size) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); +- return 0; +- } +- if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen) +- && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- } +- +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV); +- if (p != NULL) { +- if (ctx->iv_state == IV_STATE_UNINITIALISED) +- return 0; +- if (ctx->ivlen > p->data_size) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); +- return 0; +- } +- if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen) +- && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- } +- +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); +- if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); +- if (p != NULL) { +- sz = p->data_size; +- if (sz == 0 +- || sz > EVP_GCM_TLS_TAG_LEN +- || !ctx->enc +- || ctx->taglen == UNINITIALISED_SIZET) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); +- return 0; ++ int type; ++ ++ for (p = params; p->key != NULL; p++) { ++ type = ossl_param_find_pidx(p->key); ++ switch (type) { ++ default: ++ break; ++ ++ case PIDX_CIPHER_PARAM_IVLEN: ++ if (!OSSL_PARAM_set_size_t(p, ctx->ivlen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_KEYLEN: ++ if (!OSSL_PARAM_set_size_t(p, ctx->keylen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TAGLEN: ++ { ++ size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen : ++ GCM_TAG_MAX_SIZE; ++ ++ if (!OSSL_PARAM_set_size_t(p, taglen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_IV: ++ if (ctx->iv_state == IV_STATE_UNINITIALISED) ++ return 0; ++ if (ctx->ivlen > p->data_size) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); ++ return 0; ++ } ++ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen) ++ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_UPDATED_IV: ++ if (ctx->iv_state == IV_STATE_UNINITIALISED) ++ return 0; ++ if (ctx->ivlen > p->data_size) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); ++ return 0; ++ } ++ if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen) ++ && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TLS1_AAD_PAD: ++ if (!OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TAG: ++ sz = p->data_size; ++ if (sz == 0 ++ || sz > EVP_GCM_TLS_TAG_LEN ++ || !ctx->enc ++ || ctx->taglen == UNINITIALISED_SIZET) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); ++ return 0; ++ } ++ if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN: ++ if (p->data == NULL ++ || p->data_type != OSSL_PARAM_OCTET_STRING ++ || !getivgen(ctx, p->data, p->data_size)) ++ return 0; ++ break; + } +- if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); +- return 0; +- } +- } +- p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN); +- if (p != NULL) { +- if (p->data == NULL +- || p->data_type != OSSL_PARAM_OCTET_STRING +- || !getivgen(ctx, p->data, p->data_size)) +- return 0; + } + return 1; + } +@@ -233,71 +247,75 @@ int ossl_gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) + const OSSL_PARAM *p; + size_t sz; + void *vp; ++ int type; + + if (params == NULL) + return 1; + +- p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); +- if (p != NULL) { +- vp = ctx->buf; +- if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); +- return 0; +- } +- if (sz == 0 || ctx->enc) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); +- return 0; ++ for (p = params; p->key != NULL; p++) { ++ type = ossl_param_find_pidx(p->key); ++ switch (type) { ++ default: ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TAG: ++ vp = ctx->buf; ++ if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); ++ return 0; ++ } ++ if (sz == 0 || ctx->enc) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); ++ return 0; ++ } ++ ctx->taglen = sz; ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_IVLEN: ++ if (!OSSL_PARAM_get_size_t(p, &sz)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); ++ return 0; ++ } ++ if (sz == 0 || sz > sizeof(ctx->iv)) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); ++ return 0; ++ } ++ ctx->ivlen = sz; ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TLS1_AAD: ++ if (p->data_type != OSSL_PARAM_OCTET_STRING) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); ++ return 0; ++ } ++ sz = gcm_tls_init(ctx, p->data, p->data_size); ++ if (sz == 0) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD); ++ return 0; ++ } ++ ctx->tls_aad_pad_sz = sz; ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TLS1_IV_FIXED: ++ if (p->data_type != OSSL_PARAM_OCTET_STRING) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); ++ return 0; ++ } ++ if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { ++ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); ++ return 0; ++ } ++ break; ++ ++ case PIDX_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV: ++ if (p->data == NULL ++ || p->data_type != OSSL_PARAM_OCTET_STRING ++ || !setivinv(ctx, p->data, p->data_size)) ++ return 0; ++ break; + } +- ctx->taglen = sz; + } + +- p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); +- if (p != NULL) { +- if (!OSSL_PARAM_get_size_t(p, &sz)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); +- return 0; +- } +- if (sz == 0 || sz > sizeof(ctx->iv)) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); +- return 0; +- } +- ctx->ivlen = sz; +- } +- +- p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); +- if (p != NULL) { +- if (p->data_type != OSSL_PARAM_OCTET_STRING) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); +- return 0; +- } +- sz = gcm_tls_init(ctx, p->data, p->data_size); +- if (sz == 0) { +- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD); +- return 0; +- } +- ctx->tls_aad_pad_sz = sz; +- } +- +- p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED); +- if (p != NULL) { +- if (p->data_type != OSSL_PARAM_OCTET_STRING) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); +- return 0; +- } +- if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { +- ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); +- return 0; +- } +- } +- p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV); +- if (p != NULL) { +- if (p->data == NULL +- || p->data_type != OSSL_PARAM_OCTET_STRING +- || !setivinv(ctx, p->data, p->data_size)) +- return 0; +- } +- +- + return 1; + } + +diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm +new file mode 100644 +index 0000000..66c6fdd +--- /dev/null ++++ b/util/perl/OpenSSL/paramnames.pm +@@ -0,0 +1,673 @@ ++#! /usr/bin/env perl ++# Copyright 2023 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 ++ ++package OpenSSL::paramnames; ++ ++use strict; ++use warnings; ++ ++require Exporter; ++our @ISA = qw(Exporter); ++our @EXPORT_OK = qw(generate_public_macros ++ generate_internal_macros ++ produce_decoder); ++ ++my $case_sensitive = 1; ++ ++my %params = ( ++# Well known parameter names that core passes to providers ++ 'PROV_PARAM_CORE_VERSION' => "openssl-version",# utf8_ptr ++ 'PROV_PARAM_CORE_PROV_NAME' => "provider-name", # utf8_ptr ++ 'PROV_PARAM_CORE_MODULE_FILENAME' => "module-filename",# utf8_ptr ++ ++# Well known parameter names that Providers can define ++ 'PROV_PARAM_NAME' => "name", # utf8_ptr ++ 'PROV_PARAM_VERSION' => "version", # utf8_ptr ++ 'PROV_PARAM_BUILDINFO' => "buildinfo", # utf8_ptr ++ 'PROV_PARAM_STATUS' => "status", # uint ++ 'PROV_PARAM_SECURITY_CHECKS' => "security-checks", # uint ++ 'PROV_PARAM_TLS1_PRF_EMS_CHECK' => "tls1-prf-ems-check", # uint ++ 'PROV_PARAM_DRBG_TRUNC_DIGEST' => "drbg-no-trunc-md", # uint ++ ++# Self test callback parameters ++ 'PROV_PARAM_SELF_TEST_PHASE' => "st-phase",# utf8_string ++ 'PROV_PARAM_SELF_TEST_TYPE' => "st-type", # utf8_string ++ 'PROV_PARAM_SELF_TEST_DESC' => "st-desc", # utf8_string ++ ++# Provider-native object abstractions ++# ++# These are used when a provider wants to pass object data or an object ++# reference back to libcrypto. This is only useful for provider functions ++# that take a callback to which an PARAM array with these parameters ++# can be passed. ++# ++# This set of parameter names is explained in detail in provider-object(7) ++# (doc/man7/provider-object.pod) ++ ++ 'OBJECT_PARAM_TYPE' => "type", # INTEGER ++ 'OBJECT_PARAM_DATA_TYPE' => "data-type",# UTF8_STRING ++ 'OBJECT_PARAM_DATA_STRUCTURE' => "data-structure",# UTF8_STRING ++ 'OBJECT_PARAM_REFERENCE' => "reference",# OCTET_STRING ++ 'OBJECT_PARAM_DATA' => "data",# OCTET_STRING or UTF8_STRING ++ 'OBJECT_PARAM_DESC' => "desc", # UTF8_STRING ++ ++# Algorithm parameters ++# If "engine",or "properties",are specified, they should always be paired ++# with the algorithm type. ++# Note these are common names that are shared by many types (such as kdf, mac, ++# and pkey) e.g: see MAC_PARAM_DIGEST below. ++ ++ 'ALG_PARAM_DIGEST' => "digest", # utf8_string ++ 'ALG_PARAM_CIPHER' => "cipher", # utf8_string ++ 'ALG_PARAM_ENGINE' => "engine", # utf8_string ++ 'ALG_PARAM_MAC' => "mac", # utf8_string ++ 'ALG_PARAM_PROPERTIES' => "properties", # utf8_string ++ ++# cipher parameters ++ 'CIPHER_PARAM_PADDING' => "padding", # uint ++ 'CIPHER_PARAM_USE_BITS' => "use-bits", # uint ++ 'CIPHER_PARAM_TLS_VERSION' => "tls-version", # uint ++ 'CIPHER_PARAM_TLS_MAC' => "tls-mac", # octet_ptr ++ 'CIPHER_PARAM_TLS_MAC_SIZE' => "tls-mac-size",# size_t ++ 'CIPHER_PARAM_MODE' => "mode", # uint ++ 'CIPHER_PARAM_BLOCK_SIZE' => "blocksize", # size_t ++ 'CIPHER_PARAM_AEAD' => "aead", # int, 0 or 1 ++ 'CIPHER_PARAM_CUSTOM_IV' => "custom-iv", # int, 0 or 1 ++ 'CIPHER_PARAM_CTS' => "cts", # int, 0 or 1 ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK' => "tls-multi", # int, 0 or 1 ++ 'CIPHER_PARAM_HAS_RAND_KEY' => "has-randkey", # int, 0 or 1 ++ 'CIPHER_PARAM_KEYLEN' => "keylen", # size_t ++ 'CIPHER_PARAM_IVLEN' => "ivlen", # size_t ++ 'CIPHER_PARAM_IV' => "iv", # octet_string OR octet_ptr ++ 'CIPHER_PARAM_UPDATED_IV' => "updated-iv", # octet_string OR octet_ptr ++ 'CIPHER_PARAM_NUM' => "num", # uint ++ 'CIPHER_PARAM_ROUNDS' => "rounds", # uint ++ 'CIPHER_PARAM_AEAD_TAG' => "tag", # octet_string ++ 'CIPHER_PARAM_AEAD_TLS1_AAD' => "tlsaad", # octet_string ++ 'CIPHER_PARAM_AEAD_TLS1_AAD_PAD' => "tlsaadpad", # size_t ++ 'CIPHER_PARAM_AEAD_TLS1_IV_FIXED' => "tlsivfixed", # octet_string ++ 'CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN' => "tlsivgen", # octet_string ++ 'CIPHER_PARAM_AEAD_TLS1_SET_IV_INV' => "tlsivinv", # octet_string ++ 'CIPHER_PARAM_AEAD_IVLEN' => '*CIPHER_PARAM_IVLEN', ++ 'CIPHER_PARAM_AEAD_TAGLEN' => "taglen", # size_t ++ 'CIPHER_PARAM_AEAD_MAC_KEY' => "mackey", # octet_string ++ 'CIPHER_PARAM_RANDOM_KEY' => "randkey", # octet_string ++ 'CIPHER_PARAM_RC2_KEYBITS' => "keybits", # size_t ++ 'CIPHER_PARAM_SPEED' => "speed", # uint ++ 'CIPHER_PARAM_CTS_MODE' => "cts_mode", # utf8_string ++# For passing the AlgorithmIdentifier parameter in DER form ++ 'CIPHER_PARAM_ALGORITHM_ID_PARAMS' => "alg_id_param",# octet_string ++ 'CIPHER_PARAM_XTS_STANDARD' => "xts_standard",# utf8_string ++ ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT' => "tls1multi_maxsndfrag",# uint ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE' => "tls1multi_maxbufsz", # size_t ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE' => "tls1multi_interleave",# uint ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_AAD' => "tls1multi_aad", # octet_string ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN' => "tls1multi_aadpacklen",# uint ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_ENC' => "tls1multi_enc", # octet_string ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN' => "tls1multi_encin", # octet_string ++ 'CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN' => "tls1multi_enclen", # size_t ++ ++# digest parameters ++ 'DIGEST_PARAM_XOFLEN' => "xoflen", # size_t ++ 'DIGEST_PARAM_SSL3_MS' => "ssl3-ms", # octet string ++ 'DIGEST_PARAM_PAD_TYPE' => "pad-type", # uint ++ 'DIGEST_PARAM_MICALG' => "micalg", # utf8 string ++ 'DIGEST_PARAM_BLOCK_SIZE' => "blocksize", # size_t ++ 'DIGEST_PARAM_SIZE' => "size", # size_t ++ 'DIGEST_PARAM_XOF' => "xof", # int, 0 or 1 ++ 'DIGEST_PARAM_ALGID_ABSENT' => "algid-absent", # int, 0 or 1 ++ ++# MAC parameters ++ 'MAC_PARAM_KEY' => "key", # octet string ++ 'MAC_PARAM_IV' => "iv", # octet string ++ 'MAC_PARAM_CUSTOM' => "custom", # utf8 string ++ 'MAC_PARAM_SALT' => "salt", # octet string ++ 'MAC_PARAM_XOF' => "xof", # int, 0 or 1 ++ 'MAC_PARAM_DIGEST_NOINIT' => "digest-noinit", # int, 0 or 1 ++ 'MAC_PARAM_DIGEST_ONESHOT' => "digest-oneshot",# int, 0 or 1 ++ 'MAC_PARAM_C_ROUNDS' => "c-rounds", # unsigned int ++ 'MAC_PARAM_D_ROUNDS' => "d-rounds", # unsigned int ++ ++# If "engine",or "properties",are specified, they should always be paired ++# with "cipher",or "digest". ++ ++ 'MAC_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', # utf8 string ++ 'MAC_PARAM_DIGEST' => '*ALG_PARAM_DIGEST', # utf8 string ++ 'MAC_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', # utf8 string ++ 'MAC_PARAM_SIZE' => "size", # size_t ++ 'MAC_PARAM_BLOCK_SIZE' => "block-size", # size_t ++ 'MAC_PARAM_TLS_DATA_SIZE' => "tls-data-size", # size_t ++ ++# KDF / PRF parameters ++ 'KDF_PARAM_SECRET' => "secret", # octet string ++ 'KDF_PARAM_KEY' => "key", # octet string ++ 'KDF_PARAM_SALT' => "salt", # octet string ++ 'KDF_PARAM_PASSWORD' => "pass", # octet string ++ 'KDF_PARAM_PREFIX' => "prefix", # octet string ++ 'KDF_PARAM_LABEL' => "label", # octet string ++ 'KDF_PARAM_DATA' => "data", # octet string ++ 'KDF_PARAM_DIGEST' => '*ALG_PARAM_DIGEST', # utf8 string ++ 'KDF_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', # utf8 string ++ 'KDF_PARAM_MAC' => '*ALG_PARAM_MAC', # utf8 string ++ 'KDF_PARAM_MAC_SIZE' => "maclen", # size_t ++ 'KDF_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', # utf8 string ++ 'KDF_PARAM_ITER' => "iter", # unsigned int ++ 'KDF_PARAM_MODE' => "mode", # utf8 string or int ++ 'KDF_PARAM_PKCS5' => "pkcs5", # int ++ 'KDF_PARAM_UKM' => "ukm", # octet string ++ 'KDF_PARAM_CEK_ALG' => "cekalg", # utf8 string ++ 'KDF_PARAM_SCRYPT_N' => "n", # uint64_t ++ 'KDF_PARAM_SCRYPT_R' => "r", # uint32_t ++ 'KDF_PARAM_SCRYPT_P' => "p", # uint32_t ++ 'KDF_PARAM_SCRYPT_MAXMEM' => "maxmem_bytes", # uint64_t ++ 'KDF_PARAM_INFO' => "info", # octet string ++ 'KDF_PARAM_SEED' => "seed", # octet string ++ 'KDF_PARAM_SSHKDF_XCGHASH' => "xcghash", # octet string ++ 'KDF_PARAM_SSHKDF_SESSION_ID' => "session_id", # octet string ++ 'KDF_PARAM_SSHKDF_TYPE' => "type", # int ++ 'KDF_PARAM_SIZE' => "size", # size_t ++ 'KDF_PARAM_CONSTANT' => "constant", # octet string ++ 'KDF_PARAM_PKCS12_ID' => "id", # int ++ 'KDF_PARAM_KBKDF_USE_L' => "use-l", # int ++ 'KDF_PARAM_KBKDF_USE_SEPARATOR' => "use-separator", # int ++ 'KDF_PARAM_KBKDF_R' => "r", # int ++ 'KDF_PARAM_X942_ACVPINFO' => "acvp-info", ++ 'KDF_PARAM_X942_PARTYUINFO' => "partyu-info", ++ 'KDF_PARAM_X942_PARTYVINFO' => "partyv-info", ++ 'KDF_PARAM_X942_SUPP_PUBINFO' => "supp-pubinfo", ++ 'KDF_PARAM_X942_SUPP_PRIVINFO' => "supp-privinfo", ++ 'KDF_PARAM_X942_USE_KEYBITS' => "use-keybits", ++ 'KDF_PARAM_HMACDRBG_ENTROPY' => "entropy", ++ 'KDF_PARAM_HMACDRBG_NONCE' => "nonce", ++ 'KDF_PARAM_THREADS' => "threads", # uint32_t ++ 'KDF_PARAM_EARLY_CLEAN' => "early_clean", # uint32_t ++ 'KDF_PARAM_ARGON2_AD' => "ad", # octet string ++ 'KDF_PARAM_ARGON2_LANES' => "lanes", # uint32_t ++ 'KDF_PARAM_ARGON2_MEMCOST' => "memcost", # uint32_t ++ 'KDF_PARAM_ARGON2_VERSION' => "version", # uint32_t ++ ++# Known RAND names ++ 'RAND_PARAM_STATE' => "state", ++ 'RAND_PARAM_STRENGTH' => "strength", ++ 'RAND_PARAM_MAX_REQUEST' => "max_request", ++ 'RAND_PARAM_TEST_ENTROPY' => "test_entropy", ++ 'RAND_PARAM_TEST_NONCE' => "test_nonce", ++ ++# RAND/DRBG names ++ 'DRBG_PARAM_RESEED_REQUESTS' => "reseed_requests", ++ 'DRBG_PARAM_RESEED_TIME_INTERVAL' => "reseed_time_interval", ++ 'DRBG_PARAM_MIN_ENTROPYLEN' => "min_entropylen", ++ 'DRBG_PARAM_MAX_ENTROPYLEN' => "max_entropylen", ++ 'DRBG_PARAM_MIN_NONCELEN' => "min_noncelen", ++ 'DRBG_PARAM_MAX_NONCELEN' => "max_noncelen", ++ 'DRBG_PARAM_MAX_PERSLEN' => "max_perslen", ++ 'DRBG_PARAM_MAX_ADINLEN' => "max_adinlen", ++ 'DRBG_PARAM_RESEED_COUNTER' => "reseed_counter", ++ 'DRBG_PARAM_RESEED_TIME' => "reseed_time", ++ 'DRBG_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', ++ 'DRBG_PARAM_DIGEST' => '*ALG_PARAM_DIGEST', ++ 'DRBG_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', ++ 'DRBG_PARAM_MAC' => '*ALG_PARAM_MAC', ++ 'DRBG_PARAM_USE_DF' => "use_derivation_function", ++ ++# DRBG call back parameters ++ 'DRBG_PARAM_ENTROPY_REQUIRED' => "entropy_required", ++ 'DRBG_PARAM_PREDICTION_RESISTANCE' => "prediction_resistance", ++ 'DRBG_PARAM_MIN_LENGTH' => "minium_length", ++ 'DRBG_PARAM_MAX_LENGTH' => "maxium_length", ++ 'DRBG_PARAM_RANDOM_DATA' => "random_data", ++ 'DRBG_PARAM_SIZE' => "size", ++ ++# PKEY parameters ++# Common PKEY parameters ++ 'PKEY_PARAM_BITS' => "bits",# integer ++ 'PKEY_PARAM_MAX_SIZE' => "max-size",# integer ++ 'PKEY_PARAM_SECURITY_BITS' => "security-bits",# integer ++ 'PKEY_PARAM_DIGEST' => '*ALG_PARAM_DIGEST', ++ 'PKEY_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', # utf8 string ++ 'PKEY_PARAM_ENGINE' => '*ALG_PARAM_ENGINE', # utf8 string ++ 'PKEY_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', ++ 'PKEY_PARAM_DEFAULT_DIGEST' => "default-digest",# utf8 string ++ 'PKEY_PARAM_MANDATORY_DIGEST' => "mandatory-digest",# utf8 string ++ 'PKEY_PARAM_PAD_MODE' => "pad-mode", ++ 'PKEY_PARAM_DIGEST_SIZE' => "digest-size", ++ 'PKEY_PARAM_MASKGENFUNC' => "mgf", ++ 'PKEY_PARAM_MGF1_DIGEST' => "mgf1-digest", ++ 'PKEY_PARAM_MGF1_PROPERTIES' => "mgf1-properties", ++ 'PKEY_PARAM_ENCODED_PUBLIC_KEY' => "encoded-pub-key", ++ 'PKEY_PARAM_GROUP_NAME' => "group", ++ 'PKEY_PARAM_DIST_ID' => "distid", ++ 'PKEY_PARAM_PUB_KEY' => "pub", ++ 'PKEY_PARAM_PRIV_KEY' => "priv", ++ 'PKEY_PARAM_IMPLICIT_REJECTION' => "implicit-rejection", ++ ++# Diffie-Hellman/DSA Parameters ++ 'PKEY_PARAM_FFC_P' => "p", ++ 'PKEY_PARAM_FFC_G' => "g", ++ 'PKEY_PARAM_FFC_Q' => "q", ++ 'PKEY_PARAM_FFC_GINDEX' => "gindex", ++ 'PKEY_PARAM_FFC_PCOUNTER' => "pcounter", ++ 'PKEY_PARAM_FFC_SEED' => "seed", ++ 'PKEY_PARAM_FFC_COFACTOR' => "j", ++ 'PKEY_PARAM_FFC_H' => "hindex", ++ 'PKEY_PARAM_FFC_VALIDATE_PQ' => "validate-pq", ++ 'PKEY_PARAM_FFC_VALIDATE_G' => "validate-g", ++ 'PKEY_PARAM_FFC_VALIDATE_LEGACY' => "validate-legacy", ++ ++# Diffie-Hellman params ++ 'PKEY_PARAM_DH_GENERATOR' => "safeprime-generator", ++ 'PKEY_PARAM_DH_PRIV_LEN' => "priv_len", ++ ++# Elliptic Curve Domain Parameters ++ 'PKEY_PARAM_EC_PUB_X' => "qx", ++ 'PKEY_PARAM_EC_PUB_Y' => "qy", ++ ++# Elliptic Curve Explicit Domain Parameters ++ 'PKEY_PARAM_EC_FIELD_TYPE' => "field-type", ++ 'PKEY_PARAM_EC_P' => "p", ++ 'PKEY_PARAM_EC_A' => "a", ++ 'PKEY_PARAM_EC_B' => "b", ++ 'PKEY_PARAM_EC_GENERATOR' => "generator", ++ 'PKEY_PARAM_EC_ORDER' => "order", ++ 'PKEY_PARAM_EC_COFACTOR' => "cofactor", ++ 'PKEY_PARAM_EC_SEED' => "seed", ++ 'PKEY_PARAM_EC_CHAR2_M' => "m", ++ 'PKEY_PARAM_EC_CHAR2_TYPE' => "basis-type", ++ 'PKEY_PARAM_EC_CHAR2_TP_BASIS' => "tp", ++ 'PKEY_PARAM_EC_CHAR2_PP_K1' => "k1", ++ 'PKEY_PARAM_EC_CHAR2_PP_K2' => "k2", ++ 'PKEY_PARAM_EC_CHAR2_PP_K3' => "k3", ++ 'PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS' => "decoded-from-explicit", ++ ++# Elliptic Curve Key Parameters ++ 'PKEY_PARAM_USE_COFACTOR_FLAG' => "use-cofactor-flag", ++ 'PKEY_PARAM_USE_COFACTOR_ECDH' => '*PKEY_PARAM_USE_COFACTOR_FLAG', ++ ++# RSA Keys ++# ++# n, e, d are the usual public and private key components ++# ++# rsa-num is the number of factors, including p and q ++# rsa-factor is used for each factor: p, q, r_i (i = 3, ...) ++# rsa-exponent is used for each exponent: dP, dQ, d_i (i = 3, ...) ++# rsa-coefficient is used for each coefficient: qInv, t_i (i = 3, ...) ++# ++# The number of rsa-factor items must be equal to the number of rsa-exponent ++# items, and the number of rsa-coefficients must be one less. ++# (the base i for the coefficients is 2, not 1, at least as implied by ++# RFC 8017) ++ ++ 'PKEY_PARAM_RSA_N' => "n", ++ 'PKEY_PARAM_RSA_E' => "e", ++ 'PKEY_PARAM_RSA_D' => "d", ++ 'PKEY_PARAM_RSA_FACTOR' => "rsa-factor", ++ 'PKEY_PARAM_RSA_EXPONENT' => "rsa-exponent", ++ 'PKEY_PARAM_RSA_COEFFICIENT' => "rsa-coefficient", ++ 'PKEY_PARAM_RSA_FACTOR1' => "rsa-factor1", ++ 'PKEY_PARAM_RSA_FACTOR2' => "rsa-factor2", ++ 'PKEY_PARAM_RSA_FACTOR3' => "rsa-factor3", ++ 'PKEY_PARAM_RSA_FACTOR4' => "rsa-factor4", ++ 'PKEY_PARAM_RSA_FACTOR5' => "rsa-factor5", ++ 'PKEY_PARAM_RSA_FACTOR6' => "rsa-factor6", ++ 'PKEY_PARAM_RSA_FACTOR7' => "rsa-factor7", ++ 'PKEY_PARAM_RSA_FACTOR8' => "rsa-factor8", ++ 'PKEY_PARAM_RSA_FACTOR9' => "rsa-factor9", ++ 'PKEY_PARAM_RSA_FACTOR10' => "rsa-factor10", ++ 'PKEY_PARAM_RSA_EXPONENT1' => "rsa-exponent1", ++ 'PKEY_PARAM_RSA_EXPONENT2' => "rsa-exponent2", ++ 'PKEY_PARAM_RSA_EXPONENT3' => "rsa-exponent3", ++ 'PKEY_PARAM_RSA_EXPONENT4' => "rsa-exponent4", ++ 'PKEY_PARAM_RSA_EXPONENT5' => "rsa-exponent5", ++ 'PKEY_PARAM_RSA_EXPONENT6' => "rsa-exponent6", ++ 'PKEY_PARAM_RSA_EXPONENT7' => "rsa-exponent7", ++ 'PKEY_PARAM_RSA_EXPONENT8' => "rsa-exponent8", ++ 'PKEY_PARAM_RSA_EXPONENT9' => "rsa-exponent9", ++ 'PKEY_PARAM_RSA_EXPONENT10' => "rsa-exponent10", ++ 'PKEY_PARAM_RSA_COEFFICIENT1' => "rsa-coefficient1", ++ 'PKEY_PARAM_RSA_COEFFICIENT2' => "rsa-coefficient2", ++ 'PKEY_PARAM_RSA_COEFFICIENT3' => "rsa-coefficient3", ++ 'PKEY_PARAM_RSA_COEFFICIENT4' => "rsa-coefficient4", ++ 'PKEY_PARAM_RSA_COEFFICIENT5' => "rsa-coefficient5", ++ 'PKEY_PARAM_RSA_COEFFICIENT6' => "rsa-coefficient6", ++ 'PKEY_PARAM_RSA_COEFFICIENT7' => "rsa-coefficient7", ++ 'PKEY_PARAM_RSA_COEFFICIENT8' => "rsa-coefficient8", ++ 'PKEY_PARAM_RSA_COEFFICIENT9' => "rsa-coefficient9", ++ ++# Key generation parameters ++ 'PKEY_PARAM_RSA_BITS' => '*PKEY_PARAM_BITS', ++ 'PKEY_PARAM_RSA_PRIMES' => "primes", ++ 'PKEY_PARAM_RSA_DIGEST' => '*PKEY_PARAM_DIGEST', ++ 'PKEY_PARAM_RSA_DIGEST_PROPS' => '*PKEY_PARAM_PROPERTIES', ++ 'PKEY_PARAM_RSA_MASKGENFUNC' => '*PKEY_PARAM_MASKGENFUNC', ++ 'PKEY_PARAM_RSA_MGF1_DIGEST' => '*PKEY_PARAM_MGF1_DIGEST', ++ 'PKEY_PARAM_RSA_PSS_SALTLEN' => "saltlen", ++ ++# EC, X25519 and X448 Key generation parameters ++ 'PKEY_PARAM_DHKEM_IKM' => "dhkem-ikm", ++ ++# Key generation parameters ++ 'PKEY_PARAM_FFC_TYPE' => "type", ++ 'PKEY_PARAM_FFC_PBITS' => "pbits", ++ 'PKEY_PARAM_FFC_QBITS' => "qbits", ++ 'PKEY_PARAM_FFC_DIGEST' => '*PKEY_PARAM_DIGEST', ++ 'PKEY_PARAM_FFC_DIGEST_PROPS' => '*PKEY_PARAM_PROPERTIES', ++ ++ 'PKEY_PARAM_EC_ENCODING' => "encoding",# utf8_string ++ 'PKEY_PARAM_EC_POINT_CONVERSION_FORMAT' => "point-format", ++ 'PKEY_PARAM_EC_GROUP_CHECK_TYPE' => "group-check", ++ 'PKEY_PARAM_EC_INCLUDE_PUBLIC' => "include-public", ++ ++# Key Exchange parameters ++ 'EXCHANGE_PARAM_PAD' => "pad",# uint ++ 'EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE' => "ecdh-cofactor-mode",# int ++ 'EXCHANGE_PARAM_KDF_TYPE' => "kdf-type",# utf8_string ++ 'EXCHANGE_PARAM_KDF_DIGEST' => "kdf-digest",# utf8_string ++ 'EXCHANGE_PARAM_KDF_DIGEST_PROPS' => "kdf-digest-props",# utf8_string ++ 'EXCHANGE_PARAM_KDF_OUTLEN' => "kdf-outlen",# size_t ++# The following parameter is an octet_string on set and an octet_ptr on get ++ 'EXCHANGE_PARAM_KDF_UKM' => "kdf-ukm", ++ ++# Signature parameters ++ 'SIGNATURE_PARAM_ALGORITHM_ID' => "algorithm-id", ++ 'SIGNATURE_PARAM_PAD_MODE' => '*PKEY_PARAM_PAD_MODE', ++ 'SIGNATURE_PARAM_DIGEST' => '*PKEY_PARAM_DIGEST', ++ 'SIGNATURE_PARAM_PROPERTIES' => '*PKEY_PARAM_PROPERTIES', ++ 'SIGNATURE_PARAM_PSS_SALTLEN' => "saltlen", ++ 'SIGNATURE_PARAM_MGF1_DIGEST' => '*PKEY_PARAM_MGF1_DIGEST', ++ 'SIGNATURE_PARAM_MGF1_PROPERTIES' => '*PKEY_PARAM_MGF1_PROPERTIES', ++ 'SIGNATURE_PARAM_DIGEST_SIZE' => '*PKEY_PARAM_DIGEST_SIZE', ++ 'SIGNATURE_PARAM_NONCE_TYPE' => "nonce-type", ++ 'SIGNATURE_PARAM_INSTANCE' => "instance", ++ 'SIGNATURE_PARAM_CONTEXT_STRING' => "context-string", ++ ++# Asym cipher parameters ++ 'ASYM_CIPHER_PARAM_DIGEST' => '*PKEY_PARAM_DIGEST', ++ 'ASYM_CIPHER_PARAM_PROPERTIES' => '*PKEY_PARAM_PROPERTIES', ++ 'ASYM_CIPHER_PARAM_ENGINE' => '*PKEY_PARAM_ENGINE', ++ 'ASYM_CIPHER_PARAM_PAD_MODE' => '*PKEY_PARAM_PAD_MODE', ++ 'ASYM_CIPHER_PARAM_MGF1_DIGEST' => '*PKEY_PARAM_MGF1_DIGEST', ++ 'ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS' => '*PKEY_PARAM_MGF1_PROPERTIES', ++ 'ASYM_CIPHER_PARAM_OAEP_DIGEST' => '*ALG_PARAM_DIGEST', ++ 'ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS' => "digest-props", ++# The following parameter is an octet_string on set and an octet_ptr on get ++ 'ASYM_CIPHER_PARAM_OAEP_LABEL' => "oaep-label", ++ 'ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION' => "tls-client-version", ++ 'ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION' => "tls-negotiated-version", ++ 'ASYM_CIPHER_PARAM_IMPLICIT_REJECTION' => "implicit-rejection", ++ ++# Encoder / decoder parameters ++ ++ 'ENCODER_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', ++ 'ENCODER_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', ++# Currently PVK only, but reusable for others as needed ++ 'ENCODER_PARAM_ENCRYPT_LEVEL' => "encrypt-level", ++ 'ENCODER_PARAM_SAVE_PARAMETERS' => "save-parameters",# integer ++ ++ 'DECODER_PARAM_PROPERTIES' => '*ALG_PARAM_PROPERTIES', ++ ++# Passphrase callback parameters ++ 'PASSPHRASE_PARAM_INFO' => "info", ++ ++# Keygen callback parameters, from provider to libcrypto ++ 'GEN_PARAM_POTENTIAL' => "potential",# integer ++ 'GEN_PARAM_ITERATION' => "iteration",# integer ++ ++# ACVP Test parameters : These should not be used normally ++ 'PKEY_PARAM_RSA_TEST_XP1' => "xp1", ++ 'PKEY_PARAM_RSA_TEST_XP2' => "xp2", ++ 'PKEY_PARAM_RSA_TEST_XP' => "xp", ++ 'PKEY_PARAM_RSA_TEST_XQ1' => "xq1", ++ 'PKEY_PARAM_RSA_TEST_XQ2' => "xq2", ++ 'PKEY_PARAM_RSA_TEST_XQ' => "xq", ++ 'PKEY_PARAM_RSA_TEST_P1' => "p1", ++ 'PKEY_PARAM_RSA_TEST_P2' => "p2", ++ 'PKEY_PARAM_RSA_TEST_Q1' => "q1", ++ 'PKEY_PARAM_RSA_TEST_Q2' => "q2", ++ 'SIGNATURE_PARAM_KAT' => "kat", ++ ++# KEM parameters ++ 'KEM_PARAM_OPERATION' => "operation", ++ 'KEM_PARAM_IKME' => "ikme", ++ ++# Capabilities ++ ++# TLS-GROUP Capability ++ 'CAPABILITY_TLS_GROUP_NAME' => "tls-group-name", ++ 'CAPABILITY_TLS_GROUP_NAME_INTERNAL' => "tls-group-name-internal", ++ 'CAPABILITY_TLS_GROUP_ID' => "tls-group-id", ++ 'CAPABILITY_TLS_GROUP_ALG' => "tls-group-alg", ++ 'CAPABILITY_TLS_GROUP_SECURITY_BITS' => "tls-group-sec-bits", ++ 'CAPABILITY_TLS_GROUP_IS_KEM' => "tls-group-is-kem", ++ 'CAPABILITY_TLS_GROUP_MIN_TLS' => "tls-min-tls", ++ 'CAPABILITY_TLS_GROUP_MAX_TLS' => "tls-max-tls", ++ 'CAPABILITY_TLS_GROUP_MIN_DTLS' => "tls-min-dtls", ++ 'CAPABILITY_TLS_GROUP_MAX_DTLS' => "tls-max-dtls", ++ ++# TLS-SIGALG Capability ++ 'CAPABILITY_TLS_SIGALG_IANA_NAME' => "tls-sigalg-iana-name", ++ 'CAPABILITY_TLS_SIGALG_CODE_POINT' => "tls-sigalg-code-point", ++ 'CAPABILITY_TLS_SIGALG_NAME' => "tls-sigalg-name", ++ 'CAPABILITY_TLS_SIGALG_OID' => "tls-sigalg-oid", ++ 'CAPABILITY_TLS_SIGALG_SIG_NAME' => "tls-sigalg-sig-name", ++ 'CAPABILITY_TLS_SIGALG_SIG_OID' => "tls-sigalg-sig-oid", ++ 'CAPABILITY_TLS_SIGALG_HASH_NAME' => "tls-sigalg-hash-name", ++ 'CAPABILITY_TLS_SIGALG_HASH_OID' => "tls-sigalg-hash-oid", ++ 'CAPABILITY_TLS_SIGALG_KEYTYPE' => "tls-sigalg-keytype", ++ 'CAPABILITY_TLS_SIGALG_KEYTYPE_OID' => "tls-sigalg-keytype-oid", ++ 'CAPABILITY_TLS_SIGALG_SECURITY_BITS' => "tls-sigalg-sec-bits", ++ 'CAPABILITY_TLS_SIGALG_MIN_TLS' => "tls-min-tls", ++ 'CAPABILITY_TLS_SIGALG_MAX_TLS' => "tls-max-tls", ++ ++# storemgmt parameters ++ ++ ++# Used by storemgmt_ctx_set_params(): ++# ++# - STORE_PARAM_EXPECT is an INTEGER, and the value is any of the ++# STORE_INFO numbers. This is used to set the expected type of ++# object loaded. ++# ++# - STORE_PARAM_SUBJECT, STORE_PARAM_ISSUER, ++# STORE_PARAM_SERIAL, STORE_PARAM_FINGERPRINT, ++# STORE_PARAM_DIGEST, STORE_PARAM_ALIAS ++# are used as search criteria. ++# (STORE_PARAM_DIGEST is used with STORE_PARAM_FINGERPRINT) ++ ++ 'STORE_PARAM_EXPECT' => "expect", # INTEGER ++ 'STORE_PARAM_SUBJECT' => "subject", # DER blob => OCTET_STRING ++ 'STORE_PARAM_ISSUER' => "name", # DER blob => OCTET_STRING ++ 'STORE_PARAM_SERIAL' => "serial", # INTEGER ++ 'STORE_PARAM_DIGEST' => "digest", # UTF8_STRING ++ 'STORE_PARAM_FINGERPRINT' => "fingerprint", # OCTET_STRING ++ 'STORE_PARAM_ALIAS' => "alias", # UTF8_STRING ++ ++# You may want to pass properties for the provider implementation to use ++ 'STORE_PARAM_PROPERTIES' => "properties", # utf8_string ++# DECODER input type if a decoder is used by the store ++ 'STORE_PARAM_INPUT_TYPE' => "input-type", # UTF8_STRING ++ ++ ++# Libssl record layer ++ 'LIBSSL_RECORD_LAYER_PARAM_OPTIONS' => "options", ++ 'LIBSSL_RECORD_LAYER_PARAM_MODE' => "mode", ++ 'LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD' => "read_ahead", ++ 'LIBSSL_RECORD_LAYER_READ_BUFFER_LEN' => "read_buffer_len", ++ 'LIBSSL_RECORD_LAYER_PARAM_USE_ETM' => "use_etm", ++ 'LIBSSL_RECORD_LAYER_PARAM_STREAM_MAC' => "stream_mac", ++ 'LIBSSL_RECORD_LAYER_PARAM_TLSTREE' => "tlstree", ++ 'LIBSSL_RECORD_LAYER_PARAM_MAX_FRAG_LEN' => "max_frag_len", ++ 'LIBSSL_RECORD_LAYER_PARAM_MAX_EARLY_DATA' => "max_early_data", ++ 'LIBSSL_RECORD_LAYER_PARAM_BLOCK_PADDING' => "block_padding", ++); ++ ++# Generate string based macros for public consumption ++sub generate_public_macros { ++ my @macros = (); ++ ++ foreach my $name (keys %params) { ++ my $val = $params{$name}; ++ my $def = '# define OSSL_' . $name . ' '; ++ ++ if (substr($val, 0, 1) eq '*') { ++ $def .= 'OSSL_' . substr($val, 1); ++ } else { ++ $def .= '"' . $val . '"'; ++ } ++ push(@macros, $def) ++ } ++ return join("\n", sort @macros); ++} ++ ++# Generate number based macros for internal use ++# The numbers are unique per string ++sub generate_internal_macros { ++ my @macros = (); ++ my $count = 0; ++ my %reverse; ++ ++ # Determine the number for each unique string ++ # Sort the names to improve the chance of cache coherency ++ foreach my $name (sort keys %params) { ++ my $val = $params{$name}; ++ ++ if (substr($val, 0, 1) ne '*' and not defined $reverse{$val}) { ++ $reverse{$val} = $count++; ++ } ++ } ++ ++ # Output the defines ++ foreach my $name (keys %params) { ++ my $val = $params{$name}; ++ my $def = '#define PIDX_' . $name . ' '; ++ ++ if (substr($val, 0, 1) eq '*') { ++ $def .= 'PIDX_' . substr($val, 1); ++ } else { ++ $def .= $reverse{$val}; ++ } ++ push(@macros, $def) ++ } ++ return "#define NUM_PIDX $count\n\n" . join("\n", sort @macros); ++} ++ ++sub generate_trie { ++ my %trie; ++ my $nodes = 0; ++ my $chars = 0; ++ ++ foreach my $name (keys %params) { ++ my $val = $params{$name}; ++ if (substr($val, 0, 1) ne '*') { ++ my $cursor = \%trie; ++ ++ $chars += length($val); ++ for my $i (0 .. length($val) - 1) { ++ my $c = substr($val, $i, 1); ++ ++ if (not $case_sensitive) { ++ $c = '_' if $c eq '-'; ++ $c = lc $c; ++ } ++ ++ if (not defined $$cursor{$c}) { ++ $$cursor{$c} = {}; ++ $nodes++; ++ } ++ $cursor = %$cursor{$c}; ++ } ++ $$cursor{'val'} = $name; ++ } ++ } ++ #print "\n\n/* $nodes nodes for $chars letters*/\n\n"; ++ return %trie; ++} ++ ++sub generate_code_from_trie { ++ my $n = shift; ++ my $trieref = shift; ++ my $idt = " "; ++ my $indent0 = $idt x ($n + 1); ++ my $indent1 = $indent0 . $idt; ++ my $strcmp = $case_sensitive ? 'strcmp' : 'strcasecmp'; ++ ++ print "int ossl_param_find_pidx(const char *s)\n{\n" if $n == 0; ++ ++ if ($trieref->{'suffix'}) { ++ my $suf = $trieref->{'suffix'}; ++ ++ printf "%sif ($strcmp(\"$suf\", s + $n) == 0", $indent0; ++ if (not $case_sensitive) { ++ $suf =~ tr/_/-/; ++ print " || $strcmp(\"$suf\", s + $n) == 0" ++ if ($suf ne $trieref->{'suffix'}); ++ } ++ printf ")\n%sreturn PIDX_%s;\n", $indent1, $trieref->{'name'}; ++ #printf "%sbreak;\n", $indent0; ++ return; ++ } ++ ++ printf "%sswitch(s\[%d\]) {\n", $indent0, $n; ++ printf "%sdefault:\n", $indent0; ++ for my $l (sort keys %$trieref) { ++ if ($l eq 'val') { ++ printf "%sbreak;\n", $indent1; ++ printf "%scase '\\0':\n", $indent0; ++ printf "%sreturn PIDX_%s;\n", $indent1, $trieref->{'val'}; ++ } else { ++ printf "%sbreak;\n", $indent1; ++ printf "%scase '%s':", $indent0, $l; ++ if (not $case_sensitive) { ++ print " case '-':" if ($l eq '_'); ++ printf " case '%s':", uc $l if ($l =~ /[a-z]/); ++ } ++ print "\n"; ++ generate_code_from_trie($n + 1, $trieref->{$l}); ++ } ++ } ++ printf "%s}\n", $indent0; ++ print " return -1;\n}\n" if $n == 0; ++ return ""; ++} ++ ++# Find long endings and cache what they resolve to ++sub locate_long_endings { ++ my $trieref = shift; ++ my @names = keys %$trieref; ++ my $num = @names; ++ ++ return (1, '', $trieref->{$names[0]}) if ($num == 1 and $names[0] eq 'val'); ++ ++ if ($num == 1) { ++ my ($res, $suffix, $name) = locate_long_endings($trieref->{$names[0]}); ++ my $e = $names[0] . $suffix; ++ if ($res) { ++ $trieref->{'suffix'} = $e; ++ $trieref->{'name'} = $name; ++ } ++ return $res, $e, $name; ++ } ++ ++ for my $l (@names) { ++ if ($l ne 'val') { ++ my ($res, $suffix, $name) = locate_long_endings($trieref->{$l}); ++ } ++ } ++ return 0, ''; ++} ++ ++sub produce_decoder { ++ my %t = generate_trie(); ++ my $s; ++ ++ locate_long_endings(\%t); ++ ++ open local *STDOUT, '>', \$s; ++ generate_code_from_trie(0, \%t); ++ return $s; ++} +-- +2.33.0 + diff --git a/backport-property-use-a-stack-to-efficiently-convert-index-to.patch b/backport-property-use-a-stack-to-efficiently-convert-index-to.patch new file mode 100644 index 0000000000000000000000000000000000000000..197246eb8de1b6ec80a25dce34243f76ad718df7 --- /dev/null +++ b/backport-property-use-a-stack-to-efficiently-convert-index-to.patch @@ -0,0 +1,225 @@ +From b1b4806a8caf92f32d18b52985fe4b14a6a694bd Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Tue, 21 Dec 2021 11:44:31 +1100 +Subject: [PATCH] property: use a stack to efficiently convert index to string + +The existing code does this conversion by searching the hash table for the +appropriate index which is slow and expensive. + +Fixes #15867 + +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/17325) + +(cherry picked from commit 2e3c59356f847a76a90f9f837d4983428df6eb19) +Reviewed-by: Hugo Landau +--- + crypto/property/property_string.c | 114 ++++++++++++++---------------- + 1 file changed, 52 insertions(+), 62 deletions(-) + +diff --git a/crypto/property/property_string.c b/crypto/property/property_string.c +index ef87a6a782..3288c6ede8 100644 +--- a/crypto/property/property_string.c ++++ b/crypto/property/property_string.c +@@ -40,6 +40,8 @@ typedef struct { + PROP_TABLE *prop_values; + OSSL_PROPERTY_IDX prop_name_idx; + OSSL_PROPERTY_IDX prop_value_idx; ++ STACK_OF(OPENSSL_CSTRING) *prop_namelist; ++ STACK_OF(OPENSSL_CSTRING) *prop_valuelist; + } PROPERTY_STRING_DATA; + + static unsigned long property_hash(const PROPERTY_STRING *a) +@@ -78,6 +80,9 @@ static void property_string_data_free(void *vpropdata) + CRYPTO_THREAD_lock_free(propdata->lock); + property_table_free(&propdata->prop_names); + property_table_free(&propdata->prop_values); ++ sk_OPENSSL_CSTRING_free(propdata->prop_namelist); ++ sk_OPENSSL_CSTRING_free(propdata->prop_valuelist); ++ propdata->prop_namelist = propdata->prop_valuelist = NULL; + propdata->prop_name_idx = propdata->prop_value_idx = 0; + + OPENSSL_free(propdata); +@@ -90,24 +95,21 @@ static void *property_string_data_new(OSSL_LIB_CTX *ctx) { + return NULL; + + propdata->lock = CRYPTO_THREAD_lock_new(); +- if (propdata->lock == NULL) +- goto err; +- + propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash, + &property_cmp); +- if (propdata->prop_names == NULL) +- goto err; +- + propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash, + &property_cmp); +- if (propdata->prop_values == NULL) +- goto err; +- ++ propdata->prop_namelist = sk_OPENSSL_CSTRING_new_null(); ++ propdata->prop_valuelist = sk_OPENSSL_CSTRING_new_null(); ++ if (propdata->lock == NULL ++ || propdata->prop_names == NULL ++ || propdata->prop_values == NULL ++ || propdata->prop_namelist == NULL ++ || propdata->prop_valuelist == NULL) { ++ property_string_data_free(propdata); ++ return NULL; ++ } + return propdata; +- +-err: +- property_string_data_free(propdata); +- return NULL; + } + + static const OSSL_LIB_CTX_METHOD property_string_data_method = { +@@ -134,57 +136,65 @@ static PROPERTY_STRING *new_property_string(const char *s, + return ps; + } + +-static OSSL_PROPERTY_IDX ossl_property_string(CRYPTO_RWLOCK *lock, +- PROP_TABLE *t, +- OSSL_PROPERTY_IDX *pidx, +- const char *s) ++static OSSL_PROPERTY_IDX ossl_property_string(OSSL_LIB_CTX *ctx, int name, ++ int create, const char *s) + { + PROPERTY_STRING p, *ps, *ps_new; ++ PROP_TABLE *t; ++ STACK_OF(OPENSSL_CSTRING) *slist; ++ OSSL_PROPERTY_IDX *pidx; ++ PROPERTY_STRING_DATA *propdata ++ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, ++ &property_string_data_method); + ++ if (propdata == NULL) ++ return 0; ++ ++ t = name ? propdata->prop_names : propdata->prop_values; + p.s = s; +- if (!CRYPTO_THREAD_read_lock(lock)) { ++ if (!CRYPTO_THREAD_read_lock(propdata->lock)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK); + return 0; + } + ps = lh_PROPERTY_STRING_retrieve(t, &p); +- if (ps == NULL && pidx != NULL) { +- CRYPTO_THREAD_unlock(lock); +- if (!CRYPTO_THREAD_write_lock(lock)) { ++ if (ps == NULL && create) { ++ CRYPTO_THREAD_unlock(propdata->lock); ++ if (!CRYPTO_THREAD_write_lock(propdata->lock)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_WRITE_LOCK); + return 0; + } ++ pidx = name ? &propdata->prop_name_idx : &propdata->prop_value_idx; + ps = lh_PROPERTY_STRING_retrieve(t, &p); + if (ps == NULL && (ps_new = new_property_string(s, pidx)) != NULL) { ++ slist = name ? propdata->prop_namelist : propdata->prop_valuelist; ++ if (sk_OPENSSL_CSTRING_push(slist, ps_new->s) <= 0) { ++ property_free(ps_new); ++ CRYPTO_THREAD_unlock(propdata->lock); ++ return 0; ++ } + lh_PROPERTY_STRING_insert(t, ps_new); + if (lh_PROPERTY_STRING_error(t)) { ++ /*- ++ * Undo the previous push which means also decrementing the ++ * index and freeing the allocated storage. ++ */ ++ sk_OPENSSL_CSTRING_pop(slist); + property_free(ps_new); +- CRYPTO_THREAD_unlock(lock); ++ --*pidx; ++ CRYPTO_THREAD_unlock(propdata->lock); + return 0; + } + ps = ps_new; + } + } +- CRYPTO_THREAD_unlock(lock); ++ CRYPTO_THREAD_unlock(propdata->lock); + return ps != NULL ? ps->idx : 0; + } + +-struct find_str_st { +- const char *str; +- OSSL_PROPERTY_IDX idx; +-}; +- +-static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr) +-{ +- struct find_str_st *findstr = vfindstr; +- +- if (prop->idx == findstr->idx) +- findstr->str = prop->s; +-} +- + static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx, + OSSL_PROPERTY_IDX idx) + { +- struct find_str_st findstr; ++ const char *r; + PROPERTY_STRING_DATA *propdata + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, + &property_string_data_method); +@@ -192,33 +202,21 @@ static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx, + if (propdata == NULL) + return NULL; + +- findstr.str = NULL; +- findstr.idx = idx; +- + if (!CRYPTO_THREAD_read_lock(propdata->lock)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK); + return NULL; + } +- lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names +- : propdata->prop_values, +- find_str_fn, &findstr); ++ r = sk_OPENSSL_CSTRING_value(name ? propdata->prop_namelist ++ : propdata->prop_valuelist, idx - 1); + CRYPTO_THREAD_unlock(propdata->lock); + +- return findstr.str; ++ return r; + } + + OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s, + int create) + { +- PROPERTY_STRING_DATA *propdata +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, +- &property_string_data_method); +- +- if (propdata == NULL) +- return 0; +- return ossl_property_string(propdata->lock, propdata->prop_names, +- create ? &propdata->prop_name_idx : NULL, +- s); ++ return ossl_property_string(ctx, 1, create, s); + } + + const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) +@@ -229,15 +227,7 @@ const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) + OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s, + int create) + { +- PROPERTY_STRING_DATA *propdata +- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, +- &property_string_data_method); +- +- if (propdata == NULL) +- return 0; +- return ossl_property_string(propdata->lock, propdata->prop_values, +- create ? &propdata->prop_value_idx : NULL, +- s); ++ return ossl_property_string(ctx, 0, create, s); + } + + const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) +-- +2.33.0 + diff --git a/openssl.spec b/openssl.spec index 93a722dde4157ef66052dcc0233eb590f56f5961..7964393335f30ab64d1a647cd8f8173f01554f68 100644 --- a/openssl.spec +++ b/openssl.spec @@ -2,7 +2,7 @@ Name: openssl Epoch: 1 Version: 3.0.12 -Release: 13 +Release: 14 Summary: Cryptography and SSL/TLS Toolkit License: OpenSSL and SSLeay URL: https://www.openssl.org/ @@ -65,6 +65,16 @@ Patch52: backport-When-we-re-just-reading-EX_CALLBACK-data-just-get-a-.patch Patch53: backport-Avoid-an-unneccessary-lock-if-we-didn-t-add-anything.patch Patch54: backport-use-__builtin_expect-to-improve-EVP_EncryptUpdate-pe.patch Patch55: backport-Drop-ossl_namemap_add_name_n-and-simplify-ossl_namem.patch +Patch56: backport-Don-t-take-a-write-lock-to-retrieve-a-value-from-a-s.patch +Patch57: backport-aes-avoid-accessing-key-length-field-directly.patch +Patch58: backport-evp-enc-cache-cipher-key-length.patch +Patch59: backport-Avoid-calling-into-provider-with-the-same-iv_len-or-.patch +Patch60: backport-property-use-a-stack-to-efficiently-convert-index-to.patch +Patch61: backport-Revert-Release-the-drbg-in-the-global-default-contex.patch +Patch62: backport-Refactor-a-separate-func-for-provider-activation-fro.patch +Patch63: backport-Refactor-OSSL_LIB_CTX-to-avoid-using-CRYPTO_EX_DATA.patch +Patch64: backport-Release-the-drbg-in-the-global-default-context-befor.patch +Patch65: backport-params-provide-a-faster-TRIE-based-param-lookup.patch Patch9000: add-FIPS_mode_set-support.patch Patch9001: backport-CVE-2024-9143-Harden-BN_GF2m_poly2arr-against-misuse.patch @@ -268,6 +278,9 @@ make test || : %ldconfig_scriptlets libs %changelog +* Tue Nov 26 2024 steven - 1:3.0.12-14 +- backport patch for performance improvements + * Fri Nov 22 2024 zhujianwei - 1:3.0.12-13 - backport patch for performance improvements