From c9777d2659414e632c9dea09787edf988ea1e01e Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 2 Jun 2006 12:33:39 +0000 Subject: [PATCH] Add ENGINE support for EVP_PKEY_METHOD including lookups of ENGINE implementations and functional reference counting when a context is allocated, free or copied. --- CHANGES | 3 ++- crypto/engine/engine.h | 1 + crypto/evp/evp.h | 4 +++- crypto/evp/evp_err.c | 2 ++ crypto/evp/evp_locl.h | 2 ++ crypto/evp/pmeth_lib.c | 46 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index e96dc43a56..def2f8187b 100644 --- a/CHANGES +++ b/CHANGES @@ -5,7 +5,8 @@ Changes between 0.9.8b and 0.9.9 [xx XXX xxxx] *) Initial engine support for EVP_PKEY_METHOD. New functions to permit - an engine to register a method. + an engine to register a method. Add ENGINE lookups for methods and + functional reference processing. [Steve Henson] *) New functions EVP_Digest{Sign,Verify)*. These are enchance versions of diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index ef6a91f021..d8d00b3d12 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -552,6 +552,7 @@ ENGINE *ENGINE_get_default_RAND(void); * ciphering or digesting corresponding to "nid". */ ENGINE *ENGINE_get_cipher_engine(int nid); ENGINE *ENGINE_get_digest_engine(int nid); +ENGINE *ENGINE_get_pkey_meth_engine(int nid); /* This sets a new default ENGINE structure for performing RSA * operations. If the result is non-zero (success) then the ENGINE diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 064e2772e7..833257a937 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -954,7 +954,7 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, #define EVP_PKEY_FLAG_AUTOARGLEN 2 -const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e); +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); EVP_PKEY_METHOD* EVP_PKEY_meth_new(int id, int flags); void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth); int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth); @@ -1109,6 +1109,7 @@ void ERR_load_EVP_strings(void); #define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 #define EVP_F_EVP_PKEY_CTX_CTRL 137 #define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 +#define EVP_F_EVP_PKEY_CTX_DUP 156 #define EVP_F_EVP_PKEY_DECRYPT 104 #define EVP_F_EVP_PKEY_DECRYPT_INIT 138 #define EVP_F_EVP_PKEY_DECRYPT_OLD 151 @@ -1137,6 +1138,7 @@ void ERR_load_EVP_strings(void); #define EVP_F_EVP_RIJNDAEL 126 #define EVP_F_EVP_SIGNFINAL 107 #define EVP_F_EVP_VERIFYFINAL 108 +#define EVP_F_INT_CTX_NEW 157 #define EVP_F_PKCS5_PBE_KEYIVGEN 117 #define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 #define EVP_F_PKCS8_SET_BROKEN 112 diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 27111e6281..a2f253cbd0 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -92,6 +92,7 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_FUNC(EVP_F_EVP_PKEY_COPY_PARAMETERS), "EVP_PKEY_copy_parameters"}, {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL), "EVP_PKEY_CTX_ctrl"}, {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL_STR), "EVP_PKEY_CTX_ctrl_str"}, +{ERR_FUNC(EVP_F_EVP_PKEY_CTX_DUP), "EVP_PKEY_CTX_dup"}, {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT), "EVP_PKEY_decrypt"}, {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_INIT), "EVP_PKEY_decrypt_init"}, {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_OLD), "EVP_PKEY_decrypt_old"}, @@ -120,6 +121,7 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_FUNC(EVP_F_EVP_RIJNDAEL), "EVP_RIJNDAEL"}, {ERR_FUNC(EVP_F_EVP_SIGNFINAL), "EVP_SignFinal"}, {ERR_FUNC(EVP_F_EVP_VERIFYFINAL), "EVP_VerifyFinal"}, +{ERR_FUNC(EVP_F_INT_CTX_NEW), "INT_CTX_NEW"}, {ERR_FUNC(EVP_F_PKCS5_PBE_KEYIVGEN), "PKCS5_PBE_keyivgen"}, {ERR_FUNC(EVP_F_PKCS5_V2_PBE_KEYIVGEN), "PKCS5_v2_PBE_keyivgen"}, {ERR_FUNC(EVP_F_PKCS8_SET_BROKEN), "PKCS8_set_broken"}, diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index 930959f524..dca3f68f34 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -239,6 +239,8 @@ struct evp_pkey_ctx_st { /* Method associated with this operation */ const EVP_PKEY_METHOD *pmeth; + /* Engine that implements this method or NULL if builtin */ + ENGINE *engine; /* Key: may be NULL */ EVP_PKEY *pkey; /* Peer key for key agreement, may be NULL */ diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index fb07c00d89..6caf7955e4 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -61,6 +61,9 @@ #include "cryptlib.h" #include #include +#ifndef OPENSSL_NO_ENGINE +#include +#endif #include "asn1_locl.h" #include "evp_locl.h" @@ -83,7 +86,7 @@ static int pmeth_cmp(const EVP_PKEY_METHOD * const *a, return ((*a)->pkey_id - (*b)->pkey_id); } -const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e) +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) { EVP_PKEY_METHOD tmp, *t = &tmp, **ret; tmp.pkey_id = type; @@ -115,10 +118,32 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) return NULL; id = pkey->ameth->pkey_id; } - pmeth = EVP_PKEY_meth_find(id, e); + /* Try to find an ENGINE which implements this method */ + if (e) + { + if (!ENGINE_init(e)) + { + EVPerr(EVP_F_INT_CTX_NEW,ERR_R_ENGINE_LIB); + return NULL; + } + else + e = ENGINE_get_pkey_meth_engine(id); + } + + /* If an ENGINE handled this method look it up. Othewise + * use internal table.S + */ + + if (e) + pmeth = ENGINE_get_pkey_meth(e, id); + else + pmeth = EVP_PKEY_meth_find(id); + if (pmeth == NULL) return NULL; + ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); + ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; ret->pkey = pkey; @@ -199,11 +224,22 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) EVP_PKEY_CTX *rctx; if (!pctx->pmeth || !pctx->pmeth->copy) return NULL; +#ifndef OPENSSL_NO_ENGINE + /* Make sure it's safe to copy a pkey context using an ENGINE */ + if (pctx->engine && !ENGINE_init(pctx->engine)) + { + EVPerr(EVP_F_EVP_PKEY_CTX_DUP,ERR_R_ENGINE_LIB); + return 0; + } +#endif rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); if (!rctx) return NULL; rctx->pmeth = pctx->pmeth; +#ifndef OPENSSL_NO_ENGINE + rctx->engine = pctx->engine; +#endif if (pctx->pkey) { @@ -251,6 +287,12 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) EVP_PKEY_free(ctx->pkey); if (ctx->peerkey) EVP_PKEY_free(ctx->peerkey); +#ifndef OPENSSL_NO_ENGINE + if(ctx->engine) + /* The EVP_PKEY_CTX we used belongs to an ENGINE, release the + * functional reference we held for this reason. */ + ENGINE_finish(ctx->engine); +#endif OPENSSL_free(ctx); } -- GitLab