[openssl] master update

Richard Levitte levitte at openssl.org
Thu Jun 4 14:42:52 UTC 2020


The branch master has been updated
       via  c8567c392c1dc3dd15651c0d2746a5b87b5a88dd (commit)
       via  f995e5bdcd5d4c2143323ff78e4dcc0b95c5e024 (commit)
      from  4cbb196b1b33d6ff2089537df0fdb76ac4741e2a (commit)


- Log -----------------------------------------------------------------
commit c8567c392c1dc3dd15651c0d2746a5b87b5a88dd
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat May 23 16:39:18 2020 +0200

    CORE: make sure activated fallback providers stay activated
    
    Calling 'OSSL_PROVIDER_available(NULL, "default")' would search for
    the "default" provider, and in doing so, activate it if necessary,
    thereby detecting that it's available...  and then immediately free
    it, which could deactivate that provider, even though it should stay
    available.
    
    We solve this by incrementing the refcount for activated fallbacks one
    extra time, thereby simulating an explicit OSSL_PROVIDER_load(), and
    compensate for it with an extra ossl_provider_free() when emptying the
    provider store.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11926)

commit f995e5bdcd5d4c2143323ff78e4dcc0b95c5e024
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat May 23 16:34:07 2020 +0200

    TEST: Add provider_fallback_test, to test aspects of fallback providers
    
    There are cases where the fallback providers aren't treated right.
    For example, the following calls, in that order, will end up with
    a failed EVP_KEYMGMT_fetch(), even thought the default provider
    does supply an implementation of the "RSA" keytype.
    
        EVP_KEYMGMT *rsameth = NULL;
    
        OSSL_PROVIDER_available(NULL, "default");
        rsameth = EVP_KEYMGMT_fetch(NULL, "RSA", NULL);
    
    For good measure, this also tests that explicit loading of the default
    provider won't fail.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11926)

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

Summary of changes:
 crypto/provider_core.c                             | 42 +++++++++++++---
 test/build.info                                    |  5 ++
 test/provider_fallback_test.c                      | 57 ++++++++++++++++++++++
 ...t_internal_ec.t => 04-test_provider_fallback.t} | 13 +++--
 4 files changed, 103 insertions(+), 14 deletions(-)
 create mode 100644 test/provider_fallback_test.c
 copy test/recipes/{03-test_internal_ec.t => 04-test_provider_fallback.t} (52%)

diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index f8aa5721b4..8b868fdb6b 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -42,7 +42,8 @@ struct provider_store_st;        /* Forward declaration */
 struct ossl_provider_st {
     /* Flag bits */
     unsigned int flag_initialized:1;
-    unsigned int flag_fallback:1;
+    unsigned int flag_fallback:1; /* Can be used as fallback */
+    unsigned int flag_activated_as_fallback:1;
 
     /* OpenSSL library side data */
     CRYPTO_REF_COUNT refcnt;
@@ -104,6 +105,24 @@ struct provider_store_st {
     unsigned int use_fallbacks:1;
 };
 
+/*
+ * provider_deactivate_free() is a wrapper around ossl_provider_free()
+ * that also makes sure that activated fallback providers are deactivated.
+ * This is simply done by freeing them an extra time, to compensate for the
+ * refcount that provider_activate_fallbacks() gives them.
+ * Since this is only called when the provider store is being emptied, we
+ * don't need to care about any lock.
+ */
+static void provider_deactivate_free(OSSL_PROVIDER *prov)
+{
+    int extra_free = (prov->flag_initialized
+                      && prov->flag_activated_as_fallback);
+
+    if (extra_free)
+        ossl_provider_free(prov);
+    ossl_provider_free(prov);
+}
+
 static void provider_store_free(void *vstore)
 {
     struct provider_store_st *store = vstore;
@@ -111,7 +130,7 @@ static void provider_store_free(void *vstore)
     if (store == NULL)
         return;
     OPENSSL_free(store->default_path);
-    sk_OSSL_PROVIDER_pop_free(store->providers, ossl_provider_free);
+    sk_OSSL_PROVIDER_pop_free(store->providers, provider_deactivate_free);
     CRYPTO_THREAD_lock_free(store->lock);
     OPENSSL_free(store);
 }
@@ -654,13 +673,22 @@ static void provider_activate_fallbacks(struct provider_store_st *store)
             OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(store->providers, i);
 
             /*
-             * Note that we don't care if the activation succeeds or not.
-             * If it doesn't succeed, then any attempt to use any of the
-             * fallback providers will fail anyway.
+             * Activated fallback providers get an extra refcount, to
+             * simulate a regular load.
+             * Note that we don't care if the activation succeeds or not,
+             * other than to maintain a correct refcount.  If the activation
+             * doesn't succeed, then any future attempt to use the fallback
+             * provider will fail anyway.
              */
             if (prov->flag_fallback) {
-                activated_fallback_count++;
-                provider_activate(prov);
+                if (ossl_provider_up_ref(prov)) {
+                    if (!provider_activate(prov)) {
+                        ossl_provider_free(prov);
+                    } else {
+                        prov->flag_activated_as_fallback = 1;
+                        activated_fallback_count++;
+                    }
+                }
             }
         }
 
