+/*
+ * We test what happens with an empty template. For the sake of this test,
+ * the template must be ignored, and we know that's the case for RSA keys
+ * (this might arguably be a misfeature, but that's what we currently do,
+ * even in provider code, since that's how the legacy RSA implementation
+ * does things)
+ */
+static int test_keygen_with_empty_template(int n)
+{
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY *tkey = NULL;
+ int ret = 0;
+
+ switch (n) {
+ case 0:
+ /* We do test with no template at all as well */
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)))
+ goto err;
+ break;
+ case 1:
+ /* Here we create an empty RSA key that serves as our template */
+ if (!TEST_ptr(tkey = EVP_PKEY_new())
+ || !TEST_true(EVP_PKEY_set_type(tkey, EVP_PKEY_RSA))
+ || !TEST_ptr(ctx = EVP_PKEY_CTX_new(tkey, NULL)))
+ goto err;
+ break;
+ }
+
+ if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0)
+ || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0))
+ goto err;
+
+ ret = 1;
+ err:
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(tkey);
+ return ret;
+}
+
+/*
+ * Test that we fail if we attempt to use an algorithm that is not available
+ * in the current library context (unless we are using an algorithm that should
+ * be made available via legacy codepaths).
+ */
+static int test_pkey_ctx_fail_without_provider(int tst)
+{
+ OPENSSL_CTX *tmpctx = OPENSSL_CTX_new();
+ OSSL_PROVIDER *nullprov = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ int ret = 0;
+
+ if (!TEST_ptr(tmpctx))
+ goto err;
+
+ nullprov = OSSL_PROVIDER_load(tmpctx, "null");
+ if (!TEST_ptr(nullprov))
+ goto err;
+
+ pctx = EVP_PKEY_CTX_new_from_name(tmpctx, tst == 0 ? "RSA" : "HMAC", "");
+
+ /* RSA is not available via any provider so we expect this to fail */
+ if (tst == 0 && !TEST_ptr_null(pctx))
+ goto err;
+
+ /*
+ * HMAC is always available because it is implemented via legacy codepaths
+ * and not in a provider at all. We expect this to pass.
+ */
+ if (tst == 1 && !TEST_ptr(pctx))
+ goto err;
+
+ ret = 1;
+
+ err:
+ EVP_PKEY_CTX_free(pctx);
+ OSSL_PROVIDER_unload(nullprov);
+ OPENSSL_CTX_free(tmpctx);
+ return ret;
+}
+