1 | /* |
2 | * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include <stddef.h> |
11 | #include <openssl/asn1.h> |
12 | #include <openssl/objects.h> |
13 | #include <openssl/err.h> |
14 | #include <openssl/asn1t.h> |
15 | #include <string.h> |
16 | #include "asn1_local.h" |
17 | |
18 | static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
19 | int embed); |
20 | static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
21 | int embed); |
22 | static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
23 | static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
24 | static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
25 | static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
26 | |
27 | ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) |
28 | { |
29 | ASN1_VALUE *ret = NULL; |
30 | if (ASN1_item_ex_new(&ret, it) > 0) |
31 | return ret; |
32 | return NULL; |
33 | } |
34 | |
35 | /* Allocate an ASN1 structure */ |
36 | |
37 | int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) |
38 | { |
39 | return asn1_item_embed_new(pval, it, 0); |
40 | } |
41 | |
42 | int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) |
43 | { |
44 | const ASN1_TEMPLATE *tt = NULL; |
45 | const ASN1_EXTERN_FUNCS *ef; |
46 | const ASN1_AUX *aux = it->funcs; |
47 | ASN1_aux_cb *asn1_cb; |
48 | ASN1_VALUE **pseqval; |
49 | int i; |
50 | if (aux && aux->asn1_cb) |
51 | asn1_cb = aux->asn1_cb; |
52 | else |
53 | asn1_cb = 0; |
54 | |
55 | switch (it->itype) { |
56 | |
57 | case ASN1_ITYPE_EXTERN: |
58 | ef = it->funcs; |
59 | if (ef && ef->asn1_ex_new) { |
60 | if (!ef->asn1_ex_new(pval, it)) |
61 | goto memerr; |
62 | } |
63 | break; |
64 | |
65 | case ASN1_ITYPE_PRIMITIVE: |
66 | if (it->templates) { |
67 | if (!asn1_template_new(pval, it->templates)) |
68 | goto memerr; |
69 | } else if (!asn1_primitive_new(pval, it, embed)) |
70 | goto memerr; |
71 | break; |
72 | |
73 | case ASN1_ITYPE_MSTRING: |
74 | if (!asn1_primitive_new(pval, it, embed)) |
75 | goto memerr; |
76 | break; |
77 | |
78 | case ASN1_ITYPE_CHOICE: |
79 | if (asn1_cb) { |
80 | i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); |
81 | if (!i) |
82 | goto auxerr; |
83 | if (i == 2) { |
84 | return 1; |
85 | } |
86 | } |
87 | if (embed) { |
88 | memset(*pval, 0, it->size); |
89 | } else { |
90 | *pval = OPENSSL_zalloc(it->size); |
91 | if (*pval == NULL) |
92 | goto memerr; |
93 | } |
94 | asn1_set_choice_selector(pval, -1, it); |
95 | if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) |
96 | goto auxerr2; |
97 | break; |
98 | |
99 | case ASN1_ITYPE_NDEF_SEQUENCE: |
100 | case ASN1_ITYPE_SEQUENCE: |
101 | if (asn1_cb) { |
102 | i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); |
103 | if (!i) |
104 | goto auxerr; |
105 | if (i == 2) { |
106 | return 1; |
107 | } |
108 | } |
109 | if (embed) { |
110 | memset(*pval, 0, it->size); |
111 | } else { |
112 | *pval = OPENSSL_zalloc(it->size); |
113 | if (*pval == NULL) |
114 | goto memerr; |
115 | } |
116 | /* 0 : init. lock */ |
117 | if (asn1_do_lock(pval, 0, it) < 0) { |
118 | if (!embed) { |
119 | OPENSSL_free(*pval); |
120 | *pval = NULL; |
121 | } |
122 | goto memerr; |
123 | } |
124 | asn1_enc_init(pval, it); |
125 | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
126 | pseqval = asn1_get_field_ptr(pval, tt); |
127 | if (!asn1_template_new(pseqval, tt)) |
128 | goto memerr2; |
129 | } |
130 | if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) |
131 | goto auxerr2; |
132 | break; |
133 | } |
134 | return 1; |
135 | |
136 | memerr2: |
137 | asn1_item_embed_free(pval, it, embed); |
138 | memerr: |
139 | ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE); |
140 | return 0; |
141 | |
142 | auxerr2: |
143 | asn1_item_embed_free(pval, it, embed); |
144 | auxerr: |
145 | ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR); |
146 | return 0; |
147 | |
148 | } |
149 | |
150 | static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) |
151 | { |
152 | const ASN1_EXTERN_FUNCS *ef; |
153 | |
154 | switch (it->itype) { |
155 | |
156 | case ASN1_ITYPE_EXTERN: |
157 | ef = it->funcs; |
158 | if (ef && ef->asn1_ex_clear) |
159 | ef->asn1_ex_clear(pval, it); |
160 | else |
161 | *pval = NULL; |
162 | break; |
163 | |
164 | case ASN1_ITYPE_PRIMITIVE: |
165 | if (it->templates) |
166 | asn1_template_clear(pval, it->templates); |
167 | else |
168 | asn1_primitive_clear(pval, it); |
169 | break; |
170 | |
171 | case ASN1_ITYPE_MSTRING: |
172 | asn1_primitive_clear(pval, it); |
173 | break; |
174 | |
175 | case ASN1_ITYPE_CHOICE: |
176 | case ASN1_ITYPE_SEQUENCE: |
177 | case ASN1_ITYPE_NDEF_SEQUENCE: |
178 | *pval = NULL; |
179 | break; |
180 | } |
181 | } |
182 | |
183 | static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) |
184 | { |
185 | const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); |
186 | int embed = tt->flags & ASN1_TFLG_EMBED; |
187 | ASN1_VALUE *tval; |
188 | int ret; |
189 | if (embed) { |
190 | tval = (ASN1_VALUE *)pval; |
191 | pval = &tval; |
192 | } |
193 | if (tt->flags & ASN1_TFLG_OPTIONAL) { |
194 | asn1_template_clear(pval, tt); |
195 | return 1; |
196 | } |
197 | /* If ANY DEFINED BY nothing to do */ |
198 | |
199 | if (tt->flags & ASN1_TFLG_ADB_MASK) { |
200 | *pval = NULL; |
201 | return 1; |
202 | } |
203 | /* If SET OF or SEQUENCE OF, its a STACK */ |
204 | if (tt->flags & ASN1_TFLG_SK_MASK) { |
205 | STACK_OF(ASN1_VALUE) *skval; |
206 | skval = sk_ASN1_VALUE_new_null(); |
207 | if (!skval) { |
208 | ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); |
209 | ret = 0; |
210 | goto done; |
211 | } |
212 | *pval = (ASN1_VALUE *)skval; |
213 | ret = 1; |
214 | goto done; |
215 | } |
216 | /* Otherwise pass it back to the item routine */ |
217 | ret = asn1_item_embed_new(pval, it, embed); |
218 | done: |
219 | return ret; |
220 | } |
221 | |
222 | static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) |
223 | { |
224 | /* If ADB or STACK just NULL the field */ |
225 | if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) |
226 | *pval = NULL; |
227 | else |
228 | asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); |
229 | } |
230 | |
231 | /* |
232 | * NB: could probably combine most of the real XXX_new() behaviour and junk |
233 | * all the old functions. |
234 | */ |
235 | |
236 | static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
237 | int embed) |
238 | { |
239 | ASN1_TYPE *typ; |
240 | ASN1_STRING *str; |
241 | int utype; |
242 | |
243 | if (!it) |
244 | return 0; |
245 | |
246 | if (it->funcs) { |
247 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; |
248 | if (embed) { |
249 | if (pf->prim_clear) { |
250 | pf->prim_clear(pval, it); |
251 | return 1; |
252 | } |
253 | } else if (pf->prim_new) { |
254 | return pf->prim_new(pval, it); |
255 | } |
256 | } |
257 | |
258 | if (it->itype == ASN1_ITYPE_MSTRING) |
259 | utype = -1; |
260 | else |
261 | utype = it->utype; |
262 | switch (utype) { |
263 | case V_ASN1_OBJECT: |
264 | *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); |
265 | return 1; |
266 | |
267 | case V_ASN1_BOOLEAN: |
268 | *(ASN1_BOOLEAN *)pval = it->size; |
269 | return 1; |
270 | |
271 | case V_ASN1_NULL: |
272 | *pval = (ASN1_VALUE *)1; |
273 | return 1; |
274 | |
275 | case V_ASN1_ANY: |
276 | if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) { |
277 | ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE); |
278 | return 0; |
279 | } |
280 | typ->value.ptr = NULL; |
281 | typ->type = -1; |
282 | *pval = (ASN1_VALUE *)typ; |
283 | break; |
284 | |
285 | default: |
286 | if (embed) { |
287 | str = *(ASN1_STRING **)pval; |
288 | memset(str, 0, sizeof(*str)); |
289 | str->type = utype; |
290 | str->flags = ASN1_STRING_FLAG_EMBED; |
291 | } else { |
292 | str = ASN1_STRING_type_new(utype); |
293 | *pval = (ASN1_VALUE *)str; |
294 | } |
295 | if (it->itype == ASN1_ITYPE_MSTRING && str) |
296 | str->flags |= ASN1_STRING_FLAG_MSTRING; |
297 | break; |
298 | } |
299 | if (*pval) |
300 | return 1; |
301 | return 0; |
302 | } |
303 | |
304 | static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) |
305 | { |
306 | int utype; |
307 | if (it && it->funcs) { |
308 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; |
309 | if (pf->prim_clear) |
310 | pf->prim_clear(pval, it); |
311 | else |
312 | *pval = NULL; |
313 | return; |
314 | } |
315 | if (!it || (it->itype == ASN1_ITYPE_MSTRING)) |
316 | utype = -1; |
317 | else |
318 | utype = it->utype; |
319 | if (utype == V_ASN1_BOOLEAN) |
320 | *(ASN1_BOOLEAN *)pval = it->size; |
321 | else |
322 | *pval = NULL; |
323 | } |
324 | |