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