| Index: openssl/crypto/asn1/ameth_lib.c | 
| =================================================================== | 
| --- openssl/crypto/asn1/ameth_lib.c	(revision 0) | 
| +++ openssl/crypto/asn1/ameth_lib.c	(revision 0) | 
| @@ -0,0 +1,450 @@ | 
| +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 
| + * project 2006. | 
| + */ | 
| +/* ==================================================================== | 
| + * 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 <stdio.h> | 
| +#include "cryptlib.h" | 
| +#include <openssl/asn1t.h> | 
| +#include <openssl/x509.h> | 
| +#ifndef OPENSSL_NO_ENGINE | 
| +#include <openssl/engine.h> | 
| +#endif | 
| +#include "asn1_locl.h" | 
| + | 
| +extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; | 
| +extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; | 
| +extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; | 
| +extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; | 
| +extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; | 
| + | 
| +/* Keep this sorted in type order !! */ | 
| +static const EVP_PKEY_ASN1_METHOD *standard_methods[] = | 
| +	{ | 
| +#ifndef OPENSSL_NO_RSA | 
| +	&rsa_asn1_meths[0], | 
| +	&rsa_asn1_meths[1], | 
| +#endif | 
| +#ifndef OPENSSL_NO_DH | 
| +	&dh_asn1_meth, | 
| +#endif | 
| +#ifndef OPENSSL_NO_DSA | 
| +	&dsa_asn1_meths[0], | 
| +	&dsa_asn1_meths[1], | 
| +	&dsa_asn1_meths[2], | 
| +	&dsa_asn1_meths[3], | 
| +	&dsa_asn1_meths[4], | 
| +#endif | 
| +#ifndef OPENSSL_NO_EC | 
| +	&eckey_asn1_meth, | 
| +#endif | 
| +	&hmac_asn1_meth | 
| +	}; | 
| + | 
| +typedef int sk_cmp_fn_type(const char * const *a, const char * const *b); | 
| +DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD) | 
| +static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL; | 
| + | 
| + | 
| + | 
| +#ifdef TEST | 
| +void main() | 
| +	{ | 
| +	int i; | 
| +	for (i = 0; | 
| +		i < sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *); | 
| +		i++) | 
| +		fprintf(stderr, "Number %d id=%d (%s)\n", i, | 
| +			standard_methods[i]->pkey_id, | 
| +			OBJ_nid2sn(standard_methods[i]->pkey_id)); | 
| +	} | 
| +#endif | 
| + | 
| +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, | 
| +			   const EVP_PKEY_ASN1_METHOD *, ameth); | 
| + | 
| +static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a, | 
| +		     const EVP_PKEY_ASN1_METHOD * const *b) | 
| +	{ | 
| +        return ((*a)->pkey_id - (*b)->pkey_id); | 
| +	} | 
| + | 
| +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, | 
| +			     const EVP_PKEY_ASN1_METHOD *, ameth); | 
| + | 
| +int EVP_PKEY_asn1_get_count(void) | 
| +	{ | 
| +	int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *); | 
| +	if (app_methods) | 
| +		num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); | 
| +	return num; | 
| +	} | 
| + | 
| +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx) | 
| +	{ | 
| +	int num = sizeof(standard_methods)/sizeof(EVP_PKEY_ASN1_METHOD *); | 
| +	if (idx < 0) | 
| +		return NULL; | 
| +	if (idx < num) | 
| +		return standard_methods[idx]; | 
| +	idx -= num; | 
| +	return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); | 
| +	} | 
| + | 
| +static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type) | 
| +	{ | 
| +	EVP_PKEY_ASN1_METHOD tmp; | 
| +	const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; | 
| +	tmp.pkey_id = type; | 
| +	if (app_methods) | 
| +		{ | 
| +		int idx; | 
| +		idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp); | 
| +		if (idx >= 0) | 
| +			return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); | 
| +		} | 
| +	ret = OBJ_bsearch_ameth(&t, standard_methods, | 
| +			  sizeof(standard_methods) | 
| +			  /sizeof(EVP_PKEY_ASN1_METHOD *)); | 
| +	if (!ret || !*ret) | 
| +		return NULL; | 
| +	return *ret; | 
| +	} | 
| + | 
| +/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL | 
| + * also search through engines and set *pe to a functional reference | 
| + * to the engine implementing 'type' or NULL if no engine implements | 
| + * it. | 
| + */ | 
| + | 
| +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type) | 
| +	{ | 
| +	const EVP_PKEY_ASN1_METHOD *t; | 
| + | 
| +	for (;;) | 
| +		{ | 
| +		t = pkey_asn1_find(type); | 
| +		if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS)) | 
| +			break; | 
| +		type = t->pkey_base_id; | 
| +		} | 
| +	if (pe) | 
| +		{ | 
| +#ifndef OPENSSL_NO_ENGINE | 
| +		ENGINE *e; | 
| +		/* type will contain the final unaliased type */ | 
| +		e = ENGINE_get_pkey_asn1_meth_engine(type); | 
| +		if (e) | 
| +			{ | 
| +			*pe = e; | 
| +			return ENGINE_get_pkey_asn1_meth(e, type); | 
| +			} | 
| +#endif | 
| +		*pe = NULL; | 
| +		} | 
| +	return t; | 
| +	} | 
| + | 
| +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, | 
| +					const char *str, int len) | 
| +	{ | 
| +	int i; | 
| +	const EVP_PKEY_ASN1_METHOD *ameth; | 
| +	if (len == -1) | 
| +		len = strlen(str); | 
| +	if (pe) | 
| +		{ | 
| +#ifndef OPENSSL_NO_ENGINE | 
| +		ENGINE *e; | 
| +		ameth = ENGINE_pkey_asn1_find_str(&e, str, len); | 
| +		if (ameth) | 
| +			{ | 
| +			/* Convert structural into | 
| +			 * functional reference | 
| +			 */ | 
| +			if (!ENGINE_init(e)) | 
| +				ameth = NULL; | 
| +			ENGINE_free(e); | 
| +			*pe = e; | 
| +			return ameth; | 
| +			} | 
| +#endif | 
| +		*pe = NULL; | 
| +		} | 
| +	for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) | 
| +		{ | 
| +		ameth = EVP_PKEY_asn1_get0(i); | 
| +		if (ameth->pkey_flags & ASN1_PKEY_ALIAS) | 
| +			continue; | 
| +		if (((int)strlen(ameth->pem_str) == len) && | 
| +			!strncasecmp(ameth->pem_str, str, len)) | 
| +			return ameth; | 
| +		} | 
| +	return NULL; | 
| +	} | 
| + | 
| +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth) | 
| +	{ | 
| +	if (app_methods == NULL) | 
| +		{ | 
| +		app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp); | 
| +		if (!app_methods) | 
| +			return 0; | 
| +		} | 
| +	if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth)) | 
| +		return 0; | 
| +	sk_EVP_PKEY_ASN1_METHOD_sort(app_methods); | 
| +	return 1; | 
| +	} | 
| + | 
| +int EVP_PKEY_asn1_add_alias(int to, int from) | 
| +	{ | 
| +	EVP_PKEY_ASN1_METHOD *ameth; | 
| +	ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL); | 
| +	if (!ameth) | 
| +		return 0; | 
| +	ameth->pkey_base_id = to; | 
| +	return EVP_PKEY_asn1_add0(ameth); | 
| +	} | 
| + | 
| +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags, | 
| +				const char **pinfo, const char **ppem_str, | 
| +					const EVP_PKEY_ASN1_METHOD *ameth) | 
| +	{ | 
| +	if (!ameth) | 
| +		return 0; | 
| +	if (ppkey_id) | 
| +		*ppkey_id = ameth->pkey_id; | 
| +	if (ppkey_base_id) | 
| +		*ppkey_base_id = ameth->pkey_base_id; | 
| +	if (ppkey_flags) | 
| +		*ppkey_flags = ameth->pkey_flags; | 
| +	if (pinfo) | 
| +		*pinfo = ameth->info; | 
| +	if (ppem_str) | 
| +		*ppem_str = ameth->pem_str; | 
| +	return 1; | 
| +	} | 
| + | 
| +const EVP_PKEY_ASN1_METHOD* EVP_PKEY_get0_asn1(EVP_PKEY *pkey) | 
| +	{ | 
| +	return pkey->ameth; | 
| +	} | 
| + | 
| +EVP_PKEY_ASN1_METHOD* EVP_PKEY_asn1_new(int id, int flags, | 
| +					const char *pem_str, const char *info) | 
| +	{ | 
| +	EVP_PKEY_ASN1_METHOD *ameth; | 
| +	ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD)); | 
| +	if (!ameth) | 
| +		return NULL; | 
| + | 
| +	ameth->pkey_id = id; | 
| +	ameth->pkey_base_id = id; | 
| +	ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC; | 
| + | 
| +	if (info) | 
| +		{ | 
| +		ameth->info = BUF_strdup(info); | 
| +		if (!ameth->info) | 
| +			goto err; | 
| +		} | 
| +	else | 
| +		ameth->info = NULL; | 
| + | 
| +	if (pem_str) | 
| +		{ | 
| +		ameth->pem_str = BUF_strdup(pem_str); | 
| +		if (!ameth->pem_str) | 
| +			goto err; | 
| +		} | 
| +	else | 
| +		ameth->pem_str = NULL; | 
| + | 
| +	ameth->pub_decode = 0; | 
| +	ameth->pub_encode = 0; | 
| +	ameth->pub_cmp = 0; | 
| +	ameth->pub_print = 0; | 
| + | 
| +	ameth->priv_decode = 0; | 
| +	ameth->priv_encode = 0; | 
| +	ameth->priv_print = 0; | 
| + | 
| +	ameth->old_priv_encode = 0; | 
| +	ameth->old_priv_decode = 0; | 
| + | 
| +	ameth->pkey_size = 0; | 
| +	ameth->pkey_bits = 0; | 
| + | 
| +	ameth->param_decode = 0; | 
| +	ameth->param_encode = 0; | 
| +	ameth->param_missing = 0; | 
| +	ameth->param_copy = 0; | 
| +	ameth->param_cmp = 0; | 
| +	ameth->param_print = 0; | 
| + | 
| +	ameth->pkey_free = 0; | 
| +	ameth->pkey_ctrl = 0; | 
| + | 
| +	return ameth; | 
| + | 
| +	err: | 
| + | 
| +	EVP_PKEY_asn1_free(ameth); | 
| +	return NULL; | 
| + | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, | 
| +			const EVP_PKEY_ASN1_METHOD *src) | 
| +	{ | 
| + | 
| +	dst->pub_decode = src->pub_decode; | 
| +	dst->pub_encode = src->pub_encode; | 
| +	dst->pub_cmp = src->pub_cmp; | 
| +	dst->pub_print = src->pub_print; | 
| + | 
| +	dst->priv_decode = src->priv_decode; | 
| +	dst->priv_encode = src->priv_encode; | 
| +	dst->priv_print = src->priv_print; | 
| + | 
| +	dst->old_priv_encode = src->old_priv_encode; | 
| +	dst->old_priv_decode = src->old_priv_decode; | 
| + | 
| +	dst->pkey_size = src->pkey_size; | 
| +	dst->pkey_bits = src->pkey_bits; | 
| + | 
| +	dst->param_decode = src->param_decode; | 
| +	dst->param_encode = src->param_encode; | 
| +	dst->param_missing = src->param_missing; | 
| +	dst->param_copy = src->param_copy; | 
| +	dst->param_cmp = src->param_cmp; | 
| +	dst->param_print = src->param_print; | 
| + | 
| +	dst->pkey_free = src->pkey_free; | 
| +	dst->pkey_ctrl = src->pkey_ctrl; | 
| + | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) | 
| +	{ | 
| +	if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) | 
| +		{ | 
| +		if (ameth->pem_str) | 
| +			OPENSSL_free(ameth->pem_str); | 
| +		if (ameth->info) | 
| +			OPENSSL_free(ameth->info); | 
| +		OPENSSL_free(ameth); | 
| +		} | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, | 
| +		int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub), | 
| +		int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk), | 
| +		int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), | 
| +		int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, | 
| +							ASN1_PCTX *pctx), | 
| +		int (*pkey_size)(const EVP_PKEY *pk), | 
| +		int (*pkey_bits)(const EVP_PKEY *pk)) | 
| +	{ | 
| +	ameth->pub_decode = pub_decode; | 
| +	ameth->pub_encode = pub_encode; | 
| +	ameth->pub_cmp = pub_cmp; | 
| +	ameth->pub_print = pub_print; | 
| +	ameth->pkey_size = pkey_size; | 
| +	ameth->pkey_bits = pkey_bits; | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, | 
| +		int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf), | 
| +		int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk), | 
| +		int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, | 
| +							ASN1_PCTX *pctx)) | 
| +	{ | 
| +	ameth->priv_decode = priv_decode; | 
| +	ameth->priv_encode = priv_encode; | 
| +	ameth->priv_print = priv_print; | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, | 
| +		int (*param_decode)(EVP_PKEY *pkey, | 
| +				const unsigned char **pder, int derlen), | 
| +		int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder), | 
| +		int (*param_missing)(const EVP_PKEY *pk), | 
| +		int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from), | 
| +		int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), | 
| +		int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, | 
| +							ASN1_PCTX *pctx)) | 
| +	{ | 
| +	ameth->param_decode = param_decode; | 
| +	ameth->param_encode = param_encode; | 
| +	ameth->param_missing = param_missing; | 
| +	ameth->param_copy = param_copy; | 
| +	ameth->param_cmp = param_cmp; | 
| +	ameth->param_print = param_print; | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, | 
| +		void (*pkey_free)(EVP_PKEY *pkey)) | 
| +	{ | 
| +	ameth->pkey_free = pkey_free; | 
| +	} | 
| + | 
| +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, | 
| +		int (*pkey_ctrl)(EVP_PKEY *pkey, int op, | 
| +							long arg1, void *arg2)) | 
| +	{ | 
| +	ameth->pkey_ctrl = pkey_ctrl; | 
| +	} | 
|  |