1/* $OpenBSD: tasn_new.c,v 1.25 2023/07/28 10:00:10 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2000.
4 */
5/* ====================================================================
6 * Copyright (c) 2000-2004 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
67#include "asn1_local.h"
68
69static int asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
70static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
71static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
72static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
73
74ASN1_VALUE *
75ASN1_item_new(const ASN1_ITEM *it)
76{
77	ASN1_VALUE *ret = NULL;
78	if (ASN1_item_ex_new(&ret, it) > 0)
79		return ret;
80	return NULL;
81}
82LCRYPTO_ALIAS(ASN1_item_new);
83
84/* Allocate an ASN1 structure */
85
86int
87ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
88{
89	return asn1_item_ex_new(pval, it);
90}
91LCRYPTO_ALIAS(ASN1_item_ex_new);
92
93static int
94asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
95{
96	const ASN1_TEMPLATE *tt = NULL;
97	const ASN1_EXTERN_FUNCS *ef;
98	const ASN1_AUX *aux = it->funcs;
99	ASN1_aux_cb *asn1_cb = NULL;
100	ASN1_VALUE **pseqval;
101	int i;
102
103	if (aux != NULL && aux->asn1_cb != NULL)
104		asn1_cb = aux->asn1_cb;
105
106	*pval = NULL;
107
108	switch (it->itype) {
109	case ASN1_ITYPE_EXTERN:
110		ef = it->funcs;
111		if (ef && ef->asn1_ex_new) {
112			if (!ef->asn1_ex_new(pval, it))
113				goto memerr;
114		}
115		break;
116
117	case ASN1_ITYPE_PRIMITIVE:
118		if (it->templates) {
119			if (!ASN1_template_new(pval, it->templates))
120				goto memerr;
121		} else if (!ASN1_primitive_new(pval, it))
122			goto memerr;
123		break;
124
125	case ASN1_ITYPE_MSTRING:
126		if (!ASN1_primitive_new(pval, it))
127			goto memerr;
128		break;
129
130	case ASN1_ITYPE_CHOICE:
131		if (asn1_cb) {
132			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
133			if (!i)
134				goto auxerr;
135			if (i == 2) {
136				return 1;
137			}
138		}
139		*pval = calloc(1, it->size);
140		if (!*pval)
141			goto memerr;
142		asn1_set_choice_selector(pval, -1, it);
143		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
144			goto auxerr;
145		break;
146
147	case ASN1_ITYPE_NDEF_SEQUENCE:
148	case ASN1_ITYPE_SEQUENCE:
149		if (asn1_cb) {
150			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
151			if (!i)
152				goto auxerr;
153			if (i == 2) {
154				return 1;
155			}
156		}
157		*pval = calloc(1, it->size);
158		if (!*pval)
159			goto memerr;
160		asn1_do_lock(pval, 0, it);
161		asn1_enc_init(pval, it);
162		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
163			pseqval = asn1_get_field_ptr(pval, tt);
164			if (!ASN1_template_new(pseqval, tt))
165				goto memerr;
166		}
167		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
168			goto auxerr;
169		break;
170	}
171	return 1;
172
173 memerr:
174	ASN1error(ERR_R_MALLOC_FAILURE);
175	return 0;
176
177 auxerr:
178	ASN1error(ASN1_R_AUX_ERROR);
179	ASN1_item_ex_free(pval, it);
180	return 0;
181
182}
183
184static void
185asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
186{
187	const ASN1_EXTERN_FUNCS *ef;
188
189	switch (it->itype) {
190	case ASN1_ITYPE_EXTERN:
191		ef = it->funcs;
192		if (ef && ef->asn1_ex_clear)
193			ef->asn1_ex_clear(pval, it);
194		else
195			*pval = NULL;
196		break;
197
198	case ASN1_ITYPE_PRIMITIVE:
199		if (it->templates)
200			asn1_template_clear(pval, it->templates);
201		else
202			asn1_primitive_clear(pval, it);
203		break;
204
205	case ASN1_ITYPE_MSTRING:
206		asn1_primitive_clear(pval, it);
207		break;
208
209	case ASN1_ITYPE_CHOICE:
210	case ASN1_ITYPE_SEQUENCE:
211	case ASN1_ITYPE_NDEF_SEQUENCE:
212		*pval = NULL;
213		break;
214	}
215}
216
217int
218ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
219{
220	const ASN1_ITEM *it = tt->item;
221	int ret;
222
223	if (tt->flags & ASN1_TFLG_OPTIONAL) {
224		asn1_template_clear(pval, tt);
225		return 1;
226	}
227	/* If ANY DEFINED BY nothing to do */
228
229	if (tt->flags & ASN1_TFLG_ADB_MASK) {
230		*pval = NULL;
231		return 1;
232	}
233	/* If SET OF or SEQUENCE OF, its a STACK */
234	if (tt->flags & ASN1_TFLG_SK_MASK) {
235		STACK_OF(ASN1_VALUE) *skval;
236		skval = sk_ASN1_VALUE_new_null();
237		if (!skval) {
238			ASN1error(ERR_R_MALLOC_FAILURE);
239			ret = 0;
240			goto done;
241		}
242		*pval = (ASN1_VALUE *)skval;
243		ret = 1;
244		goto done;
245	}
246	/* Otherwise pass it back to the item routine */
247	ret = asn1_item_ex_new(pval, it);
248 done:
249	return ret;
250}
251
252static void
253asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
254{
255	/* If ADB or STACK just NULL the field */
256	if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
257		*pval = NULL;
258	else
259		asn1_item_clear(pval, tt->item);
260}
261
262
263/* NB: could probably combine most of the real XXX_new() behaviour and junk
264 * all the old functions.
265 */
266
267int
268ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
269{
270	ASN1_TYPE *typ;
271	ASN1_STRING *str;
272	int utype;
273
274	if (it != NULL && it->funcs != NULL) {
275		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
276
277		if (pf->prim_new == NULL)
278			return 0;
279		return pf->prim_new(pval, it);
280	}
281
282	if (!it || (it->itype == ASN1_ITYPE_MSTRING))
283		utype = V_ASN1_UNDEF;
284	else
285		utype = it->utype;
286	switch (utype) {
287	case V_ASN1_OBJECT:
288		*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
289		return 1;
290
291	case V_ASN1_BOOLEAN:
292		*(ASN1_BOOLEAN *)pval = it->size;
293		return 1;
294
295	case V_ASN1_NULL:
296		*pval = (ASN1_VALUE *)1;
297		return 1;
298
299	case V_ASN1_ANY:
300		typ = malloc(sizeof(ASN1_TYPE));
301		if (typ != NULL) {
302			typ->value.ptr = NULL;
303			typ->type = V_ASN1_UNDEF;
304		}
305		*pval = (ASN1_VALUE *)typ;
306		break;
307
308	default:
309		str = ASN1_STRING_type_new(utype);
310		if (it != NULL && it->itype == ASN1_ITYPE_MSTRING &&
311		    str != NULL)
312			str->flags |= ASN1_STRING_FLAG_MSTRING;
313		*pval = (ASN1_VALUE *)str;
314		break;
315	}
316	if (*pval)
317		return 1;
318	return 0;
319}
320
321static void
322asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
323{
324	int utype;
325
326	if (it != NULL && it->funcs != NULL) {
327		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
328
329		if (pf->prim_clear)
330			pf->prim_clear(pval, it);
331		else
332			*pval = NULL;
333		return;
334	}
335
336	if (!it || (it->itype == ASN1_ITYPE_MSTRING))
337		utype = V_ASN1_UNDEF;
338	else
339		utype = it->utype;
340	if (utype == V_ASN1_BOOLEAN)
341		*(ASN1_BOOLEAN *)pval = it->size;
342	else
343		*pval = NULL;
344}
345