Add the provider function signatures for DigestSign*
[openssl.git] / crypto / evp / digest.c
index bb6d31bf4ff0c7baa42d4c0b1c3ca40db8225dbb..4b9395d58bf6ae37c1652f969c84900bd2c8aac5 100644 (file)
@@ -14,9 +14,9 @@
 #include <openssl/params.h>
 #include <openssl/core_names.h>
 #include "internal/cryptlib.h"
-#include "internal/evp_int.h"
+#include "crypto/evp.h"
 #include "internal/provider.h"
-#include "evp_locl.h"
+#include "evp_local.h"
 
 /* This call frees resources associated with the context */
 int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
@@ -81,23 +81,15 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
     if (ctx == NULL)
         return;
 
-    if (ctx->digest == NULL || ctx->digest->prov == NULL)
-        goto legacy;
-
     EVP_MD_CTX_reset(ctx);
 
-    EVP_MD_meth_free(ctx->fetched_digest);
+    EVP_MD_free(ctx->fetched_digest);
     ctx->fetched_digest = NULL;
     ctx->digest = NULL;
     ctx->reqdigest = NULL;
 
     OPENSSL_free(ctx);
     return;
-
-    /* TODO(3.0): Remove legacy code below */
- legacy:
-    EVP_MD_CTX_reset(ctx);
-    OPENSSL_free(ctx);
 }
 
 int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
@@ -156,7 +148,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
         if (ctx->digest == ctx->fetched_digest)
             ctx->digest = NULL;
-        EVP_MD_meth_free(ctx->fetched_digest);
+        EVP_MD_free(ctx->fetched_digest);
         ctx->fetched_digest = NULL;
         goto legacy;
     }
@@ -181,7 +173,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             return 0;
         }
         type = provmd;
-        EVP_MD_meth_free(ctx->fetched_digest);
+        EVP_MD_free(ctx->fetched_digest);
         ctx->fetched_digest = provmd;
 #endif
     }
@@ -266,8 +258,13 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
  skip_to_init:
 #endif
 #ifndef FIPS_MODE
-    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
-    if (ctx->pctx != NULL) {
+    /*
+     * TODO(3.0): Temporarily no support for EVP_DigestSign* inside FIPS module
+     * or when using providers.
+     */
+    if (ctx->pctx != NULL
+            && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+                 || ctx->pctx->op.sig.signature == NULL)) {
         int r;
         r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
                               EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
@@ -415,7 +412,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 
     EVP_MD_CTX_reset(out);
     if (out->fetched_digest != NULL)
-        EVP_MD_meth_free(out->fetched_digest);
+        EVP_MD_free(out->fetched_digest);
     *out = *in;
     /* NULL out pointers in case of error */
     out->pctx = NULL;
@@ -545,10 +542,20 @@ int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[])
     return 0;
 }
 
-const OSSL_PARAM *EVP_MD_CTX_settable_params(const EVP_MD *digest)
+const OSSL_PARAM *EVP_MD_settable_ctx_params(const EVP_MD *md)
 {
-    if (digest != NULL && digest->settable_ctx_params != NULL)
-        return digest->settable_ctx_params();
+    if (md != NULL && md->settable_ctx_params != NULL)
+        return md->settable_ctx_params();
+    return NULL;
+}
+
+const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx)
+{
+    if (ctx != NULL
+            && ctx->digest != NULL
+            && ctx->digest->settable_ctx_params != NULL)
+        return ctx->digest->settable_ctx_params();
+
     return NULL;
 }
 
@@ -559,10 +566,20 @@ int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[])
     return 0;
 }
 
-const OSSL_PARAM *EVP_MD_CTX_gettable_params(const EVP_MD *digest)
+const OSSL_PARAM *EVP_MD_gettable_ctx_params(const EVP_MD *md)
 {
-    if (digest != NULL && digest->gettable_ctx_params != NULL)
-        return digest->gettable_ctx_params();
+    if (md != NULL && md->gettable_ctx_params != NULL)
+        return md->gettable_ctx_params();
+    return NULL;
+}
+
+const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx)
+{
+    if (ctx != NULL
+            && ctx->digest != NULL
+            && ctx->digest->gettable_ctx_params != NULL)
+        return ctx->digest->gettable_ctx_params();
+
     return NULL;
 }
 
