diff options
| author | Parménides GV <parmegv@sdf.org> | 2014-06-13 13:24:13 +0200 | 
|---|---|---|
| committer | Parménides GV <parmegv@sdf.org> | 2014-06-13 13:24:13 +0200 | 
| commit | 69b10487fcd63dfe1e94fa97c9f3fd9b035646b4 (patch) | |
| tree | d4960893a4444634d404c7fbe4fa3e8778d30179 /app/openssl/crypto/engine | |
| parent | 9f6cfff38ae87922adc022300e1e2fd1c0d4c3e4 (diff) | |
| parent | e45929e220fe49e30235a1d4d36c1a413547f8bf (diff) | |
Merge branch 'develop'
Diffstat (limited to 'app/openssl/crypto/engine')
| -rw-r--r-- | app/openssl/crypto/engine/eng_all.c | 9 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/eng_cryptodev.c | 71 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/eng_dyn.c | 5 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/eng_fat.c | 3 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/eng_list.c | 1 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/engine.h | 9 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/tb_asnmth.c | 246 | ||||
| -rw-r--r-- | app/openssl/crypto/engine/tb_pkmeth.c | 167 | 
8 files changed, 489 insertions, 22 deletions
diff --git a/app/openssl/crypto/engine/eng_all.c b/app/openssl/crypto/engine/eng_all.c index 22c12045..6093376d 100644 --- a/app/openssl/crypto/engine/eng_all.c +++ b/app/openssl/crypto/engine/eng_all.c @@ -61,6 +61,8 @@  void ENGINE_load_builtin_engines(void)  	{ +	/* Some ENGINEs need this */ +	OPENSSL_cpuid_setup();  #if 0  	/* There's no longer any need for an "openssl" ENGINE unless, one day,  	 * it is the *only* way for standard builtin implementations to be be @@ -71,6 +73,12 @@ void ENGINE_load_builtin_engines(void)  #if !defined(OPENSSL_NO_HW) && (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))  	ENGINE_load_cryptodev();  #endif +#ifndef OPENSSL_NO_RSAX +	ENGINE_load_rsax(); +#endif +#ifndef OPENSSL_NO_RDRAND +	ENGINE_load_rdrand(); +#endif  	ENGINE_load_dynamic();  #ifndef OPENSSL_NO_STATIC_ENGINE  #ifndef OPENSSL_NO_HW @@ -112,6 +120,7 @@ void ENGINE_load_builtin_engines(void)  	ENGINE_load_capi();  #endif  #endif +	ENGINE_register_all_complete();  	}  #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) diff --git a/app/openssl/crypto/engine/eng_cryptodev.c b/app/openssl/crypto/engine/eng_cryptodev.c index 52f4ca39..5a715aca 100644 --- a/app/openssl/crypto/engine/eng_cryptodev.c +++ b/app/openssl/crypto/engine/eng_cryptodev.c @@ -79,8 +79,6 @@ struct dev_crypto_state {  	unsigned char digest_res[HASH_MAX_LEN];  	char *mac_data;  	int mac_len; - -	int copy;  #endif  }; @@ -200,6 +198,7 @@ get_dev_crypto(void)  	if ((fd = open_dev_crypto()) == -1)  		return (-1); +#ifndef CRIOGET_NOT_NEEDED  	if (ioctl(fd, CRIOGET, &retfd) == -1)  		return (-1); @@ -208,9 +207,19 @@ get_dev_crypto(void)  		close(retfd);  		return (-1);  	} +#else +        retfd = fd; +#endif  	return (retfd);  } +static void put_dev_crypto(int fd) +{ +#ifndef CRIOGET_NOT_NEEDED +	close(fd); +#endif +} +  /* Caching version for asym operations */  static int  get_asym_dev_crypto(void) @@ -252,7 +261,7 @@ get_cryptodev_ciphers(const int **cnids)  		    ioctl(fd, CIOCFSESSION, &sess.ses) != -1)  			nids[count++] = ciphers[i].nid;  	} -	close(fd); +	put_dev_crypto(fd);  	if (count > 0)  		*cnids = nids; @@ -291,7 +300,7 @@ get_cryptodev_digests(const int **cnids)  		    ioctl(fd, CIOCFSESSION, &sess.ses) != -1)  			nids[count++] = digests[i].nid;  	} -	close(fd); +	put_dev_crypto(fd);  	if (count > 0)  		*cnids = nids; @@ -436,7 +445,7 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,  	sess->cipher = cipher;  	if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { -		close(state->d_fd); +		put_dev_crypto(state->d_fd);  		state->d_fd = -1;  		return (0);  	} @@ -473,7 +482,7 @@ cryptodev_cleanup(EVP_CIPHER_CTX *ctx)  	} else {  		ret = 1;  	} -	close(state->d_fd); +	put_dev_crypto(state->d_fd);  	state->d_fd = -1;  	return (ret); @@ -686,7 +695,7 @@ static int cryptodev_digest_init(EVP_MD_CTX *ctx)  	sess->mac = digest;  	if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) { -		close(state->d_fd); +		put_dev_crypto(state->d_fd);  		state->d_fd = -1;  		printf("cryptodev_digest_init: Open session failed\n");  		return (0); @@ -758,14 +767,12 @@ static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)  	if (! (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) ) {  		/* if application doesn't support one buffer */  		memset(&cryp, 0, sizeof(cryp)); -  		cryp.ses = sess->ses;  		cryp.flags = 0;  		cryp.len = state->mac_len;  		cryp.src = state->mac_data;  		cryp.dst = NULL;  		cryp.mac = (caddr_t)md; -  		if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {  			printf("cryptodev_digest_final: digest failed\n");  			return (0); @@ -786,6 +793,9 @@ static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)  	struct dev_crypto_state *state = ctx->md_data;  	struct session_op *sess = &state->d_sess; +	if (state == NULL) +	  return 0; +  	if (state->d_fd < 0) {  		printf("cryptodev_digest_cleanup: illegal input\n");  		return (0); @@ -797,16 +807,13 @@ static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)  		state->mac_len = 0;  	} -	if (state->copy) -		return 1; -  	if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {  		printf("cryptodev_digest_cleanup: failed to close session\n");  		ret = 0;  	} else {  		ret = 1;  	} -	close(state->d_fd);	 +	put_dev_crypto(state->d_fd);	  	state->d_fd = -1;  	return (ret); @@ -816,15 +823,39 @@ static int cryptodev_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)  {  	struct dev_crypto_state *fstate = from->md_data;  	struct dev_crypto_state *dstate = to->md_data; +	struct session_op *sess; +	int digest; -	memcpy(dstate, fstate, sizeof(struct dev_crypto_state)); +	if (dstate == NULL || fstate == NULL) +	  return 1; -	if (fstate->mac_len != 0) { -		dstate->mac_data = OPENSSL_malloc(fstate->mac_len); -		memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len); +       	memcpy(dstate, fstate, sizeof(struct dev_crypto_state)); + +	sess = &dstate->d_sess; + +	digest = digest_nid_to_cryptodev(to->digest->type); + +	sess->mackey = dstate->dummy_mac_key; +	sess->mackeylen = digest_key_length(to->digest->type); +	sess->mac = digest; + +	dstate->d_fd = get_dev_crypto(); + +	if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) { +		put_dev_crypto(dstate->d_fd); +		dstate->d_fd = -1; +		printf("cryptodev_digest_init: Open session failed\n"); +		return (0);  	} -	dstate->copy = 1; +	if (fstate->mac_len != 0) { +	        if (fstate->mac_data != NULL) +	                { +        		dstate->mac_data = OPENSSL_malloc(fstate->mac_len); +	        	memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len); +           		dstate->mac_len = fstate->mac_len; +	        	} +	}  	return 1;  } @@ -1347,11 +1378,11 @@ ENGINE_load_cryptodev(void)  	 * find out what asymmetric crypto algorithms we support  	 */  	if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) { -		close(fd); +		put_dev_crypto(fd);  		ENGINE_free(engine);  		return;  	} -	close(fd); +	put_dev_crypto(fd);  	if (!ENGINE_set_id(engine, "cryptodev") ||  	    !ENGINE_set_name(engine, "BSD cryptodev engine") || diff --git a/app/openssl/crypto/engine/eng_dyn.c b/app/openssl/crypto/engine/eng_dyn.c index 807da7a5..8fb8634e 100644 --- a/app/openssl/crypto/engine/eng_dyn.c +++ b/app/openssl/crypto/engine/eng_dyn.c @@ -408,7 +408,7 @@ static int int_load(dynamic_data_ctx *ctx)  	int num, loop;  	/* Unless told not to, try a direct load */  	if((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso, -				ctx->DYNAMIC_LIBNAME, NULL, 0)) != NULL) +				ctx->DYNAMIC_LIBNAME, NULL, 0) != NULL))  		return 1;  	/* If we're not allowed to use 'dirs' or we have none, fail */  	if(!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1) @@ -423,6 +423,9 @@ static int int_load(dynamic_data_ctx *ctx)  			{  			/* Found what we're looking for */  			OPENSSL_free(merge); +			/* Previous failed loop iterations, if any, will have resulted in +			 * errors. Clear them out before returning success. */ +			ERR_clear_error();  			return 1;  			}  		OPENSSL_free(merge); diff --git a/app/openssl/crypto/engine/eng_fat.c b/app/openssl/crypto/engine/eng_fat.c index db66e623..789b8d57 100644 --- a/app/openssl/crypto/engine/eng_fat.c +++ b/app/openssl/crypto/engine/eng_fat.c @@ -176,6 +176,7 @@ int ENGINE_register_all_complete(void)  	ENGINE *e;  	for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) -		ENGINE_register_complete(e); +		if (!(e->flags & ENGINE_FLAGS_NO_REGISTER_ALL)) +			ENGINE_register_complete(e);  	return 1;  	} diff --git a/app/openssl/crypto/engine/eng_list.c b/app/openssl/crypto/engine/eng_list.c index 27846edb..95c85896 100644 --- a/app/openssl/crypto/engine/eng_list.c +++ b/app/openssl/crypto/engine/eng_list.c @@ -408,6 +408,7 @@ ENGINE *ENGINE_by_id(const char *id)  				!ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||  				!ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",  					load_dir, 0) || +				!ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||  				!ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))  				goto notfound;  		return iterator; diff --git a/app/openssl/crypto/engine/engine.h b/app/openssl/crypto/engine/engine.h index 943aeae2..f8be4977 100644 --- a/app/openssl/crypto/engine/engine.h +++ b/app/openssl/crypto/engine/engine.h @@ -141,6 +141,13 @@ extern "C" {   * the existing ENGINE's structural reference count. */  #define ENGINE_FLAGS_BY_ID_COPY		(int)0x0004 +/* This flag if for an ENGINE that does not want its methods registered as  + * part of ENGINE_register_all_complete() for example if the methods are + * not usable as default methods. + */ + +#define ENGINE_FLAGS_NO_REGISTER_ALL	(int)0x0008 +  /* ENGINEs can support their own command types, and these flags are used in   * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each   * command expects. Currently only numeric and string input is supported. If a @@ -344,6 +351,8 @@ void ENGINE_load_gost(void);  #endif  #endif  void ENGINE_load_cryptodev(void); +void ENGINE_load_rsax(void); +void ENGINE_load_rdrand(void);  void ENGINE_load_builtin_engines(void);  /* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation diff --git a/app/openssl/crypto/engine/tb_asnmth.c b/app/openssl/crypto/engine/tb_asnmth.c new file mode 100644 index 00000000..75090339 --- /dev/null +++ b/app/openssl/crypto/engine/tb_asnmth.c @@ -0,0 +1,246 @@ +/* ==================================================================== + * Copyright (c) 2006 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). + * + */ + +#include "eng_int.h" +#include "asn1_locl.h" +#include <openssl/evp.h> + +/* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the + * function that is used by EVP to hook in pkey_asn1_meth code and cache + * defaults (etc), will display brief debugging summaries to stderr with the + * 'nid'. */ +/* #define ENGINE_PKEY_ASN1_METH_DEBUG */ + +static ENGINE_TABLE *pkey_asn1_meth_table = NULL; + +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e) +	{ +	engine_table_unregister(&pkey_asn1_meth_table, e); +	} + +static void engine_unregister_all_pkey_asn1_meths(void) +	{ +	engine_table_cleanup(&pkey_asn1_meth_table); +	} + +int ENGINE_register_pkey_asn1_meths(ENGINE *e) +	{ +	if(e->pkey_asn1_meths) +		{ +		const int *nids; +		int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0); +		if(num_nids > 0) +			return engine_table_register(&pkey_asn1_meth_table, +				engine_unregister_all_pkey_asn1_meths, e, nids, +					num_nids, 0); +		} +	return 1; +	} + +void ENGINE_register_all_pkey_asn1_meths(void) +	{ +	ENGINE *e; + +	for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) +		ENGINE_register_pkey_asn1_meths(e); +	} + +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e) +	{ +	if(e->pkey_asn1_meths) +		{ +		const int *nids; +		int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0); +		if(num_nids > 0) +			return engine_table_register(&pkey_asn1_meth_table, +				engine_unregister_all_pkey_asn1_meths, e, nids, +					num_nids, 1); +		} +	return 1; +	} + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given pkey_asn1_meth 'nid' */ +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid) +	{ +	return engine_table_select(&pkey_asn1_meth_table, nid); +	} + +/* Obtains a pkey_asn1_meth implementation from an ENGINE functional reference */ +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid) +	{ +	EVP_PKEY_ASN1_METHOD *ret; +	ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e); +	if(!fn || !fn(e, &ret, NULL, nid)) +		{ +		ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH, +				ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD); +		return NULL; +		} +	return ret; +	} + +/* Gets the pkey_asn1_meth callback from an ENGINE structure */ +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e) +	{ +	return e->pkey_asn1_meths; +	} + +/* Sets the pkey_asn1_meth callback in an ENGINE structure */ +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f) +	{ +	e->pkey_asn1_meths = f; +	return 1; +	} + +/* Internal function to free up EVP_PKEY_ASN1_METHOD structures before an + * ENGINE is destroyed + */ + +void engine_pkey_asn1_meths_free(ENGINE *e) +	{ +	int i; +	EVP_PKEY_ASN1_METHOD *pkm; +	if (e->pkey_asn1_meths) +		{ +		const int *pknids; +		int npknids; +		npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0); +		for (i = 0; i < npknids; i++) +			{ +			if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i])) +				{ +				EVP_PKEY_asn1_free(pkm); +				} +			} +		} +	} + +/* Find a method based on a string. This does a linear search through + * all implemented algorithms. This is OK in practice because only + * a small number of algorithms are likely to be implemented in an engine + * and it is not used for speed critical operations. + */ + +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, +					const char *str, int len) +	{ +	int i, nidcount; +	const int *nids; +	EVP_PKEY_ASN1_METHOD *ameth; +	if (!e->pkey_asn1_meths) +		return NULL; +	if (len == -1) +		len = strlen(str); +	nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0); +	for (i = 0; i < nidcount; i++) +		{ +		e->pkey_asn1_meths(e, &ameth, NULL, nids[i]); +		if (((int)strlen(ameth->pem_str) == len) &&  +					!strncasecmp(ameth->pem_str, str, len)) +			return ameth; +		} +	return NULL; +	} + +typedef struct  +	{ +	ENGINE *e; +	const EVP_PKEY_ASN1_METHOD *ameth; +	const char *str; +	int len; +	} ENGINE_FIND_STR; + +static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg) +	{ +	ENGINE_FIND_STR *lk = arg; +	int i; +	if (lk->ameth) +		return; +	for (i = 0; i < sk_ENGINE_num(sk); i++) +		{ +		ENGINE *e = sk_ENGINE_value(sk, i); +		EVP_PKEY_ASN1_METHOD *ameth; +		e->pkey_asn1_meths(e, &ameth, NULL, nid); +		if (((int)strlen(ameth->pem_str) == lk->len) &&  +				!strncasecmp(ameth->pem_str, lk->str, lk->len)) +			{ +			lk->e = e; +			lk->ameth = ameth; +			return; +			} +		} +	} + +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, +					const char *str, int len) +	{ +	ENGINE_FIND_STR fstr; +	fstr.e = NULL; +	fstr.ameth = NULL; +	fstr.str = str; +	fstr.len = len; +	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); +	engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr); +	/* If found obtain a structural reference to engine */ +	if (fstr.e) +		{ +		fstr.e->struct_ref++; +		engine_ref_debug(fstr.e, 0, 1) +		} +	*pe = fstr.e; +	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); +	return fstr.ameth; +	} diff --git a/app/openssl/crypto/engine/tb_pkmeth.c b/app/openssl/crypto/engine/tb_pkmeth.c new file mode 100644 index 00000000..1cdb967f --- /dev/null +++ b/app/openssl/crypto/engine/tb_pkmeth.c @@ -0,0 +1,167 @@ +/* ==================================================================== + * Copyright (c) 2006 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). + * + */ + +#include "eng_int.h" +#include <openssl/evp.h> + +/* If this symbol is defined then ENGINE_get_pkey_meth_engine(), the function + * that is used by EVP to hook in pkey_meth code and cache defaults (etc), will + * display brief debugging summaries to stderr with the 'nid'. */ +/* #define ENGINE_PKEY_METH_DEBUG */ + +static ENGINE_TABLE *pkey_meth_table = NULL; + +void ENGINE_unregister_pkey_meths(ENGINE *e) +	{ +	engine_table_unregister(&pkey_meth_table, e); +	} + +static void engine_unregister_all_pkey_meths(void) +	{ +	engine_table_cleanup(&pkey_meth_table); +	} + +int ENGINE_register_pkey_meths(ENGINE *e) +	{ +	if(e->pkey_meths) +		{ +		const int *nids; +		int num_nids = e->pkey_meths(e, NULL, &nids, 0); +		if(num_nids > 0) +			return engine_table_register(&pkey_meth_table, +				engine_unregister_all_pkey_meths, e, nids, +					num_nids, 0); +		} +	return 1; +	} + +void ENGINE_register_all_pkey_meths() +	{ +	ENGINE *e; + +	for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e)) +		ENGINE_register_pkey_meths(e); +	} + +int ENGINE_set_default_pkey_meths(ENGINE *e) +	{ +	if(e->pkey_meths) +		{ +		const int *nids; +		int num_nids = e->pkey_meths(e, NULL, &nids, 0); +		if(num_nids > 0) +			return engine_table_register(&pkey_meth_table, +				engine_unregister_all_pkey_meths, e, nids, +					num_nids, 1); +		} +	return 1; +	} + +/* Exposed API function to get a functional reference from the implementation + * table (ie. try to get a functional reference from the tabled structural + * references) for a given pkey_meth 'nid' */ +ENGINE *ENGINE_get_pkey_meth_engine(int nid) +	{ +	return engine_table_select(&pkey_meth_table, nid); +	} + +/* Obtains a pkey_meth implementation from an ENGINE functional reference */ +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid) +	{ +	EVP_PKEY_METHOD *ret; +	ENGINE_PKEY_METHS_PTR fn = ENGINE_get_pkey_meths(e); +	if(!fn || !fn(e, &ret, NULL, nid)) +		{ +		ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_METH, +				ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD); +		return NULL; +		} +	return ret; +	} + +/* Gets the pkey_meth callback from an ENGINE structure */ +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e) +	{ +	return e->pkey_meths; +	} + +/* Sets the pkey_meth callback in an ENGINE structure */ +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f) +	{ +	e->pkey_meths = f; +	return 1; +	} + +/* Internal function to free up EVP_PKEY_METHOD structures before an + * ENGINE is destroyed + */ + +void engine_pkey_meths_free(ENGINE *e) +	{ +	int i; +	EVP_PKEY_METHOD *pkm; +	if (e->pkey_meths) +		{ +		const int *pknids; +		int npknids; +		npknids = e->pkey_meths(e, NULL, &pknids, 0); +		for (i = 0; i < npknids; i++) +			{ +			if (e->pkey_meths(e, &pkm, NULL, pknids[i])) +				{ +				EVP_PKEY_meth_free(pkm); +				} +			} +		} +	}  | 
