⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eng_table.c

📁 openssl包含TLS
💻 C
字号:
/* ==================================================================== * Copyright (c) 2001 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 <openssl/evp.h>#include <openssl/engine.h>#include "eng_int.h"/* This is the type of item in the 'implementation' table. Each 'nid' hashes to * a (potentially NULL) ENGINE_PILE structure which contains a stack of ENGINE* * pointers. These pointers aren't references, because they're inserted and * removed during ENGINE creation and ENGINE destruction. They point to ENGINEs * that *exist* (ie. have a structural reference count greater than zero) rather * than ENGINEs that are *functional*. Each pointer in those stacks are to * ENGINEs that implements the algorithm corresponding to each 'nid'. *//* The type of the items in the table */typedef struct st_engine_pile	{	/* The 'nid' of the algorithm/mode this ENGINE_PILE structure represents	 * */	int nid;	/* A stack of ENGINE pointers for ENGINEs that support this	 * algorithm/mode. In the event that 'funct' is NULL, the first entry in	 * this stack that initialises will be set as 'funct' and assumed as the	 * default for operations of this type. */	STACK_OF(ENGINE) *sk;	/* The default ENGINE to perform this algorithm/mode. */	ENGINE *funct;	/* This value optimises engine_table_select(). If it is called it sets	 * this value to 1. Any changes to this ENGINE_PILE resets it to zero.	 * As such, no ENGINE_init() thrashing is done unless ENGINEs	 * continually register (and/or unregister). */	int uptodate;	} ENGINE_PILE;/* The type of the hash table of ENGINE_PILE structures such that each are * unique and keyed by the 'nid' value. */struct st_engine_table	{	LHASH piles;	}; /* ENGINE_TABLE *//* This value stores global options controlling behaviour of (mostly) the * engine_table_select() function. It's a bitmask of flag values of the form * ENGINE_TABLE_FLAG_*** (as defined in engine.h) and is controlled by the * ENGINE_[get|set]_table_flags() function. */static unsigned int table_flags = 0;/* API function manipulating 'table_flags' */unsigned int ENGINE_get_table_flags(void)	{	return table_flags;	}void ENGINE_set_table_flags(unsigned int flags)	{	table_flags = flags;	}/* Internal functions for the "piles" hash table */static unsigned long engine_pile_hash(const ENGINE_PILE *c)	{	return c->nid;	}static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)	{	return a->nid - b->nid;	}static IMPLEMENT_LHASH_HASH_FN(engine_pile_hash, const ENGINE_PILE *)static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *)static int int_table_check(ENGINE_TABLE **t, int create)	{	LHASH *lh;	if(*t)		return 1;	if(!create)		return 0;	if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash),			LHASH_COMP_FN(engine_pile_cmp))) == NULL)		return 0;	*t = (ENGINE_TABLE *)lh;	return 1;	}/* Privately exposed (via eng_int.h) functions for adding and/or removing * ENGINEs from the implementation table */int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,		ENGINE *e, const int *nids, int num_nids, int setdefault)	{	int ret = 0, added = 0;	ENGINE_PILE tmplate, *fnd;	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);	if(!(*table))		added = 1;	if(!int_table_check(table, 1))		goto end;	if(added)		/* The cleanup callback needs to be added */		engine_cleanup_add_first(cleanup);	while(num_nids--)		{		tmplate.nid = *nids;		fnd = lh_retrieve(&(*table)->piles, &tmplate);		if(!fnd)			{			fnd = OPENSSL_malloc(sizeof(ENGINE_PILE));			if(!fnd)				goto end;			fnd->uptodate = 1;			fnd->nid = *nids;			fnd->sk = sk_ENGINE_new_null();			if(!fnd->sk)				{				OPENSSL_free(fnd);				goto end;				}			fnd->funct= NULL;			lh_insert(&(*table)->piles, fnd);			}		/* A registration shouldn't add duplciate entries */		sk_ENGINE_delete_ptr(fnd->sk, e);		/* if 'setdefault', this ENGINE goes to the head of the list */		if(!sk_ENGINE_push(fnd->sk, e))			goto end;		/* "touch" this ENGINE_PILE */		fnd->uptodate = 0;		if(setdefault)			{			if(!engine_unlocked_init(e))				{				ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,						ENGINE_R_INIT_FAILED);				goto end;				}			if(fnd->funct)				engine_unlocked_finish(fnd->funct, 0);			fnd->funct = e;			}		nids++;		}	ret = 1;end:	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);	return ret;	}static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)	{	int n;	/* Iterate the 'c->sk' stack removing any occurance of 'e' */	while((n = sk_ENGINE_find(pile->sk, e)) >= 0)		{		sk_ENGINE_delete(pile->sk, n);		/* "touch" this ENGINE_CIPHER */		pile->uptodate = 0;		}	if(pile->funct == e)		{		engine_unlocked_finish(e, 0);		pile->funct = NULL;		}	}static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *)void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)	{	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);	if(int_table_check(table, 0))		lh_doall_arg(&(*table)->piles,			LHASH_DOALL_ARG_FN(int_unregister_cb), e);	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);	}static void int_cleanup_cb(ENGINE_PILE *p)	{	sk_ENGINE_free(p->sk);	if(p->funct)		engine_unlocked_finish(p->funct, 0);	OPENSSL_free(p);	}static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb,ENGINE_PILE *)void engine_table_cleanup(ENGINE_TABLE **table)	{	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);	if(*table)		{		lh_doall(&(*table)->piles, LHASH_DOALL_FN(int_cleanup_cb));		lh_free(&(*table)->piles);		*table = NULL;		}	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);	}/* 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 cipher 'nid' */#ifndef ENGINE_TABLE_DEBUGENGINE *engine_table_select(ENGINE_TABLE **table, int nid)#elseENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l)#endif	{	ENGINE *ret = NULL;	ENGINE_PILE tmplate, *fnd=NULL;	int initres, loop = 0;	/* If 'engine_ciphers' is NULL, then it's absolutely *sure* that no	 * ENGINEs have registered any implementations! */	if(!(*table))		{#ifdef ENGINE_TABLE_DEBUG		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "			"registered for anything!\n", f, l, nid);#endif		return NULL;		}	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);	/* Check again inside the lock otherwise we could race against cleanup	 * operations. But don't worry about a fprintf(stderr). */	if(!int_table_check(table, 0))		goto end;	tmplate.nid = nid;	fnd = lh_retrieve(&(*table)->piles, &tmplate);	if(!fnd)		goto end;	if(fnd->funct && engine_unlocked_init(fnd->funct))		{#ifdef ENGINE_TABLE_DEBUG		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "			"ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);#endif		ret = fnd->funct;		goto end;		}	if(fnd->uptodate)		{		ret = fnd->funct;		goto end;		}trynext:	ret = sk_ENGINE_value(fnd->sk, loop++);	if(!ret)		{#ifdef ENGINE_TABLE_DEBUG		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "				"registered implementations would initialise\n",				f, l, nid);#endif		goto end;		}#if 0	/* Don't need to get a reference if we hold the lock. If the locking has	 * to change in future, that would be different ... */	ret->struct_ref++; engine_ref_debug(ret, 0, 1)#endif	/* Try and initialise the ENGINE if it's already functional *or* if the	 * ENGINE_TABLE_FLAG_NOINIT flag is not set. */	if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))		initres = engine_unlocked_init(ret);	else		initres = 0;#if 0	/* Release the structural reference */	ret->struct_ref--; engine_ref_debug(ret, 0, -1);#endif	if(initres)		{		/* If we didn't have a default (functional reference) for this		 * 'nid' (or we had one but for whatever reason we're now		 * initialising a different one), use this opportunity to set		 * 'funct'. */		if((fnd->funct != ret) && engine_unlocked_init(ret))			{			/* If there was a previous default we release it. */			if(fnd->funct)				engine_unlocked_finish(fnd->funct, 0);			/* We got an extra functional reference for the			 * per-'nid' default */			fnd->funct = ret;#ifdef ENGINE_TABLE_DEBUG			fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "				"setting default to '%s'\n", f, l, nid, ret->id);#endif			}#ifdef ENGINE_TABLE_DEBUG		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "				"newly initialised '%s'\n", f, l, nid, ret->id);#endif		goto end;		}	goto trynext;end:	/* Whatever happened - we should "untouch" our uptodate file seeing as	 * we have tried our best to find a functional reference for 'nid'. If	 * it failed, it is unlikely to succeed again until some future	 * registrations (or unregistrations) have taken place that affect that	 * 'nid'. */	if(fnd)		fnd->uptodate = 1;#ifdef ENGINE_TABLE_DEBUG	if(ret)		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "				"ENGINE '%s'\n", f, l, nid, ret->id);	else		fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "				"'no matching ENGINE'\n", f, l, nid);#endif	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);	/* Whatever happened, any failed init()s are not failures in this	 * context, so clear our error state. */	ERR_clear_error();	return ret;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -