[openssl] master update

Richard Levitte levitte at openssl.org
Sun Jun 28 08:57:50 UTC 2020


The branch master has been updated
       via  92db29e5e8c26af79f740dfd3bddfeae9b5345a8 (commit)
       via  6c689e58f70726cfa5533bc10f9669abce199fb8 (commit)
       via  cfbd76c1a9737617d4cf90d3a1af704241c97d98 (commit)
       via  e31eda006faaadc8bbe0bb809dbbaba0e4323fe6 (commit)
       via  3bd65f9b5b4731acae395d045dea63d7fdfd507b (commit)
       via  5a9752756b68632320c5aed7b6eb38e63a8ebf31 (commit)
      from  270540fd5413b00a746a581e8939c30862c689b1 (commit)


- Log -----------------------------------------------------------------
commit 92db29e5e8c26af79f740dfd3bddfeae9b5345a8
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 26 11:02:29 2020 +0100

    Add a test to make sure ASYNC aware code gets the right default libctx
    
    Even if a fibre changes the default libctx - or the main application code
    changes it, the "current" default libctx should remain consistent.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

commit 6c689e58f70726cfa5533bc10f9669abce199fb8
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 26 11:00:25 2020 +0100

    Make the ASYNC code default libctx aware
    
    Since the default libctx is now stored in a thread local variable
    swapping in and out of fibres in the ASYNC code could mean that the
    "current" default libctx can get confused. Therefore we ensure that
    everytime we call async_fibre_swapcontext() we always restore the default
    libctx to whatever it was the last time the fibre ran. Similarly when
    async_fibre_swapcontext() returns we need to restore the current thread's
    default libctx.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

commit cfbd76c1a9737617d4cf90d3a1af704241c97d98
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Jun 23 10:09:20 2020 +0200

    CORE: Add an internal function to distinguish the global default context
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

commit e31eda006faaadc8bbe0bb809dbbaba0e4323fe6
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Jun 22 15:49:55 2020 +0200

    TEST: Add test to exercise OPENSSL_CTX_set0_default()
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

commit 3bd65f9b5b4731acae395d045dea63d7fdfd507b
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Jun 22 13:15:22 2020 +0200

    Update NEWS and CHANGES
    
    NEWS and CHANGES hasn't mentioned OPENSSL_CTX before, so adding entries now.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

commit 5a9752756b68632320c5aed7b6eb38e63a8ebf31
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Jun 22 13:12:53 2020 +0200

    CORE: Add OPENSSL_CTX_set0_default(), to set a default library context
    
    Applications may want to set their own default library context,
    possibly per-thread.  OPENSSL_CTX_set0_default() does that.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12228)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                  |  22 +++++++++
 NEWS.md                     |   1 +
 crypto/async/async.c        |  18 ++++++++
 crypto/async/async_local.h  |   1 +
 crypto/context.c            |  84 ++++++++++++++++++++++++---------
 crypto/evp/evp_fetch.c      |  19 +++++---
 doc/man3/OPENSSL_CTX.pod    |  41 ++++++++++++-----
 include/internal/cryptlib.h |   1 +
 include/openssl/crypto.h    |   1 +
 test/asynctest.c            | 110 +++++++++++++++++++++++++++++++++++++++++++-
 test/evp_extra_test2.c      |  52 ++++++++++++++++++---
 util/libcrypto.num          |   1 +
 12 files changed, 304 insertions(+), 47 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 8f8ee33415..7da5ccd55c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -23,6 +23,28 @@ OpenSSL 3.0
 
 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
 
+ * Added a library context that applications as well as other
+   libraries can use to form a separate context within which libcrypto
+   operations are performed.
+
+   There are two ways this can be used:
+
+   - Directly, by passing a library context to functions that take
+     such an argument, such as `EVP_CIPHER_fetch` and similar algorithm
+     fetching functions.
+   - Indirectly, by creating a new library context and then assigning
+     it as the new default, with `OPENSSL_CTX_set0_default`.
+
+   All public OpenSSL functions that take an `OPENSSL_CTX` pointer,
+   apart from the functions directly related to `OPENSSL_CTX`, accept
+   NULL to indicate that the default library context should be used.
+
+   Library code that changes the default library context using
+   `OPENSSL_CTX_set0_default` should take care to restore it with a
+   second call before returning to the caller.
+
+   *Richard Levitte*
+
  * Handshake now fails if Extended Master Secret extension is dropped
    on renegotiation.
 
