+ if (ctx->pctx == NULL)
+ return 0;
+ } else if (pkey != NULL) {
+ if (!EVP_PKEY_up_ref(pkey))
+ return 0;
+ EVP_PKEY_free(ctx->pctx->pkey);
+ ctx->pctx->pkey = pkey;
+ }
+ locpctx = ctx->pctx;
+ evp_pkey_ctx_free_old_ops(locpctx);
+ if (locpctx->pkey == NULL)
+ goto legacy;
+
+ if (e != NULL || locpctx->engine != NULL)
+ goto legacy;
+
+ if (signature != NULL) {
+ if (!EVP_SIGNATURE_up_ref(signature))
+ goto err;
+ } else {
+ /*
+ * TODO(3.0): Check for legacy handling. Remove this once all all
+ * algorithms are moved to providers.
+ */
+ switch (locpctx->pkey->type) {
+ default:
+ goto legacy;
+ }
+ signature
+ = EVP_SIGNATURE_fetch(NULL, OBJ_nid2sn(locpctx->pkey->type), NULL);
+
+ if (signature == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ }
+ locpctx->operation = ver ? EVP_PKEY_OP_VERIFYCTX
+ : EVP_PKEY_OP_SIGNCTX;
+
+ locpctx->op.sig.signature = signature;
+
+ locpctx->op.sig.sigprovctx
+ = signature->newctx(ossl_provider_ctx(signature->prov));
+ if (locpctx->op.sig.sigprovctx == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ provkey = evp_keymgmt_export_to_provider(locpctx->pkey, signature->keymgmt);
+ if (provkey == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+
+ if (mdname == NULL) {
+ mdname = EVP_MD_name(type);
+ ctx->reqdigest = type;
+ } else {
+ /*
+ * This might be requested by a later call to EVP_MD_CTX_md(). In that
+ * case the "explicit fetch" rules apply for that function (as per
+ * man pages), i.e. the ref count is not updated so the EVP_MD should
+ * not be used beyound the lifetime of the EVP_MD_CTX.
+ */
+ ctx->reqdigest
+ = ctx->fetched_digest
+ = EVP_MD_fetch(
+ ossl_provider_library_context(EVP_SIGNATURE_provider(signature)),
+ mdname, props);
+ }
+
+ if (ver) {
+ if (signature->digest_verify_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ret = signature->digest_verify_init(locpctx->op.sig.sigprovctx, mdname,
+ props, provkey);
+ } else {
+ if (signature->digest_sign_init == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+ goto err;
+ }
+ ret = signature->digest_sign_init(locpctx->op.sig.sigprovctx, mdname,
+ props, provkey);
+ }
+
+ return ret ? 1 : 0;
+ err:
+ evp_pkey_ctx_free_old_ops(locpctx);
+ locpctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return 0;