Add key derivation support.
[openssl.git] / crypto / evp / pmeth_lib.c
index 9ca351a53e9d37560ef0de13a34a8de5abd0e0cc..95b1e4ed3c3e5bf9828c232a7846d1748e7aa406 100644 (file)
 
 STACK *app_pkey_methods = NULL;
 
-extern EVP_PKEY_METHOD rsa_pkey_meth;
+extern EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth;
 
 static const EVP_PKEY_METHOD *standard_methods[] =
        {
-       &rsa_pkey_meth
+       &rsa_pkey_meth,
+       &dh_pkey_meth,
+       &dsa_pkey_meth
        };
 
 static int pmeth_cmp(const EVP_PKEY_METHOD * const *a,
@@ -101,20 +103,26 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e)
        return *ret;
        }
 
-EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey)
+static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
        {
        EVP_PKEY_CTX *ret;
        const EVP_PKEY_METHOD *pmeth;
-       if (!pkey || !pkey->ameth)
-               return NULL;
-       pmeth = EVP_PKEY_meth_find(pkey->ameth->pkey_id, NULL);
+       if (id == -1)
+               {
+               if (!pkey || !pkey->ameth)
+                       return NULL;
+               id = pkey->ameth->pkey_id;
+               }
+       pmeth = EVP_PKEY_meth_find(id, e);
        if (pmeth == NULL)
                return NULL;
        ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
        ret->pmeth = pmeth;
        ret->operation = EVP_PKEY_OP_UNDEFINED;
-       CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
        ret->pkey = pkey;
+       ret->peerkey = NULL;
+       if (pkey)
+               CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
        ret->data = NULL;
 
        if (pmeth->init)
@@ -129,6 +137,16 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey)
        return ret;
        }
 
+EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
+       {
+       return int_ctx_new(pkey, e, -1);
+       }
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
+       {
+       return int_ctx_new(NULL, e, id);
+       }
+
 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
        {
        if (ctx->pmeth && ctx->pmeth->cleanup)
@@ -156,7 +174,7 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
                return -1;
                }
 
-       if ((optype != -1) && (ctx->operation != optype))
+       if ((optype != -1) && !(ctx->operation & optype))
                {
                EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
                return -1;
@@ -171,12 +189,45 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
 
        }
 
-int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, char *name, char *value)
+int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
+                                       const char *name, const char *value)
        {
-       if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl)
+       if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str)
                {
-               EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+               EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR,
+                                               EVP_R_COMMAND_NOT_SUPPORTED);
                return -2;
                }
+       if (!strcmp(name, "digest"))
+               {
+               const EVP_MD *md;
+               if (!value || !(md = EVP_get_digestbyname(value)))
+                       {
+                       EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR,
+                                               EVP_R_INVALID_DIGEST);
+                       return 0;
+                       }
+               return EVP_PKEY_CTX_set_signature_md(ctx, md);
+               }
        return ctx->pmeth->ctrl_str(ctx, name, value);
        }
+
+void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
+       {
+       ctx->data = data;
+       }
+
+void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
+       {
+       return ctx->data;
+       }
+
+void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
+       {
+       ctx->app_data = data;
+       }
+
+void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
+       {
+       return ctx->app_data;
+       }