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