tasn_new.c revision 109998
1139826Simp/* tasn_new.c */
252904Sshin/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
352904Sshin * project 2000.
453541Sshin */
552904Sshin/* ====================================================================
652904Sshin * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
752904Sshin *
852904Sshin * Redistribution and use in source and binary forms, with or without
952904Sshin * modification, are permitted provided that the following conditions
1052904Sshin * are met:
1152904Sshin *
1252904Sshin * 1. Redistributions of source code must retain the above copyright
1352904Sshin *    notice, this list of conditions and the following disclaimer.
1452904Sshin *
1552904Sshin * 2. Redistributions in binary form must reproduce the above copyright
1653541Sshin *    notice, this list of conditions and the following disclaimer in
1752904Sshin *    the documentation and/or other materials provided with the
1852904Sshin *    distribution.
1952904Sshin *
2052904Sshin * 3. All advertising materials mentioning features or use of this
2152904Sshin *    software must display the following acknowledgment:
2252904Sshin *    "This product includes software developed by the OpenSSL Project
2352904Sshin *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2452904Sshin *
2552904Sshin * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2652904Sshin *    endorse or promote products derived from this software without
2752904Sshin *    prior written permission. For written permission, please contact
28174510Sobrien *    licensing@OpenSSL.org.
29174510Sobrien *
3052904Sshin * 5. Products derived from this software may not be called "OpenSSL"
3152904Sshin *    nor may "OpenSSL" appear in their names without prior written
32139826Simp *    permission of the OpenSSL Project.
3352904Sshin *
3452904Sshin * 6. Redistributions of any form whatsoever must retain the following
3552904Sshin *    acknowledgment:
3652904Sshin *    "This product includes software developed by the OpenSSL Project
3752904Sshin *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3852904Sshin *
3952904Sshin * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4052904Sshin * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4152904Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4252904Sshin * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4352904Sshin * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4452904Sshin * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4552904Sshin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4652904Sshin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4752904Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4852904Sshin * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4952904Sshin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5052904Sshin * OF THE POSSIBILITY OF SUCH DAMAGE.
5152904Sshin * ====================================================================
5252904Sshin *
5352904Sshin * This product includes cryptographic software written by Eric Young
5452904Sshin * (eay@cryptsoft.com).  This product includes software written by Tim
5552904Sshin * Hudson (tjh@cryptsoft.com).
5652904Sshin *
5752904Sshin */
5852904Sshin
5952904Sshin
6052904Sshin#include <stddef.h>
61174510Sobrien#include <openssl/asn1.h>
6252904Sshin#include <openssl/objects.h>
6352904Sshin#include <openssl/err.h>
6462587Sitojun#include <openssl/asn1t.h>
6578064Sume#include <string.h>
6657120Sshin
6757120Sshinstatic int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
6862587Sitojunstatic void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
6962587Sitojunstatic void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
7062587Sitojunvoid asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
7152904Sshin
7252904SshinASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
7378064Sume{
7478064Sume	ASN1_VALUE *ret = NULL;
7552904Sshin	if(ASN1_item_ex_new(&ret, it) > 0) return ret;
7662587Sitojun	return NULL;
77156865Ssuz}
7852904Sshin
7952904Sshin/* Allocate an ASN1 structure */
80157209Sdwmalone
81218909Sbrucecint ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
82157209Sdwmalone{
8352904Sshin	return asn1_item_ex_combine_new(pval, it, 0);
8497181Smike}
8552904Sshin
8652904Sshinstatic int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
8752904Sshin{
8852904Sshin	const ASN1_TEMPLATE *tt = NULL;
8952904Sshin	const ASN1_COMPAT_FUNCS *cf;
9097181Smike	const ASN1_EXTERN_FUNCS *ef;
9152904Sshin	const ASN1_AUX *aux = it->funcs;
9252904Sshin	ASN1_aux_cb *asn1_cb;
9352904Sshin	ASN1_VALUE **pseqval;
9452904Sshin	int i;
9552904Sshin	if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb;
9652904Sshin	else asn1_cb = 0;
9797181Smike
9897181Smike	if(!combine) *pval = NULL;
9997181Smike
10052904Sshin#ifdef CRYPTO_MDEBUG
10152904Sshin	if(it->sname) CRYPTO_push_info(it->sname);
10252904Sshin#endif
10362587Sitojun
10495023Ssuz	switch(it->itype) {
10562587Sitojun
10662587Sitojun		case ASN1_ITYPE_EXTERN:
10762587Sitojun		ef = it->funcs;
10852904Sshin		if(ef && ef->asn1_ex_new) {
10952904Sshin			if(!ef->asn1_ex_new(pval, it))
11062587Sitojun				goto memerr;
11152904Sshin		}
11252904Sshin		break;
11397181Smike
11497181Smike		case ASN1_ITYPE_COMPAT:
11597181Smike		cf = it->funcs;
11697181Smike		if(cf && cf->asn1_new) {
11752904Sshin			*pval = cf->asn1_new();
11852904Sshin			if(!*pval) goto memerr;
11997181Smike		}
12062587Sitojun		break;
12152904Sshin
12297181Smike		case ASN1_ITYPE_PRIMITIVE:
12352904Sshin		if(it->templates) {
124100503Sume			if(!ASN1_template_new(pval, it->templates))
12597181Smike				goto memerr;
12697181Smike		} else {
12797181Smike			if(!ASN1_primitive_new(pval, it))
12862587Sitojun				goto memerr;
12997181Smike		}
13052904Sshin		break;
13152904Sshin
13252904Sshin		case ASN1_ITYPE_MSTRING:
13352904Sshin		if(!ASN1_primitive_new(pval, it))
13452904Sshin				goto memerr;
13595023Ssuz		break;
13662587Sitojun
13762587Sitojun		case ASN1_ITYPE_CHOICE:
13852904Sshin		if(asn1_cb) {
13962587Sitojun			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
14052904Sshin			if(!i) goto auxerr;
14162587Sitojun			if(i==2) {
14252904Sshin#ifdef CRYPTO_MDEBUG
14362587Sitojun				if(it->sname) CRYPTO_pop_info();
14452904Sshin#endif
14552904Sshin				return 1;
14652904Sshin			}
14752904Sshin		}
14878064Sume		if(!combine) {
14978064Sume			*pval = OPENSSL_malloc(it->size);
15052904Sshin			if(!*pval) goto memerr;
15152904Sshin			memset(*pval, 0, it->size);
15252904Sshin		}
15352904Sshin		asn1_set_choice_selector(pval, -1, it);
15452904Sshin		if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
15552904Sshin				goto auxerr;
15652904Sshin		break;
15752904Sshin
15852904Sshin		case ASN1_ITYPE_SEQUENCE:
15952904Sshin		if(asn1_cb) {
16095023Ssuz			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
16197181Smike			if(!i) goto auxerr;
16262587Sitojun			if(i==2) {
16362587Sitojun#ifdef CRYPTO_MDEBUG
16462587Sitojun				if(it->sname) CRYPTO_pop_info();
16562587Sitojun#endif
16662587Sitojun				return 1;
16762587Sitojun			}
16862587Sitojun		}
16962587Sitojun		if(!combine) {
17097181Smike			*pval = OPENSSL_malloc(it->size);
17162587Sitojun			if(!*pval) goto memerr;
17262587Sitojun			memset(*pval, 0, it->size);
17362587Sitojun			asn1_do_lock(pval, 0, it);
17462587Sitojun			asn1_enc_init(pval, it);
17562587Sitojun		}
17662587Sitojun		for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
17762587Sitojun			pseqval = asn1_get_field_ptr(pval, tt);
17862587Sitojun			if(!ASN1_template_new(pseqval, tt)) goto memerr;
17952904Sshin		}
18052904Sshin		if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
18152904Sshin				goto auxerr;
18252904Sshin		break;
18352904Sshin	}
18452904Sshin#ifdef CRYPTO_MDEBUG
18597181Smike	if(it->sname) CRYPTO_pop_info();
18662587Sitojun#endif
18752904Sshin	return 1;
18852904Sshin
18962587Sitojun	memerr:
19052904Sshin	ASN1err(ASN1_F_ASN1_ITEM_NEW, ERR_R_MALLOC_FAILURE);
19152904Sshin#ifdef CRYPTO_MDEBUG
19262587Sitojun	if(it->sname) CRYPTO_pop_info();
19352904Sshin#endif
19452904Sshin	return 0;
195121315Sume
196121315Sume	auxerr:
197121315Sume	ASN1err(ASN1_F_ASN1_ITEM_NEW, ASN1_R_AUX_ERROR);
19862587Sitojun	ASN1_item_ex_free(pval, it);
19952904Sshin#ifdef CRYPTO_MDEBUG
20052904Sshin	if(it->sname) CRYPTO_pop_info();
20162587Sitojun#endif
20252904Sshin	return 0;
20352904Sshin
204191662Sbms}
205191662Sbms
206191662Sbmsstatic void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
20797181Smike{
20852904Sshin	const ASN1_EXTERN_FUNCS *ef;
20952904Sshin
21052904Sshin	switch(it->itype) {
21197181Smike
21252904Sshin		case ASN1_ITYPE_EXTERN:
21352904Sshin		ef = it->funcs;
21452904Sshin		if(ef && ef->asn1_ex_clear)
215191662Sbms			ef->asn1_ex_clear(pval, it);
21697181Smike		else *pval = NULL;
21752904Sshin		break;
21852904Sshin
21952904Sshin
22053877Sitojun		case ASN1_ITYPE_PRIMITIVE:
22153877Sitojun		if(it->templates)
22253877Sitojun			asn1_template_clear(pval, it->templates);
22352904Sshin		else
22453877Sitojun			asn1_primitive_clear(pval, it);
22562587Sitojun		break;
22662587Sitojun
22753877Sitojun		case ASN1_ITYPE_MSTRING:
22897181Smike		asn1_primitive_clear(pval, it);
22962587Sitojun		break;
23062587Sitojun
23153877Sitojun		case ASN1_ITYPE_COMPAT:
23297181Smike		case ASN1_ITYPE_CHOICE:
23352904Sshin		case ASN1_ITYPE_SEQUENCE:
23452904Sshin		*pval = NULL;
23552904Sshin		break;
23652904Sshin	}
23762587Sitojun}
23878064Sume
23978064Sume
24078064Sumeint ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
24178064Sume{
24252904Sshin	const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
24352904Sshin	int ret;
24452904Sshin	if(tt->flags & ASN1_TFLG_OPTIONAL) {
24552904Sshin		asn1_template_clear(pval, tt);
24662587Sitojun		return 1;
24778064Sume	}
24878064Sume	/* If ANY DEFINED BY nothing to do */
24978064Sume
25078064Sume	if(tt->flags & ASN1_TFLG_ADB_MASK) {
25152904Sshin		*pval = NULL;
25252904Sshin		return 1;
25352904Sshin	}
25452904Sshin#ifdef CRYPTO_MDEBUG
25562587Sitojun	if(tt->field_name) CRYPTO_push_info(tt->field_name);
25678064Sume#endif
25778064Sume	/* If SET OF or SEQUENCE OF, its a STACK */
25878064Sume	if(tt->flags & ASN1_TFLG_SK_MASK) {
25978064Sume		STACK_OF(ASN1_VALUE) *skval;
26078064Sume		skval = sk_ASN1_VALUE_new_null();
26152904Sshin		if(!skval) {
26252904Sshin			ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
26352904Sshin			ret = 0;
26452904Sshin			goto done;
26562587Sitojun		}
26678064Sume		*pval = (ASN1_VALUE *)skval;
26778064Sume		ret = 1;
26878064Sume		goto done;
26952904Sshin	}
27052904Sshin	/* Otherwise pass it back to the item routine */
27152904Sshin	ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
27252904Sshin	done:
27352904Sshin#ifdef CRYPTO_MDEBUG
27495023Ssuz	if(it->sname) CRYPTO_pop_info();
27562587Sitojun#endif
276121315Sume	return ret;
27762587Sitojun}
27862587Sitojun
27962587Sitojunstatic void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
28062587Sitojun{
28152904Sshin	/* If ADB or STACK just NULL the field */
28262587Sitojun	if(tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
283121315Sume		*pval = NULL;
28462587Sitojun	else
28562587Sitojun		asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
28662587Sitojun}
28762587Sitojun
28852904Sshin
28952904Sshin/* NB: could probably combine most of the real XXX_new() behaviour and junk all the old
29052904Sshin * functions.
29152904Sshin */
29252904Sshin
29352904Sshinint ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
29462587Sitojun{
29552904Sshin	ASN1_TYPE *typ;
29662587Sitojun	int utype;
29752904Sshin	const ASN1_PRIMITIVE_FUNCS *pf;
29852904Sshin	pf = it->funcs;
29952904Sshin	if(pf && pf->prim_new) return pf->prim_new(pval, it);
30052904Sshin	if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1;
30152904Sshin	else utype = it->utype;
30252904Sshin	switch(utype) {
30352904Sshin		case V_ASN1_OBJECT:
30495023Ssuz		*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
30562587Sitojun		return 1;
30652904Sshin
30762587Sitojun		case V_ASN1_BOOLEAN:
30852904Sshin		if (it)
30952904Sshin			*(ASN1_BOOLEAN *)pval = it->size;
31052904Sshin		else
31152904Sshin			*(ASN1_BOOLEAN *)pval = -1;
31252904Sshin		return 1;
31395023Ssuz
31462587Sitojun		case V_ASN1_NULL:
31552904Sshin		*pval = (ASN1_VALUE *)1;
31652904Sshin		return 1;
317121315Sume
318121315Sume		case V_ASN1_ANY:
319121315Sume		typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
32062587Sitojun		if(!typ) return 0;
32152904Sshin		typ->value.ptr = NULL;
32252904Sshin		typ->type = -1;
32362587Sitojun		*pval = (ASN1_VALUE *)typ;
324171260Sdelphij		break;
32552904Sshin
32662587Sitojun		default:
32752904Sshin		*pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype);
32852904Sshin		break;
32962587Sitojun	}
33052904Sshin	if(*pval) return 1;
33152904Sshin	return 0;
33252904Sshin}
33362587Sitojun
33452904Sshinvoid asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
33552904Sshin{
33662587Sitojun	int utype;
33752904Sshin	const ASN1_PRIMITIVE_FUNCS *pf;
33852904Sshin	pf = it->funcs;
33962587Sitojun	if(pf) {
340171260Sdelphij		if(pf->prim_clear)
34152904Sshin			pf->prim_clear(pval, it);
34262587Sitojun		else
34352904Sshin			*pval = NULL;
34452904Sshin		return;
34562587Sitojun	}
34652904Sshin	if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1;
34752904Sshin	else utype = it->utype;
34852904Sshin	if(utype == V_ASN1_BOOLEAN)
34952904Sshin		*(ASN1_BOOLEAN *)pval = it->size;
35095023Ssuz	else *pval = NULL;
35178064Sume}
35252904Sshin