diff --git a/NEWS.md b/NEWS.md
index 759600cef9..1d36a903f1 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -20,6 +20,7 @@ OpenSSL 3.0
 
 ### Major changes between OpenSSL 1.1.1 and OpenSSL 3.0 [under development]
 
+  * Added `OPENSSL_CTX`, a libcrypto library context.
   * Interactive mode is removed from the 'openssl' program.
   * The X25519, X448, Ed25519, Ed448 and SHAKE256 algorithms are included in
     the FIPS provider.  None have the "fips=yes" property set and, as such,
diff --git a/crypto/async/async.c b/crypto/async/async.c
index 312f47325b..b985505309 100644
--- a/crypto/async/async.c
+++ b/crypto/async/async.c
@@ -170,6 +170,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
                     int (*func)(void *), void *args, size_t size)
 {
     async_ctx *ctx;
+    OPENSSL_CTX *libctx;
 
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
         return ASYNC_ERR;
@@ -203,6 +204,11 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
 
             if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
                 ctx->currjob = *job;
+                /*
+                 * Restore the default libctx to what it was the last time the
+                 * fibre ran
+                 */
+                libctx = OPENSSL_CTX_set0_default(ctx->currjob->libctx);
                 /* Resume previous job */
                 if (!async_fibre_swapcontext(&ctx->dispatcher,
                         &ctx->currjob->fibrectx, 1)) {
@@ -210,6 +216,12 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
                              ASYNC_R_FAILED_TO_SWAP_CONTEXT);
                     goto err;
                 }
+                /*
+                 * In case the fibre changed the default libctx we set it back
+                 * again to what it was originally, and remember what it had
+                 * been changed to.
+                 */
+                ctx->currjob->libctx = OPENSSL_CTX_set0_default(libctx);
                 continue;
             }
 
@@ -240,11 +252,17 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
 
         ctx->currjob->func = func;
         ctx->currjob->waitctx = wctx;
+        libctx = openssl_ctx_get_concrete(NULL);
         if (!async_fibre_swapcontext(&ctx->dispatcher,
                 &ctx->currjob->fibrectx, 1)) {
             ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
             goto err;
         }
+        /*
+         * In case the fibre changed the default libctx we set it back again
+         * to what it was, and remember what it had been changed to.
+         */
+        ctx->currjob->libctx = OPENSSL_CTX_set0_default(libctx);
     }
 
 err:
diff --git a/crypto/async/async_local.h b/crypto/async/async_local.h
index 549a27e611..f2f0a56186 100644
--- a/crypto/async/async_local.h
+++ b/crypto/async/async_local.h
@@ -43,6 +43,7 @@ struct async_job_st {
     int ret;
     int status;
     ASYNC_WAIT_CTX *waitctx;
+    OPENSSL_CTX *libctx;
 };
 
 struct fd_lookup_st {
diff --git a/crypto/context.c b/crypto/context.c
index 1c95298ea2..de289fcb68 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -39,13 +39,6 @@ struct openssl_ctx_st {
     struct openssl_ctx_onfree_list_st *onfreelist;
 };
 
-#ifndef FIPS_MODULE
-static OPENSSL_CTX default_context_int;
-
-/* Always points at default_context_int if it has been initialised */
-static OPENSSL_CTX *default_context = NULL;
-#endif
-
 static int context_init(OPENSSL_CTX *ctx)
 {
     size_t i;
@@ -120,18 +113,46 @@ static int context_deinit(OPENSSL_CTX *ctx)
 }
 
 #ifndef FIPS_MODULE
+/* The default default context */
+static OPENSSL_CTX default_context_int;
+
+static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_THREAD_LOCAL default_context_thread_local;
+
+DEFINE_RUN_ONCE_STATIC(default_context_do_init)
+{
+    return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)
+        && context_init(&default_context_int);
+}
+
 void openssl_ctx_default_deinit(void)
 {
-    context_deinit(default_context);
+    context_deinit(&default_context_int);
 }
 
