]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
28428130 | 2 | * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. |
9d6b1ce6 | 3 | * |
365a2d99 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
2039c421 RS |
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 | |
9d6b1ce6 DSH |
8 | */ |
9 | ||
9d6b1ce6 DSH |
10 | #include <stddef.h> |
11 | #include <openssl/asn1.h> | |
12 | #include <openssl/objects.h> | |
13 | #include <openssl/err.h> | |
14 | #include <openssl/asn1t.h> | |
448361a8 | 15 | #include <string.h> |
706457b7 | 16 | #include "asn1_local.h" |
9d6b1ce6 | 17 | |
de17bd5d DSH |
18 | static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
19 | int embed); | |
47c9a1b5 DSH |
20 | static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
21 | int embed); | |
9d6b1ce6 | 22 | static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
c315a547 | 23 | static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
9d6b1ce6 | 24 | static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); |
b3e72fc3 | 25 | static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); |
9d6b1ce6 DSH |
26 | |
27 | ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) | |
0f113f3e MC |
28 | { |
29 | ASN1_VALUE *ret = NULL; | |
30 | if (ASN1_item_ex_new(&ret, it) > 0) | |
31 | return ret; | |
32 | return NULL; | |
33 | } | |
9d6b1ce6 DSH |
34 | |
35 | /* Allocate an ASN1 structure */ | |
36 | ||
37 | int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) | |
de17bd5d DSH |
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) | |
0f113f3e MC |
43 | { |
44 | const ASN1_TEMPLATE *tt = NULL; | |
0f113f3e MC |
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 | ||
0f113f3e MC |
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 | ||
0f113f3e MC |
65 | case ASN1_ITYPE_PRIMITIVE: |
66 | if (it->templates) { | |
c315a547 | 67 | if (!asn1_template_new(pval, it->templates)) |
0f113f3e | 68 | goto memerr; |
47c9a1b5 | 69 | } else if (!asn1_primitive_new(pval, it, embed)) |
0f113f3e MC |
70 | goto memerr; |
71 | break; | |
72 | ||
73 | case ASN1_ITYPE_MSTRING: | |
47c9a1b5 | 74 | if (!asn1_primitive_new(pval, it, embed)) |
0f113f3e MC |
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) { | |
0f113f3e MC |
84 | return 1; |
85 | } | |
86 | } | |
44c734e9 DSH |
87 | if (embed) { |
88 | memset(*pval, 0, it->size); | |
89 | } else { | |
90 | *pval = OPENSSL_zalloc(it->size); | |
90945fa3 | 91 | if (*pval == NULL) |
44c734e9 DSH |
92 | goto memerr; |
93 | } | |
0f113f3e MC |
94 | asn1_set_choice_selector(pval, -1, it); |
95 | if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) | |
83b4049a | 96 | goto auxerr2; |
0f113f3e MC |
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) { | |
0f113f3e MC |
106 | return 1; |
107 | } | |
108 | } | |
de17bd5d DSH |
109 | if (embed) { |
110 | memset(*pval, 0, it->size); | |
111 | } else { | |
112 | *pval = OPENSSL_zalloc(it->size); | |
90945fa3 | 113 | if (*pval == NULL) |
de17bd5d DSH |
114 | goto memerr; |
115 | } | |
687b4868 | 116 | /* 0 : init. lock */ |
fe6fcd31 RL |
117 | if (asn1_do_lock(pval, 0, it) < 0) { |
118 | if (!embed) { | |
119 | OPENSSL_free(*pval); | |
120 | *pval = NULL; | |
121 | } | |
122 | goto memerr; | |
123 | } | |
ee9d7637 | 124 | asn1_enc_init(pval, it); |
0f113f3e MC |
125 | for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { |
126 | pseqval = asn1_get_field_ptr(pval, tt); | |
c315a547 | 127 | if (!asn1_template_new(pseqval, tt)) |
83b4049a | 128 | goto memerr2; |
0f113f3e MC |
129 | } |
130 | if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) | |
83b4049a | 131 | goto auxerr2; |
0f113f3e MC |
132 | break; |
133 | } | |
0f113f3e | 134 | return 1; |
9d6b1ce6 | 135 | |
83b4049a | 136 | memerr2: |
03996c19 | 137 | asn1_item_embed_free(pval, it, embed); |
0f113f3e | 138 | memerr: |
de17bd5d | 139 | ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE); |
0f113f3e | 140 | return 0; |
9d6b1ce6 | 141 | |
83b4049a | 142 | auxerr2: |
03996c19 | 143 | asn1_item_embed_free(pval, it, embed); |
0f113f3e | 144 | auxerr: |
de17bd5d | 145 | ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR); |
0f113f3e | 146 | return 0; |
9d6b1ce6 | 147 | |
0f113f3e | 148 | } |
9d6b1ce6 DSH |
149 | |
150 | static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) | |
0f113f3e MC |
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 | ||
0f113f3e MC |
175 | case ASN1_ITYPE_CHOICE: |
176 | case ASN1_ITYPE_SEQUENCE: | |
177 | case ASN1_ITYPE_NDEF_SEQUENCE: | |
178 | *pval = NULL; | |
179 | break; | |
180 | } | |
181 | } | |
9d6b1ce6 | 182 | |
c315a547 | 183 | static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) |
0f113f3e MC |
184 | { |
185 | const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); | |
de17bd5d DSH |
186 | int embed = tt->flags & ASN1_TFLG_EMBED; |
187 | ASN1_VALUE *tval; | |
0f113f3e | 188 | int ret; |
de17bd5d DSH |
189 | if (embed) { |
190 | tval = (ASN1_VALUE *)pval; | |
191 | pval = &tval; | |
192 | } | |
0f113f3e MC |
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 | } | |
0f113f3e MC |
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 */ | |
de17bd5d | 217 | ret = asn1_item_embed_new(pval, it, embed); |
0f113f3e | 218 | done: |
0f113f3e MC |
219 | return ret; |
220 | } | |
9d6b1ce6 | 221 | |
866eedb9 | 222 | static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) |
0f113f3e MC |
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 | |
f3f52d7f | 233 | * all the old functions. |
9d6b1ce6 DSH |
234 | */ |
235 | ||
47c9a1b5 DSH |
236 | static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, |
237 | int embed) | |
0f113f3e MC |
238 | { |
239 | ASN1_TYPE *typ; | |
240 | ASN1_STRING *str; | |
241 | int utype; | |
242 | ||
9e488fd6 MC |
243 | if (!it) |
244 | return 0; | |
245 | ||
246 | if (it->funcs) { | |
0f113f3e | 247 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; |
49005bb8 RL |
248 | if (embed) { |
249 | if (pf->prim_clear) { | |
250 | pf->prim_clear(pval, it); | |
251 | return 1; | |
252 | } | |
253 | } else if (pf->prim_new) { | |
0f113f3e | 254 | return pf->prim_new(pval, it); |
49005bb8 | 255 | } |
0f113f3e MC |
256 | } |
257 | ||
9e488fd6 | 258 | if (it->itype == ASN1_ITYPE_MSTRING) |
0f113f3e MC |
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: | |
cdb10bae RS |
276 | if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) { |
277 | ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE); | |
0f113f3e | 278 | return 0; |
cdb10bae | 279 | } |
0f113f3e MC |
280 | typ->value.ptr = NULL; |
281 | typ->type = -1; | |
282 | *pval = (ASN1_VALUE *)typ; | |
283 | break; | |
284 | ||
285 | default: | |
47c9a1b5 DSH |
286 | if (embed) { |
287 | str = *(ASN1_STRING **)pval; | |
288 | memset(str, 0, sizeof(*str)); | |
7f3e6f8c | 289 | str->type = utype; |
47c9a1b5 DSH |
290 | str->flags = ASN1_STRING_FLAG_EMBED; |
291 | } else { | |
292 | str = ASN1_STRING_type_new(utype); | |
293 | *pval = (ASN1_VALUE *)str; | |
294 | } | |
0f113f3e MC |
295 | if (it->itype == ASN1_ITYPE_MSTRING && str) |
296 | str->flags |= ASN1_STRING_FLAG_MSTRING; | |
0f113f3e MC |
297 | break; |
298 | } | |
299 | if (*pval) | |
300 | return 1; | |
301 | return 0; | |
302 | } | |
9d6b1ce6 | 303 | |
b3e72fc3 | 304 | static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) |
0f113f3e MC |
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 | } |