/src/libressl/crypto/asn1/tasn_fre.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD: tasn_fre.c,v 1.20 2022/05/12 19:55:58 jsing Exp $ */ |
2 | | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | | * project 2000. |
4 | | */ |
5 | | /* ==================================================================== |
6 | | * Copyright (c) 2000 The OpenSSL Project. All rights reserved. |
7 | | * |
8 | | * Redistribution and use in source and binary forms, with or without |
9 | | * modification, are permitted provided that the following conditions |
10 | | * are met: |
11 | | * |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, this list of conditions and the following disclaimer. |
14 | | * |
15 | | * 2. Redistributions in binary form must reproduce the above copyright |
16 | | * notice, this list of conditions and the following disclaimer in |
17 | | * the documentation and/or other materials provided with the |
18 | | * distribution. |
19 | | * |
20 | | * 3. All advertising materials mentioning features or use of this |
21 | | * software must display the following acknowledgment: |
22 | | * "This product includes software developed by the OpenSSL Project |
23 | | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
24 | | * |
25 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
26 | | * endorse or promote products derived from this software without |
27 | | * prior written permission. For written permission, please contact |
28 | | * licensing@OpenSSL.org. |
29 | | * |
30 | | * 5. Products derived from this software may not be called "OpenSSL" |
31 | | * nor may "OpenSSL" appear in their names without prior written |
32 | | * permission of the OpenSSL Project. |
33 | | * |
34 | | * 6. Redistributions of any form whatsoever must retain the following |
35 | | * acknowledgment: |
36 | | * "This product includes software developed by the OpenSSL Project |
37 | | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
38 | | * |
39 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
40 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
41 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
42 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
43 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
44 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
45 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
46 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
48 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
49 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
50 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
51 | | * ==================================================================== |
52 | | * |
53 | | * This product includes cryptographic software written by Eric Young |
54 | | * (eay@cryptsoft.com). This product includes software written by Tim |
55 | | * Hudson (tjh@cryptsoft.com). |
56 | | * |
57 | | */ |
58 | | |
59 | | |
60 | | #include <stddef.h> |
61 | | #include <openssl/asn1.h> |
62 | | #include <openssl/asn1t.h> |
63 | | #include <openssl/objects.h> |
64 | | |
65 | | #include "asn1_locl.h" |
66 | | |
67 | | static void asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it); |
68 | | |
69 | | /* Free up an ASN1 structure */ |
70 | | |
71 | | void |
72 | | ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) |
73 | 858k | { |
74 | 858k | asn1_item_free(&val, it); |
75 | 858k | } |
76 | | |
77 | | void |
78 | | ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) |
79 | 950k | { |
80 | 950k | asn1_item_free(pval, it); |
81 | 950k | } |
82 | | |
83 | | static void |
84 | | asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it) |
85 | 4.69M | { |
86 | 4.69M | const ASN1_TEMPLATE *tt = NULL, *seqtt; |
87 | 4.69M | const ASN1_EXTERN_FUNCS *ef; |
88 | 4.69M | const ASN1_AUX *aux = it->funcs; |
89 | 4.69M | ASN1_aux_cb *asn1_cb = NULL; |
90 | 4.69M | int i; |
91 | | |
92 | 4.69M | if (pval == NULL) |
93 | 0 | return; |
94 | | /* For primitive types *pval may be something other than C pointer. */ |
95 | 4.69M | if (it->itype != ASN1_ITYPE_PRIMITIVE && *pval == NULL) |
96 | 51.2k | return; |
97 | | |
98 | 4.64M | if (aux != NULL && aux->asn1_cb != NULL) |
99 | 52.0k | asn1_cb = aux->asn1_cb; |
100 | | |
101 | 4.64M | switch (it->itype) { |
102 | 3.15M | case ASN1_ITYPE_PRIMITIVE: |
103 | 3.15M | if (it->templates) |
104 | 818k | ASN1_template_free(pval, it->templates); |
105 | 2.33M | else |
106 | 2.33M | ASN1_primitive_free(pval, it); |
107 | 3.15M | break; |
108 | | |
109 | 613k | case ASN1_ITYPE_MSTRING: |
110 | 613k | ASN1_primitive_free(pval, it); |
111 | 613k | break; |
112 | | |
113 | 60.4k | case ASN1_ITYPE_CHOICE: |
114 | 60.4k | if (asn1_cb) { |
115 | 13.9k | i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); |
116 | 13.9k | if (i == 2) |
117 | 0 | return; |
118 | 13.9k | } |
119 | 60.4k | i = asn1_get_choice_selector(pval, it); |
120 | 60.4k | if ((i >= 0) && (i < it->tcount)) { |
121 | 40.9k | ASN1_VALUE **pchval; |
122 | 40.9k | tt = it->templates + i; |
123 | 40.9k | pchval = asn1_get_field_ptr(pval, tt); |
124 | 40.9k | ASN1_template_free(pchval, tt); |
125 | 40.9k | } |
126 | 60.4k | if (asn1_cb) |
127 | 13.9k | asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); |
128 | 60.4k | free(*pval); |
129 | 60.4k | *pval = NULL; |
130 | 60.4k | break; |
131 | | |
132 | 12.3k | case ASN1_ITYPE_EXTERN: |
133 | 12.3k | ef = it->funcs; |
134 | 12.3k | if (ef && ef->asn1_ex_free) |
135 | 12.3k | ef->asn1_ex_free(pval, it); |
136 | 12.3k | break; |
137 | | |
138 | 13.4k | case ASN1_ITYPE_NDEF_SEQUENCE: |
139 | 797k | case ASN1_ITYPE_SEQUENCE: |
140 | 797k | if (asn1_do_lock(pval, -1, it) > 0) |
141 | 0 | return; |
142 | 797k | if (asn1_cb) { |
143 | 23.8k | i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); |
144 | 23.8k | if (i == 2) |
145 | 0 | return; |
146 | 23.8k | } |
147 | 797k | asn1_enc_cleanup(pval, it); |
148 | | /* If we free up as normal we will invalidate any |
149 | | * ANY DEFINED BY field and we wont be able to |
150 | | * determine the type of the field it defines. So |
151 | | * free up in reverse order. |
152 | | */ |
153 | 797k | tt = it->templates + it->tcount - 1; |
154 | 2.67M | for (i = 0; i < it->tcount; tt--, i++) { |
155 | 1.87M | ASN1_VALUE **pseqval; |
156 | 1.87M | seqtt = asn1_do_adb(pval, tt, 0); |
157 | 1.87M | if (!seqtt) |
158 | 0 | continue; |
159 | 1.87M | pseqval = asn1_get_field_ptr(pval, seqtt); |
160 | 1.87M | ASN1_template_free(pseqval, seqtt); |
161 | 1.87M | } |
162 | 797k | if (asn1_cb) |
163 | 23.8k | asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); |
164 | 797k | free(*pval); |
165 | 797k | *pval = NULL; |
166 | 797k | break; |
167 | 4.64M | } |
168 | 4.64M | } |
169 | | |
170 | | void |
171 | | ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) |
172 | 2.87M | { |
173 | 2.87M | int i; |
174 | 2.87M | if (tt->flags & ASN1_TFLG_SK_MASK) { |
175 | 944k | STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; |
176 | 1.90M | for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { |
177 | 956k | ASN1_VALUE *vtmp; |
178 | 956k | vtmp = sk_ASN1_VALUE_value(sk, i); |
179 | 956k | asn1_item_free(&vtmp, tt->item); |
180 | 956k | } |
181 | 944k | sk_ASN1_VALUE_free(sk); |
182 | 944k | *pval = NULL; |
183 | 944k | } else |
184 | 1.92M | asn1_item_free(pval, tt->item); |
185 | 2.87M | } |
186 | | |
187 | | void |
188 | | ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) |
189 | 3.71M | { |
190 | 3.71M | int utype; |
191 | | |
192 | 3.71M | if (it != NULL && it->funcs != NULL) { |
193 | 14.2k | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; |
194 | | |
195 | 14.2k | pf->prim_free(pval, it); |
196 | 14.2k | return; |
197 | 14.2k | } |
198 | | |
199 | | /* Special case: if 'it' is NULL free contents of ASN1_TYPE */ |
200 | 3.70M | if (!it) { |
201 | 767k | ASN1_TYPE *typ = (ASN1_TYPE *)*pval; |
202 | 767k | utype = typ->type; |
203 | 767k | pval = &typ->value.asn1_value; |
204 | 767k | if (!*pval) |
205 | 190k | return; |
206 | 2.93M | } else if (it->itype == ASN1_ITYPE_MSTRING) { |
207 | 613k | utype = -1; |
208 | 613k | if (!*pval) |
209 | 0 | return; |
210 | 2.32M | } else { |
211 | 2.32M | utype = it->utype; |
212 | 2.32M | if ((utype != V_ASN1_BOOLEAN) && !*pval) |
213 | 290k | return; |
214 | 2.32M | } |
215 | | |
216 | 3.22M | switch (utype) { |
217 | 679k | case V_ASN1_OBJECT: |
218 | 679k | ASN1_OBJECT_free((ASN1_OBJECT *)*pval); |
219 | 679k | break; |
220 | | |
221 | 192k | case V_ASN1_BOOLEAN: |
222 | 192k | if (it) |
223 | 190k | *(ASN1_BOOLEAN *)pval = it->size; |
224 | 1.56k | else |
225 | 1.56k | *(ASN1_BOOLEAN *)pval = -1; |
226 | 192k | return; |
227 | | |
228 | 0 | case V_ASN1_NULL: |
229 | 0 | break; |
230 | | |
231 | 767k | case V_ASN1_ANY: |
232 | 767k | ASN1_primitive_free(pval, NULL); |
233 | 767k | free(*pval); |
234 | 767k | break; |
235 | | |
236 | 1.58M | default: |
237 | 1.58M | ASN1_STRING_free((ASN1_STRING *)*pval); |
238 | 1.58M | break; |
239 | 3.22M | } |
240 | 3.03M | *pval = NULL; |
241 | 3.03M | } |