-static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_default_context_init)
+static OPENSSL_CTX *get_thread_default_context(void)
 {
-    if (context_init(&default_context_int))
-        default_context = &default_context_int;
+    if (!RUN_ONCE(&default_context_init, default_context_do_init))
+        return NULL;
 
-    return 1;
+    return CRYPTO_THREAD_get_local(&default_context_thread_local);
+}
+
+static OPENSSL_CTX *get_default_context(void)
+{
+    OPENSSL_CTX *current_defctx = get_thread_default_context();
+
+    if (current_defctx == NULL)
+        current_defctx = &default_context_int;
+    return current_defctx;
+}
+
+static int set_default_context(OPENSSL_CTX *defctx)
+{
+    if (defctx == &default_context_int)
+        defctx = NULL;
+
+    return CRYPTO_THREAD_set_local(&default_context_thread_local, defctx);
 }
 #endif
 
@@ -155,19 +176,31 @@ int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file)
 
 void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
 {
-    if (ctx != NULL)
-        context_deinit(ctx);
+    if (openssl_ctx_is_default(ctx))
+        return;
+
+    context_deinit(ctx);
     OPENSSL_free(ctx);
 }
 
+OPENSSL_CTX *OPENSSL_CTX_set0_default(OPENSSL_CTX *libctx)
+{
+#ifndef FIPS_MODULE
+    OPENSSL_CTX *current_defctx;
+
+    if ((current_defctx = get_default_context()) != NULL
+        && set_default_context(libctx))
+        return current_defctx;
+#endif
+
+    return NULL;
+}
+
 OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)
 {
 #ifndef FIPS_MODULE
-    if (ctx == NULL) {
-        if (!RUN_ONCE(&default_context_init, do_default_context_init))
-            return 0;
-        return default_context;
-    }
+    if (ctx == NULL)
+        return get_default_context();
 #endif
     return ctx;
 }
@@ -175,7 +208,16 @@ OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)
 int openssl_ctx_is_default(OPENSSL_CTX *ctx)
 {
 #ifndef FIPS_MODULE
-    if (ctx == NULL || ctx == default_context)
+    if (ctx == NULL || ctx == get_default_context())
+        return 1;
+#endif
+    return 0;
+}
+
+int openssl_ctx_is_global_default(OPENSSL_CTX *ctx)
+{
+#ifndef FIPS_MODULE
+    if (openssl_ctx_get_concrete(ctx) == &default_context_int)
         return 1;
 #endif
     return 0;
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index f63e135d3a..5cb59d98fc 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -286,6 +286,17 @@ inner_evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
     return method;
 }
 
+#ifndef FIPS_MODULE
+static const char *libctx_descriptor(OPENSSL_CTX *libctx)
+{
+    if (openssl_ctx_is_global_default(libctx))
+        return "Global default library context";
+    if (openssl_ctx_is_default(libctx))
+        return "Thread-local default library context";
+    return "Non-default library context";
+}
+#endif
+
 void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
                         const char *name, const char *properties,
                         void *(*new_method)(int name_id,
@@ -306,9 +317,7 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
 #else
         ERR_raise_data(ERR_LIB_EVP, code,
                        "%s, Algorithm (%s), Properties (%s)",
-                       (openssl_ctx_is_default(libctx)
-                        ? "Default library context"
-                        : "Non-default library context"),
+                       libctx_descriptor(libctx),
                        name = NULL ? "<null>" : name,
                        properties == NULL ? "<null>" : properties);
 #endif
@@ -350,9 +359,7 @@ void *evp_generic_fetch_by_number(OPENSSL_CTX *libctx, int operation_id,
 
             ERR_raise_data(ERR_LIB_EVP, code,
                            "%s, Algorithm (%s), Properties (%s)",
-                           (openssl_ctx_is_default(libctx)
-                            ? "Default library context"
-                            : "Non-default library context"),
+                           libctx_descriptor(libctx),
                            name = NULL ? "<null>" : name,
                            properties == NULL ? "<null>" : properties);
         }
diff --git a/doc/man3/OPENSSL_CTX.pod b/doc/man3/OPENSSL_CTX.pod
index 3301250756..01737de2ef 100644
--- a/doc/man3/OPENSSL_CTX.pod
+++ b/doc/man3/OPENSSL_CTX.pod
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free, OPENSSL_CTX_load_config
+OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free, OPENSSL_CTX_load_config,
+OPENSSL_CTX_set0_default
 - OpenSSL library context
 
 =head1 SYNOPSIS
@@ -14,37 +15,53 @@ OPENSSL_CTX, OPENSSL_CTX_new, OPENSSL_CTX_free, OPENSSL_CTX_load_config
  OPENSSL_CTX *OPENSSL_CTX_new(void);
  int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file);
  void OPENSSL_CTX_free(OPENSSL_CTX *ctx);
+ OPENSSL_CTX *OPENSSL_CTX_set0_default(OPENSSL_CTX *ctx);
 
 =head1 DESCRIPTION
 
-C<OPENSSL_CTX> is an internal OpenSSL library context type.
-Applications may allocate their own, but may also use C<NULL> to use
-the internal default context with functions that take a C<OPENSSL_CTX>
+B<OPENSSL_CTX> is an internal OpenSSL library context type.
+Applications may allocate their own, but may also use NULL to use
+a default context with functions that take an B<OPENSSL_CTX>
 argument.
 
-OPENSSL_CTX_new() creates a new OpenSSL library context.
 When a non default library context is in use care should be taken with
 multi-threaded applications to properly clean up thread local resources before
 the OPENSSL_CTX is freed.
 See L<OPENSSL_thread_stop_ex(3)> for more information.
 
+OPENSSL_CTX_new() creates a new OpenSSL library context.
+
 OPENSSL_CTX_load_config() loads a configuration file using the given C<ctx>.
-This can be used to associate a libctx with providers that are loaded from
-a configuration.
+This can be used to associate a library context with providers that are loaded
+from a configuration.
+
+OPENSSL_CTX_free() frees the given I<ctx>, unless it happens to be the
+default OpenSSL library context.
+
+OPENSSL_CTX_set0_default() sets the default OpenSSL library context to be
+I<ctx> in the current thread.  The previous default library context is
+returned.  Care should be taken by the caller to restore the previous
+default library context with a subsequent call of this function.
 
-OPENSSL_CTX_free() frees the given C<ctx>.
+Care should be taken when changing the default library context and starting
+async jobs (see L<ASYNC_start_job(3)>), as the default library context when
+the job is started will be used throughout the lifetime of an async job, no
+matter how the calling thread makes further default library context changes
+in the mean time.  This means that the calling thread must not free the
+library context that was the default at the start of the async job before
+that job has finished.
 
 =head1 RETURN VALUES
 
-OPENSSL_CTX_new() return a library context pointer on success, or
-C<NULL> on error.
+OPENSSL_CTX_new() and OPENSSL_CTX_set0_default() return a library context
+pointer on success, or NULL on error.
 
 OPENSSL_CTX_free() doesn't return any value.
 
 =head1 HISTORY
 
-OPENSSL_CTX, OPENSSL_CTX_new(), OPENSSL_CTX_load_config() and OPENSSL_CTX_free()
-were added in OpenSSL 3.0.
+OPENSSL_CTX, OPENSSL_CTX_new(), OPENSSL_CTX_load_config(), OPENSSL_CTX_free()
+and OPENSSL_CTX_set0_default() were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 5118bfbe57..fba1d5643f 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -168,6 +168,7 @@ typedef struct openssl_ctx_method {
 
 OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx);
 int openssl_ctx_is_default(OPENSSL_CTX *ctx);
+int openssl_ctx_is_global_default(OPENSSL_CTX *ctx);
 
 /* Functions to retrieve pointers to data by index */
 void *openssl_ctx_get_data(OPENSSL_CTX *, int /* index */,
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index 58965de0e8..33296b6ada 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -494,6 +494,7 @@ int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b);
 OPENSSL_CTX *OPENSSL_CTX_new(void);
 int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file);
 void OPENSSL_CTX_free(OPENSSL_CTX *);
