• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2000-2021 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) /* if error or ref-counter > 0 */
89             return;
90         if (asn1_cb) {
91             i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
92             if (i == 2)
93                 return;
94         }
95         ossl_asn1_enc_free(pval, it);
96         /*
97          * If we free up as normal we will invalidate any ANY DEFINED BY
98          * field and we won't be able to determine the type of the field it
99          * defines. So free up in reverse order.
100          */
101         tt = it->templates + it->tcount;
102         for (i = 0; i < it->tcount; i++) {
103             ASN1_VALUE **pseqval;
104 
105             tt--;
106             seqtt = ossl_asn1_do_adb(*pval, tt, 0);
107             if (!seqtt)
108                 continue;
109             pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
110             ossl_asn1_template_free(pseqval, seqtt);
111         }
112         if (asn1_cb)
113             asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
114         if (embed == 0) {
115             OPENSSL_free(*pval);
116             *pval = NULL;
117         }
118         break;
119     }
120 }
121 
ossl_asn1_template_free(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt)122 void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
123 {
124     int embed = tt->flags & ASN1_TFLG_EMBED;
125     ASN1_VALUE *tval;
126     if (embed) {
127         tval = (ASN1_VALUE *)pval;
128         pval = &tval;
129     }
130     if (tt->flags & ASN1_TFLG_SK_MASK) {
131         STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
132         int i;
133 
134         for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
135             ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);
136 
137             ossl_asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
138         }
139         sk_ASN1_VALUE_free(sk);
140         *pval = NULL;
141     } else {
142         ossl_asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
143     }
144 }
145 
ossl_asn1_primitive_free(ASN1_VALUE ** pval,const ASN1_ITEM * it,int embed)146 void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
147 {
148     int utype;
149 
150     /* Special case: if 'it' is a primitive with a free_func, use that. */
151     if (it) {
152         const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
153 
154         if (embed) {
155             if (pf && pf->prim_clear) {
156                 pf->prim_clear(pval, it);
157                 return;
158             }
159         } else if (pf && pf->prim_free) {
160             pf->prim_free(pval, it);
161             return;
162         }
163     }
164 
165     /* Special case: if 'it' is NULL, free contents of ASN1_TYPE */
166     if (!it) {
167         ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
168 
169         utype = typ->type;
170         pval = &typ->value.asn1_value;
171         if (*pval == NULL)
172             return;
173     } else if (it->itype == ASN1_ITYPE_MSTRING) {
174         utype = -1;
175         if (*pval == NULL)
176             return;
177     } else {
178         utype = it->utype;
179         if ((utype != V_ASN1_BOOLEAN) && *pval == NULL)
180             return;
181     }
182 
183     switch (utype) {
184     case V_ASN1_OBJECT:
185         ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
186         break;
187 
188     case V_ASN1_BOOLEAN:
189         if (it)
190             *(ASN1_BOOLEAN *)pval = it->size;
191         else
192             *(ASN1_BOOLEAN *)pval = -1;
193         return;
194 
195     case V_ASN1_NULL:
196         break;
197 
198     case V_ASN1_ANY:
199         ossl_asn1_primitive_free(pval, NULL, 0);
200         OPENSSL_free(*pval);
201         break;
202 
203     default:
204         ossl_asn1_string_embed_free((ASN1_STRING *)*pval, embed);
205         break;
206     }
207     *pval = NULL;
208 }
209