diff --git a/test/build.info b/test/build.info
index 9697e55f12..3255a836de 100644
--- a/test/build.info
+++ b/test/build.info
@@ -731,6 +731,11 @@ IF[{- !$disabled{tests} -}]
   DEPEND[]=provider_internal_test.cnf
   GENERATE[provider_internal_test.cnf]=provider_internal_test.cnf.in
 
+  PROGRAMS{noinst}=provider_fallback_test
+  SOURCE[provider_fallback_test]=provider_fallback_test.c
+  INCLUDE[provider_fallback_test]=../include ../apps/include
+  DEPEND[provider_fallback_test]=../libcrypto libtestutil.a
+
   PROGRAMS{noinst}=params_test
   SOURCE[params_test]=params_test.c
   INCLUDE[params_test]=.. ../include ../apps/include
diff --git a/test/provider_fallback_test.c b/test/provider_fallback_test.c
new file mode 100644
index 0000000000..ce62184551
--- /dev/null
+++ b/test/provider_fallback_test.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 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 <stddef.h>
+#include <openssl/provider.h>
+#include <openssl/evp.h>
+#include "testutil.h"
+
+static int test_provider(OPENSSL_CTX *ctx)
+{
+    EVP_KEYMGMT *rsameth = NULL;
+    const OSSL_PROVIDER *prov = NULL;
+    int ok;
+
+    ok = TEST_true(OSSL_PROVIDER_available(ctx, "default"))
+        && TEST_ptr(rsameth = EVP_KEYMGMT_fetch(ctx, "RSA", NULL))
+        && TEST_ptr(prov = EVP_KEYMGMT_provider(rsameth))
+        && TEST_str_eq(OSSL_PROVIDER_name(prov), "default");
+
+    EVP_KEYMGMT_free(rsameth);
+    return ok;
+}
+
+static int test_fallback_provider(void)
+{
+    return test_provider(NULL);
+}
+
+static int test_explicit_provider(void)
+{
+    OPENSSL_CTX *ctx = NULL;
+    OSSL_PROVIDER *prov = NULL;
+    int ok;
+
+    ok = TEST_ptr(ctx = OPENSSL_CTX_new())
+        && TEST_ptr(prov = OSSL_PROVIDER_load(ctx, "default"))
+        && test_provider(ctx)
+        && TEST_true(OSSL_PROVIDER_unload(prov));
+
+    OPENSSL_CTX_free(ctx);
+    return ok;
+}
+
+
+int setup_tests(void)
+{
+    ADD_TEST(test_fallback_provider);
+    ADD_TEST(test_explicit_provider);
+    return 1;
+}
+
diff --git a/test/recipes/03-test_internal_ec.t b/test/recipes/04-test_provider_fallback.t
similarity index 52%
copy from test/recipes/03-test_internal_ec.t
copy to test/recipes/04-test_provider_fallback.t
index 0d31d0ac07..39d3b105dc 100644
--- a/test/recipes/03-test_internal_ec.t
+++ b/test/recipes/04-test_provider_fallback.t
@@ -7,13 +7,12 @@
 # https://www.openssl.org/source/license.html
 
 use strict;
-use OpenSSL::Test;              # get 'plan'
+use File::Spec;
 use OpenSSL::Test::Simple;
-use OpenSSL::Test::Utils;
 
-setup("test_internal_ec");
+# We must ensure that OPENSSL_CONF points at an empty file.  Otherwise, we
+# risk that the configuration file contains statements that load providers,
+# which defeats the purpose of this test.  The NUL device is good enough.
+$ENV{OPENSSL_CONF} = File::Spec->devnull();
 
-plan skip_all => "This test is unsupported in a no-ec build"
-    if disabled("ec");
-
-simple_test("test_internal_ec", "ec_internal_test");
+simple_test("test_provider_fallback", "provider_fallback_test");


More information about the openssl-commits mailing list