/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2021 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
extern OSSL_provider_init_fn PROVIDER_INIT_FUNCTION_NAME;
static char buf[256];
-static size_t buf_l = 0;
static OSSL_PARAM greeting_request[] = {
- { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf), &buf_l },
- { NULL, 0, NULL, 0, NULL }
+ { "greeting", OSSL_PARAM_UTF8_STRING, buf, sizeof(buf) },
+ { NULL, 0, NULL, 0, 0 }
};
-static int test_provider(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 unsigned int stopsuccess = 0;
+static OSSL_PARAM stop_property_mirror[] = {
+ { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
+ sizeof(stopsuccess) },
+ { 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;
char expected_greeting[256];
+ 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);
+
+
+ /*
+ * We set properties that we know the providers we are using don't have.
+ * This should mean that the p_test provider will fail any fetches - which
+ * is something we test inside the provider.
+ */
+ EVP_set_default_properties(*libctx, "fips=yes");
+ /*
+ * 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;
+
+ /*
+ * Once the provider is loaded we clear the default properties and fetches
+ * should start working again.
+ */
+ EVP_set_default_properties(*libctx, "");
+ if (dolegacycheck) {
+ if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
+ || !TEST_true(digestsuccess))
+ goto err;
+
+ /*
+ * Check that a provider can prevent property mirroring if it sets its
+ * own properties explicitly
+ */
+ if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
+ || !TEST_true(stopsuccess))
+ goto err;
+ EVP_set_default_properties(*libctx, "fips=yes");
+ if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
+ || !TEST_true(digestsuccess))
+ goto err;
+ EVP_set_default_properties(*libctx, "");
+ }
+ 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))
+ goto err;
- snprintf(expected_greeting, sizeof(expected_greeting),
- "Hello OpenSSL %.20s, greetings from %s!",
- OPENSSL_VERSION_STR, name);
-
- return
- TEST_ptr(prov = OSSL_PROVIDER_load(NULL, name))
- && TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
- && TEST_ptr(greeting = greeting_request[0].buffer)
- && TEST_size_t_gt(greeting_request[0].buffer_size, 0)
- && TEST_str_eq(greeting, expected_greeting)
- && TEST_true(OSSL_PROVIDER_unload(prov));
+ /* Make sure we got the error we were expecting */
+ err = ERR_peek_last_error();
+ if (!TEST_int_gt(err, 0)
+ || !TEST_int_eq(ERR_GET_REASON(err), 1))
+ goto err;
+
+ OSSL_PROVIDER_unload(legacy);
+ legacy = NULL;
+
+ if (dolegacycheck) {
+ /* Legacy provider should also be unloaded from child libctx */
+ if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
+ || !TEST_false(digestsuccess))
+ goto err;
+ /*
+ * Loading the legacy provider again should make it available again in
+ * 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;
+ OSSL_PROVIDER_unload(legacy);
+ legacy = NULL;
+ }
+
+ if (!TEST_true(OSSL_PROVIDER_unload(base)))
+ goto err;
+ base = NULL;
+ if (!TEST_true(OSSL_PROVIDER_unload(prov)))
+ goto err;
+ prov = NULL;
+
+ /*
+ * We must free the libctx to force the provider to really be unloaded from
+ * memory
+ */
+ OSSL_LIB_CTX_free(*libctx);
+ *libctx = NULL;
+
+ /* We print out all the data to make sure it can still be accessed */
+ 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);
+ OSSL_LIB_CTX_free(*libctx);
+ *libctx = NULL;
+ return ok;
}
static int test_builtin_provider(void)
{
+ OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
const char *name = "p_test_builtin";
+ int ok;
+
+ ok =
+ TEST_ptr(libctx)
+ && TEST_true(OSSL_PROVIDER_add_builtin(libctx, name,
+ PROVIDER_INIT_FUNCTION_NAME))
+ && test_provider(&libctx, name, NULL);
- return
- TEST_true(OSSL_PROVIDER_add_builtin(NULL, name,
- PROVIDER_INIT_FUNCTION_NAME))
- && test_provider(name);
+ OSSL_LIB_CTX_free(libctx);
+
+ return ok;
}
-#ifndef OPENSSL_NO_SHARED
+/* 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();
+ 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);
+}
+#endif
+
+#ifndef NO_PROVIDER_MODULE
static int test_loaded_provider(void)
{
+ OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
const char *name = "p_test";
- return test_provider(name);
+ if (!TEST_ptr(libctx))
+ return 0;
+
+ /* test_provider will free libctx as part of the test */
+ 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);
-#ifndef OPENSSL_NO_SHARED
- ADD_TEST(test_loaded_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);
+#ifndef OPENSSL_NO_MD4
+ ADD_TEST(test_builtin_provider_with_child);
+#endif
+ }
+#ifndef NO_PROVIDER_MODULE
+ else {
+ ADD_TEST(test_loaded_provider);
+ }
#endif
return 1;
}