]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add a test for OSSL_LIB_CTX_new_child()
authorMatt Caswell <matt@openssl.org>
Thu, 22 Apr 2021 14:58:50 +0000 (15:58 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 11 May 2021 13:59:43 +0000 (14:59 +0100)
Check that we can create such a libctx and usable providers are loaded
into it.

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

test/p_test.c
test/provider_test.c
test/recipes/04-test_provider.t

index 6f55abda01928d73bf519074e21208c2386d7122..421287edb31b4e6dd3eef16fd39e22e45114eaca 100644 (file)
 #include <openssl/core.h>
 #include <openssl/core_dispatch.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
 
 typedef struct p_test_ctx {
     char *thisfile;
     char *thisfunc;
     const OSSL_CORE_HANDLE *handle;
+    OSSL_LIB_CTX *libctx;
 } P_TEST_CTX;
 
 static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
@@ -46,6 +49,7 @@ static OSSL_FUNC_core_vset_error_fn *c_vset_error;
 /* Tell the core what params we provide and what type they are */
 static const OSSL_PARAM p_param_types[] = {
     { "greeting", OSSL_PARAM_UTF8_STRING, NULL, 0, 0 },
+    { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
     { NULL, 0, NULL, 0, 0 }
 };
 
@@ -109,6 +113,36 @@ static int p_get_params(void *provctx, OSSL_PARAM params[])
                 strcpy(p->data, buf);
             else
                 ok = 0;
+        } else if (strcmp(p->key, "digest-check") == 0) {
+            unsigned int digestsuccess = 0;
+
+            /*
+             * Test we can use an algorithm from another provider. We're using
+             * legacy to check that legacy is actually available and we haven't
+             * just fallen back to default.
+             */
+#ifdef PROVIDER_INIT_FUNCTION_NAME
+            EVP_MD *md4 = EVP_MD_fetch(ctx->libctx, "MD4", NULL);
+            EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+            const char *msg = "Hello world";
+            unsigned char out[16];
+
+            if (md4 != NULL && mdctx != NULL) {
+                if (EVP_DigestInit_ex(mdctx, md4, NULL)
+                        && EVP_DigestUpdate(mdctx, (const unsigned char *)msg,
+                                            strlen(msg))
+                        &&EVP_DigestFinal(mdctx, out, NULL))
+                    digestsuccess = 1;
+            }
+            EVP_MD_CTX_free(mdctx);
+            EVP_MD_free(md4);
+#endif
+            if (p->data_size >= sizeof(digestsuccess)) {
+                *(unsigned int *)p->data = digestsuccess;
+                p->return_size = sizeof(digestsuccess);
+            } else {
+                ok = 0;
+            }
         }
     }
     return ok;
@@ -146,11 +180,12 @@ static const OSSL_DISPATCH p_test_table[] = {
 };
 
 int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
