Home | History | Annotate | Download | only in engine
      1 /* ====================================================================
      2  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in
     13  *    the documentation and/or other materials provided with the
     14  *    distribution.
     15  *
     16  * 3. All advertising materials mentioning features or use of this
     17  *    software must display the following acknowledgment:
     18  *    "This product includes software developed by the OpenSSL Project
     19  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     20  *
     21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     22  *    endorse or promote products derived from this software without
     23  *    prior written permission. For written permission, please contact
     24  *    licensing (at) OpenSSL.org.
     25  *
     26  * 5. Products derived from this software may not be called "OpenSSL"
     27  *    nor may "OpenSSL" appear in their names without prior written
     28  *    permission of the OpenSSL Project.
     29  *
     30  * 6. Redistributions of any form whatsoever must retain the following
     31  *    acknowledgment:
     32  *    "This product includes software developed by the OpenSSL Project
     33  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     34  *
     35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     46  * OF THE POSSIBILITY OF SUCH DAMAGE.
     47  * ====================================================================
     48  *
     49  * This product includes cryptographic software written by Eric Young
     50  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     51  * Hudson (tjh (at) cryptsoft.com).
     52  *
     53  */
     54 
     55 #include "eng_int.h"
     56 #include "asn1_locl.h"
     57 #include <openssl/evp.h>
     58 
     59 /* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
     60  * function that is used by EVP to hook in pkey_asn1_meth code and cache
     61  * defaults (etc), will display brief debugging summaries to stderr with the
     62  * 'nid'. */
     63 /* #define ENGINE_PKEY_ASN1_METH_DEBUG */
     64 
     65 static ENGINE_TABLE *pkey_asn1_meth_table = NULL;
     66 
     67 void ENGINE_unregister_pkey_asn1_meths(ENGINE *e)
     68 	{
     69 	engine_table_unregister(&pkey_asn1_meth_table, e);
     70 	}
     71 
     72 static void engine_unregister_all_pkey_asn1_meths(void)
     73 	{
     74 	engine_table_cleanup(&pkey_asn1_meth_table);
     75 	}
     76 
     77 int ENGINE_register_pkey_asn1_meths(ENGINE *e)
     78 	{
     79 	if(e->pkey_asn1_meths)
     80 		{
     81 		const int *nids;
     82 		int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
     83 		if(num_nids > 0)
     84 			return engine_table_register(&pkey_asn1_meth_table,
     85 				engine_unregister_all_pkey_asn1_meths, e, nids,
     86 					num_nids, 0);
     87 		}
     88 	return 1;
     89 	}
     90 
     91 void ENGINE_register_all_pkey_asn1_meths(void)
     92 	{
     93 	ENGINE *e;
     94 
     95 	for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
     96 		ENGINE_register_pkey_asn1_meths(e);
     97 	}
     98 
     99 int ENGINE_set_default_pkey_asn1_meths(ENGINE *e)
    100 	{
    101 	if(e->pkey_asn1_meths)
    102 		{
    103 		const int *nids;
    104 		int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
    105 		if(num_nids > 0)
    106 			return engine_table_register(&pkey_asn1_meth_table,
    107 				engine_unregister_all_pkey_asn1_meths, e, nids,
    108 					num_nids, 1);
    109 		}
    110 	return 1;
    111 	}
    112 
    113 /* Exposed API function to get a functional reference from the implementation
    114  * table (ie. try to get a functional reference from the tabled structural
    115  * references) for a given pkey_asn1_meth 'nid' */
    116 ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid)
    117 	{
    118 	return engine_table_select(&pkey_asn1_meth_table, nid);
    119 	}
    120 
    121 /* Obtains a pkey_asn1_meth implementation from an ENGINE functional reference */
    122 const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
    123 	{
    124 	EVP_PKEY_ASN1_METHOD *ret;
    125 	ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);
    126 	if(!fn || !fn(e, &ret, NULL, nid))
    127 		{
    128 		ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH,
    129 				ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
    130 		return NULL;
    131 		}
    132 	return ret;
    133 	}
    134 
    135 /* Gets the pkey_asn1_meth callback from an ENGINE structure */
    136 ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e)
    137 	{
    138 	return e->pkey_asn1_meths;
    139 	}
    140 
    141 /* Sets the pkey_asn1_meth callback in an ENGINE structure */
    142 int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f)
    143 	{
    144 	e->pkey_asn1_meths = f;
    145 	return 1;
    146 	}
    147 
    148 /* Internal function to free up EVP_PKEY_ASN1_METHOD structures before an
    149  * ENGINE is destroyed
    150  */
    151 
    152 void engine_pkey_asn1_meths_free(ENGINE *e)
    153 	{
    154 	int i;
    155 	EVP_PKEY_ASN1_METHOD *pkm;
    156 	if (e->pkey_asn1_meths)
    157 		{
    158 		const int *pknids;
    159 		int npknids;
    160 		npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0);
    161 		for (i = 0; i < npknids; i++)
    162 			{
    163 			if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i]))
    164 				{
    165 				EVP_PKEY_asn1_free(pkm);
    166 				}
    167 			}
    168 		}
    169 	}
    170 
    171 /* Find a method based on a string. This does a linear search through
    172  * all implemented algorithms. This is OK in practice because only
    173  * a small number of algorithms are likely to be implemented in an engine
    174  * and it is not used for speed critical operations.
    175  */
    176 
    177 const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
    178 					const char *str, int len)
    179 	{
    180 	int i, nidcount;
    181 	const int *nids;
    182 	EVP_PKEY_ASN1_METHOD *ameth;
    183 	if (!e->pkey_asn1_meths)
    184 		return NULL;
    185 	if (len == -1)
    186 		len = strlen(str);
    187 	nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0);
    188 	for (i = 0; i < nidcount; i++)
    189 		{
    190 		e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
    191 		if (((int)strlen(ameth->pem_str) == len) &&
    192 					!strncasecmp(ameth->pem_str, str, len))
    193 			return ameth;
    194 		}
    195 	return NULL;
    196 	}
    197 
    198 typedef struct
    199 	{
    200 	ENGINE *e;
    201 	const EVP_PKEY_ASN1_METHOD *ameth;
    202 	const char *str;
    203 	int len;
    204 	} ENGINE_FIND_STR;
    205 
    206 static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
    207 	{
    208 	ENGINE_FIND_STR *lk = arg;
    209 	int i;
    210 	if (lk->ameth)
    211 		return;
    212 	for (i = 0; i < sk_ENGINE_num(sk); i++)
    213 		{
    214 		ENGINE *e = sk_ENGINE_value(sk, i);
    215 		EVP_PKEY_ASN1_METHOD *ameth;
    216 		e->pkey_asn1_meths(e, &ameth, NULL, nid);
    217 		if (((int)strlen(ameth->pem_str) == lk->len) &&
    218 				!strncasecmp(ameth->pem_str, lk->str, lk->len))
    219 			{
    220 			lk->e = e;
    221 			lk->ameth = ameth;
    222 			return;
    223 			}
    224 		}
    225 	}
    226 
    227 const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
    228 					const char *str, int len)
    229 	{
    230 	ENGINE_FIND_STR fstr;
    231 	fstr.e = NULL;
    232 	fstr.ameth = NULL;
    233 	fstr.str = str;
    234 	fstr.len = len;
    235 	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
    236 	engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
    237 	/* If found obtain a structural reference to engine */
    238 	if (fstr.e)
    239 		{
    240 		fstr.e->struct_ref++;
    241 		engine_ref_debug(fstr.e, 0, 1)
    242 		}
    243 	*pe = fstr.e;
    244 	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
    245 	return fstr.ameth;
    246 	}
    247