1/* tasn_new.c */
2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 2000.
4 */
5/* ====================================================================
6 * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in
17 *    the documentation and/or other materials provided with the
18 *    distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 *    software must display the following acknowledgment:
22 *    "This product includes software developed by the OpenSSL Project
23 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 *    endorse or promote products derived from this software without
27 *    prior written permission. For written permission, please contact
28 *    licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 *    nor may "OpenSSL" appear in their names without prior written
32 *    permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 *    acknowledgment:
36 *    "This product includes software developed by the OpenSSL Project
37 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com).  This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59
60#include <stddef.h>
61#include <openssl/asn1.h>
62#include <openssl/objects.h>
63#include <openssl/err.h>
64#include <openssl/asn1t.h>
65#include <string.h>
66
67static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
68static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
69static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
70void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
71
72ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
73{
74	ASN1_VALUE *ret = NULL;
75	if(ASN1_item_ex_new(&ret, it) > 0) return ret;
76	return NULL;
77}
78
79/* Allocate an ASN1 structure */
80
81int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
82{
83	return asn1_item_ex_combine_new(pval, it, 0);
84}
85
86static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
87{
88	const ASN1_TEMPLATE *tt = NULL;
89	const ASN1_COMPAT_FUNCS *cf;
90	const ASN1_EXTERN_FUNCS *ef;
91	const ASN1_AUX *aux = it->funcs;
92	ASN1_aux_cb *asn1_cb;
93	ASN1_VALUE **pseqval;
94	int i;
95	if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb;
96	else asn1_cb = 0;
97
98	if(!combine) *pval = NULL;
99
100#ifdef CRYPTO_MDEBUG
101	if(it->sname) CRYPTO_push_info(it->sname);
102#endif
103
104	switch(it->itype) {
105
106		case ASN1_ITYPE_EXTERN:
107		ef = it->funcs;
108		if(ef && ef->asn1_ex_new) {
109			if(!ef->asn1_ex_new(pval, it))
110				goto memerr;
111		}
112		break;
113
114		case ASN1_ITYPE_COMPAT:
115		cf = it->funcs;
116		if(cf && cf->asn1_new) {
117			*pval = cf->asn1_new();
118			if(!*pval) goto memerr;
119		}
120		break;
121
122		case ASN1_ITYPE_PRIMITIVE:
123		if(it->templates) {
124			if(!ASN1_template_new(pval, it->templates))
125				goto memerr;
126		} else {
127			if(!ASN1_primitive_new(pval, it))
128				goto memerr;
129		}
130		break;
131
132		case ASN1_ITYPE_MSTRING:
133		if(!ASN1_primitive_new(pval, it))
134				goto memerr;
135		break;
136
137		case ASN1_ITYPE_CHOICE:
138		if(asn1_cb) {
139			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
140			if(!i) goto auxerr;
141			if(i==2) {
142#ifdef CRYPTO_MDEBUG
143				if(it->sname) CRYPTO_pop_info();
144#endif
145				return 1;
146			}
147		}
148		if(!combine) {
149			*pval = OPENSSL_malloc(it->size);
150			if(!*pval) goto memerr;
151			memset(*pval, 0, it->size);
152		}
153		asn1_set_choice_selector(pval, -1, it);
154		if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
155				goto auxerr;
156		break;
157
158		case ASN1_ITYPE_SEQUENCE:
159		if(asn1_cb) {
160			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
161			if(!i) goto auxerr;
162			if(i==2) {
163#ifdef CRYPTO_MDEBUG
164				if(it->sname) CRYPTO_pop_info();
165#endif
166				return 1;
167			}
168		}
169		if(!combine) {
170			*pval = OPENSSL_malloc(it->size);
171			if(!*pval) goto memerr;
172			memset(*pval, 0, it->size);
173			asn1_do_lock(pval, 0, it);
174			asn1_enc_init(pval, it);
175		}
176		for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
177			pseqval = asn1_get_field_ptr(pval, tt);
178			if(!ASN1_template_new(pseqval, tt)) goto memerr;
179		}
180		if(asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
181				goto auxerr;
182		break;
183	}
184#ifdef CRYPTO_MDEBUG
185	if(it->sname) CRYPTO_pop_info();
186#endif
187	return 1;
188
189	memerr:
190	ASN1err(ASN1_F_ASN1_ITEM_NEW, ERR_R_MALLOC_FAILURE);
191#ifdef CRYPTO_MDEBUG
192	if(it->sname) CRYPTO_pop_info();
193#endif
194	return 0;
195
196	auxerr:
197	ASN1err(ASN1_F_ASN1_ITEM_NEW, ASN1_R_AUX_ERROR);
198	ASN1_item_ex_free(pval, it);
199#ifdef CRYPTO_MDEBUG
200	if(it->sname) CRYPTO_pop_info();
201#endif
202	return 0;
203
204}
205
206static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
207{
208	const ASN1_EXTERN_FUNCS *ef;
209
210	switch(it->itype) {
211
212		case ASN1_ITYPE_EXTERN:
213		ef = it->funcs;
214		if(ef && ef->asn1_ex_clear)
215			ef->asn1_ex_clear(pval, it);
216		else *pval = NULL;
217		break;
218
219
220		case ASN1_ITYPE_PRIMITIVE:
221		if(it->templates)
222			asn1_template_clear(pval, it->templates);
223		else
224			asn1_primitive_clear(pval, it);
225		break;
226
227		case ASN1_ITYPE_MSTRING:
228		asn1_primitive_clear(pval, it);
229		break;
230
231		case ASN1_ITYPE_COMPAT:
232		case ASN1_ITYPE_CHOICE:
233		case ASN1_ITYPE_SEQUENCE:
234		*pval = NULL;
235		break;
236	}
237}
238
239
240int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
241{
242	const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
243	int ret;
244	if(tt->flags & ASN1_TFLG_OPTIONAL) {
245		asn1_template_clear(pval, tt);
246		return 1;
247	}
248	/* If ANY DEFINED BY nothing to do */
249
250	if(tt->flags & ASN1_TFLG_ADB_MASK) {
251		*pval = NULL;
252		return 1;
253	}
254#ifdef CRYPTO_MDEBUG
255	if(tt->field_name) CRYPTO_push_info(tt->field_name);
256#endif
257	/* If SET OF or SEQUENCE OF, its a STACK */
258	if(tt->flags & ASN1_TFLG_SK_MASK) {
259		STACK_OF(ASN1_VALUE) *skval;
260		skval = sk_ASN1_VALUE_new_null();
261		if(!skval) {
262			ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
263			ret = 0;
264			goto done;
265		}
266		*pval = (ASN1_VALUE *)skval;
267		ret = 1;
268		goto done;
269	}
270	/* Otherwise pass it back to the item routine */
271	ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
272	done:
273#ifdef CRYPTO_MDEBUG
274	if(it->sname) CRYPTO_pop_info();
275#endif
276	return ret;
277}
278
279static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
280{
281	/* If ADB or STACK just NULL the field */
282	if(tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
283		*pval = NULL;
284	else
285		asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
286}
287
288
289/* NB: could probably combine most of the real XXX_new() behaviour and junk all the old
290 * functions.
291 */
292
293int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
294{
295	ASN1_TYPE *typ;
296	int utype;
297	const ASN1_PRIMITIVE_FUNCS *pf;
298	pf = it->funcs;
299	if(pf && pf->prim_new) return pf->prim_new(pval, it);
300	if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1;
301	else utype = it->utype;
302	switch(utype) {
303		case V_ASN1_OBJECT:
304		*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
305		return 1;
306
307		case V_ASN1_BOOLEAN:
308		if (it)
309			*(ASN1_BOOLEAN *)pval = it->size;
310		else
311			*(ASN1_BOOLEAN *)pval = -1;
312		return 1;
313
314		case V_ASN1_NULL:
315		*pval = (ASN1_VALUE *)1;
316		return 1;
317
318		case V_ASN1_ANY:
319		typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
320		if(!typ) return 0;
321		typ->value.ptr = NULL;
322		typ->type = -1;
323		*pval = (ASN1_VALUE *)typ;
324		break;
325
326		default:
327		*pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype);
328		break;
329	}
330	if(*pval) return 1;
331	return 0;
332}
333
334void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
335{
336	int utype;
337	const ASN1_PRIMITIVE_FUNCS *pf;
338	pf = it->funcs;
339	if(pf) {
340		if(pf->prim_clear)
341			pf->prim_clear(pval, it);
342		else
343			*pval = NULL;
344		return;
345	}
346	if(!it || (it->itype == ASN1_ITYPE_MSTRING)) utype = -1;
347	else utype = it->utype;
348	if(utype == V_ASN1_BOOLEAN)
349		*(ASN1_BOOLEAN *)pval = it->size;
350	else *pval = NULL;
351}
352