-                       const OSSL_DISPATCH *in,
+                       const OSSL_DISPATCH *oin,
                        const OSSL_DISPATCH **out,
                        void **provctx)
 {
     P_TEST_CTX *ctx;
+    const OSSL_DISPATCH *in = oin;
 
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
@@ -191,6 +226,14 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
     ctx->thisfile = strdup(OPENSSL_FILE);
     ctx->thisfunc = strdup(OPENSSL_FUNC);
     ctx->handle = handle;
+#ifdef PROVIDER_INIT_FUNCTION_NAME
+    /* We only do this if we are linked with libcrypto */
+    ctx->libctx = OSSL_LIB_CTX_new_child(handle, oin);
+    if (ctx->libctx == NULL) {
+        p_teardown(ctx);
+        return 0;
+    }
+#endif
 
     /*
      * Set a spurious error to check error handling works correctly. This will
@@ -207,6 +250,9 @@ static void p_teardown(void *provctx)
 {
     P_TEST_CTX *ctx = (P_TEST_CTX *)provctx;
 
+#ifdef PROVIDER_INIT_FUNCTION_NAME
+    OSSL_LIB_CTX_free(ctx->libctx);
+#endif
     free(ctx->thisfile);
     free(ctx->thisfunc);
     free(ctx);
index d89611b9b280eeac608b6a730038ee2d8145be6e..0abf55e33d65be99503038d8833e387d94b63449 100644 (file)
@@ -19,7 +19,15 @@ static OSSL_PARAM greeting_request[] = {
     { NULL, 0, NULL, 0, 0 }
 };
 
-static int test_provider(OSSL_LIB_CTX **libctx, const char *name)
+static unsigned int digestsuccess = 0;
+static OSSL_PARAM digest_check[] = {
+    { "digest-check", OSSL_PARAM_UNSIGNED_INTEGER, &digestsuccess,
+      sizeof(digestsuccess) },
+    { NULL, 0, NULL, 0, 0 }
+};
+
+static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
+                         OSSL_PROVIDER *legacy)
 {
     OSSL_PROVIDER *prov = NULL;
     const char *greeting = NULL;
@@ -31,8 +39,14 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name)
                  "Hello OpenSSL %.20s, greetings from %s!",
                  OPENSSL_VERSION_STR, name);
 
-    if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name))
-            || !TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
+    if (!TEST_ptr(prov = OSSL_PROVIDER_load(*libctx, name)))
+        goto err;
+    if (legacy != NULL) {
+        if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
+                || !TEST_true(digestsuccess))
+            goto err;
+    }
+    if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
             || !TEST_ptr(greeting = greeting_request[0].data)
             || !TEST_size_t_gt(greeting_request[0].data_size, 0)
             || !TEST_str_eq(greeting, expected_greeting)
@@ -40,6 +54,8 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name)
         goto err;
 
     prov = NULL;
+    OSSL_PROVIDER_unload(legacy);
+    legacy = NULL;
 
     /*
      * We must free the libctx to force the provider to really be unloaded from
@@ -58,6 +74,8 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name)
     ERR_print_errors_fp(stderr);
     ok = 1;
  err:
+    OSSL_PROVIDER_unload(legacy);
+    legacy = NULL;
     OSSL_PROVIDER_unload(prov);
     OSSL_LIB_CTX_free(*libctx);
     *libctx = NULL;
@@ -74,13 +92,39 @@ static int test_builtin_provider(void)
         TEST_ptr(libctx)
         && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
                                                PROVIDER_INIT_FUNCTION_NAME))
-        && test_provider(&libctx, name);
+        && test_provider(&libctx, name, NULL);
 
     OSSL_LIB_CTX_free(libctx);
 
     return ok;
 }
 
+static int test_builtin_provider_with_child(void)
+{
+    OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
+    const char *name = "p_test";
+    OSSL_PROVIDER *legacy;
+
+    if (!TEST_ptr(libctx))
+        return 0;
+
+    legacy = OSSL_PROVIDER_load(libctx, "legacy");
+    if (legacy == NULL) {
+        /*
+         * In this case we assume we've been built with "no-legacy" and skip
+         * this test (there is no OPENSSL_NO_LEGACY)
+         */
+        return 1;
+    }
+
+    if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
+                                             PROVIDER_INIT_FUNCTION_NAME)))
+        return 0;
+
+    /* test_provider will free libctx and unload legacy as part of the test */
+    return test_provider(&libctx, name, legacy);
+}
+
 #ifndef NO_PROVIDER_MODULE
 static int test_loaded_provider(void)
 {
@@ -91,15 +135,52 @@ static int test_loaded_provider(void)
         return 0;
 
     /* test_provider will free libctx as part of the test */
-    return test_provider(&libctx, name);
+    return test_provider(&libctx, name, NULL);
 }
 #endif
 
+typedef enum OPTION_choice {
+    OPT_ERR = -1,
+    OPT_EOF = 0,
+    OPT_LOADED,
+    OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+    static const OPTIONS test_options[] = {
+        OPT_TEST_OPTIONS_DEFAULT_USAGE,
+        { "loaded", OPT_LOADED, '-', "Run test with a loaded provider" },
+        { NULL }
+    };
+    return test_options;
+}
+
 int setup_tests(void)
 {
-    ADD_TEST(test_builtin_provider);
+    OPTION_CHOICE o;
+    int loaded = 0;
+
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_TEST_CASES:
+            break;
+        case OPT_LOADED:
+            loaded = 1;
+            break;
+        default:
+            return 0;
+        }
+    }
+
+    if (!loaded) {
+        ADD_TEST(test_builtin_provider);
+        ADD_TEST(test_builtin_provider_with_child);
+    }
 #ifndef NO_PROVIDER_MODULE
-    ADD_TEST(test_loaded_provider);
+    else {
+        ADD_TEST(test_loaded_provider);
+    }
 #endif
     return 1;
 }
index 9195a424cd2ef8891c51e938dd499d12c6ea5c9f..44274f8f077df86a922200ccbe9063fe80e89fc1 100644 (file)
@@ -8,11 +8,14 @@
 
 use strict;
 use OpenSSL::Test qw(:DEFAULT bldtop_dir);
-use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
 setup("test_provider");
 
+plan tests => 2;
+
+ok(run(test(['provider_test'])), "provider_test");
+
 $ENV{"OPENSSL_MODULES"} = bldtop_dir("test");
 
-simple_test("test_provider", "provider_test");
+ok(run(test(['provider_test', '-loaded'])), "provider_test -loaded");