1109998Smarkm/* tasn_new.c */
2296465Sdelphij/*
3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4296465Sdelphij * 2000.
5109998Smarkm */
6109998Smarkm/* ====================================================================
7160814Ssimon * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
8109998Smarkm *
9109998Smarkm * Redistribution and use in source and binary forms, with or without
10109998Smarkm * modification, are permitted provided that the following conditions
11109998Smarkm * are met:
12109998Smarkm *
13109998Smarkm * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
15109998Smarkm *
16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
17109998Smarkm *    notice, this list of conditions and the following disclaimer in
18109998Smarkm *    the documentation and/or other materials provided with the
19109998Smarkm *    distribution.
20109998Smarkm *
21109998Smarkm * 3. All advertising materials mentioning features or use of this
22109998Smarkm *    software must display the following acknowledgment:
23109998Smarkm *    "This product includes software developed by the OpenSSL Project
24109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25109998Smarkm *
26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27109998Smarkm *    endorse or promote products derived from this software without
28109998Smarkm *    prior written permission. For written permission, please contact
29109998Smarkm *    licensing@OpenSSL.org.
30109998Smarkm *
31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
32109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
33109998Smarkm *    permission of the OpenSSL Project.
34109998Smarkm *
35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
36109998Smarkm *    acknowledgment:
37109998Smarkm *    "This product includes software developed by the OpenSSL Project
38109998Smarkm *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39109998Smarkm *
40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
52109998Smarkm * ====================================================================
53109998Smarkm *
54109998Smarkm * This product includes cryptographic software written by Eric Young
55109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
56109998Smarkm * Hudson (tjh@cryptsoft.com).
57109998Smarkm *
58109998Smarkm */
59109998Smarkm
60109998Smarkm#include <stddef.h>
61109998Smarkm#include <openssl/asn1.h>
62109998Smarkm#include <openssl/objects.h>
63109998Smarkm#include <openssl/err.h>
64109998Smarkm#include <openssl/asn1t.h>
65109998Smarkm#include <string.h>
66109998Smarkm
67160814Ssimonstatic int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
68296465Sdelphij                                    int combine);
69109998Smarkmstatic void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
70109998Smarkmstatic void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
71109998Smarkmvoid asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
72109998Smarkm
73109998SmarkmASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
74296465Sdelphij{
75296465Sdelphij    ASN1_VALUE *ret = NULL;
76296465Sdelphij    if (ASN1_item_ex_new(&ret, it) > 0)
77296465Sdelphij        return ret;
78296465Sdelphij    return NULL;
79296465Sdelphij}
80109998Smarkm
81109998Smarkm/* Allocate an ASN1 structure */
82109998Smarkm
83109998Smarkmint ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
84296465Sdelphij{
85296465Sdelphij    return asn1_item_ex_combine_new(pval, it, 0);
86296465Sdelphij}
87109998Smarkm
88160814Ssimonstatic int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
89296465Sdelphij                                    int combine)
90296465Sdelphij{
91296465Sdelphij    const ASN1_TEMPLATE *tt = NULL;
92296465Sdelphij    const ASN1_COMPAT_FUNCS *cf;
93296465Sdelphij    const ASN1_EXTERN_FUNCS *ef;
94296465Sdelphij    const ASN1_AUX *aux = it->funcs;
95296465Sdelphij    ASN1_aux_cb *asn1_cb;
96296465Sdelphij    ASN1_VALUE **pseqval;
97296465Sdelphij    int i;
98296465Sdelphij    if (aux && aux->asn1_cb)
99296465Sdelphij        asn1_cb = aux->asn1_cb;
100296465Sdelphij    else
101296465Sdelphij        asn1_cb = 0;
102109998Smarkm
103109998Smarkm#ifdef CRYPTO_MDEBUG
104296465Sdelphij    if (it->sname)
105296465Sdelphij        CRYPTO_push_info(it->sname);
106109998Smarkm#endif
107109998Smarkm
108296465Sdelphij    switch (it->itype) {
109109998Smarkm
110296465Sdelphij    case ASN1_ITYPE_EXTERN:
111296465Sdelphij        ef = it->funcs;
112296465Sdelphij        if (ef && ef->asn1_ex_new) {
113296465Sdelphij            if (!ef->asn1_ex_new(pval, it))
114296465Sdelphij                goto memerr;
115296465Sdelphij        }
116296465Sdelphij        break;
117109998Smarkm
118296465Sdelphij    case ASN1_ITYPE_COMPAT:
119296465Sdelphij        cf = it->funcs;
120296465Sdelphij        if (cf && cf->asn1_new) {
121296465Sdelphij            *pval = cf->asn1_new();
122296465Sdelphij            if (!*pval)
123296465Sdelphij                goto memerr;
124296465Sdelphij        }
125296465Sdelphij        break;
126109998Smarkm
127296465Sdelphij    case ASN1_ITYPE_PRIMITIVE:
128296465Sdelphij        if (it->templates) {
129296465Sdelphij            if (!ASN1_template_new(pval, it->templates))
130296465Sdelphij                goto memerr;
131296465Sdelphij        } else if (!ASN1_primitive_new(pval, it))
132296465Sdelphij            goto memerr;
133296465Sdelphij        break;
134109998Smarkm
135296465Sdelphij    case ASN1_ITYPE_MSTRING:
136296465Sdelphij        if (!ASN1_primitive_new(pval, it))
137296465Sdelphij            goto memerr;
138296465Sdelphij        break;
139109998Smarkm
140296465Sdelphij    case ASN1_ITYPE_CHOICE:
141296465Sdelphij        if (asn1_cb) {
142296465Sdelphij            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
143296465Sdelphij            if (!i)
144296465Sdelphij                goto auxerr;
145296465Sdelphij            if (i == 2) {
146109998Smarkm#ifdef CRYPTO_MDEBUG
147296465Sdelphij                if (it->sname)
148296465Sdelphij                    CRYPTO_pop_info();
149109998Smarkm#endif
150296465Sdelphij                return 1;
151296465Sdelphij            }
152296465Sdelphij        }
153296465Sdelphij        if (!combine) {
154296465Sdelphij            *pval = OPENSSL_malloc(it->size);
155296465Sdelphij            if (!*pval)
156296465Sdelphij                goto memerr;
157296465Sdelphij            memset(*pval, 0, it->size);
158296465Sdelphij        }
159296465Sdelphij        asn1_set_choice_selector(pval, -1, it);
160296465Sdelphij        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
161296465Sdelphij            goto auxerr;
162296465Sdelphij        break;
163109998Smarkm
164296465Sdelphij    case ASN1_ITYPE_NDEF_SEQUENCE:
165296465Sdelphij    case ASN1_ITYPE_SEQUENCE:
166296465Sdelphij        if (asn1_cb) {
167296465Sdelphij            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it);
168296465Sdelphij            if (!i)
169296465Sdelphij                goto auxerr;
170296465Sdelphij            if (i == 2) {
171109998Smarkm#ifdef CRYPTO_MDEBUG
172296465Sdelphij                if (it->sname)
173296465Sdelphij                    CRYPTO_pop_info();
174109998Smarkm#endif
175296465Sdelphij                return 1;
176296465Sdelphij            }
177296465Sdelphij        }
178296465Sdelphij        if (!combine) {
179296465Sdelphij            *pval = OPENSSL_malloc(it->size);
180296465Sdelphij            if (!*pval)
181296465Sdelphij                goto memerr;
182296465Sdelphij            memset(*pval, 0, it->size);
183296465Sdelphij            asn1_do_lock(pval, 0, it);
184296465Sdelphij            asn1_enc_init(pval, it);
185296465Sdelphij        }
186296465Sdelphij        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
187296465Sdelphij            pseqval = asn1_get_field_ptr(pval, tt);
188296465Sdelphij            if (!ASN1_template_new(pseqval, tt))
189296465Sdelphij                goto memerr;
190296465Sdelphij        }
191296465Sdelphij        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it))
192296465Sdelphij            goto auxerr;
193296465Sdelphij        break;
194296465Sdelphij    }
195109998Smarkm#ifdef CRYPTO_MDEBUG
196296465Sdelphij    if (it->sname)
197296465Sdelphij        CRYPTO_pop_info();
198109998Smarkm#endif
199296465Sdelphij    return 1;
200109998Smarkm
201296465Sdelphij memerr:
202296465Sdelphij    ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE);
203109998Smarkm#ifdef CRYPTO_MDEBUG
204296465Sdelphij    if (it->sname)
205296465Sdelphij        CRYPTO_pop_info();
206109998Smarkm#endif
207296465Sdelphij    return 0;
208109998Smarkm
209296465Sdelphij auxerr:
210296465Sdelphij    ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR);
211296465Sdelphij    ASN1_item_ex_free(pval, it);
212109998Smarkm#ifdef CRYPTO_MDEBUG
213296465Sdelphij    if (it->sname)
214296465Sdelphij        CRYPTO_pop_info();
215109998Smarkm#endif
216296465Sdelphij    return 0;
217109998Smarkm
218296465Sdelphij}
219109998Smarkm
220109998Smarkmstatic void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
221296465Sdelphij{
222296465Sdelphij    const ASN1_EXTERN_FUNCS *ef;
223109998Smarkm
224296465Sdelphij    switch (it->itype) {
225109998Smarkm
226296465Sdelphij    case ASN1_ITYPE_EXTERN:
227296465Sdelphij        ef = it->funcs;
228296465Sdelphij        if (ef && ef->asn1_ex_clear)
229296465Sdelphij            ef->asn1_ex_clear(pval, it);
230296465Sdelphij        else
231296465Sdelphij            *pval = NULL;
232296465Sdelphij        break;
233109998Smarkm
234296465Sdelphij    case ASN1_ITYPE_PRIMITIVE:
235296465Sdelphij        if (it->templates)
236296465Sdelphij            asn1_template_clear(pval, it->templates);
237296465Sdelphij        else
238296465Sdelphij            asn1_primitive_clear(pval, it);
239296465Sdelphij        break;
240109998Smarkm
241296465Sdelphij    case ASN1_ITYPE_MSTRING:
242296465Sdelphij        asn1_primitive_clear(pval, it);
243296465Sdelphij        break;
244109998Smarkm
245296465Sdelphij    case ASN1_ITYPE_COMPAT:
246296465Sdelphij    case ASN1_ITYPE_CHOICE:
247296465Sdelphij    case ASN1_ITYPE_SEQUENCE:
248296465Sdelphij    case ASN1_ITYPE_NDEF_SEQUENCE:
249296465Sdelphij        *pval = NULL;
250296465Sdelphij        break;
251296465Sdelphij    }
252296465Sdelphij}
253109998Smarkm
254109998Smarkmint ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
255296465Sdelphij{
256296465Sdelphij    const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
257296465Sdelphij    int ret;
258296465Sdelphij    if (tt->flags & ASN1_TFLG_OPTIONAL) {
259296465Sdelphij        asn1_template_clear(pval, tt);
260296465Sdelphij        return 1;
261296465Sdelphij    }
262296465Sdelphij    /* If ANY DEFINED BY nothing to do */
263109998Smarkm
264296465Sdelphij    if (tt->flags & ASN1_TFLG_ADB_MASK) {
265296465Sdelphij        *pval = NULL;
266296465Sdelphij        return 1;
267296465Sdelphij    }
268109998Smarkm#ifdef CRYPTO_MDEBUG
269296465Sdelphij    if (tt->field_name)
270296465Sdelphij        CRYPTO_push_info(tt->field_name);
271109998Smarkm#endif
272296465Sdelphij    /* If SET OF or SEQUENCE OF, its a STACK */
273296465Sdelphij    if (tt->flags & ASN1_TFLG_SK_MASK) {
274296465Sdelphij        STACK_OF(ASN1_VALUE) *skval;
275296465Sdelphij        skval = sk_ASN1_VALUE_new_null();
276296465Sdelphij        if (!skval) {
277296465Sdelphij            ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
278296465Sdelphij            ret = 0;
279296465Sdelphij            goto done;
280296465Sdelphij        }
281296465Sdelphij        *pval = (ASN1_VALUE *)skval;
282296465Sdelphij        ret = 1;
283296465Sdelphij        goto done;
284296465Sdelphij    }
285296465Sdelphij    /* Otherwise pass it back to the item routine */
286296465Sdelphij    ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
287296465Sdelphij done:
288109998Smarkm#ifdef CRYPTO_MDEBUG
289296465Sdelphij    if (it->sname)
290296465Sdelphij        CRYPTO_pop_info();
291109998Smarkm#endif
292296465Sdelphij    return ret;
293296465Sdelphij}
294109998Smarkm
295109998Smarkmstatic void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
296296465Sdelphij{
297296465Sdelphij    /* If ADB or STACK just NULL the field */
298296465Sdelphij    if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
299296465Sdelphij        *pval = NULL;
300296465Sdelphij    else
301296465Sdelphij        asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
302296465Sdelphij}
303109998Smarkm
304296465Sdelphij/*
305296465Sdelphij * NB: could probably combine most of the real XXX_new() behaviour and junk
306160814Ssimon * all the old functions.
307109998Smarkm */
308109998Smarkm
309109998Smarkmint ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
310296465Sdelphij{
311296465Sdelphij    ASN1_TYPE *typ;
312296465Sdelphij    int utype;
313160814Ssimon
314296465Sdelphij    if (it && it->funcs) {
315296465Sdelphij        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
316296465Sdelphij        if (pf->prim_new)
317296465Sdelphij            return pf->prim_new(pval, it);
318296465Sdelphij    }
319160814Ssimon
320296465Sdelphij    if (!it || (it->itype == ASN1_ITYPE_MSTRING))
321296465Sdelphij        utype = -1;
322296465Sdelphij    else
323296465Sdelphij        utype = it->utype;
324296465Sdelphij    switch (utype) {
325296465Sdelphij    case V_ASN1_OBJECT:
326296465Sdelphij        *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
327296465Sdelphij        return 1;
328109998Smarkm
329296465Sdelphij    case V_ASN1_BOOLEAN:
330296465Sdelphij        if (it)
331296465Sdelphij            *(ASN1_BOOLEAN *)pval = it->size;
332296465Sdelphij        else
333296465Sdelphij            *(ASN1_BOOLEAN *)pval = -1;
334296465Sdelphij        return 1;
335109998Smarkm
336296465Sdelphij    case V_ASN1_NULL:
337296465Sdelphij        *pval = (ASN1_VALUE *)1;
338296465Sdelphij        return 1;
339109998Smarkm
340296465Sdelphij    case V_ASN1_ANY:
341296465Sdelphij        typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
342296465Sdelphij        if (!typ)
343296465Sdelphij            return 0;
344296465Sdelphij        typ->value.ptr = NULL;
345296465Sdelphij        typ->type = -1;
346296465Sdelphij        *pval = (ASN1_VALUE *)typ;
347296465Sdelphij        break;
348109998Smarkm
349296465Sdelphij    default:
350296465Sdelphij        *pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype);
351296465Sdelphij        break;
352296465Sdelphij    }
353296465Sdelphij    if (*pval)
354296465Sdelphij        return 1;
355296465Sdelphij    return 0;
356296465Sdelphij}
357109998Smarkm
358109998Smarkmvoid asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
359296465Sdelphij{
360296465Sdelphij    int utype;
361296465Sdelphij    if (it && it->funcs) {
362296465Sdelphij        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
363296465Sdelphij        if (pf->prim_clear)
364296465Sdelphij            pf->prim_clear(pval, it);
365296465Sdelphij        else
366296465Sdelphij            *pval = NULL;
367296465Sdelphij        return;
368296465Sdelphij    }
369296465Sdelphij    if (!it || (it->itype == ASN1_ITYPE_MSTRING))
370296465Sdelphij        utype = -1;
371296465Sdelphij    else
372296465Sdelphij        utype = it->utype;
373296465Sdelphij    if (utype == V_ASN1_BOOLEAN)
374296465Sdelphij        *(ASN1_BOOLEAN *)pval = it->size;
375296465Sdelphij    else
376296465Sdelphij        *pval = NULL;
377296465Sdelphij}
378