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/asn1t.h>
13e1051a39Sopenharmony_ci#include <openssl/objects.h>
14e1051a39Sopenharmony_ci#include "asn1_local.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci/* Free up an ASN1 structure */
17e1051a39Sopenharmony_ci
18e1051a39Sopenharmony_civoid ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
19e1051a39Sopenharmony_ci{
20e1051a39Sopenharmony_ci    ossl_asn1_item_embed_free(&val, it, 0);
21e1051a39Sopenharmony_ci}
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_civoid ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
24e1051a39Sopenharmony_ci{
25e1051a39Sopenharmony_ci    ossl_asn1_item_embed_free(pval, it, 0);
26e1051a39Sopenharmony_ci}
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_civoid ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
29e1051a39Sopenharmony_ci{
30e1051a39Sopenharmony_ci    const ASN1_TEMPLATE *tt = NULL, *seqtt;
31e1051a39Sopenharmony_ci    const ASN1_EXTERN_FUNCS *ef;
32e1051a39Sopenharmony_ci    const ASN1_AUX *aux = it->funcs;
33e1051a39Sopenharmony_ci    ASN1_aux_cb *asn1_cb;
34e1051a39Sopenharmony_ci    int i;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    if (pval == NULL)
37e1051a39Sopenharmony_ci        return;
38e1051a39Sopenharmony_ci    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
39e1051a39Sopenharmony_ci        return;
40e1051a39Sopenharmony_ci    if (aux && aux->asn1_cb)
41e1051a39Sopenharmony_ci        asn1_cb = aux->asn1_cb;
42e1051a39Sopenharmony_ci    else
43e1051a39Sopenharmony_ci        asn1_cb = 0;
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci    switch (it->itype) {
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ci    case ASN1_ITYPE_PRIMITIVE:
48e1051a39Sopenharmony_ci        if (it->templates)
49e1051a39Sopenharmony_ci            ossl_asn1_template_free(pval, it->templates);
50e1051a39Sopenharmony_ci        else
51e1051a39Sopenharmony_ci            ossl_asn1_primitive_free(pval, it, embed);
52e1051a39Sopenharmony_ci        break;
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_ci    case ASN1_ITYPE_MSTRING:
55e1051a39Sopenharmony_ci        ossl_asn1_primitive_free(pval, it, embed);
56e1051a39Sopenharmony_ci        break;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci    case ASN1_ITYPE_CHOICE:
59e1051a39Sopenharmony_ci        if (asn1_cb) {
60e1051a39Sopenharmony_ci            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
61e1051a39Sopenharmony_ci            if (i == 2)
62e1051a39Sopenharmony_ci                return;
63e1051a39Sopenharmony_ci        }
64e1051a39Sopenharmony_ci        i = ossl_asn1_get_choice_selector(pval, it);
65e1051a39Sopenharmony_ci        if ((i >= 0) && (i < it->tcount)) {
66e1051a39Sopenharmony_ci            ASN1_VALUE **pchval;
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci            tt = it->templates + i;
69e1051a39Sopenharmony_ci            pchval = ossl_asn1_get_field_ptr(pval, tt);
70e1051a39Sopenharmony_ci            ossl_asn1_template_free(pchval, tt);
71e1051a39Sopenharmony_ci        }
72e1051a39Sopenharmony_ci        if (asn1_cb)
73e1051a39Sopenharmony_ci            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
74e1051a39Sopenharmony_ci        if (embed == 0) {
75e1051a39Sopenharmony_ci            OPENSSL_free(*pval);
76e1051a39Sopenharmony_ci            *pval = NULL;
77e1051a39Sopenharmony_ci        }
78e1051a39Sopenharmony_ci        break;
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci    case ASN1_ITYPE_EXTERN:
81e1051a39Sopenharmony_ci        ef = it->funcs;
82e1051a39Sopenharmony_ci        if (ef && ef->asn1_ex_free)
83e1051a39Sopenharmony_ci            ef->asn1_ex_free(pval, it);
84e1051a39Sopenharmony_ci        break;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    case ASN1_ITYPE_NDEF_SEQUENCE:
87e1051a39Sopenharmony_ci    case ASN1_ITYPE_SEQUENCE:
88e1051a39Sopenharmony_ci        if (ossl_asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
89e1051a39Sopenharmony_ci            return;
90e1051a39Sopenharmony_ci        if (asn1_cb) {
91e1051a39Sopenharmony_ci            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
92e1051a39Sopenharmony_ci            if (i == 2)
93e1051a39Sopenharmony_ci                return;
94e1051a39Sopenharmony_ci        }
95e1051a39Sopenharmony_ci        ossl_asn1_enc_free(pval, it);
96e1051a39Sopenharmony_ci        /*
97e1051a39Sopenharmony_ci         * If we free up as normal we will invalidate any ANY DEFINED BY
98e1051a39Sopenharmony_ci         * field and we won't be able to determine the type of the field it
99e1051a39Sopenharmony_ci         * defines. So free up in reverse order.
100e1051a39Sopenharmony_ci         */
101e1051a39Sopenharmony_ci        tt = it->templates + it->tcount;
102e1051a39Sopenharmony_ci        for (i = 0; i < it->tcount; i++) {
103e1051a39Sopenharmony_ci            ASN1_VALUE **pseqval;
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci            tt--;
106e1051a39Sopenharmony_ci            seqtt = ossl_asn1_do_adb(*pval, tt, 0);
107e1051a39Sopenharmony_ci            if (!seqtt)
108e1051a39Sopenharmony_ci                continue;
109e1051a39Sopenharmony_ci            pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
110e1051a39Sopenharmony_ci            ossl_asn1_template_free(pseqval, seqtt);
111e1051a39Sopenharmony_ci        }
112e1051a39Sopenharmony_ci        if (asn1_cb)
113e1051a39Sopenharmony_ci            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
114e1051a39Sopenharmony_ci        if (embed == 0) {
115e1051a39Sopenharmony_ci            OPENSSL_free(*pval);
116e1051a39Sopenharmony_ci            *pval = NULL;
117e1051a39Sopenharmony_ci        }
118e1051a39Sopenharmony_ci        break;
119e1051a39Sopenharmony_ci    }
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_civoid ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    int embed = tt->flags & ASN1_TFLG_EMBED;
125e1051a39Sopenharmony_ci    ASN1_VALUE *tval;
126e1051a39Sopenharmony_ci    if (embed) {
127e1051a39Sopenharmony_ci        tval = (ASN1_VALUE *)pval;
128e1051a39Sopenharmony_ci        pval = &tval;
129e1051a39Sopenharmony_ci    }
130e1051a39Sopenharmony_ci    if (tt->flags & ASN1_TFLG_SK_MASK) {
131e1051a39Sopenharmony_ci        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
132e1051a39Sopenharmony_ci        int i;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
135e1051a39Sopenharmony_ci            ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci            ossl_asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
138e1051a39Sopenharmony_ci        }
139e1051a39Sopenharmony_ci        sk_ASN1_VALUE_free(sk);
140e1051a39Sopenharmony_ci        *pval = NULL;
141e1051a39Sopenharmony_ci    } else {
142e1051a39Sopenharmony_ci        ossl_asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
143e1051a39Sopenharmony_ci    }
144e1051a39Sopenharmony_ci}
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_civoid ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
147e1051a39Sopenharmony_ci{
148e1051a39Sopenharmony_ci    int utype;
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    /* Special case: if 'it' is a primitive with a free_func, use that. */
151e1051a39Sopenharmony_ci    if (it) {
152e1051a39Sopenharmony_ci        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_ci        if (embed) {
155e1051a39Sopenharmony_ci            if (pf && pf->prim_clear) {
156e1051a39Sopenharmony_ci                pf->prim_clear(pval, it);
157e1051a39Sopenharmony_ci                return;
158e1051a39Sopenharmony_ci            }
159e1051a39Sopenharmony_ci        } else if (pf && pf->prim_free) {
160e1051a39Sopenharmony_ci            pf->prim_free(pval, it);
161e1051a39Sopenharmony_ci            return;
162e1051a39Sopenharmony_ci        }
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci    /* Special case: if 'it' is NULL, free contents of ASN1_TYPE */
166e1051a39Sopenharmony_ci    if (!it) {
167e1051a39Sopenharmony_ci        ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci        utype = typ->type;
170e1051a39Sopenharmony_ci        pval = &typ->value.asn1_value;
171e1051a39Sopenharmony_ci        if (*pval == NULL)
172e1051a39Sopenharmony_ci            return;
173e1051a39Sopenharmony_ci    } else if (it->itype == ASN1_ITYPE_MSTRING) {
174e1051a39Sopenharmony_ci        utype = -1;
175e1051a39Sopenharmony_ci        if (*pval == NULL)
176e1051a39Sopenharmony_ci            return;
177e1051a39Sopenharmony_ci    } else {
178e1051a39Sopenharmony_ci        utype = it->utype;
179e1051a39Sopenharmony_ci        if ((utype != V_ASN1_BOOLEAN) && *pval == NULL)
180e1051a39Sopenharmony_ci            return;
181e1051a39Sopenharmony_ci    }
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ci    switch (utype) {
184e1051a39Sopenharmony_ci    case V_ASN1_OBJECT:
185e1051a39Sopenharmony_ci        ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
186e1051a39Sopenharmony_ci        break;
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci    case V_ASN1_BOOLEAN:
189e1051a39Sopenharmony_ci        if (it)
190e1051a39Sopenharmony_ci            *(ASN1_BOOLEAN *)pval = it->size;
191e1051a39Sopenharmony_ci        else
192e1051a39Sopenharmony_ci            *(ASN1_BOOLEAN *)pval = -1;
193e1051a39Sopenharmony_ci        return;
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    case V_ASN1_NULL:
196e1051a39Sopenharmony_ci        break;
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ci    case V_ASN1_ANY:
199e1051a39Sopenharmony_ci        ossl_asn1_primitive_free(pval, NULL, 0);
200e1051a39Sopenharmony_ci        OPENSSL_free(*pval);
201e1051a39Sopenharmony_ci        break;
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci    default:
204e1051a39Sopenharmony_ci        ossl_asn1_string_embed_free((ASN1_STRING *)*pval, embed);
205e1051a39Sopenharmony_ci        break;
206e1051a39Sopenharmony_ci    }
207e1051a39Sopenharmony_ci    *pval = NULL;
208e1051a39Sopenharmony_ci}
209