-/* evp_locl.h */
/*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
- * 2000.
- */
-/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
+ * Licensed under the Apache License 2.0 (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
*/
/* EVP_MD_CTX related stuff */
+#include <openssl/core_numbers.h>
+
+#define EVP_CTRL_RET_UNSUPPORTED -1
+
+
struct evp_md_ctx_st {
+ const EVP_MD *reqdigest; /* The original requested digest */
const EVP_MD *digest;
ENGINE *engine; /* functional reference if 'digest' is
* ENGINE-provided */
EVP_PKEY_CTX *pctx;
/* Update function: usually copied from EVP_MD */
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+
+ /* Provider ctx */
+ void *provctx;
+ EVP_MD *fetched_digest;
} /* EVP_MD_CTX */ ;
-# define M_EVP_MD_size(e) ((e)->md_size)
-# define M_EVP_MD_block_size(e) ((e)->block_size)
-# define M_EVP_MD_CTX_set_flags(ctx,flgs) ((ctx)->flags|=(flgs))
-# define M_EVP_MD_CTX_clear_flags(ctx,flgs) ((ctx)->flags&=~(flgs))
-# define M_EVP_MD_CTX_test_flags(ctx,flgs) ((ctx)->flags&(flgs))
-# define M_EVP_MD_type(e) ((e)->type)
-# define M_EVP_MD_CTX_type(e) M_EVP_MD_type(M_EVP_MD_CTX_md(e))
-# define M_EVP_MD_CTX_md(e) ((e)->digest)
-
-/* Macros to code block cipher wrappers */
-
-/* Wrapper functions for each cipher mode */
-
-#define BLOCK_CIPHER_ecb_loop() \
- size_t i, bl; \
- bl = ctx->cipher->block_size;\
- if(inl < bl) return 1;\
- inl -= bl; \
- for(i=0; i <= inl; i+=bl)
-
-#define BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \
-static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
-{\
- BLOCK_CIPHER_ecb_loop() \
- cprefix##_ecb_encrypt(in + i, out + i, &((kstruct *)ctx->cipher_data)->ksched, ctx->encrypt);\
- return 1;\
-}
-
-#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2))
-
-#define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \
-static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
-{\
- while(inl>=EVP_MAXCHUNK)\
- {\
- cprefix##_ofb##cbits##_encrypt(in, out, (long)EVP_MAXCHUNK, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num);\
- inl-=EVP_MAXCHUNK;\
- in +=EVP_MAXCHUNK;\
- out+=EVP_MAXCHUNK;\
- }\
- if (inl)\
- cprefix##_ofb##cbits##_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num);\
- return 1;\
-}
-
-#define BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \
-static int cname##_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
-{\
- while(inl>=EVP_MAXCHUNK) \
- {\
- cprefix##_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, ctx->encrypt);\
- inl-=EVP_MAXCHUNK;\
- in +=EVP_MAXCHUNK;\
- out+=EVP_MAXCHUNK;\
- }\
- if (inl)\
- cprefix##_cbc_encrypt(in, out, (long)inl, &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, ctx->encrypt);\
- return 1;\
-}
-
-#define BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \
-static int cname##_cfb##cbits##_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \
-{\
- size_t chunk=EVP_MAXCHUNK;\
- if (cbits==1) chunk>>=3;\
- if (inl<chunk) chunk=inl;\
- while(inl && inl>=chunk)\
- {\
- cprefix##_cfb##cbits##_encrypt(in, out, (long)((cbits==1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ?inl*8:inl), &((kstruct *)ctx->cipher_data)->ksched, ctx->iv, &ctx->num, ctx->encrypt);\
- inl-=chunk;\
- in +=chunk;\
- out+=chunk;\
- if(inl<chunk) chunk=inl;\
- }\
- return 1;\
-}
-
-#define BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \
- BLOCK_CIPHER_func_cbc(cname, cprefix, kstruct, ksched) \
- BLOCK_CIPHER_func_cfb(cname, cprefix, cbits, kstruct, ksched) \
- BLOCK_CIPHER_func_ecb(cname, cprefix, kstruct, ksched) \
- BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched)
-
-#define BLOCK_CIPHER_def1(cname, nmode, mode, MODE, kstruct, nid, block_size, \
- key_len, iv_len, flags, init_key, cleanup, \
- set_asn1, get_asn1, ctrl) \
-static const EVP_CIPHER cname##_##mode = { \
- nid##_##nmode, block_size, key_len, iv_len, \
- flags | EVP_CIPH_##MODE##_MODE, \
- init_key, \
- cname##_##mode##_cipher, \
- cleanup, \
- sizeof(kstruct), \
- set_asn1, get_asn1,\
- ctrl, \
- NULL \
-}; \
-const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; }
-
-#define BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, \
- iv_len, flags, init_key, cleanup, set_asn1, \
- get_asn1, ctrl) \
-BLOCK_CIPHER_def1(cname, cbc, cbc, CBC, kstruct, nid, block_size, key_len, \
- iv_len, flags, init_key, cleanup, set_asn1, get_asn1, ctrl)
-
-#define BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, \
- iv_len, cbits, flags, init_key, cleanup, \
- set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def1(cname, cfb##cbits, cfb##cbits, CFB, kstruct, nid, 1, \
- key_len, iv_len, flags, init_key, cleanup, set_asn1, \
- get_asn1, ctrl)
-
-#define BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, \
- iv_len, cbits, flags, init_key, cleanup, \
- set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def1(cname, ofb##cbits, ofb, OFB, kstruct, nid, 1, \
- key_len, iv_len, flags, init_key, cleanup, set_asn1, \
- get_asn1, ctrl)
-
-#define BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, \
- flags, init_key, cleanup, set_asn1, \
- get_asn1, ctrl) \
-BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \
- 0, flags, init_key, cleanup, set_asn1, get_asn1, ctrl)
-
-#define BLOCK_CIPHER_defs(cname, kstruct, \
- nid, block_size, key_len, iv_len, cbits, flags, \
- init_key, cleanup, set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \
- init_key, cleanup, set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, iv_len, cbits, \
- flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, iv_len, cbits, \
- flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
-BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, flags, \
- init_key, cleanup, set_asn1, get_asn1, ctrl)
-
-/*-
-#define BLOCK_CIPHER_defs(cname, kstruct, \
- nid, block_size, key_len, iv_len, flags,\
- init_key, cleanup, set_asn1, get_asn1, ctrl)\
-static const EVP_CIPHER cname##_cbc = {\
- nid##_cbc, block_size, key_len, iv_len, \
- flags | EVP_CIPH_CBC_MODE,\
- init_key,\
- cname##_cbc_cipher,\
- cleanup,\
- sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
- sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
- set_asn1, get_asn1,\
- ctrl, \
- NULL \
-};\
-const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\
-static const EVP_CIPHER cname##_cfb = {\
- nid##_cfb64, 1, key_len, iv_len, \
- flags | EVP_CIPH_CFB_MODE,\
- init_key,\
- cname##_cfb_cipher,\
- cleanup,\
- sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
- sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
- set_asn1, get_asn1,\
- ctrl,\
- NULL \
-};\
-const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\
-static const EVP_CIPHER cname##_ofb = {\
- nid##_ofb64, 1, key_len, iv_len, \
- flags | EVP_CIPH_OFB_MODE,\
- init_key,\
- cname##_ofb_cipher,\
- cleanup,\
- sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
- sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
- set_asn1, get_asn1,\
- ctrl,\
- NULL \
-};\
-const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\
-static const EVP_CIPHER cname##_ecb = {\
- nid##_ecb, block_size, key_len, iv_len, \
- flags | EVP_CIPH_ECB_MODE,\
- init_key,\
- cname##_ecb_cipher,\
- cleanup,\
- sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
- sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
- set_asn1, get_asn1,\
- ctrl,\
- NULL \
-};\
-const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
-*/
-
-#define IMPLEMENT_BLOCK_CIPHER(cname, ksched, cprefix, kstruct, nid, \
- block_size, key_len, iv_len, cbits, \
- flags, init_key, \
- cleanup, set_asn1, get_asn1, ctrl) \
- BLOCK_CIPHER_all_funcs(cname, cprefix, cbits, kstruct, ksched) \
- BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, \
- cbits, flags, init_key, cleanup, set_asn1, \
- get_asn1, ctrl)
-
-#define EVP_C_DATA(kstruct, ctx) ((kstruct *)(ctx)->cipher_data)
-
-#define IMPLEMENT_CFBR(cipher,cprefix,kstruct,ksched,keysize,cbits,iv_len,fl) \
- BLOCK_CIPHER_func_cfb(cipher##_##keysize,cprefix,cbits,kstruct,ksched) \
- BLOCK_CIPHER_def_cfb(cipher##_##keysize,kstruct, \
- NID_##cipher##_##keysize, keysize/8, iv_len, cbits, \
- (fl)|EVP_CIPH_FLAG_DEFAULT_ASN1, \
- cipher##_init_key, NULL, NULL, NULL, NULL)
+struct evp_cipher_ctx_st {
+ const EVP_CIPHER *cipher;
+ ENGINE *engine; /* functional reference if 'cipher' is
+ * ENGINE-provided */
+ int encrypt; /* encrypt or decrypt */
+ int buf_len; /* number we have left */
+ unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */
+ unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */
+ unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */
+ int num; /* used by cfb/ofb/ctr mode */
+ /* FIXME: Should this even exist? It appears unused */
+ void *app_data; /* application stuff */
+ int key_len; /* May change for variable length cipher */
+ unsigned long flags; /* Various flags */
+ void *cipher_data; /* per EVP data */
+ int final_used;
+ int block_mask;
+ unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
+
+ /* Provider ctx */
+ void *provctx;
+ EVP_CIPHER *fetched_cipher;
+} /* EVP_CIPHER_CTX */ ;
+
+struct evp_mac_ctx_st {
+ EVP_MAC *meth; /* Method structure */
+ void *data; /* Individual method data */
+} /* EVP_MAC_CTX */;
+
+struct evp_kdf_ctx_st {
+ EVP_KDF *meth; /* Method structure */
+ void *data; /* Algorithm-specific data */
+} /* EVP_KDF_CTX */ ;
+
+struct evp_keymgmt_st {
+ int id; /* libcrypto internal */
+
+ char *name;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ /* Domain parameter routines */
+ OSSL_OP_keymgmt_importdomparams_fn *importdomparams;
+ OSSL_OP_keymgmt_gendomparams_fn *gendomparams;
+ OSSL_OP_keymgmt_freedomparams_fn *freedomparams;
+ OSSL_OP_keymgmt_exportdomparams_fn *exportdomparams;
+ OSSL_OP_keymgmt_importdomparam_types_fn *importdomparam_types;
+ OSSL_OP_keymgmt_exportdomparam_types_fn *exportdomparam_types;
+
+ /* Key routines */
+ OSSL_OP_keymgmt_importkey_fn *importkey;
+ OSSL_OP_keymgmt_genkey_fn *genkey;
+ OSSL_OP_keymgmt_loadkey_fn *loadkey;
+ OSSL_OP_keymgmt_freekey_fn *freekey;
+ OSSL_OP_keymgmt_exportkey_fn *exportkey;
+ OSSL_OP_keymgmt_importkey_types_fn *importkey_types;
+ OSSL_OP_keymgmt_exportkey_types_fn *exportkey_types;
+} /* EVP_KEYMGMT */ ;
+
+struct keymgmt_data_st {
+ OPENSSL_CTX *ctx;
+ const char *properties;
+};
+
+struct evp_keyexch_st {
+ char *name;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ EVP_KEYMGMT *keymgmt;
+
+ OSSL_OP_keyexch_newctx_fn *newctx;
+ OSSL_OP_keyexch_init_fn *init;
+ OSSL_OP_keyexch_set_peer_fn *set_peer;
+ OSSL_OP_keyexch_derive_fn *derive;
+ OSSL_OP_keyexch_freectx_fn *freectx;
+ OSSL_OP_keyexch_dupctx_fn *dupctx;
+ OSSL_OP_keyexch_set_ctx_params_fn *set_ctx_params;
+ OSSL_OP_keyexch_settable_ctx_params_fn *settable_ctx_params;
+} /* EVP_KEYEXCH */;
+
+struct evp_signature_st {
+ char *name;
+ OSSL_PROVIDER *prov;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ EVP_KEYMGMT *keymgmt;
+
+ OSSL_OP_signature_newctx_fn *newctx;
+ OSSL_OP_signature_sign_init_fn *sign_init;
+ OSSL_OP_signature_sign_fn *sign;
+ OSSL_OP_signature_verify_init_fn *verify_init;
+ OSSL_OP_signature_verify_fn *verify;
+ OSSL_OP_signature_verify_recover_init_fn *verify_recover_init;
+ OSSL_OP_signature_verify_recover_fn *verify_recover;
+ OSSL_OP_signature_freectx_fn *freectx;
+ OSSL_OP_signature_dupctx_fn *dupctx;
+ OSSL_OP_signature_get_ctx_params_fn *get_ctx_params;
+ OSSL_OP_signature_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_OP_signature_set_ctx_params_fn *set_ctx_params;
+ OSSL_OP_signature_settable_ctx_params_fn *settable_ctx_params;
+} /* EVP_SIGNATURE */;
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md,
int en_de);
+
+struct evp_Encode_Ctx_st {
+ /* number saved in a partial encode/decode */
+ int num;
+ /*
+ * The length is either the output line length (in input bytes) or the
+ * shortest input line length that is ok. Once decoding begins, the
+ * length is adjusted up each time a longer line is decoded
+ */
+ int length;
+ /* data to encode */
+ unsigned char enc_data[80];
+ /* number read on current line */
+ int line_num;
+ unsigned int flags;
+};
+
+typedef struct evp_pbe_st EVP_PBE_CTL;
+DEFINE_STACK_OF(EVP_PBE_CTL)
+
+int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
+
+#include <openssl/ossl_typ.h>
+#include <openssl/core.h>
+
+void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
+ const char *algorithm, const char *properties,
+ void *(*new_method)(const char *name,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
+ int (*up_ref_method)(void *),
+ void (*free_method)(void *));
+void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
+ void (*user_fn)(void *method, void *arg),
+ void *user_arg,
+ void *(*new_method)(const char *name,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
+ void (*free_method)(void *));
+
+/* Internal structure constructors for fetched methods */
+EVP_MD *evp_md_new(void);
+EVP_CIPHER *evp_cipher_new(void);
+
+/* Helper functions to avoid duplicating code */
+
+/*
+ * These methods implement different ways to pass a params array to the
+ * provider. They will return one of these values:
+ *
+ * -2 if the method doesn't come from a provider
+ * (evp_do_param will return this to the called)
+ * -1 if the provider doesn't offer the desired function
+ * (evp_do_param will raise an error and return 0)
+ * or the return value from the desired function
+ * (evp_do_param will return it to the caller)
+ */
+int evp_do_ciph_getparams(const EVP_CIPHER *ciph, OSSL_PARAM params[]);
+int evp_do_ciph_ctx_getparams(const EVP_CIPHER *ciph, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_ciph_ctx_setparams(const EVP_CIPHER *ciph, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_md_getparams(const EVP_MD *md, OSSL_PARAM params[]);
+int evp_do_md_ctx_getparams(const EVP_MD *md, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_md_ctx_setparams(const EVP_MD *md, void *provctx,
+ OSSL_PARAM params[]);
+
+OSSL_PARAM *evp_pkey_to_param(EVP_PKEY *pkey, size_t *sz);
+
+#define M_check_autoarg(ctx, arg, arglen, err) \
+ if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) { \
+ size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \
+ \
+ if (pksize == 0) { \
+ EVPerr(err, EVP_R_INVALID_KEY); /*ckerr_ignore*/ \
+ return 0; \
+ } \
+ if (arg == NULL) { \
+ *arglen = pksize; \
+ return 1; \
+ } \
+ if (*arglen < pksize) { \
+ EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \
+ return 0; \
+ } \
+ }
+
+void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx);