/* Does EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) reach a provider on 3.0?
 * Discriminator: constrain the DEFAULT PROPERTIES to a provider that lacks
 * SHA256. If the implicit path is provider-mediated, init must FAIL. */
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/provider.h>

static const char *pn(const OSSL_PROVIDER *p)
{ return p ? OSSL_PROVIDER_get0_name(p) : "NO PROVIDER"; }

static int try_init(void)
{
	EVP_MD_CTX *c = EVP_MD_CTX_new();
	int ok = EVP_DigestInit_ex(c, EVP_sha256(), NULL);
	EVP_MD_CTX_free(c);
	return ok;
}

int main(void)
{
	EVP_MD *f;
	EVP_MD_CTX *c;

	printf("Runtime: %s\n\n", OpenSSL_version(OPENSSL_VERSION));

	printf("A. baseline DigestInit_ex(EVP_sha256())      : %s\n",
		   try_init() ? "OK" : "FAILED");

	/* The measurement artifact our original probe hit. */
	c = EVP_MD_CTX_new();
	EVP_DigestInit_ex(c, EVP_sha256(), NULL);
	printf("B. get0_md provider after that init          : %s\n",
		   pn(EVP_MD_get0_provider(EVP_MD_CTX_get0_md(c))));
	printf("   (get0_md returns ctx->reqdigest = the STATIC md we passed,\n"
		   "    NOT what OpenSSL actually used -- so B proves nothing)\n");
	EVP_MD_CTX_free(c);

	/* Now constrain default properties to the legacy provider. */
	if (!OSSL_PROVIDER_load(NULL, "legacy"))
		printf("   (warning: legacy provider failed to load)\n");
	if (!EVP_set_default_properties(NULL, "provider=legacy"))
		printf("   (warning: could not set default properties)\n");

	f = EVP_MD_fetch(NULL, "SHA256", NULL);
	printf("C. explicit EVP_MD_fetch under provider=legacy: %s\n",
		   f ? "OK" : "FAILED (legacy has no SHA256)");
	EVP_MD_free(f);

	printf("D. DigestInit_ex(EVP_sha256()) under same     : %s\n",
		   try_init() ? "OK -> implicit path IGNORES providers"
					  : "FAILED -> implicit path IS provider-mediated");
	return 0;
}
