33a8e97442ec19684d7d030a28d2af41105f79c0
[openssl.git] / crypto / asn1 / tasn_new.c
1 /* tasn_new.c */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4  * 2000.
5  */
6 /* ====================================================================
7  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
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 #include "asn1_locl.h"
67
68 static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
69                                int embed);
70 static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
71                               int embed);
72 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
73 static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
74 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
75 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
76
77 ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
78 {
79     ASN1_VALUE *ret = NULL;
80     if (ASN1_item_ex_new(&ret, it) > 0)
81         return ret;
82     return NULL;
83 }
84
85 /* Allocate an ASN1 structure */
86
87 int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
88 {
89     return asn1_item_embed_new(pval, it, 0);
90 }
91
92 int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
93 {
94     const ASN1_TEMPLATE *tt = NULL;
95     const ASN1_EXTERN_FUNCS *ef;
96     const ASN1_AUX *aux = it->funcs;
97     ASN1_aux_cb *asn1_cb;
98     ASN1_VALUE **pseqval;
99     int i;
100     if (aux && aux->asn1_cb)
101         asn1_cb = aux->asn1_cb;
102     else
103         asn1_cb = 0;
104
105 #ifdef CRYPTO_MDEBUG
106     if (it->sname)
107         CRYPTO_push_info(it->sname);
108 #endif
109
110     switch (it->itype) {
111
112     case ASN1_ITYPE_EXTERN:
113         ef = it->funcs;
114         if (ef && ef->asn1_ex_new) {
115             if (!ef->asn1_ex_new(pval, it))
116                 goto memerr;
117         }
118         break;
119
120     case ASN1_ITYPE_PRIMITIVE:
121         if (it->templates) {
122             if (!asn1_template_new(pval, it->templates))
123                 goto memerr;
124         } else if (!asn1_primitive_new(pval, it, embed))
125             goto memerr;
126         break;
127
128     case ASN1_ITYPE_MSTRING:
129         if (!asn1_primitive_new(pval, it, embed))
130             goto memerr;
131         break;
132
133     case ASN1_ITYPE_CHOICE:
134         if (asn1_cb) {
135             i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
136             if (!i)
137                 goto auxerr;
138             if (i == 2) {
139 #ifdef CRYPTO_MDEBUG
140                 if (it->sname)
141                     CRYPTO_pop_info();
142 #endif
143                 return 1;
144             }
145         }
146         if (embed) {
147             memset(*pval, 0, it->size);
148         } else {
149             *pval = OPENSSL_zalloc(it->size);
150             if (!*pval)
151                 goto memerr;
152         }
153         asn1_set_choice_selector(pval, -1, it);
154         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
155             goto auxerr;
156         break;
157
158     case ASN1_ITYPE_NDEF_SEQUENCE:
159     case ASN1_ITYPE_SEQUENCE:
160         if (asn1_cb) {
161             i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
162             if (!i)
163                 goto auxerr;
164             if (i == 2) {
165 #ifdef CRYPTO_MDEBUG
166                 if (it->sname)
167                     CRYPTO_pop_info();
168 #endif
169                 return 1;
170             }
171         }
172         if (embed) {
173             memset(*pval, 0, it->size);
174         } else {
175             *pval = OPENSSL_zalloc(it->size);
176             if (!*pval)
177                 goto memerr;
178         }
179         asn1_do_lock(pval, 0, it);
180         asn1_enc_init(pval, it);
181         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
182             pseqval = asn1_get_field_ptr(pval, tt);
183             if (!asn1_template_new(pseqval, tt))
184                 goto memerr;
185         }
186         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
187             goto auxerr;
188         break;
189     }
190 #ifdef CRYPTO_MDEBUG
191     if (it->sname)
192         CRYPTO_pop_info();
193 #endif
194     return 1;
195
196  memerr:
197     ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
198 #ifdef CRYPTO_MDEBUG
199     if (it->sname)
200         CRYPTO_pop_info();
201 #endif
202     return 0;
203
204  auxerr:
205     ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
206     ASN1_item_ex_free(pval, it);
207 #ifdef CRYPTO_MDEBUG
208     if (it->sname)
209         CRYPTO_pop_info();
210 #endif
211     return 0;
212
213 }
214
215 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
216 {
217     const ASN1_EXTERN_FUNCS *ef;
218
219     switch (it->itype) {
220
221     case ASN1_ITYPE_EXTERN:
222         ef = it->funcs;
223         if (ef && ef->asn1_ex_clear)
224             ef->asn1_ex_clear(pval, it);
225         else
226             *pval = NULL;
227         break;
228
229     case ASN1_ITYPE_PRIMITIVE:
230         if (it->templates)
231             asn1_template_clear(pval, it->templates);
232         else
233             asn1_primitive_clear(pval, it);
234         break;
235
236     case ASN1_ITYPE_MSTRING:
237         asn1_primitive_clear(pval, it);
238         break;
239
240     case ASN1_ITYPE_CHOICE:
241     case ASN1_ITYPE_SEQUENCE:
242     case ASN1_ITYPE_NDEF_SEQUENCE:
243         *pval = NULL;
244         break;
245     }
246 }
247
248 static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
249 {
250     const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
251     int embed = tt->flags & ASN1_TFLG_EMBED;
252     ASN1_VALUE *tval;
253     int ret;
254     if (embed) {
255         tval = (ASN1_VALUE *)pval;
256         pval = &tval;
257     }
258     if (tt->flags & ASN1_TFLG_OPTIONAL) {
259         asn1_template_clear(pval, tt);
260         return 1;
261     }
262     /* If ANY DEFINED BY nothing to do */
263
264     if (tt->flags & ASN1_TFLG_ADB_MASK) {
265         *pval = NULL;
266         return 1;
267     }
268 #ifdef CRYPTO_MDEBUG
269     if (tt->field_name)
270         CRYPTO_push_info(tt->field_name);
271 #endif
272     /* If SET OF or SEQUENCE OF, its a STACK */
273     if (tt->flags & ASN1_TFLG_SK_MASK) {
274         STACK_OF(ASN1_VALUE) *skval;
275         skval = sk_ASN1_VALUE_new_null();
276         if (!skval) {
277             ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
278             ret = 0;
279             goto done;
280         }
281         *pval = (ASN1_VALUE *)skval;
282         ret = 1;
283         goto done;
284     }
285     /* Otherwise pass it back to the item routine */
286     ret = asn1_item_embed_new(pval, it, embed);
287  done:
288 #ifdef CRYPTO_MDEBUG
289     if (it->sname)
290         CRYPTO_pop_info();
291 #endif
292     return ret;
293 }
294
295 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
296 {
297     /* If ADB or STACK just NULL the field */
298     if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
299         *pval = NULL;
300     else
301         asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
302 }
303
304 /*
305  * NB: could probably combine most of the real XXX_new() behaviour and junk
306  * all the old functions.
307  */
308
309 static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
310                               int embed)
311 {
312     ASN1_TYPE *typ;
313     ASN1_STRING *str;
314     int utype;
315
316     if (!it)
317         return 0;
318
319     if (it->funcs) {
320         const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
321         if (pf->prim_new)
322             return pf->prim_new(pval, it);
323     }
324
325     if (it->itype == ASN1_ITYPE_MSTRING)
326         utype = -1;
327     else
328         utype = it->utype;
329     switch (utype) {
330     case V_ASN1_OBJECT:
331         *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
332         return 1;
333
334     case V_ASN1_BOOLEAN:
335         *(ASN1_BOOLEAN *)pval = it->size;
336         return 1;
337
338     case V_ASN1_NULL:
339         *pval = (ASN1_VALUE *)1;
340         return 1;
341
342     case V_ASN1_ANY:
343         typ = OPENSSL_malloc(sizeof(*typ));
344         if (!typ)
345             return 0;
346         typ->value.ptr = NULL;
347         typ->type = -1;
348         *pval = (ASN1_VALUE *)typ;
349         break;
350
351     default:
352         if (embed) {
353             str = *(ASN1_STRING **)pval;
354             memset(str, 0, sizeof(*str));
355             str->flags = ASN1_STRING_FLAG_EMBED;
356         } else {
357             str = ASN1_STRING_type_new(utype);
358             *pval = (ASN1_VALUE *)str;
359         }
360         if (it->itype == ASN1_ITYPE_MSTRING && str)
361             str->flags |= ASN1_STRING_FLAG_MSTRING;
362         break;
363     }
364     if (*pval)
365         return 1;
366     return 0;
367 }
368
369 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
370 {
371     int utype;
372     if (it && it->funcs) {
373         const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
374         if (pf->prim_clear)
375             pf->prim_clear(pval, it);
376         else
377             *pval = NULL;
378         return;
379     }
380     if (!it || (it->itype == ASN1_ITYPE_MSTRING))
381         utype = -1;
382     else
383         utype = it->utype;
384     if (utype == V_ASN1_BOOLEAN)
385         *(ASN1_BOOLEAN *)pval = it->size;
386     else
387         *pval = NULL;
388 }