xref: /openbsd/lib/libcrypto/asn1/tasn_new.c (revision c9ae38aa)
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 
69 static int asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
70 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
71 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
72 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
73 
74 ASN1_VALUE *
ASN1_item_new(const ASN1_ITEM * it)75 ASN1_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 }
82 LCRYPTO_ALIAS(ASN1_item_new);
83 
84 /* Allocate an ASN1 structure */
85 
86 int
ASN1_item_ex_new(ASN1_VALUE ** pval,const ASN1_ITEM * it)87 ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
88 {
89 	return asn1_item_ex_new(pval, it);
90 }
91 LCRYPTO_ALIAS(ASN1_item_ex_new);
92 
93 static int
asn1_item_ex_new(ASN1_VALUE ** pval,const ASN1_ITEM * it)94 asn1_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 
184 static void
asn1_item_clear(ASN1_VALUE ** pval,const ASN1_ITEM * it)185 asn1_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 
217 int
ASN1_template_new(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt)218 ASN1_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 
252 static void
asn1_template_clear(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt)253 asn1_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 
267 int
ASN1_primitive_new(ASN1_VALUE ** pval,const ASN1_ITEM * it)268 ASN1_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 
321 static void
asn1_primitive_clear(ASN1_VALUE ** pval,const ASN1_ITEM * it)322 asn1_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