Home | History | Annotate | Download | only in asn1
      1 /* Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL
      2  * project 2006.
      3  */
      4 /* ====================================================================
      5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in
     16  *    the documentation and/or other materials provided with the
     17  *    distribution.
     18  *
     19  * 3. All advertising materials mentioning features or use of this
     20  *    software must display the following acknowledgment:
     21  *    "This product includes software developed by the OpenSSL Project
     22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     23  *
     24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     25  *    endorse or promote products derived from this software without
     26  *    prior written permission. For written permission, please contact
     27  *    licensing (at) OpenSSL.org.
     28  *
     29  * 5. Products derived from this software may not be called "OpenSSL"
     30  *    nor may "OpenSSL" appear in their names without prior written
     31  *    permission of the OpenSSL Project.
     32  *
     33  * 6. Redistributions of any form whatsoever must retain the following
     34  *    acknowledgment:
     35  *    "This product includes software developed by the OpenSSL Project
     36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     37  *
     38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     49  * OF THE POSSIBILITY OF SUCH DAMAGE.
     50  * ====================================================================
     51  *
     52  * This product includes cryptographic software written by Eric Young
     53  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     54  * Hudson (tjh (at) cryptsoft.com).
     55  *
     56  */
     57 
     58 #include <stdio.h>
     59 #include "cryptlib.h"
     60 #include <openssl/asn1t.h>
     61 #include <openssl/x509.h>
     62 #ifndef OPENSSL_NO_ENGINE
     63 #include <openssl/engine.h>
     64 #endif
     65 #include "asn1_locl.h"
     66 
     67 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
     68 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
     69 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
     70 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
     71 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
     72 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
     73 
     74 /* Keep this sorted in type order !! */
     75 static const EVP_PKEY_ASN1_METHOD *standard_methods[] =
     76 	{
     77 #ifndef OPENSSL_NO_RSA
     78 	&rsa_asn1_meths[0],
     79 	&rsa_asn1_meths[1],
     80 #endif
     81 #ifndef OPENSSL_NO_DH
     82 	&dh_asn1_meth,
     83 #endif
     84 #ifndef OPENSSL_NO_DSA
     85 	&dsa_asn1_meths[0],
     86 	&dsa_asn1_meths[1],
     87 	&dsa_asn1_meths[2],
     88 	&dsa_asn1_meths[3],
     89 	&dsa_asn1_meths[4],
     90 #endif
     91 #ifndef OPENSSL_NO_EC
     92 	&eckey_asn1_meth,
     93 #endif
     94 	&hmac_asn1_meth,
     95 	&cmac_asn1_meth
     96 	};
     97 
     98 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
     99 DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
    100 static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
    101 
    102 
    103 
    104 #ifdef TEST
    105 void main()
    106 	{
    107 	int i;
    108 	for (i = 0;
    109 		i < sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
    110 		i++)
    111 		fprintf(stderr, "Number %d id=%d (%s)\n", i,
    112 			standard_methods[i]->pkey_id,
    113 			OBJ_nid2sn(standard_methods[i]->pkey_id));
    114 	}
    115 #endif
    116 
    117 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
    118 			   const EVP_PKEY_ASN1_METHOD *, ameth);
    119 
    120 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
    121 		     const EVP_PKEY_ASN1_METHOD * const *b)
    122 	{
    123         return ((*a)->pkey_id - (*b)->pkey_id);
    124 	}
    125 
    126 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
    127 			     const EVP_PKEY_ASN1_METHOD *, ameth);
    128 
    129 int EVP_PKEY_asn1_get_count(void)
    130 	{
    131 	int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
    132 	if (app_methods)
    133 		num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
    134 	return num;
    135 	}
    136 
    137 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
    138 	{
    139 	int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *);
    140 	if (idx < 0)
    141 		return NULL;
    142 	if (idx < num)
    143 		return standard_methods[idx];
    144 	idx -= num;
    145 	return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
    146 	}
    147 
    148 static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
    149 	{
    150 	EVP_PKEY_ASN1_METHOD tmp;
    151 	const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
    152 	tmp.pkey_id = type;
    153 	if (app_methods)
    154 		{
    155 		int idx;
    156 		idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
    157 		if (idx >= 0)
    158 			return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
    159 		}
    160 	ret = OBJ_bsearch_ameth(&t, standard_methods,
    161 			  sizeof(standard_methods)
    162 			  /sizeof(EVP_PKEY_ASN1_METHOD *));
    163 	if (!ret || !*ret)
    164 		return NULL;
    165 	return *ret;
    166 	}
    167 
    168 /* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
    169  * also search through engines and set *pe to a functional reference
    170  * to the engine implementing 'type' or NULL if no engine implements
    171  * it.
    172  */
    173 
    174 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
    175 	{
    176 	const EVP_PKEY_ASN1_METHOD *t;
    177 
    178 	for (;;)
    179 		{
    180 		t = pkey_asn1_find(type);
    181 		if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
    182 			break;
    183 		type = t->pkey_base_id;
    184 		}
    185 	if (pe)
    186 		{
    187 #ifndef OPENSSL_NO_ENGINE
    188 		ENGINE *e;
    189 		/* type will contain the final unaliased type */
    190 		e = ENGINE_get_pkey_asn1_meth_engine(type);
    191 		if (e)
    192 			{
    193 			*pe = e;
    194 			return ENGINE_get_pkey_asn1_meth(e, type);
    195 			}
    196 #endif
    197 		*pe = NULL;
    198 		}
    199 	return t;
    200 	}
    201 
    202 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
    203 					const char *str, int len)
    204 	{
    205 	int i;
    206 	const EVP_PKEY_ASN1_METHOD *ameth;
    207 	if (len == -1)
    208 		len = strlen(str);
    209 	if (pe)
    210 		{
    211 #ifndef OPENSSL_NO_ENGINE
    212 		ENGINE *e;
    213 		ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
    214 		if (ameth)
    215 			{
    216 			/* Convert structural into
    217 			 * functional reference
    218 			 */
    219 			if (!ENGINE_init(e))
    220 				ameth = NULL;
    221 			ENGINE_free(e);
    222 			*pe = e;
    223 			return ameth;
    224 			}
    225 #endif
    226 		*pe = NULL;
    227 		}
    228 	for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
    229 		{
    230 		ameth = EVP_PKEY_asn1_get0(i);
    231 		if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
    232 			continue;
    233 		if (((int)strlen(ameth->pem_str) == len) &&
    234 			!strncasecmp(ameth->pem_str, str, len))
    235 			return ameth;
    236 		}
    237 	return NULL;
    238 	}
    239 
    240 int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
    241 	{
    242 	if (app_methods == NULL)
    243 		{
    244 		app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
    245 		if (!app_methods)
    246 			return 0;
    247 		}
    248 	if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
    249 		return 0;
    250 	sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
    251 	return 1;
    252 	}
    253 
    254 int EVP_PKEY_asn1_add_alias(int to, int from)
    255 	{
    256 	EVP_PKEY_ASN1_METHOD *ameth;
    257 	ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
    258 	if (!ameth)
    259 		return 0;
    260 	ameth->pkey_base_id = to;
    261 	return EVP_PKEY_asn1_add0(ameth);
    262 	}
    263 
    264 int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
    265 				const char **pinfo, const char **ppem_str,
    266 					const EVP_PKEY_ASN1_METHOD *ameth)
    267 	{
    268 	if (!ameth)
    269 		return 0;
    270 	if (ppkey_id)
    271 		*ppkey_id = ameth->pkey_id;
    272 	if (ppkey_base_id)
    273 		*ppkey_base_id = ameth->pkey_base_id;
    274 	if (ppkey_flags)
    275 		*ppkey_flags = ameth->pkey_flags;
    276 	if (pinfo)
    277 		*pinfo = ameth->info;
    278 	if (ppem_str)
    279 		*ppem_str = ameth->pem_str;
    280 	return 1;
    281 	}
    282 
    283 const EVP_PKEY_ASN1_METHOD* EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
    284 	{
    285 	return pkey->ameth;
    286 	}
    287 
    288 EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags,
    289 					const char *pem_str, const char *info)
    290 	{
    291 	EVP_PKEY_ASN1_METHOD *ameth;
    292 	ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
    293 	if (!ameth)
    294 		return NULL;
    295 
    296 	memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
    297 
    298 	ameth->pkey_id = id;
    299 	ameth->pkey_base_id = id;
    300 	ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
    301 
    302 	if (info)
    303 		{
    304 		ameth->info = BUF_strdup(info);
    305 		if (!ameth->info)
    306 			goto err;
    307 		}
    308 	else
    309 		ameth->info = NULL;
    310 
    311 	if (pem_str)
    312 		{
    313 		ameth->pem_str = BUF_strdup(pem_str);
    314 		if (!ameth->pem_str)
    315 			goto err;
    316 		}
    317 	else
    318 		ameth->pem_str = NULL;
    319 
    320 	ameth->pub_decode = 0;
    321 	ameth->pub_encode = 0;
    322 	ameth->pub_cmp = 0;
    323 	ameth->pub_print = 0;
    324 
    325 	ameth->priv_decode = 0;
    326 	ameth->priv_encode = 0;
    327 	ameth->priv_print = 0;
    328 
    329 	ameth->old_priv_encode = 0;
    330 	ameth->old_priv_decode = 0;
    331 
    332 	ameth->item_verify = 0;
    333 	ameth->item_sign = 0;
    334 
    335 	ameth->pkey_size = 0;
    336 	ameth->pkey_bits = 0;
    337 
    338 	ameth->param_decode = 0;
    339 	ameth->param_encode = 0;
    340 	ameth->param_missing = 0;
    341 	ameth->param_copy = 0;
    342 	ameth->param_cmp = 0;
    343 	ameth->param_print = 0;
    344 
    345 	ameth->pkey_free = 0;
    346 	ameth->pkey_ctrl = 0;
    347 
    348 	return ameth;
    349 
    350 	err:
    351 
    352 	EVP_PKEY_asn1_free(ameth);
    353 	return NULL;
    354 
    355 	}
    356 
    357 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
    358 			const EVP_PKEY_ASN1_METHOD *src)
    359 	{
    360 
    361 	dst->pub_decode = src->pub_decode;
    362 	dst->pub_encode = src->pub_encode;
    363 	dst->pub_cmp = src->pub_cmp;
    364 	dst->pub_print = src->pub_print;
    365 
    366 	dst->priv_decode = src->priv_decode;
    367 	dst->priv_encode = src->priv_encode;
    368 	dst->priv_print = src->priv_print;
    369 
    370 	dst->old_priv_encode = src->old_priv_encode;
    371 	dst->old_priv_decode = src->old_priv_decode;
    372 
    373 	dst->pkey_size = src->pkey_size;
    374 	dst->pkey_bits = src->pkey_bits;
    375 
    376 	dst->param_decode = src->param_decode;
    377 	dst->param_encode = src->param_encode;
    378 	dst->param_missing = src->param_missing;
    379 	dst->param_copy = src->param_copy;
    380 	dst->param_cmp = src->param_cmp;
    381 	dst->param_print = src->param_print;
    382 
    383 	dst->pkey_free = src->pkey_free;
    384 	dst->pkey_ctrl = src->pkey_ctrl;
    385 
    386 	dst->item_sign = src->item_sign;
    387 	dst->item_verify = src->item_verify;
    388 
    389 	}
    390 
    391 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
    392 	{
    393 	if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC))
    394 		{
    395 		if (ameth->pem_str)
    396 			OPENSSL_free(ameth->pem_str);
    397 		if (ameth->info)
    398 			OPENSSL_free(ameth->info);
    399 		OPENSSL_free(ameth);
    400 		}
    401 	}
    402 
    403 void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
    404 		int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
    405 		int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
    406 		int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
    407 		int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
    408 							ASN1_PCTX *pctx),
    409 		int (*pkey_size)(const EVP_PKEY *pk),
    410 		int (*pkey_bits)(const EVP_PKEY *pk))
    411 	{
    412 	ameth->pub_decode = pub_decode;
    413 	ameth->pub_encode = pub_encode;
    414 	ameth->pub_cmp = pub_cmp;
    415 	ameth->pub_print = pub_print;
    416 	ameth->pkey_size = pkey_size;
    417 	ameth->pkey_bits = pkey_bits;
    418 	}
    419 
    420 void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
    421 		int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf),
    422 		int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
    423 		int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
    424 							ASN1_PCTX *pctx))
    425 	{
    426 	ameth->priv_decode = priv_decode;
    427 	ameth->priv_encode = priv_encode;
    428 	ameth->priv_print = priv_print;
    429 	}
    430 
    431 void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
    432 		int (*param_decode)(EVP_PKEY *pkey,
    433 				const unsigned char **pder, int derlen),
    434 		int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
    435 		int (*param_missing)(const EVP_PKEY *pk),
    436 		int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
    437 		int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
    438 		int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
    439 							ASN1_PCTX *pctx))
    440 	{
    441 	ameth->param_decode = param_decode;
    442 	ameth->param_encode = param_encode;
    443 	ameth->param_missing = param_missing;
    444 	ameth->param_copy = param_copy;
    445 	ameth->param_cmp = param_cmp;
    446 	ameth->param_print = param_print;
    447 	}
    448 
    449 void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
    450 		void (*pkey_free)(EVP_PKEY *pkey))
    451 	{
    452 	ameth->pkey_free = pkey_free;
    453 	}
    454 
    455 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
    456 		int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
    457 							long arg1, void *arg2))
    458 	{
    459 	ameth->pkey_ctrl = pkey_ctrl;
    460 	}
    461