Commit dd8ac62036 for openssl.org

commit dd8ac62036068437486ca5827adc14471204c182
Author: Neil Horman <nhorman@openssl.org>
Date:   Wed Sep 23 12:42:35 2026 -0400

    add new_provider_loaded methods to libctx

    Add a integer field to the libctx which tracks weather or not we have
    constructed methods in this libctx for every operation type.

    Reviewed-by: Bob Beck <beck@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Merge-date: Mon Oct 26 19:25:23 2026
    Merged-from: https://github.com/openssl/openssl/pull/32965

diff --git a/crypto/context.c b/crypto/context.c
index 66d7e42955..1c6fd03da8 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -53,6 +53,7 @@ struct ossl_lib_ctx_st {

     int ischild;
     int conf_diagnostics;
+    uint64_t new_provider_loaded;
 };

 int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx)
@@ -128,6 +129,9 @@ static int context_init(OSSL_LIB_CTX *ctx)
         goto err;
     exdata_done = 1;

+    if (!CRYPTO_atomic_store(&ctx->new_provider_loaded, UINT64_MAX, ctx->lock))
+        goto err;
+
     /* 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)
@@ -680,6 +684,43 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index)
     }
 }

+int ossl_lib_ctx_get_new_providers_loaded(OSSL_LIB_CTX *ctx, int op)
+{
+    uint64_t ret = 0;
+
+    ctx = ossl_lib_ctx_get_concrete(ctx);
+
+    /*
+     * if the atomic read operation fails here, return 1 to pretend like new
+     * providers are loaded, it ensures that we behave as though there are
+     * new providers loaded if we fail.
+     */
+    if (!CRYPTO_atomic_load(&ctx->new_provider_loaded, &ret, ctx->lock))
+        return 1;
+    return !!(ret & (1ULL << op));
+}
+
+int ossl_lib_ctx_set_new_providers_loaded(OSSL_LIB_CTX *ctx)
+{
+    ctx = ossl_lib_ctx_get_concrete(ctx);
+
+    if (!CRYPTO_atomic_store(&ctx->new_provider_loaded, UINT64_MAX, ctx->lock))
+        return 0;
+    return 1;
+}
+
+int ossl_lib_ctx_clear_new_providers_loaded(OSSL_LIB_CTX *ctx, int op)
+{
+    uint64_t val = ~(1ULL << op);
+    uint64_t ret;
+
+    ctx = ossl_lib_ctx_get_concrete(ctx);
+
+    if (!CRYPTO_atomic_and(&ctx->new_provider_loaded, val, &ret, ctx->lock))
+        return 0;
+    return 1;
+}
+
 void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index)
 {
     return ossl_lib_ctx_get_data(ctx, index);
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index a6a38a53b9..f09d4dddc1 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -128,6 +128,9 @@ 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 */);
+int ossl_lib_ctx_get_new_providers_loaded(OSSL_LIB_CTX *, int);
+int ossl_lib_ctx_set_new_providers_loaded(OSSL_LIB_CTX *);
+int ossl_lib_ctx_clear_new_providers_loaded(OSSL_LIB_CTX *, int);

 void ossl_lib_ctx_default_deinit(void);
 OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx);