X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fpmeth_lib.c;h=c7491785eddb6b07aec69e3f9d7768d04c074882;hp=3c923b7a73a1842b69e354ec55b83068c9e2cef0;hb=2e5975285e2b65261ce780fa3f5744277b66db34;hpb=ba30bad57bd0b02ebf952a550716a5a202b6004d diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 3c923b7a73..c7491785ed 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1,5 +1,5 @@ /* pmeth_lib.c */ -/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ /* ==================================================================== @@ -58,47 +58,58 @@ #include #include -#include #include "cryptlib.h" +#include #include +#ifndef OPENSSL_NO_ENGINE +#include +#endif #include "asn1_locl.h" #include "evp_locl.h" typedef int sk_cmp_fn_type(const char * const *a, const char * const *b); -STACK *app_pkey_methods = NULL; -extern EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth; +DECLARE_STACK_OF(EVP_PKEY_METHOD) +STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; + +extern const EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth; +extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth; static const EVP_PKEY_METHOD *standard_methods[] = { &rsa_pkey_meth, &dh_pkey_meth, - &dsa_pkey_meth + &dsa_pkey_meth, + &ec_pkey_meth, + &hmac_pkey_meth, }; +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, + pmeth); + static int pmeth_cmp(const EVP_PKEY_METHOD * const *a, - const EVP_PKEY_METHOD * const *b) + const EVP_PKEY_METHOD * const *b) { return ((*a)->pkey_id - (*b)->pkey_id); } -const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e) +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, + pmeth); + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) { - EVP_PKEY_METHOD tmp, *t = &tmp, **ret; + EVP_PKEY_METHOD tmp; + const EVP_PKEY_METHOD *t = &tmp, **ret; tmp.pkey_id = type; if (app_pkey_methods) { int idx; - idx = sk_find(app_pkey_methods, (char *)&tmp); + idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp); if (idx >= 0) - return (EVP_PKEY_METHOD *) - sk_value(app_pkey_methods, idx); + return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); } - ret = (EVP_PKEY_METHOD **) OBJ_bsearch((char *)&t, - (char *)standard_methods, - sizeof(standard_methods)/sizeof(EVP_PKEY_METHOD *), - sizeof(EVP_PKEY_METHOD *), - (int (*)(const void *, const void *))pmeth_cmp); + ret = OBJ_bsearch_pmeth(&t, standard_methods, + sizeof(standard_methods)/sizeof(EVP_PKEY_METHOD *)); if (!ret || !*ret) return NULL; return *ret; @@ -114,10 +125,42 @@ 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 tables. + */ + + if (e) + pmeth = ENGINE_get_pkey_meth(e, id); + else + pmeth = EVP_PKEY_meth_find(id); + if (pmeth == NULL) + { + EVPerr(EVP_F_INT_CTX_NEW,EVP_R_UNSUPPORTED_ALGORITHM); return NULL; + } + ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); + if (!ret) + { + if (e) + ENGINE_finish(e); + EVPerr(EVP_F_INT_CTX_NEW,ERR_R_MALLOC_FAILURE); + return NULL; + } + ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; ret->pkey = pkey; @@ -146,9 +189,10 @@ EVP_PKEY_METHOD* EVP_PKEY_meth_new(int id, int flags) return NULL; pmeth->pkey_id = id; - pmeth->flags = flags | EVP_PKEY_DYNAMIC; + pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; pmeth->init = 0; + pmeth->copy = 0; pmeth->cleanup = 0; pmeth->paramgen_init = 0; pmeth->paramgen = 0; @@ -178,7 +222,7 @@ EVP_PKEY_METHOD* EVP_PKEY_meth_new(int id, int flags) void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth) { - if (pmeth && (pmeth->flags & EVP_PKEY_DYNAMIC)) + if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC)) OPENSSL_free(pmeth); } @@ -192,28 +236,80 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) return int_ctx_new(NULL, e, id); } +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) + CRYPTO_add(&pctx->pkey->references,1,CRYPTO_LOCK_EVP_PKEY); + + rctx->pkey = pctx->pkey; + + if (pctx->peerkey) + CRYPTO_add(&pctx->peerkey->references,1,CRYPTO_LOCK_EVP_PKEY); + + rctx->peerkey = pctx->peerkey; + + rctx->data = NULL; + rctx->app_data = NULL; + rctx->operation = pctx->operation; + + if (pctx->pmeth->copy(rctx, pctx) > 0) + return rctx; + + EVP_PKEY_CTX_free(rctx); + return NULL; + + } + int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth) { if (app_pkey_methods == NULL) { - app_pkey_methods = sk_new((sk_cmp_fn_type *)pmeth_cmp); + app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp); if (!app_pkey_methods) return 0; } - if (!sk_push(app_pkey_methods, (char *)pmeth)) + if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) return 0; - sk_sort(app_pkey_methods); + sk_EVP_PKEY_METHOD_sort(app_pkey_methods); return 1; } void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) { + if (ctx == NULL) + return; if (ctx->pmeth && ctx->pmeth->cleanup) ctx->pmeth->cleanup(ctx); if (ctx->pkey) 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); } @@ -273,6 +369,17 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, return ctx->pmeth->ctrl_str(ctx, name, value); } +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx) + { + return ctx->operation; + } + +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen) + { + ctx->keygen_info = dat; + ctx->keygen_info_count = datlen; + } + void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data) { ctx->data = data; @@ -283,6 +390,16 @@ void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx) return ctx->data; } +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) + { + return ctx->pkey; + } + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx) + { + return ctx->peerkey; + } + void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) { ctx->app_data = data; @@ -299,6 +416,12 @@ void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, pmeth->init = init; } +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)) + { + pmeth->copy = copy; + } + void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, void (*cleanup)(EVP_PKEY_CTX *ctx)) { @@ -323,8 +446,8 @@ void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, int (*sign_init)(EVP_PKEY_CTX *ctx), - int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen, - const unsigned char *tbs, int tbslen)) + int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen)) { pmeth->sign_init = sign_init; pmeth->sign = sign; @@ -332,8 +455,8 @@ void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, int (*verify_init)(EVP_PKEY_CTX *ctx), - int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, - const unsigned char *tbs, int tbslen)) + int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen)) { pmeth->verify_init = verify_init; pmeth->verify = verify; @@ -342,8 +465,8 @@ void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, int (*verify_recover_init)(EVP_PKEY_CTX *ctx), int (*verify_recover)(EVP_PKEY_CTX *ctx, - unsigned char *sig, int *siglen, - const unsigned char *tbs, int tbslen)) + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen)) { pmeth->verify_recover_init = verify_recover_init; pmeth->verify_recover = verify_recover; @@ -351,7 +474,7 @@ void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx), - int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen, + int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx)) { pmeth->signctx_init = signctx_init; @@ -369,8 +492,8 @@ void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, int (*encrypt_init)(EVP_PKEY_CTX *ctx), - int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen, - const unsigned char *in, int inlen)) + int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen)) { pmeth->encrypt_init = encrypt_init; pmeth->encrypt = encrypt; @@ -378,8 +501,8 @@ void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, int (*decrypt_init)(EVP_PKEY_CTX *ctx), - int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen, - const unsigned char *in, int inlen)) + int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen)) { pmeth->decrypt_init = decrypt_init; pmeth->decrypt = decrypt; @@ -387,7 +510,7 @@ void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, int (*derive_init)(EVP_PKEY_CTX *ctx), - int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, int *keylen)) + int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)) { pmeth->derive_init = derive_init; pmeth->derive = derive;