+OPENSSL_CTX *OPENSSL_CTX_set0_default(OPENSSL_CTX *libctx);
 
 # ifdef  __cplusplus
 }
diff --git a/test/asynctest.c b/test/asynctest.c
index dc357da8b7..13b66993c5 100644
--- a/test/asynctest.c
+++ b/test/asynctest.c
@@ -43,6 +43,39 @@ static int save_current(void *args)
     return 1;
 }
 
+static int change_deflt_libctx(void *args)
+{
+    OPENSSL_CTX *libctx = OPENSSL_CTX_new();
+    OPENSSL_CTX *oldctx, *tmpctx;
+    int ret = 0;
+
+    if (libctx == NULL)
+        return 0;
+
+    oldctx = OPENSSL_CTX_set0_default(libctx);
+    ASYNC_pause_job();
+
+    /* Check the libctx is set up as we expect */
+    tmpctx = OPENSSL_CTX_set0_default(oldctx);
+    if (tmpctx != libctx)
+        goto err;
+
+    /* Set it back again to continue to use our own libctx */
+    oldctx = OPENSSL_CTX_set0_default(libctx);
+    ASYNC_pause_job();
+
+    /* Check the libctx is set up as we expect */
+    tmpctx = OPENSSL_CTX_set0_default(oldctx);
+    if (tmpctx != libctx)
+        goto err;
+
+    ret = 1;
+ err:
+    OPENSSL_CTX_free(libctx);
+    return ret;
+}
+
+
 #define MAGIC_WAIT_FD   ((OSSL_ASYNC_FD)99)
 static int waitfd(void *args)
 {
@@ -306,6 +339,80 @@ static int test_ASYNC_block_pause(void)
     return 1;
 }
 
+static int test_ASYNC_start_job_with_libctx(void)
+{
+    ASYNC_JOB *job = NULL;
+    int funcret;
+    ASYNC_WAIT_CTX *waitctx = NULL;
+    OPENSSL_CTX *libctx = OPENSSL_CTX_new();
+    OPENSSL_CTX *oldctx, *tmpctx, *globalctx;
+    int ret = 0;
+
+    if (libctx == NULL) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() failed to create libctx\n");
+        goto err;
+    }
+
+    globalctx = oldctx = OPENSSL_CTX_set0_default(libctx);
+
+    if ((waitctx = ASYNC_WAIT_CTX_new()) == NULL
+            || ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx,
+                               NULL, 0)
+               != ASYNC_PAUSE) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() failed to start job\n");
+        goto err;
+    }
+
+    /* Reset the libctx temporarily to find out what it is*/
+    tmpctx = OPENSSL_CTX_set0_default(oldctx);
+    oldctx = OPENSSL_CTX_set0_default(tmpctx);
+    if (tmpctx != libctx) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() failed - unexpected libctx\n");
+        goto err;
+    }
+
+    if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0)
+               != ASYNC_PAUSE) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() - restarting job failed\n");
+        goto err;
+    }
+
+    /* Reset the libctx and continue with the global default libctx */
+    tmpctx = OPENSSL_CTX_set0_default(oldctx);
+    if (tmpctx != libctx) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() failed - unexpected libctx\n");
+        goto err;
+    }
+
+    if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0)
+               != ASYNC_FINISH
+                || funcret != 1) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() - finishing job failed\n");
+        goto err;
+    }
+
+    /* Reset the libctx temporarily to find out what it is*/
+    tmpctx = OPENSSL_CTX_set0_default(libctx);
+    OPENSSL_CTX_set0_default(tmpctx);
+    if (tmpctx != globalctx) {
+        fprintf(stderr,
+                "test_ASYNC_start_job_with_libctx() failed - global libctx check failed\n");
+        goto err;
+    }
+
+    ret = 1;
+ err:
+    ASYNC_WAIT_CTX_free(waitctx);
+    OPENSSL_CTX_free(libctx);
+    return ret;
+}
+
 int main(int argc, char **argv)
 {
     if (!ASYNC_is_capable()) {
@@ -317,7 +424,8 @@ int main(int argc, char **argv)
                 || !test_ASYNC_start_job()
                 || !test_ASYNC_get_current_job()
                 || !test_ASYNC_WAIT_CTX_get_all_fds()
-                || !test_ASYNC_block_pause()) {
+                || !test_ASYNC_block_pause()
+                || !test_ASYNC_start_job_with_libctx()) {
             return 1;
         }
     }
diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c
index f4d8b98256..63380f878a 100644
--- a/test/evp_extra_test2.c
+++ b/test/evp_extra_test2.c
@@ -19,7 +19,7 @@
 #include "testutil.h"
 #include "internal/nelem.h"
 
-static OPENSSL_CTX *libctx = NULL;
+static OPENSSL_CTX *mainctx = NULL;
 static OSSL_PROVIDER *nullprov = NULL;
 
 /*
@@ -198,7 +198,7 @@ static int test_d2i_AutoPrivateKey_ex(int i)
     int expected_id = ak->evptype;
 
     p = input;
-    if (!TEST_ptr(pkey = d2i_AutoPrivateKey_ex(NULL, &p, input_len, libctx,
+    if (!TEST_ptr(pkey = d2i_AutoPrivateKey_ex(NULL, &p, input_len, mainctx,
                                                NULL))
             || !TEST_ptr_eq(p, input + input_len)
             || !TEST_int_eq(EVP_PKEY_id(pkey), expected_id))
@@ -211,20 +211,58 @@ static int test_d2i_AutoPrivateKey_ex(int i)
     return ret;
 }
 
+static int test_alternative_default(void)
+{
+    OPENSSL_CTX *oldctx;
+    EVP_MD *sha256;
+    int ok = 0;
+
+    /*
+     * setup_tests() loaded the "null" provider in the current default, so
+     * we know this fetch should fail.
+     */
+    if (!TEST_ptr_null(sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL)))
+        goto err;
+
+    /*
+     * Now we switch to our main library context, and try again.  Since no
+     * providers are loaded in this one, it should fall back to the default.
+     */
+    if (!TEST_ptr(oldctx = OPENSSL_CTX_set0_default(mainctx))
+        || !TEST_ptr(sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL)))
+        goto err;
+    EVP_MD_free(sha256);
+    sha256 = NULL;
+
+    /*
+     * Switching back should give us our main library context back, and
+     * fetching SHA2-256 should fail again.
+     */
+    if (!TEST_ptr_eq(OPENSSL_CTX_set0_default(oldctx), mainctx)
+        || !TEST_ptr_null(sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL)))
+        goto err;
+
+    ok = 1;
+ err:
+    EVP_MD_free(sha256);
+    return ok;
+}
+
 int setup_tests(void)
 {
-    libctx = OPENSSL_CTX_new();
+    mainctx = OPENSSL_CTX_new();
 
-    if (!TEST_ptr(libctx))
+    if (!TEST_ptr(mainctx))
         return 0;
 
     nullprov = OSSL_PROVIDER_load(NULL, "null");
     if (!TEST_ptr(nullprov)) {
-        OPENSSL_CTX_free(libctx);
-        libctx = NULL;
+        OPENSSL_CTX_free(mainctx);
+        mainctx = NULL;
         return 0;
     }
 
+    ADD_TEST(test_alternative_default);
     ADD_ALL_TESTS(test_d2i_AutoPrivateKey_ex, OSSL_NELEM(keydata));
 
     return 1;
@@ -232,6 +270,6 @@ int setup_tests(void)
 
 void cleanup_tests(void)
 {
-    OPENSSL_CTX_free(libctx);
+    OPENSSL_CTX_free(mainctx);
     OSSL_PROVIDER_unload(nullprov);
 }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index ee3aa6d97c..22c7cdc709 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5134,3 +5134,4 @@ OSSL_PROVIDER_get_capabilities          ?	3_0_0	EXIST::FUNCTION:
 EC_GROUP_new_by_curve_name_with_libctx  ?	3_0_0	EXIST::FUNCTION:EC
 EC_KEY_new_with_libctx                  ?	3_0_0	EXIST::FUNCTION:EC
 EC_KEY_new_by_curve_name_with_libctx    ?	3_0_0	EXIST::FUNCTION:EC
+OPENSSL_CTX_set0_default                ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list