@@ -616,31 +633,72 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
     return ret;
 }
 
-static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
+EVP_MD *evp_md_new(void)
+{
+    EVP_MD *md = OPENSSL_zalloc(sizeof(*md));
+
+    if (md != NULL) {
+        md->lock = CRYPTO_THREAD_lock_new();
+        if (md->lock == NULL) {
+            OPENSSL_free(md);
+            return NULL;
+        }
+        md->refcnt = 1;
+    }
+    return md;
+}
+
+/*
+ * FIPS module note: since internal fetches will be entirely
+ * provider based, we know that none of its code depends on legacy
+ * NIDs or any functionality that use them.
+ */
+#ifndef FIPS_MODE
+/* TODO(3.x) get rid of the need for legacy NIDs */
+static void set_legacy_nid(const char *name, void *vlegacy_nid)
+{
+    int nid;
+    int *legacy_nid = vlegacy_nid;
+
+    if (*legacy_nid == -1)       /* We found a clash already */
+        return;
+    if ((nid = OBJ_sn2nid(name)) == NID_undef
+        && (nid = OBJ_ln2nid(name)) == NID_undef)
+        return;
+    if (*legacy_nid != NID_undef && *legacy_nid != nid) {
+        *legacy_nid = -1;
+        return;
+    }
+    *legacy_nid = nid;
+}
+#endif
+
+static void *evp_md_from_dispatch(int name_id,
+                                  const OSSL_DISPATCH *fns,
                                   OSSL_PROVIDER *prov, void *unused)
 {
     EVP_MD *md = NULL;
     int fncnt = 0;
 
     /* EVP_MD_fetch() will set the legacy NID if available */
-    if ((md = EVP_MD_meth_new(NID_undef, NID_undef)) == NULL
-        || (md->name = OPENSSL_strdup(name)) == NULL) {
-        EVP_MD_meth_free(md);
+    if ((md = evp_md_new()) == NULL) {
         EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
 #ifndef FIPS_MODE
-    /*
-     * FIPS module note: since internal fetches will be entirely
-     * provider based, we know that none of its code depends on legacy
-     * NIDs or any functionality that use them.
-     *
-     * TODO(3.x) get rid of the need for legacy NIDs
-     */
-    md->type = OBJ_sn2nid(name);
+    /* TODO(3.x) get rid of the need for legacy NIDs */
+    md->type = NID_undef;
+    evp_doall_names(prov, name_id, set_legacy_nid, &md->type);
+    if (md->type == -1) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
+        EVP_MD_free(md);
+        return NULL;
+    }
 #endif
 
+    md->name_id = name_id;
+
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
         case OSSL_FUNC_DIGEST_NEWCTX:
@@ -718,7 +776,7 @@ static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
          * The "digest" function can standalone. We at least need one way to
          * generate digests.
          */
-        EVP_MD_meth_free(md);
+        EVP_MD_free(md);
         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
         return NULL;
     }
@@ -736,7 +794,7 @@ static int evp_md_up_ref(void *md)
 
 static void evp_md_free(void *md)
 {
-    EVP_MD_meth_free(md);
+    EVP_MD_free(md);
 }
 
 EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
@@ -750,6 +808,29 @@ EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
     return md;
 }
 
+int EVP_MD_up_ref(EVP_MD *md)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
+    return 1;
+}
+
+void EVP_MD_free(EVP_MD *md)
+{
+    int i;
+
+    if (md == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
+    if (i > 0)
+        return;
+    ossl_provider_free(md->prov);
+    CRYPTO_THREAD_lock_free(md->lock);
+    OPENSSL_free(md);
+}
+
 void EVP_MD_do_all_ex(OPENSSL_CTX *libctx,
                           void (*fn)(EVP_MD *mac, void *arg),
                           void *arg)