openssl/crypto/evp/pmeth_lib.c

717 lines
22 KiB
C
Raw Normal View History

/*
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
2008-06-04 11:01:43 +00:00
static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
static const EVP_PKEY_METHOD *standard_methods[] = {
2009-04-26 22:18:22 +00:00
#ifndef OPENSSL_NO_RSA
&rsa_pkey_meth,
2009-04-26 22:18:22 +00:00
#endif
#ifndef OPENSSL_NO_DH
&dh_pkey_meth,
2009-04-26 22:18:22 +00:00
#endif
#ifndef OPENSSL_NO_DSA
&dsa_pkey_meth,
2009-04-26 22:18:22 +00:00
#endif
2009-04-23 16:32:42 +00:00
#ifndef OPENSSL_NO_EC
&ec_pkey_meth,
2009-04-23 16:32:42 +00:00
#endif
&hmac_pkey_meth,
#ifndef OPENSSL_NO_CMAC
&cmac_pkey_meth,
#endif
#ifndef OPENSSL_NO_DH
&dhx_pkey_meth,
#endif
&tls1_prf_pkey_meth,
&hkdf_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)
{
return ((*a)->pkey_id - (*b)->pkey_id);
}
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;
const EVP_PKEY_METHOD *t = &tmp, **ret;
tmp.pkey_id = type;
if (app_pkey_methods) {
int idx;
idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx);
}
ret = OBJ_bsearch_pmeth(&t, standard_methods,
sizeof(standard_methods) /
sizeof(EVP_PKEY_METHOD *));
if (!ret || !*ret)
return NULL;
return *ret;
}
2006-04-11 13:28:52 +00:00
static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
{
EVP_PKEY_CTX *ret;
const EVP_PKEY_METHOD *pmeth;
if (id == -1) {
if (!pkey || !pkey->ameth)
return NULL;
id = pkey->ameth->pkey_id;
}
2009-02-15 15:28:18 +00:00
#ifndef OPENSSL_NO_ENGINE
if (pkey && pkey->engine)
e = pkey->engine;
/* 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. Otherwise use internal
* tables.
*/
if (e)
pmeth = ENGINE_get_pkey_meth(e, id);
else
2009-02-15 15:28:18 +00:00
#endif
pmeth = EVP_PKEY_meth_find(id);
if (pmeth == NULL) {
EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
2009-02-15 15:28:18 +00:00
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
2009-02-15 15:28:18 +00:00
#endif
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;
if (pkey)
EVP_PKEY_up_ref(pkey);
if (pmeth->init) {
if (pmeth->init(ret) <= 0) {
EVP_PKEY_CTX_free(ret);
return NULL;
}
}
return ret;
}
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
{
EVP_PKEY_METHOD *pmeth;
pmeth = OPENSSL_zalloc(sizeof(*pmeth));
if (pmeth == NULL)
return NULL;
pmeth->pkey_id = id;
pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
return pmeth;
}
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
const EVP_PKEY_METHOD *meth)
{
if (ppkey_id)
*ppkey_id = meth->pkey_id;
if (pflags)
*pflags = meth->flags;
}
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
{
dst->init = src->init;
dst->copy = src->copy;
dst->cleanup = src->cleanup;
dst->paramgen_init = src->paramgen_init;
dst->paramgen = src->paramgen;
dst->keygen_init = src->keygen_init;
dst->keygen = src->keygen;
dst->sign_init = src->sign_init;
dst->sign = src->sign;
dst->verify_init = src->verify_init;
dst->verify = src->verify;
dst->verify_recover_init = src->verify_recover_init;
dst->verify_recover = src->verify_recover;
dst->signctx_init = src->signctx_init;
dst->signctx = src->signctx;
dst->verifyctx_init = src->verifyctx_init;
dst->verifyctx = src->verifyctx;
dst->encrypt_init = src->encrypt_init;
dst->encrypt = src->encrypt;
dst->decrypt_init = src->decrypt_init;
dst->decrypt = src->decrypt;
dst->derive_init = src->derive_init;
dst->derive = src->derive;
dst->ctrl = src->ctrl;
dst->ctrl_str = src->ctrl_str;
}
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
{
if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC))
OPENSSL_free(pmeth);
}
2006-04-11 13:28:52 +00:00
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
{
return int_ctx_new(pkey, e, -1);
}
2006-04-11 13:28:52 +00:00
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
{
return int_ctx_new(NULL, e, id);
}
2006-04-11 13:28:52 +00:00
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(*rctx));
if (rctx == NULL)
return NULL;
rctx->pmeth = pctx->pmeth;
#ifndef OPENSSL_NO_ENGINE
rctx->engine = pctx->engine;
#endif
if (pctx->pkey)
EVP_PKEY_up_ref(pctx->pkey);
rctx->pkey = pctx->pkey;
if (pctx->peerkey)
EVP_PKEY_up_ref(pctx->peerkey);
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_EVP_PKEY_METHOD_new(pmeth_cmp);
if (app_pkey_methods == NULL)
return 0;
}
if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth))
return 0;
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);
EVP_PKEY_free(ctx->pkey);
EVP_PKEY_free(ctx->peerkey);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
OPENSSL_free(ctx);
}
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2)
{
int ret;
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
return -1;
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
return -1;
}
if ((optype != -1) && !(ctx->operation & optype)) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
return -1;
}
ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
if (ret == -2)
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
const char *name, const char *value)
{
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
if (strcmp(name, "digest") == 0) {
const EVP_MD *md;
if (value == NULL || (md = EVP_get_digestbyname(value)) == NULL) {
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);
}
2006-04-11 13:28:52 +00:00
/* Utility functions to send a string of hex string to a ctrl */
int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
{
size_t len;
len = strlen(str);
if (len > INT_MAX)
return -1;
return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str);
}
int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
{
unsigned char *bin;
long binlen;
int rv = -1;
bin = OPENSSL_hexstr2buf(hex, &binlen);
if (bin == NULL)
return 0;
if (binlen <= INT_MAX)
rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin);
OPENSSL_free(bin);
return rv;
}
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;
}
2006-04-11 13:28:52 +00:00
void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->data = data;
}
2006-04-11 13:28:52 +00:00
void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
{
return ctx->data;
}
2006-04-11 13:28:52 +00:00
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
{
return ctx->pkey;
}
1. Changes for s_client.c to make it return non-zero exit code in case of handshake failure 2. Changes to x509_certificate_type function (crypto/x509/x509type.c) to make it recognize GOST certificates as EVP_PKT_SIGN|EVP_PKT_EXCH (required for s3_srvr to accept GOST client certificates). 3. Changes to EVP - adding of function EVP_PKEY_CTX_get0_peerkey - Make function EVP_PKEY_derive_set_peerkey work for context with ENCRYPT operation, because we use peerkey field in the context to pass non-ephemeral secret key to GOST encrypt operation. - added EVP_PKEY_CTRL_SET_IV control command. It is really GOST-specific, but it is used in SSL code, so it has to go in some header file, available during libssl compilation 4. Fix to HMAC to avoid call of OPENSSL_cleanse on undefined data 5. Include des.h if KSSL_DEBUG is defined into some libssl files, to make debugging output which depends on constants defined there, work and other KSSL_DEBUG output fixes 6. Declaration of real GOST ciphersuites, two authentication methods SSL_aGOST94 and SSL_aGOST2001 and one key exchange method SSL_kGOST 7. Implementation of these methods. 8. Support for sending unsolicited serverhello extension if GOST ciphersuite is selected. It is require for interoperability with CryptoPro CSP 3.0 and 3.6 and controlled by SSL_OP_CRYPTOPRO_TLSEXT_BUG constant. This constant is added to SSL_OP_ALL, because it does nothing, if non-GOST ciphersuite is selected, and all implementation of GOST include compatibility with CryptoPro. 9. Support for CertificateVerify message without length field. It is another CryptoPro bug, but support is made unconditional, because it does no harm for draft-conforming implementation. 10. In tls1_mac extra copy of stream mac context is no more done. When I've written currently commited code I haven't read EVP_DigestSignFinal manual carefully enough and haven't noticed that it does an internal digest ctx copying. This implementation was tested against 1. CryptoPro CSP 3.6 client and server 2. Cryptopro CSP 3.0 server
2007-10-26 12:06:36 +00:00
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
{
return ctx->peerkey;
}
2006-04-11 13:28:52 +00:00
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
{
ctx->app_data = data;
}
2006-04-11 13:28:52 +00:00
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
{
return ctx->app_data;
}
void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
int (*init) (EVP_PKEY_CTX *ctx))
{
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))
{
pmeth->cleanup = cleanup;
}
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
int (*paramgen_init) (EVP_PKEY_CTX *ctx),
int (*paramgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
pmeth->paramgen_init = paramgen_init;
pmeth->paramgen = paramgen;
}
void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
int (*keygen_init) (EVP_PKEY_CTX *ctx),
int (*keygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
pmeth->keygen_init = keygen_init;
pmeth->keygen = keygen;
}
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, size_t *siglen,
const unsigned char *tbs,
size_t tbslen))
{
pmeth->sign_init = sign_init;
pmeth->sign = sign;
}
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,
size_t siglen,
const unsigned char *tbs,
size_t tbslen))
{
pmeth->verify_init = verify_init;
pmeth->verify = verify;
}
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,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen))
{
pmeth->verify_recover_init = verify_recover_init;
pmeth->verify_recover = verify_recover;
}
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,
size_t *siglen,
EVP_MD_CTX *mctx))
{
pmeth->signctx_init = signctx_init;
pmeth->signctx = signctx;
}
void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*verifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx))
{
pmeth->verifyctx_init = verifyctx_init;
pmeth->verifyctx = verifyctx;
}
void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
int (*encrypt_init) (EVP_PKEY_CTX *ctx),
int (*encryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
pmeth->encrypt_init = encrypt_init;
pmeth->encrypt = encryptfn;
}
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,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
pmeth->decrypt_init = decrypt_init;
pmeth->decrypt = decrypt;
}
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,
size_t *keylen))
{
pmeth->derive_init = derive_init;
pmeth->derive = derive;
}
void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (*ctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value))
{
pmeth->ctrl = ctrl;
pmeth->ctrl_str = ctrl_str;
}
void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
int (**pinit) (EVP_PKEY_CTX *ctx))
{
*pinit = pmeth->init;
}
void EVP_PKEY_meth_get_copy(EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src))
{
*pcopy = pmeth->copy;
}
void EVP_PKEY_meth_get_cleanup(EVP_PKEY_METHOD *pmeth,
void (**pcleanup) (EVP_PKEY_CTX *ctx))
{
*pcleanup = pmeth->cleanup;
}
void EVP_PKEY_meth_get_paramgen(EVP_PKEY_METHOD *pmeth,
int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
int (**pparamgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
if (pparamgen_init)
*pparamgen_init = pmeth->paramgen_init;
if (pparamgen)
*pparamgen = pmeth->paramgen;
}
void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth,
int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
int (**pkeygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey))
{
if (pkeygen_init)
*pkeygen_init = pmeth->keygen_init;
if (pkeygen)
*pkeygen = pmeth->keygen;
}
void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth,
int (**psign_init) (EVP_PKEY_CTX *ctx),
int (**psign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen))
{
if (psign_init)
*psign_init = pmeth->sign_init;
if (psign)
*psign = pmeth->sign;
}
void EVP_PKEY_meth_get_verify(EVP_PKEY_METHOD *pmeth,
int (**pverify_init) (EVP_PKEY_CTX *ctx),
int (**pverify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen))
{
if (pverify_init)
*pverify_init = pmeth->verify_init;
if (pverify)
*pverify = pmeth->verify;
}
void EVP_PKEY_meth_get_verify_recover(EVP_PKEY_METHOD *pmeth,
int (**pverify_recover_init) (EVP_PKEY_CTX
*ctx),
int (**pverify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen))
{
if (pverify_recover_init)
*pverify_recover_init = pmeth->verify_recover_init;
if (pverify_recover)
*pverify_recover = pmeth->verify_recover;
}
void EVP_PKEY_meth_get_signctx(EVP_PKEY_METHOD *pmeth,
int (**psignctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**psignctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx))
{
if (psignctx_init)
*psignctx_init = pmeth->signctx_init;
if (psignctx)
*psignctx = pmeth->signctx;
}
void EVP_PKEY_meth_get_verifyctx(EVP_PKEY_METHOD *pmeth,
int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**pverifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx))
{
if (pverifyctx_init)
*pverifyctx_init = pmeth->verifyctx_init;
if (pverifyctx)
*pverifyctx = pmeth->verifyctx;
}
void EVP_PKEY_meth_get_encrypt(EVP_PKEY_METHOD *pmeth,
int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
int (**pencryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
if (pencrypt_init)
*pencrypt_init = pmeth->encrypt_init;
if (pencryptfn)
*pencryptfn = pmeth->encrypt;
}
void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth,
int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
int (**pdecrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen))
{
if (pdecrypt_init)
*pdecrypt_init = pmeth->decrypt_init;
if (pdecrypt)
*pdecrypt = pmeth->decrypt;
}
void EVP_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth,
int (**pderive_init) (EVP_PKEY_CTX *ctx),
int (**pderive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen))
{
if (pderive_init)
*pderive_init = pmeth->derive_init;
if (pderive)
*pderive = pmeth->derive;
}
void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth,
int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (**pctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value))
{
if (pctrl)
*pctrl = pmeth->ctrl;
if (pctrl_str)
*pctrl_str = pmeth->ctrl_str;
}