Make EVP_PKEY_CTX initialization more precise
[openssl.git] / crypto / evp / pmeth_lib.c
index 8b386cf19fe1c218219d4f3898079fb7617c6666..5ba844f53e808d4f1fb153d5b55733bbf7657a6f 100644 (file)
 #include <openssl/core_names.h>
 #include <openssl/dh.h>
 #include "internal/cryptlib.h"
-#include "internal/asn1_int.h"
-#include "internal/evp_int.h"
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
 #include "internal/numbers.h"
 #include "internal/provider.h"
-#include "evp_locl.h"
+#include "evp_local.h"
 
 typedef const EVP_PKEY_METHOD *(*pmeth_fn)(void);
 typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
@@ -95,6 +95,7 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
     pmeth_fn *ret;
     EVP_PKEY_METHOD tmp;
     const EVP_PKEY_METHOD *t = &tmp;
+
     tmp.pkey_id = type;
     if (app_pkey_methods) {
         int idx;
@@ -105,12 +106,14 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
     ret = OBJ_bsearch_pmeth_func(&t, standard_methods,
                                  sizeof(standard_methods) /
                                  sizeof(pmeth_fn));
-    if (!ret || !*ret)
+    if (ret == NULL || *ret == NULL)
         return NULL;
     return (**ret)();
 }
 
-static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
+static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e,
+                                 const char *name, const char *propquery,
+                                 int id)
 {
     EVP_PKEY_CTX *ret;
     const EVP_PKEY_METHOD *pmeth = NULL;
@@ -129,6 +132,24 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
             return 0;
         id = pkey->type;
     }
+
+    /*
+     * Here, we extract what information we can for the purpose of
+     * supporting usage with implementations from providers, to make
+     * for a smooth transition from legacy stuff to provider based stuff.
+     *
+     * If an engine is given, this is entirely legacy, and we should not
+     * pretend anything else, so we only set the name when no engine is
+     * given.  If both are already given, someone made a mistake, and
+     * since that can only happen internally, it's safe to make an
+     * assertion.
+     */
+    if (!ossl_assert(e == NULL || name == NULL))
+        return NULL;
+    if (e == NULL)
+        name = OBJ_nid2sn(id);
+    propquery = NULL;
+
 #ifndef OPENSSL_NO_ENGINE
     if (e == NULL && pkey != NULL)
         e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
@@ -170,6 +191,8 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
         EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
+    ret->algorithm = name;
+    ret->propquery = propquery;
     ret->engine = e;
     ret->pmeth = pmeth;
     ret->operation = EVP_PKEY_OP_UNDEFINED;
@@ -194,10 +217,14 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
         if (ctx->op.kex.exchprovctx != NULL && ctx->op.kex.exchange != NULL)
             ctx->op.kex.exchange->freectx(ctx->op.kex.exchprovctx);
         EVP_KEYEXCH_free(ctx->op.kex.exchange);
+        ctx->op.kex.exchprovctx = NULL;
+        ctx->op.kex.exchange = NULL;
     } else if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
         if (ctx->op.sig.sigprovctx != NULL && ctx->op.sig.signature != NULL)
             ctx->op.sig.signature->freectx(ctx->op.sig.sigprovctx);
         EVP_SIGNATURE_free(ctx->op.sig.signature);
+        ctx->op.sig.sigprovctx = NULL;
+        ctx->op.sig.signature = NULL;
     }
 }
 
@@ -276,12 +303,18 @@ void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
 {
-    return int_ctx_new(pkey, e, -1);
+    return int_ctx_new(pkey, e, NULL, NULL, -1);
 }
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
 {
-    return int_ctx_new(NULL, e, id);
+    return int_ctx_new(NULL, e, NULL, NULL, id);
+}
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_provided(const char *name,
+                                        const char *propquery)
+{
+    return int_ctx_new(NULL, NULL, name, propquery, -1);
 }
 
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
@@ -311,6 +344,8 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx)
         EVP_PKEY_up_ref(pctx->pkey);
     rctx->pkey = pctx->pkey;
     rctx->operation = pctx->operation;
+    rctx->algorithm = pctx->algorithm;
+    rctx->propquery = pctx->propquery;
 
     if (EVP_PKEY_CTX_IS_DERIVE_OP(pctx)) {
         if (pctx->op.kex.exchange != NULL) {
@@ -619,7 +654,7 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
     }
 
     if ((EVP_PKEY_CTX_IS_DERIVE_OP(ctx) && ctx->op.kex.exchprovctx != NULL)
-            || (EVP_PKEY_CTX_IS_DERIVE_OP(ctx)
+            || (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
                 && ctx->op.sig.sigprovctx != NULL))
         return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);