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