Add additional testing of child libctx/providers
authorMatt Caswell <matt@openssl.org>
Tue, 4 May 2021 16:38:10 +0000 (17:38 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 11 May 2021 14:03:13 +0000 (15:03 +0100)
Add a case where a provider explicitly loads a provider into a child
libctx where it does not already exist.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14991)

test/p_test.c
test/provider_test.c

index 421287edb31b4e6dd3eef16fd39e22e45114eaca..8c7bdaf7b86e5afd284ea1c4d54ad9c5ecdaee68 100644 (file)
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/crypto.h>
+#include <openssl/provider.h>
 
 typedef struct p_test_ctx {
     char *thisfile;
     char *thisfunc;
     const OSSL_CORE_HANDLE *handle;
     OSSL_LIB_CTX *libctx;
+    OSSL_PROVIDER *deflt;
 } P_TEST_CTX;
 
 static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
@@ -127,7 +129,18 @@ static int p_get_params(void *provctx, OSSL_PARAM params[])
             const char *msg = "Hello world";
             unsigned char out[16];
 
-            if (md4 != NULL && mdctx != NULL) {
+            /*
+             * We should have the default provider available that we loaded
+             * ourselves, and the base and legacy providers which we inherit
+             * from the parent libctx. We should also have "this" provider
+             * available.
+             */
+            if (OSSL_PROVIDER_available(ctx->libctx, "default")
+                    && OSSL_PROVIDER_available(ctx->libctx, "base")
+                    && OSSL_PROVIDER_available(ctx->libctx, "legacy")
+                    && OSSL_PROVIDER_available(ctx->libctx, "p_test")
+                    && md4 != NULL
+                    && mdctx != NULL) {
                 if (EVP_DigestInit_ex(mdctx, md4, NULL)
                         && EVP_DigestUpdate(mdctx, (const unsigned char *)msg,
                                             strlen(msg))
@@ -164,6 +177,8 @@ static const OSSL_ITEM *p_get_reason_strings(void *_)
 {
     static const OSSL_ITEM reason_strings[] = {
         {1, "dummy reason string"},
+        {2, "Can't create child library context"},
+        {3, "Can't load default provider"},
         {0, NULL}
     };
 
@@ -230,6 +245,22 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
     /* We only do this if we are linked with libcrypto */
     ctx->libctx = OSSL_LIB_CTX_new_child(handle, oin);
     if (ctx->libctx == NULL) {
+        /* We set error "2" for a failure to create the child libctx*/
+        p_set_error(ERR_LIB_PROV, 2, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc,
+                    NULL);
+        p_teardown(ctx);
+        return 0;
+    }
+    /*
+     * "default" has not been loaded into the parent libctx. We should be able
+     * to explicitly load it as a non-child provider.
+     */
+    ctx->deflt = OSSL_PROVIDER_load(ctx->libctx, "default");
+    if (ctx->deflt == NULL
+            || !OSSL_PROVIDER_available(ctx->libctx, "default")) {
+        /* We set error "3" for a failure to load the default provider */
+        p_set_error(ERR_LIB_PROV, 3, ctx->thisfile, OPENSSL_LINE, ctx->thisfunc,
+                    NULL);
         p_teardown(ctx);
         return 0;
     }
@@ -251,6 +282,7 @@ static void p_teardown(void *provctx)
     P_TEST_CTX *ctx = (P_TEST_CTX *)provctx;
 
 #ifdef PROVIDER_INIT_FUNCTION_NAME
+    OSSL_PROVIDER_unload(ctx->deflt);
     OSSL_LIB_CTX_free(ctx->libctx);
 #endif
     free(ctx->thisfile);
index b2236e3a36679a948b72c4a3c03a1e257ac90b72..4d8dbaee6f4040fe7070b85b1df9adf257ad6e39 100644 (file)
@@ -35,11 +35,18 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
     int ok = 0;
     long err;
     int dolegacycheck = (legacy != NULL);
+    OSSL_PROVIDER *deflt = NULL, *base = NULL;
 
     BIO_snprintf(expected_greeting, sizeof(expected_greeting),
                  "Hello OpenSSL %.20s, greetings from %s!",
                  OPENSSL_VERSION_STR, name);
 
+    /*
+        * Check that it is possible to have a built-in provider mirrored in
+        * a child lib ctx.
+        */
+    if (!TEST_ptr(base = OSSL_PROVIDER_load(*libctx, "base")))
+        goto err;
     if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
         goto err;
     if (dolegacycheck) {
@@ -69,10 +76,19 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
             goto err;
         /*
          * Loading the legacy provider again should make it available again in
-         * the child libctx.
+         * the child libctx. Loading and unloading the default provider should
+         * have no impact on the child because the child loads it explicitly
+         * before this point.
          */
         legacy = OSSL_PROVIDER_load(*libctx, "legacy");
+        deflt = OSSL_PROVIDER_load(*libctx, "default");
+        if (!TEST_ptr(deflt)
+                || !TEST_true(OSSL_PROVIDER_available(*libctx, "default")))
+            goto err;
+        OSSL_PROVIDER_unload(deflt);
+        deflt = NULL;
         if (!TEST_ptr(legacy)
+                || !TEST_false(OSSL_PROVIDER_available(*libctx, "default"))
                 || !TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
                 || !TEST_true(digestsuccess))
         goto err;
@@ -80,6 +96,9 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
         legacy = NULL;
     }
 
+    if (!TEST_true(OSSL_PROVIDER_unload(base)))
+        goto err;
+    base = NULL;
     if (!TEST_true(OSSL_PROVIDER_unload(prov)))
         goto err;
     prov = NULL;
@@ -95,6 +114,8 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
     ERR_print_errors_fp(stderr);
     ok = 1;
  err:
+    OSSL_PROVIDER_unload(base);
+    OSSL_PROVIDER_unload(deflt);
     OSSL_PROVIDER_unload(legacy);
     legacy = NULL;
     OSSL_PROVIDER_unload(prov);
@@ -120,6 +141,8 @@ static int test_builtin_provider(void)
     return ok;
 }
 
+/* Test relies on fetching the MD4 digest from the legacy provider */
+#ifndef OPENSSL_NO_MD4
 static int test_builtin_provider_with_child(void)
 {
     OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
@@ -145,6 +168,7 @@ static int test_builtin_provider_with_child(void)
     /* test_provider will free libctx and unload legacy as part of the test */
     return test_provider(&libctx, name, legacy);
 }
+#endif
 
 #ifndef NO_PROVIDER_MODULE
 static int test_loaded_provider(void)
@@ -196,7 +220,9 @@ int setup_tests(void)
 
     if (!loaded) {
         ADD_TEST(test_builtin_provider);
+#ifndef OPENSSL_NO_MD4
         ADD_TEST(test_builtin_provider_with_child);
+#endif
     }
 #ifndef NO_PROVIDER_MODULE
     else {