1 |
|
|
/* $OpenBSD: tasn_dec.c,v 1.32 2016/05/04 15:00:24 tedu Exp $ */ |
2 |
|
|
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 |
|
|
* project 2000. |
4 |
|
|
*/ |
5 |
|
|
/* ==================================================================== |
6 |
|
|
* Copyright (c) 2000-2005 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 <string.h> |
62 |
|
|
#include <openssl/asn1.h> |
63 |
|
|
#include <openssl/asn1t.h> |
64 |
|
|
#include <openssl/objects.h> |
65 |
|
|
#include <openssl/buffer.h> |
66 |
|
|
#include <openssl/err.h> |
67 |
|
|
|
68 |
|
|
static int asn1_check_eoc(const unsigned char **in, long len); |
69 |
|
|
static int asn1_find_end(const unsigned char **in, long len, char inf); |
70 |
|
|
|
71 |
|
|
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, |
72 |
|
|
char inf, int tag, int aclass, int depth); |
73 |
|
|
|
74 |
|
|
static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); |
75 |
|
|
|
76 |
|
|
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, |
77 |
|
|
char *inf, char *cst, const unsigned char **in, long len, int exptag, |
78 |
|
|
int expclass, char opt, ASN1_TLC *ctx); |
79 |
|
|
|
80 |
|
|
static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, |
81 |
|
|
long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); |
82 |
|
|
static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, |
83 |
|
|
long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); |
84 |
|
|
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, |
85 |
|
|
long len, const ASN1_ITEM *it, int tag, int aclass, char opt, |
86 |
|
|
ASN1_TLC *ctx); |
87 |
|
|
|
88 |
|
|
/* Table to convert tags to bit values, used for MSTRING type */ |
89 |
|
|
static const unsigned long tag2bit[32] = { |
90 |
|
|
0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ |
91 |
|
|
B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ |
92 |
|
|
B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ |
93 |
|
|
B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */ |
94 |
|
|
B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */ |
95 |
|
|
B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */ |
96 |
|
|
B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ |
97 |
|
|
B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */ |
98 |
|
|
B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */ |
99 |
|
|
}; |
100 |
|
|
|
101 |
|
|
unsigned long |
102 |
|
|
ASN1_tag2bit(int tag) |
103 |
|
3026 |
{ |
104 |
✗✓ |
3026 |
if ((tag < 0) || (tag > 30)) |
105 |
|
|
return 0; |
106 |
|
3026 |
return tag2bit[tag]; |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
/* Macro to initialize and invalidate the cache */ |
110 |
|
|
|
111 |
|
|
#define asn1_tlc_clear(c) if (c) (c)->valid = 0 |
112 |
|
|
/* Version to avoid compiler warning about 'c' always non-NULL */ |
113 |
|
|
#define asn1_tlc_clear_nc(c) (c)->valid = 0 |
114 |
|
|
|
115 |
|
|
/* Decode an ASN1 item, this currently behaves just |
116 |
|
|
* like a standard 'd2i' function. 'in' points to |
117 |
|
|
* a buffer to read the data from, in future we will |
118 |
|
|
* have more advanced versions that can input data |
119 |
|
|
* a piece at a time and this will simply be a special |
120 |
|
|
* case. |
121 |
|
|
*/ |
122 |
|
|
|
123 |
|
|
ASN1_VALUE * |
124 |
|
|
ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
125 |
|
|
const ASN1_ITEM *it) |
126 |
|
764 |
{ |
127 |
|
|
ASN1_TLC c; |
128 |
|
764 |
ASN1_VALUE *ptmpval = NULL; |
129 |
|
|
|
130 |
✓✓ |
764 |
if (!pval) |
131 |
|
145 |
pval = &ptmpval; |
132 |
|
764 |
asn1_tlc_clear_nc(&c); |
133 |
✓✓ |
764 |
if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) |
134 |
|
688 |
return *pval; |
135 |
|
76 |
return NULL; |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
int |
139 |
|
|
ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
140 |
|
|
const ASN1_TEMPLATE *tt) |
141 |
|
|
{ |
142 |
|
|
ASN1_TLC c; |
143 |
|
|
|
144 |
|
|
asn1_tlc_clear_nc(&c); |
145 |
|
|
return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
|
149 |
|
|
/* Decode an item, taking care of IMPLICIT tagging, if any. |
150 |
|
|
* If 'opt' set and tag mismatch return -1 to handle OPTIONAL |
151 |
|
|
*/ |
152 |
|
|
|
153 |
|
|
int |
154 |
|
|
ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
155 |
|
|
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) |
156 |
|
13515 |
{ |
157 |
|
13515 |
const ASN1_TEMPLATE *tt, *errtt = NULL; |
158 |
|
|
const ASN1_EXTERN_FUNCS *ef; |
159 |
|
13515 |
const ASN1_AUX *aux = it->funcs; |
160 |
|
|
ASN1_aux_cb *asn1_cb; |
161 |
|
13515 |
const unsigned char *p = NULL, *q; |
162 |
|
|
unsigned char oclass; |
163 |
|
|
char seq_eoc, seq_nolen, cst, isopt; |
164 |
|
|
long tmplen; |
165 |
|
|
int i; |
166 |
|
|
int otag; |
167 |
|
13515 |
int ret = 0; |
168 |
|
|
ASN1_VALUE **pchptr; |
169 |
|
|
int combine; |
170 |
|
|
|
171 |
|
13515 |
combine = aclass & ASN1_TFLG_COMBINE; |
172 |
|
13515 |
aclass &= ~ASN1_TFLG_COMBINE; |
173 |
|
|
|
174 |
✗✓ |
13515 |
if (!pval) |
175 |
|
|
return 0; |
176 |
|
|
|
177 |
✓✓✓✓
|
14802 |
if (aux && aux->asn1_cb) |
178 |
|
1287 |
asn1_cb = aux->asn1_cb; |
179 |
|
|
else |
180 |
|
12228 |
asn1_cb = 0; |
181 |
|
|
|
182 |
✓✓✓✓ ✓✗ |
13515 |
switch (it->itype) { |
183 |
|
|
case ASN1_ITYPE_PRIMITIVE: |
184 |
✓✓ |
7770 |
if (it->templates) { |
185 |
|
|
/* tagging or OPTIONAL is currently illegal on an item |
186 |
|
|
* template because the flags can't get passed down. |
187 |
|
|
* In practice this isn't a problem: we include the |
188 |
|
|
* relevant flags from the item template in the |
189 |
|
|
* template itself. |
190 |
|
|
*/ |
191 |
✗✓ |
1693 |
if ((tag != -1) || opt) { |
192 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
193 |
|
|
ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); |
194 |
|
|
goto err; |
195 |
|
|
} |
196 |
|
1693 |
return asn1_template_ex_d2i(pval, in, len, |
197 |
|
|
it->templates, opt, ctx); |
198 |
|
|
} |
199 |
|
6077 |
return asn1_d2i_ex_primitive(pval, in, len, it, |
200 |
|
|
tag, aclass, opt, ctx); |
201 |
|
|
break; |
202 |
|
|
|
203 |
|
|
case ASN1_ITYPE_MSTRING: |
204 |
|
1674 |
p = *in; |
205 |
|
|
/* Just read in tag and class */ |
206 |
|
1674 |
ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, |
207 |
|
|
&p, len, -1, 0, 1, ctx); |
208 |
✗✓ |
1674 |
if (!ret) { |
209 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
210 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
211 |
|
|
goto err; |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
/* Must be UNIVERSAL class */ |
215 |
✗✓ |
1674 |
if (oclass != V_ASN1_UNIVERSAL) { |
216 |
|
|
/* If OPTIONAL, assume this is OK */ |
217 |
|
|
if (opt) |
218 |
|
|
return -1; |
219 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
220 |
|
|
ASN1_R_MSTRING_NOT_UNIVERSAL); |
221 |
|
|
goto err; |
222 |
|
|
} |
223 |
|
|
/* Check tag matches bit map */ |
224 |
✗✓ |
1674 |
if (!(ASN1_tag2bit(otag) & it->utype)) { |
225 |
|
|
/* If OPTIONAL, assume this is OK */ |
226 |
|
|
if (opt) |
227 |
|
|
return -1; |
228 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
229 |
|
|
ASN1_R_MSTRING_WRONG_TAG); |
230 |
|
|
goto err; |
231 |
|
|
} |
232 |
|
1674 |
return asn1_d2i_ex_primitive(pval, in, len, |
233 |
|
|
it, otag, 0, 0, ctx); |
234 |
|
|
|
235 |
|
|
case ASN1_ITYPE_EXTERN: |
236 |
|
|
/* Use new style d2i */ |
237 |
|
330 |
ef = it->funcs; |
238 |
|
330 |
return ef->asn1_ex_d2i(pval, in, len, |
239 |
|
|
it, tag, aclass, opt, ctx); |
240 |
|
|
|
241 |
|
|
case ASN1_ITYPE_CHOICE: |
242 |
✓✓✓✗
|
38 |
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) |
243 |
|
|
goto auxerr; |
244 |
|
|
|
245 |
✓✓ |
38 |
if (*pval) { |
246 |
|
|
/* Free up and zero CHOICE value if initialised */ |
247 |
|
12 |
i = asn1_get_choice_selector(pval, it); |
248 |
✗✓✗✗
|
12 |
if ((i >= 0) && (i < it->tcount)) { |
249 |
|
|
tt = it->templates + i; |
250 |
|
|
pchptr = asn1_get_field_ptr(pval, tt); |
251 |
|
|
ASN1_template_free(pchptr, tt); |
252 |
|
|
asn1_set_choice_selector(pval, -1, it); |
253 |
|
|
} |
254 |
✗✓ |
26 |
} else if (!ASN1_item_ex_new(pval, it)) { |
255 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
256 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
257 |
|
|
goto err; |
258 |
|
|
} |
259 |
|
|
/* CHOICE type, try each possibility in turn */ |
260 |
|
38 |
p = *in; |
261 |
✓✗ |
106 |
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
262 |
|
106 |
pchptr = asn1_get_field_ptr(pval, tt); |
263 |
|
|
/* We mark field as OPTIONAL so its absence |
264 |
|
|
* can be recognised. |
265 |
|
|
*/ |
266 |
|
106 |
ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); |
267 |
|
|
/* If field not present, try the next one */ |
268 |
✓✓ |
106 |
if (ret == -1) |
269 |
|
68 |
continue; |
270 |
|
|
/* If positive return, read OK, break loop */ |
271 |
✓✗ |
38 |
if (ret > 0) |
272 |
|
38 |
break; |
273 |
|
|
/* Otherwise must be an ASN1 parsing error */ |
274 |
|
|
errtt = tt; |
275 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
276 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
277 |
|
|
goto err; |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
/* Did we fall off the end without reading anything? */ |
281 |
✗✓ |
38 |
if (i == it->tcount) { |
282 |
|
|
/* If OPTIONAL, this is OK */ |
283 |
|
|
if (opt) { |
284 |
|
|
/* Free and zero it */ |
285 |
|
|
ASN1_item_ex_free(pval, it); |
286 |
|
|
return -1; |
287 |
|
|
} |
288 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
289 |
|
|
ASN1_R_NO_MATCHING_CHOICE_TYPE); |
290 |
|
|
goto err; |
291 |
|
|
} |
292 |
|
|
|
293 |
|
38 |
asn1_set_choice_selector(pval, i, it); |
294 |
|
38 |
*in = p; |
295 |
✓✓✗✓
|
38 |
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) |
296 |
|
|
goto auxerr; |
297 |
|
38 |
return 1; |
298 |
|
|
|
299 |
|
|
case ASN1_ITYPE_NDEF_SEQUENCE: |
300 |
|
|
case ASN1_ITYPE_SEQUENCE: |
301 |
|
3703 |
p = *in; |
302 |
|
3703 |
tmplen = len; |
303 |
|
|
|
304 |
|
|
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ |
305 |
✓✓ |
3703 |
if (tag == -1) { |
306 |
|
3677 |
tag = V_ASN1_SEQUENCE; |
307 |
|
3677 |
aclass = V_ASN1_UNIVERSAL; |
308 |
|
|
} |
309 |
|
|
/* Get SEQUENCE length and update len, p */ |
310 |
|
3703 |
ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, |
311 |
|
|
&p, len, tag, aclass, opt, ctx); |
312 |
✓✓ |
3703 |
if (!ret) { |
313 |
|
76 |
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
314 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
315 |
|
76 |
goto err; |
316 |
✓✓ |
3627 |
} else if (ret == -1) |
317 |
|
26 |
return -1; |
318 |
✓✓✗✓
|
3601 |
if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { |
319 |
|
|
len = tmplen - (p - *in); |
320 |
|
|
seq_nolen = 1; |
321 |
|
|
} |
322 |
|
|
/* If indefinite we don't do a length check */ |
323 |
|
|
else |
324 |
|
3601 |
seq_nolen = seq_eoc; |
325 |
✗✓ |
3601 |
if (!cst) { |
326 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
327 |
|
|
ASN1_R_SEQUENCE_NOT_CONSTRUCTED); |
328 |
|
|
goto err; |
329 |
|
|
} |
330 |
|
|
|
331 |
✓✓✗✓
|
3601 |
if (!*pval && !ASN1_item_ex_new(pval, it)) { |
332 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
333 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
334 |
|
|
goto err; |
335 |
|
|
} |
336 |
|
|
|
337 |
✓✓✗✓
|
3601 |
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) |
338 |
|
|
goto auxerr; |
339 |
|
|
|
340 |
|
|
/* Free up and zero any ADB found */ |
341 |
✓✓ |
12884 |
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
342 |
✓✓ |
9283 |
if (tt->flags & ASN1_TFLG_ADB_MASK) { |
343 |
|
|
const ASN1_TEMPLATE *seqtt; |
344 |
|
|
ASN1_VALUE **pseqval; |
345 |
|
5 |
seqtt = asn1_do_adb(pval, tt, 1); |
346 |
✗✓ |
5 |
if (!seqtt) |
347 |
|
|
goto err; |
348 |
|
5 |
pseqval = asn1_get_field_ptr(pval, seqtt); |
349 |
|
5 |
ASN1_template_free(pseqval, seqtt); |
350 |
|
|
} |
351 |
|
|
} |
352 |
|
|
|
353 |
|
|
/* Get each field entry */ |
354 |
✓✓ |
12779 |
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
355 |
|
|
const ASN1_TEMPLATE *seqtt; |
356 |
|
|
ASN1_VALUE **pseqval; |
357 |
|
9248 |
seqtt = asn1_do_adb(pval, tt, 1); |
358 |
✗✓ |
9248 |
if (!seqtt) |
359 |
|
|
goto err; |
360 |
|
9248 |
pseqval = asn1_get_field_ptr(pval, seqtt); |
361 |
|
|
/* Have we ran out of data? */ |
362 |
✓✓ |
9248 |
if (!len) |
363 |
|
70 |
break; |
364 |
|
9178 |
q = p; |
365 |
✗✓ |
9178 |
if (asn1_check_eoc(&p, len)) { |
366 |
|
|
if (!seq_eoc) { |
367 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
368 |
|
|
ASN1_R_UNEXPECTED_EOC); |
369 |
|
|
goto err; |
370 |
|
|
} |
371 |
|
|
len -= p - q; |
372 |
|
|
seq_eoc = 0; |
373 |
|
|
q = p; |
374 |
|
|
break; |
375 |
|
|
} |
376 |
|
|
/* This determines the OPTIONAL flag value. The field |
377 |
|
|
* cannot be omitted if it is the last of a SEQUENCE |
378 |
|
|
* and there is still data to be read. This isn't |
379 |
|
|
* strictly necessary but it increases efficiency in |
380 |
|
|
* some cases. |
381 |
|
|
*/ |
382 |
✓✓ |
9178 |
if (i == (it->tcount - 1)) |
383 |
|
3531 |
isopt = 0; |
384 |
|
|
else |
385 |
|
5647 |
isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); |
386 |
|
|
/* attempt to read in field, allowing each to be |
387 |
|
|
* OPTIONAL */ |
388 |
|
|
|
389 |
|
9178 |
ret = asn1_template_ex_d2i(pseqval, &p, len, |
390 |
|
|
seqtt, isopt, ctx); |
391 |
✗✓ |
9178 |
if (!ret) { |
392 |
|
|
errtt = seqtt; |
393 |
|
|
goto err; |
394 |
✓✓ |
9178 |
} else if (ret == -1) { |
395 |
|
|
/* OPTIONAL component absent. |
396 |
|
|
* Free and zero the field. |
397 |
|
|
*/ |
398 |
|
635 |
ASN1_template_free(pseqval, seqtt); |
399 |
|
635 |
continue; |
400 |
|
|
} |
401 |
|
|
/* Update length */ |
402 |
|
8543 |
len -= p - q; |
403 |
|
|
} |
404 |
|
|
|
405 |
|
|
/* Check for EOC if expecting one */ |
406 |
✗✓✗✗
|
3601 |
if (seq_eoc && !asn1_check_eoc(&p, len)) { |
407 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); |
408 |
|
|
goto err; |
409 |
|
|
} |
410 |
|
|
/* Check all data read */ |
411 |
✓✗✗✓
|
3601 |
if (!seq_nolen && len) { |
412 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
413 |
|
|
ASN1_R_SEQUENCE_LENGTH_MISMATCH); |
414 |
|
|
goto err; |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
/* If we get here we've got no more data in the SEQUENCE, |
418 |
|
|
* however we may not have read all fields so check all |
419 |
|
|
* remaining are OPTIONAL and clear any that are. |
420 |
|
|
*/ |
421 |
✓✓ |
3811 |
for (; i < it->tcount; tt++, i++) { |
422 |
|
|
const ASN1_TEMPLATE *seqtt; |
423 |
|
105 |
seqtt = asn1_do_adb(pval, tt, 1); |
424 |
✗✓ |
105 |
if (!seqtt) |
425 |
|
|
goto err; |
426 |
✓✗ |
105 |
if (seqtt->flags & ASN1_TFLG_OPTIONAL) { |
427 |
|
|
ASN1_VALUE **pseqval; |
428 |
|
105 |
pseqval = asn1_get_field_ptr(pval, seqtt); |
429 |
|
105 |
ASN1_template_free(pseqval, seqtt); |
430 |
|
|
} else { |
431 |
|
|
errtt = seqtt; |
432 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, |
433 |
|
|
ASN1_R_FIELD_MISSING); |
434 |
|
|
goto err; |
435 |
|
|
} |
436 |
|
|
} |
437 |
|
|
/* Save encoding */ |
438 |
✗✓ |
3601 |
if (!asn1_enc_save(pval, *in, p - *in, it)) { |
439 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_MALLOC_FAILURE); |
440 |
|
|
goto auxerr; |
441 |
|
|
} |
442 |
|
3601 |
*in = p; |
443 |
✓✓✗✓
|
3601 |
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) |
444 |
|
|
goto auxerr; |
445 |
|
3601 |
return 1; |
446 |
|
|
|
447 |
|
|
default: |
448 |
|
|
return 0; |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
auxerr: |
452 |
|
|
ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); |
453 |
|
76 |
err: |
454 |
✓✗ |
76 |
if (combine == 0) |
455 |
|
76 |
ASN1_item_ex_free(pval, it); |
456 |
✗✓ |
76 |
if (errtt) |
457 |
|
|
ERR_asprintf_error_data("Field=%s, Type=%s", errtt->field_name, |
458 |
|
|
it->sname); |
459 |
|
|
else |
460 |
|
76 |
ERR_asprintf_error_data("Type=%s", it->sname); |
461 |
|
76 |
return 0; |
462 |
|
|
} |
463 |
|
|
|
464 |
|
|
/* Templates are handled with two separate functions. |
465 |
|
|
* One handles any EXPLICIT tag and the other handles the rest. |
466 |
|
|
*/ |
467 |
|
|
|
468 |
|
|
static int |
469 |
|
|
asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen, |
470 |
|
|
const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) |
471 |
|
10977 |
{ |
472 |
|
|
int flags, aclass; |
473 |
|
|
int ret; |
474 |
|
|
long len; |
475 |
|
|
const unsigned char *p, *q; |
476 |
|
|
char exp_eoc; |
477 |
|
|
|
478 |
✗✓ |
10977 |
if (!val) |
479 |
|
|
return 0; |
480 |
|
10977 |
flags = tt->flags; |
481 |
|
10977 |
aclass = flags & ASN1_TFLG_TAG_CLASS; |
482 |
|
|
|
483 |
|
10977 |
p = *in; |
484 |
|
|
|
485 |
|
|
/* Check if EXPLICIT tag expected */ |
486 |
✓✓ |
10977 |
if (flags & ASN1_TFLG_EXPTAG) { |
487 |
|
|
char cst; |
488 |
|
|
/* Need to work out amount of data available to the inner |
489 |
|
|
* content and where it starts: so read in EXPLICIT header to |
490 |
|
|
* get the info. |
491 |
|
|
*/ |
492 |
|
339 |
ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, |
493 |
|
|
&p, inlen, tt->tag, aclass, opt, ctx); |
494 |
|
339 |
q = p; |
495 |
✗✓ |
339 |
if (!ret) { |
496 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, |
497 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
498 |
|
|
return 0; |
499 |
✓✓ |
339 |
} else if (ret == -1) |
500 |
|
19 |
return -1; |
501 |
✗✓ |
320 |
if (!cst) { |
502 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, |
503 |
|
|
ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); |
504 |
|
|
return 0; |
505 |
|
|
} |
506 |
|
|
/* We've found the field so it can't be OPTIONAL now */ |
507 |
|
320 |
ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); |
508 |
✗✓ |
320 |
if (!ret) { |
509 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, |
510 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
511 |
|
|
return 0; |
512 |
|
|
} |
513 |
|
|
/* We read the field in OK so update length */ |
514 |
|
320 |
len -= p - q; |
515 |
✗✓ |
320 |
if (exp_eoc) { |
516 |
|
|
/* If NDEF we must have an EOC here */ |
517 |
|
|
if (!asn1_check_eoc(&p, len)) { |
518 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, |
519 |
|
|
ASN1_R_MISSING_EOC); |
520 |
|
|
goto err; |
521 |
|
|
} |
522 |
|
|
} else { |
523 |
|
|
/* Otherwise we must hit the EXPLICIT tag end or its |
524 |
|
|
* an error */ |
525 |
✗✓ |
320 |
if (len) { |
526 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, |
527 |
|
|
ASN1_R_EXPLICIT_LENGTH_MISMATCH); |
528 |
|
|
goto err; |
529 |
|
|
} |
530 |
|
|
} |
531 |
|
|
} else |
532 |
|
10638 |
return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); |
533 |
|
|
|
534 |
|
320 |
*in = p; |
535 |
|
320 |
return 1; |
536 |
|
|
|
537 |
|
|
err: |
538 |
|
|
ASN1_template_free(val, tt); |
539 |
|
|
return 0; |
540 |
|
|
} |
541 |
|
|
|
542 |
|
|
static int |
543 |
|
|
asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len, |
544 |
|
|
const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) |
545 |
|
10958 |
{ |
546 |
|
|
int flags, aclass; |
547 |
|
|
int ret; |
548 |
|
|
const unsigned char *p, *q; |
549 |
|
|
|
550 |
✗✓ |
10958 |
if (!val) |
551 |
|
|
return 0; |
552 |
|
10958 |
flags = tt->flags; |
553 |
|
10958 |
aclass = flags & ASN1_TFLG_TAG_CLASS; |
554 |
|
|
|
555 |
|
10958 |
p = *in; |
556 |
|
10958 |
q = p; |
557 |
|
|
|
558 |
✓✓ |
10958 |
if (flags & ASN1_TFLG_SK_MASK) { |
559 |
|
|
/* SET OF, SEQUENCE OF */ |
560 |
|
|
int sktag, skaclass; |
561 |
|
|
char sk_eoc; |
562 |
|
|
/* First work out expected inner tag value */ |
563 |
✓✓ |
1871 |
if (flags & ASN1_TFLG_IMPTAG) { |
564 |
|
11 |
sktag = tt->tag; |
565 |
|
11 |
skaclass = aclass; |
566 |
|
|
} else { |
567 |
|
1860 |
skaclass = V_ASN1_UNIVERSAL; |
568 |
✓✓ |
1860 |
if (flags & ASN1_TFLG_SET_OF) |
569 |
|
1365 |
sktag = V_ASN1_SET; |
570 |
|
|
else |
571 |
|
495 |
sktag = V_ASN1_SEQUENCE; |
572 |
|
|
} |
573 |
|
|
/* Get the tag */ |
574 |
|
1871 |
ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, |
575 |
|
|
&p, len, sktag, skaclass, opt, ctx); |
576 |
✗✓ |
1871 |
if (!ret) { |
577 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
578 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
579 |
|
|
return 0; |
580 |
✓✓ |
1871 |
} else if (ret == -1) |
581 |
|
2 |
return -1; |
582 |
✓✓ |
1869 |
if (!*val) |
583 |
|
1862 |
*val = (ASN1_VALUE *)sk_new_null(); |
584 |
|
|
else { |
585 |
|
|
/* We've got a valid STACK: free up any items present */ |
586 |
|
|
STACK_OF(ASN1_VALUE) *sktmp = |
587 |
|
7 |
(STACK_OF(ASN1_VALUE) *)*val; |
588 |
|
|
ASN1_VALUE *vtmp; |
589 |
✗✓ |
14 |
while (sk_ASN1_VALUE_num(sktmp) > 0) { |
590 |
|
|
vtmp = sk_ASN1_VALUE_pop(sktmp); |
591 |
|
|
ASN1_item_ex_free(&vtmp, |
592 |
|
|
ASN1_ITEM_ptr(tt->item)); |
593 |
|
|
} |
594 |
|
|
} |
595 |
|
|
|
596 |
✗✓ |
1869 |
if (!*val) { |
597 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
598 |
|
|
ERR_R_MALLOC_FAILURE); |
599 |
|
|
goto err; |
600 |
|
|
} |
601 |
|
|
|
602 |
|
|
/* Read as many items as we can */ |
603 |
✓✓ |
5203 |
while (len > 0) { |
604 |
|
|
ASN1_VALUE *skfield; |
605 |
|
3334 |
q = p; |
606 |
|
|
/* See if EOC found */ |
607 |
✗✓ |
3334 |
if (asn1_check_eoc(&p, len)) { |
608 |
|
|
if (!sk_eoc) { |
609 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
610 |
|
|
ASN1_R_UNEXPECTED_EOC); |
611 |
|
|
goto err; |
612 |
|
|
} |
613 |
|
|
len -= p - q; |
614 |
|
|
sk_eoc = 0; |
615 |
|
|
break; |
616 |
|
|
} |
617 |
|
3334 |
skfield = NULL; |
618 |
✗✓ |
3334 |
if (!ASN1_item_ex_d2i(&skfield, &p, len, |
619 |
|
|
ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { |
620 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
621 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
622 |
|
|
goto err; |
623 |
|
|
} |
624 |
|
3334 |
len -= p - q; |
625 |
✗✓ |
3334 |
if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, |
626 |
|
|
skfield)) { |
627 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
628 |
|
|
ERR_R_MALLOC_FAILURE); |
629 |
|
|
goto err; |
630 |
|
|
} |
631 |
|
|
} |
632 |
✗✓ |
1869 |
if (sk_eoc) { |
633 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
634 |
|
|
ASN1_R_MISSING_EOC); |
635 |
|
|
goto err; |
636 |
|
|
} |
637 |
✓✓ |
9087 |
} else if (flags & ASN1_TFLG_IMPTAG) { |
638 |
|
|
/* IMPLICIT tagging */ |
639 |
|
391 |
ret = ASN1_item_ex_d2i(val, &p, len, |
640 |
|
|
ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx); |
641 |
✗✓ |
391 |
if (!ret) { |
642 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
643 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
644 |
|
|
goto err; |
645 |
✓✓ |
391 |
} else if (ret == -1) |
646 |
|
363 |
return -1; |
647 |
|
|
} else { |
648 |
|
|
/* Nothing special */ |
649 |
|
8696 |
ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), |
650 |
|
|
-1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); |
651 |
✗✓ |
8696 |
if (!ret) { |
652 |
|
|
ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, |
653 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
654 |
|
|
goto err; |
655 |
✓✓ |
8696 |
} else if (ret == -1) |
656 |
|
319 |
return -1; |
657 |
|
|
} |
658 |
|
|
|
659 |
|
10274 |
*in = p; |
660 |
|
10274 |
return 1; |
661 |
|
|
|
662 |
|
|
err: |
663 |
|
|
ASN1_template_free(val, tt); |
664 |
|
|
return 0; |
665 |
|
|
} |
666 |
|
|
|
667 |
|
|
static int |
668 |
|
|
asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen, |
669 |
|
|
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx) |
670 |
|
7751 |
{ |
671 |
|
7751 |
int ret = 0, utype; |
672 |
|
|
long plen; |
673 |
|
7751 |
char cst, inf, free_cont = 0; |
674 |
|
|
const unsigned char *p; |
675 |
|
|
BUF_MEM buf; |
676 |
|
7751 |
const unsigned char *cont = NULL; |
677 |
|
|
long len; |
678 |
|
|
|
679 |
|
7751 |
buf.length = 0; |
680 |
|
7751 |
buf.max = 0; |
681 |
|
7751 |
buf.data = NULL; |
682 |
|
|
|
683 |
✗✓ |
7751 |
if (!pval) { |
684 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); |
685 |
|
|
return 0; /* Should never happen */ |
686 |
|
|
} |
687 |
|
|
|
688 |
✓✓ |
7751 |
if (it->itype == ASN1_ITYPE_MSTRING) { |
689 |
|
1674 |
utype = tag; |
690 |
|
1674 |
tag = -1; |
691 |
|
|
} else |
692 |
|
6077 |
utype = it->utype; |
693 |
|
|
|
694 |
✓✓ |
7751 |
if (utype == V_ASN1_ANY) { |
695 |
|
|
/* If type is ANY need to figure out type from tag */ |
696 |
|
|
unsigned char oclass; |
697 |
✗✓ |
476 |
if (tag >= 0) { |
698 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, |
699 |
|
|
ASN1_R_ILLEGAL_TAGGED_ANY); |
700 |
|
|
return 0; |
701 |
|
|
} |
702 |
✗✓ |
476 |
if (opt) { |
703 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, |
704 |
|
|
ASN1_R_ILLEGAL_OPTIONAL_ANY); |
705 |
|
|
return 0; |
706 |
|
|
} |
707 |
|
476 |
p = *in; |
708 |
|
476 |
ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, |
709 |
|
|
&p, inlen, -1, 0, 0, ctx); |
710 |
✗✓ |
476 |
if (!ret) { |
711 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, |
712 |
|
|
ERR_R_NESTED_ASN1_ERROR); |
713 |
|
|
return 0; |
714 |
|
|
} |
715 |
✗✓ |
476 |
if (oclass != V_ASN1_UNIVERSAL) |
716 |
|
|
utype = V_ASN1_OTHER; |
717 |
|
|
} |
718 |
✓✓ |
7751 |
if (tag == -1) { |
719 |
|
7386 |
tag = utype; |
720 |
|
7386 |
aclass = V_ASN1_UNIVERSAL; |
721 |
|
|
} |
722 |
|
7751 |
p = *in; |
723 |
|
|
/* Check header */ |
724 |
|
7751 |
ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, |
725 |
|
|
&p, inlen, tag, aclass, opt, ctx); |
726 |
✗✓ |
7751 |
if (!ret) { |
727 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); |
728 |
|
|
return 0; |
729 |
✓✓ |
7751 |
} else if (ret == -1) |
730 |
|
656 |
return -1; |
731 |
|
7095 |
ret = 0; |
732 |
|
|
/* SEQUENCE, SET and "OTHER" are left in encoded form */ |
733 |
✓✓ |
7095 |
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || |
734 |
|
|
(utype == V_ASN1_OTHER)) { |
735 |
|
|
/* Clear context cache for type OTHER because the auto clear |
736 |
|
|
* when we have a exact match wont work |
737 |
|
|
*/ |
738 |
✗✓ |
2 |
if (utype == V_ASN1_OTHER) { |
739 |
|
|
asn1_tlc_clear(ctx); |
740 |
|
|
} |
741 |
|
|
/* SEQUENCE and SET must be constructed */ |
742 |
✗✓ |
2 |
else if (!cst) { |
743 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, |
744 |
|
|
ASN1_R_TYPE_NOT_CONSTRUCTED); |
745 |
|
|
return 0; |
746 |
|
|
} |
747 |
|
|
|
748 |
|
2 |
cont = *in; |
749 |
|
|
/* If indefinite length constructed find the real end */ |
750 |
✗✓ |
2 |
if (inf) { |
751 |
|
|
if (!asn1_find_end(&p, plen, inf)) |
752 |
|
|
goto err; |
753 |
|
|
len = p - cont; |
754 |
|
|
} else { |
755 |
|
2 |
len = p - cont + plen; |
756 |
|
2 |
p += plen; |
757 |
|
2 |
buf.data = NULL; |
758 |
|
|
} |
759 |
✗✓ |
7093 |
} else if (cst) { |
760 |
|
|
/* Should really check the internal tags are correct but |
761 |
|
|
* some things may get this wrong. The relevant specs |
762 |
|
|
* say that constructed string types should be OCTET STRINGs |
763 |
|
|
* internally irrespective of the type. So instead just check |
764 |
|
|
* for UNIVERSAL class and ignore the tag. |
765 |
|
|
*/ |
766 |
|
|
if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { |
767 |
|
|
free_cont = 1; |
768 |
|
|
goto err; |
769 |
|
|
} |
770 |
|
|
len = buf.length; |
771 |
|
|
/* Append a final null to string */ |
772 |
|
|
if (!BUF_MEM_grow_clean(&buf, len + 1)) { |
773 |
|
|
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, |
774 |
|
|
ERR_R_MALLOC_FAILURE); |
775 |
|
|
return 0; |
776 |
|
|
} |
777 |
|
|
buf.data[len] = 0; |
778 |
|
|
cont = (const unsigned char *)buf.data; |
779 |
|
|
free_cont = 1; |
780 |
|
|
} else { |
781 |
|
7093 |
cont = p; |
782 |
|
7093 |
len = plen; |
783 |
|
7093 |
p += plen; |
784 |
|
|
} |
785 |
|
|
|
786 |
|
|
/* We now have content length and type: translate into a structure */ |
787 |
✗✓ |
7095 |
if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) |
788 |
|
|
goto err; |
789 |
|
|
|
790 |
|
7095 |
*in = p; |
791 |
|
7095 |
ret = 1; |
792 |
|
|
|
793 |
|
7095 |
err: |
794 |
✗✓✗✗
|
7095 |
if (free_cont && buf.data) |
795 |
|
|
free(buf.data); |
796 |
|
7095 |
return ret; |
797 |
|
|
} |
798 |
|
|
|
799 |
|
|
/* Translate ASN1 content octets into a structure */ |
800 |
|
|
|
801 |
|
|
int |
802 |
|
|
asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, |
803 |
|
|
char *free_cont, const ASN1_ITEM *it) |
804 |
|
7095 |
{ |
805 |
|
7095 |
ASN1_VALUE **opval = NULL; |
806 |
|
|
ASN1_STRING *stmp; |
807 |
|
7095 |
ASN1_TYPE *typ = NULL; |
808 |
|
7095 |
int ret = 0; |
809 |
|
|
const ASN1_PRIMITIVE_FUNCS *pf; |
810 |
|
|
ASN1_INTEGER **tint; |
811 |
|
|
|
812 |
|
7095 |
pf = it->funcs; |
813 |
|
|
|
814 |
✓✓✓✗
|
7095 |
if (pf && pf->prim_c2i) |
815 |
|
943 |
return pf->prim_c2i(pval, cont, len, utype, free_cont, it); |
816 |
|
|
/* If ANY type clear type and set pointer to internal value */ |
817 |
✓✓ |
6152 |
if (it->utype == V_ASN1_ANY) { |
818 |
✓✗ |
476 |
if (!*pval) { |
819 |
|
476 |
typ = ASN1_TYPE_new(); |
820 |
✗✓ |
476 |
if (typ == NULL) |
821 |
|
|
goto err; |
822 |
|
476 |
*pval = (ASN1_VALUE *)typ; |
823 |
|
|
} else |
824 |
|
|
typ = (ASN1_TYPE *)*pval; |
825 |
|
|
|
826 |
✓✗ |
476 |
if (utype != typ->type) |
827 |
|
476 |
ASN1_TYPE_set(typ, utype, NULL); |
828 |
|
476 |
opval = pval; |
829 |
|
476 |
pval = &typ->value.asn1_value; |
830 |
|
|
} |
831 |
✓✓✓✓ ✓✓ |
6152 |
switch (utype) { |
832 |
|
|
case V_ASN1_OBJECT: |
833 |
✗✓ |
2468 |
if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) |
834 |
|
|
goto err; |
835 |
|
|
break; |
836 |
|
|
|
837 |
|
|
case V_ASN1_NULL: |
838 |
✗✓ |
451 |
if (len) { |
839 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
840 |
|
|
ASN1_R_NULL_IS_WRONG_LENGTH); |
841 |
|
|
goto err; |
842 |
|
|
} |
843 |
|
451 |
*pval = (ASN1_VALUE *)1; |
844 |
|
451 |
break; |
845 |
|
|
|
846 |
|
|
case V_ASN1_BOOLEAN: |
847 |
✗✓ |
257 |
if (len != 1) { |
848 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
849 |
|
|
ASN1_R_BOOLEAN_IS_WRONG_LENGTH); |
850 |
|
|
goto err; |
851 |
|
|
} else { |
852 |
|
|
ASN1_BOOLEAN *tbool; |
853 |
|
257 |
tbool = (ASN1_BOOLEAN *)pval; |
854 |
|
257 |
*tbool = *cont; |
855 |
|
|
} |
856 |
|
257 |
break; |
857 |
|
|
|
858 |
|
|
case V_ASN1_BIT_STRING: |
859 |
✗✓ |
332 |
if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) |
860 |
|
|
goto err; |
861 |
|
|
break; |
862 |
|
|
|
863 |
|
|
case V_ASN1_INTEGER: |
864 |
|
|
case V_ASN1_ENUMERATED: |
865 |
|
327 |
tint = (ASN1_INTEGER **)pval; |
866 |
✗✓ |
327 |
if (!c2i_ASN1_INTEGER(tint, &cont, len)) |
867 |
|
|
goto err; |
868 |
|
|
/* Fixup type to match the expected form */ |
869 |
|
327 |
(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); |
870 |
|
327 |
break; |
871 |
|
|
|
872 |
|
|
case V_ASN1_OCTET_STRING: |
873 |
|
|
case V_ASN1_NUMERICSTRING: |
874 |
|
|
case V_ASN1_PRINTABLESTRING: |
875 |
|
|
case V_ASN1_T61STRING: |
876 |
|
|
case V_ASN1_VIDEOTEXSTRING: |
877 |
|
|
case V_ASN1_IA5STRING: |
878 |
|
|
case V_ASN1_UTCTIME: |
879 |
|
|
case V_ASN1_GENERALIZEDTIME: |
880 |
|
|
case V_ASN1_GRAPHICSTRING: |
881 |
|
|
case V_ASN1_VISIBLESTRING: |
882 |
|
|
case V_ASN1_GENERALSTRING: |
883 |
|
|
case V_ASN1_UNIVERSALSTRING: |
884 |
|
|
case V_ASN1_BMPSTRING: |
885 |
|
|
case V_ASN1_UTF8STRING: |
886 |
|
|
case V_ASN1_OTHER: |
887 |
|
|
case V_ASN1_SET: |
888 |
|
|
case V_ASN1_SEQUENCE: |
889 |
|
|
default: |
890 |
✗✓✗✗
|
2317 |
if (utype == V_ASN1_BMPSTRING && (len & 1)) { |
891 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
892 |
|
|
ASN1_R_BMPSTRING_IS_WRONG_LENGTH); |
893 |
|
|
goto err; |
894 |
|
|
} |
895 |
✗✓✗✗
|
2317 |
if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { |
896 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
897 |
|
|
ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); |
898 |
|
|
goto err; |
899 |
|
|
} |
900 |
|
|
/* All based on ASN1_STRING and handled the same */ |
901 |
✓✓ |
2317 |
if (!*pval) { |
902 |
|
44 |
stmp = ASN1_STRING_type_new(utype); |
903 |
✗✓ |
44 |
if (!stmp) { |
904 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
905 |
|
|
ERR_R_MALLOC_FAILURE); |
906 |
|
|
goto err; |
907 |
|
|
} |
908 |
|
44 |
*pval = (ASN1_VALUE *)stmp; |
909 |
|
|
} else { |
910 |
|
2273 |
stmp = (ASN1_STRING *)*pval; |
911 |
|
2273 |
stmp->type = utype; |
912 |
|
|
} |
913 |
|
|
/* If we've already allocated a buffer use it */ |
914 |
✗✓ |
2317 |
if (*free_cont) { |
915 |
|
|
free(stmp->data); |
916 |
|
|
stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ |
917 |
|
|
stmp->length = len; |
918 |
|
|
*free_cont = 0; |
919 |
|
|
} else { |
920 |
✗✓ |
2317 |
if (!ASN1_STRING_set(stmp, cont, len)) { |
921 |
|
|
ASN1err(ASN1_F_ASN1_EX_C2I, |
922 |
|
|
ERR_R_MALLOC_FAILURE); |
923 |
|
|
ASN1_STRING_free(stmp); |
924 |
|
|
*pval = NULL; |
925 |
|
|
goto err; |
926 |
|
|
} |
927 |
|
|
} |
928 |
|
|
break; |
929 |
|
|
} |
930 |
|
|
/* If ASN1_ANY and NULL type fix up value */ |
931 |
✓✓ |
6152 |
if (typ && (utype == V_ASN1_NULL)) |
932 |
|
449 |
typ->value.ptr = NULL; |
933 |
|
|
|
934 |
|
6152 |
ret = 1; |
935 |
|
|
|
936 |
|
6152 |
err: |
937 |
✗✓ |
6152 |
if (!ret) { |
938 |
|
|
ASN1_TYPE_free(typ); |
939 |
|
|
if (opval) |
940 |
|
|
*opval = NULL; |
941 |
|
|
} |
942 |
|
6152 |
return ret; |
943 |
|
|
} |
944 |
|
|
|
945 |
|
|
|
946 |
|
|
/* This function finds the end of an ASN1 structure when passed its maximum |
947 |
|
|
* length, whether it is indefinite length and a pointer to the content. |
948 |
|
|
* This is more efficient than calling asn1_collect because it does not |
949 |
|
|
* recurse on each indefinite length header. |
950 |
|
|
*/ |
951 |
|
|
|
952 |
|
|
static int |
953 |
|
|
asn1_find_end(const unsigned char **in, long len, char inf) |
954 |
|
|
{ |
955 |
|
|
int expected_eoc; |
956 |
|
|
long plen; |
957 |
|
|
const unsigned char *p = *in, *q; |
958 |
|
|
|
959 |
|
|
/* If not indefinite length constructed just add length */ |
960 |
|
|
if (inf == 0) { |
961 |
|
|
*in += len; |
962 |
|
|
return 1; |
963 |
|
|
} |
964 |
|
|
expected_eoc = 1; |
965 |
|
|
/* Indefinite length constructed form. Find the end when enough EOCs |
966 |
|
|
* are found. If more indefinite length constructed headers |
967 |
|
|
* are encountered increment the expected eoc count otherwise just |
968 |
|
|
* skip to the end of the data. |
969 |
|
|
*/ |
970 |
|
|
while (len > 0) { |
971 |
|
|
if (asn1_check_eoc(&p, len)) { |
972 |
|
|
expected_eoc--; |
973 |
|
|
if (expected_eoc == 0) |
974 |
|
|
break; |
975 |
|
|
len -= 2; |
976 |
|
|
continue; |
977 |
|
|
} |
978 |
|
|
q = p; |
979 |
|
|
/* Just read in a header: only care about the length */ |
980 |
|
|
if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, |
981 |
|
|
-1, 0, 0, NULL)) { |
982 |
|
|
ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); |
983 |
|
|
return 0; |
984 |
|
|
} |
985 |
|
|
if (inf) |
986 |
|
|
expected_eoc++; |
987 |
|
|
else |
988 |
|
|
p += plen; |
989 |
|
|
len -= p - q; |
990 |
|
|
} |
991 |
|
|
if (expected_eoc) { |
992 |
|
|
ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); |
993 |
|
|
return 0; |
994 |
|
|
} |
995 |
|
|
*in = p; |
996 |
|
|
return 1; |
997 |
|
|
} |
998 |
|
|
/* This function collects the asn1 data from a constructred string |
999 |
|
|
* type into a buffer. The values of 'in' and 'len' should refer |
1000 |
|
|
* to the contents of the constructed type and 'inf' should be set |
1001 |
|
|
* if it is indefinite length. |
1002 |
|
|
*/ |
1003 |
|
|
|
1004 |
|
|
#ifndef ASN1_MAX_STRING_NEST |
1005 |
|
|
/* This determines how many levels of recursion are permitted in ASN1 |
1006 |
|
|
* string types. If it is not limited stack overflows can occur. If set |
1007 |
|
|
* to zero no recursion is allowed at all. Although zero should be adequate |
1008 |
|
|
* examples exist that require a value of 1. So 5 should be more than enough. |
1009 |
|
|
*/ |
1010 |
|
|
#define ASN1_MAX_STRING_NEST 5 |
1011 |
|
|
#endif |
1012 |
|
|
|
1013 |
|
|
static int |
1014 |
|
|
asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf, |
1015 |
|
|
int tag, int aclass, int depth) |
1016 |
|
|
{ |
1017 |
|
|
const unsigned char *p, *q; |
1018 |
|
|
long plen; |
1019 |
|
|
char cst, ininf; |
1020 |
|
|
|
1021 |
|
|
p = *in; |
1022 |
|
|
inf &= 1; |
1023 |
|
|
/* If no buffer and not indefinite length constructed just pass over |
1024 |
|
|
* the encoded data */ |
1025 |
|
|
if (!buf && !inf) { |
1026 |
|
|
*in += len; |
1027 |
|
|
return 1; |
1028 |
|
|
} |
1029 |
|
|
while (len > 0) { |
1030 |
|
|
q = p; |
1031 |
|
|
/* Check for EOC */ |
1032 |
|
|
if (asn1_check_eoc(&p, len)) { |
1033 |
|
|
/* EOC is illegal outside indefinite length |
1034 |
|
|
* constructed form */ |
1035 |
|
|
if (!inf) { |
1036 |
|
|
ASN1err(ASN1_F_ASN1_COLLECT, |
1037 |
|
|
ASN1_R_UNEXPECTED_EOC); |
1038 |
|
|
return 0; |
1039 |
|
|
} |
1040 |
|
|
inf = 0; |
1041 |
|
|
break; |
1042 |
|
|
} |
1043 |
|
|
|
1044 |
|
|
if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, |
1045 |
|
|
len, tag, aclass, 0, NULL)) { |
1046 |
|
|
ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); |
1047 |
|
|
return 0; |
1048 |
|
|
} |
1049 |
|
|
|
1050 |
|
|
/* If indefinite length constructed update max length */ |
1051 |
|
|
if (cst) { |
1052 |
|
|
if (depth >= ASN1_MAX_STRING_NEST) { |
1053 |
|
|
ASN1err(ASN1_F_ASN1_COLLECT, |
1054 |
|
|
ASN1_R_NESTED_ASN1_STRING); |
1055 |
|
|
return 0; |
1056 |
|
|
} |
1057 |
|
|
if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, |
1058 |
|
|
depth + 1)) |
1059 |
|
|
return 0; |
1060 |
|
|
} else if (plen && !collect_data(buf, &p, plen)) |
1061 |
|
|
return 0; |
1062 |
|
|
len -= p - q; |
1063 |
|
|
} |
1064 |
|
|
if (inf) { |
1065 |
|
|
ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); |
1066 |
|
|
return 0; |
1067 |
|
|
} |
1068 |
|
|
*in = p; |
1069 |
|
|
return 1; |
1070 |
|
|
} |
1071 |
|
|
|
1072 |
|
|
static int |
1073 |
|
|
collect_data(BUF_MEM *buf, const unsigned char **p, long plen) |
1074 |
|
|
{ |
1075 |
|
|
int len; |
1076 |
|
|
if (buf) { |
1077 |
|
|
len = buf->length; |
1078 |
|
|
if (!BUF_MEM_grow_clean(buf, len + plen)) { |
1079 |
|
|
ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); |
1080 |
|
|
return 0; |
1081 |
|
|
} |
1082 |
|
|
memcpy(buf->data + len, *p, plen); |
1083 |
|
|
} |
1084 |
|
|
*p += plen; |
1085 |
|
|
return 1; |
1086 |
|
|
} |
1087 |
|
|
|
1088 |
|
|
/* Check for ASN1 EOC and swallow it if found */ |
1089 |
|
|
|
1090 |
|
|
static int |
1091 |
|
|
asn1_check_eoc(const unsigned char **in, long len) |
1092 |
|
12512 |
{ |
1093 |
|
|
const unsigned char *p; |
1094 |
|
|
|
1095 |
✗✓ |
12512 |
if (len < 2) |
1096 |
|
|
return 0; |
1097 |
|
12512 |
p = *in; |
1098 |
✗✓✗✗
|
12512 |
if (!p[0] && !p[1]) { |
1099 |
|
|
*in += 2; |
1100 |
|
|
return 1; |
1101 |
|
|
} |
1102 |
|
12512 |
return 0; |
1103 |
|
|
} |
1104 |
|
|
|
1105 |
|
|
/* Check an ASN1 tag and length: a bit like ASN1_get_object |
1106 |
|
|
* but it sets the length for indefinite length constructed |
1107 |
|
|
* form, we don't know the exact length but we can set an |
1108 |
|
|
* upper bound to the amount of data available minus the |
1109 |
|
|
* header length just read. |
1110 |
|
|
*/ |
1111 |
|
|
|
1112 |
|
|
static int |
1113 |
|
|
asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, |
1114 |
|
|
char *cst, const unsigned char **in, long len, int exptag, int expclass, |
1115 |
|
|
char opt, ASN1_TLC *ctx) |
1116 |
|
15814 |
{ |
1117 |
|
|
int i; |
1118 |
|
|
int ptag, pclass; |
1119 |
|
|
long plen; |
1120 |
|
|
const unsigned char *p, *q; |
1121 |
|
|
|
1122 |
|
15814 |
p = *in; |
1123 |
|
15814 |
q = p; |
1124 |
|
|
|
1125 |
✓✗✓✓
|
18667 |
if (ctx && ctx->valid) { |
1126 |
|
2853 |
i = ctx->ret; |
1127 |
|
2853 |
plen = ctx->plen; |
1128 |
|
2853 |
pclass = ctx->pclass; |
1129 |
|
2853 |
ptag = ctx->ptag; |
1130 |
|
2853 |
p += ctx->hdrlen; |
1131 |
|
|
} else { |
1132 |
|
12961 |
i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); |
1133 |
✓✗ |
12961 |
if (ctx) { |
1134 |
|
12961 |
ctx->ret = i; |
1135 |
|
12961 |
ctx->plen = plen; |
1136 |
|
12961 |
ctx->pclass = pclass; |
1137 |
|
12961 |
ctx->ptag = ptag; |
1138 |
|
12961 |
ctx->hdrlen = p - q; |
1139 |
|
12961 |
ctx->valid = 1; |
1140 |
|
|
/* If definite length, and no error, length + |
1141 |
|
|
* header can't exceed total amount of data available. |
1142 |
|
|
*/ |
1143 |
✓✓✗✓
|
12961 |
if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { |
1144 |
|
|
ASN1err(ASN1_F_ASN1_CHECK_TLEN, |
1145 |
|
|
ASN1_R_TOO_LONG); |
1146 |
|
|
asn1_tlc_clear(ctx); |
1147 |
|
|
return 0; |
1148 |
|
|
} |
1149 |
|
|
} |
1150 |
|
|
} |
1151 |
|
|
|
1152 |
✓✓ |
15814 |
if (i & 0x80) { |
1153 |
|
76 |
ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); |
1154 |
✓✗ |
76 |
asn1_tlc_clear(ctx); |
1155 |
|
76 |
return 0; |
1156 |
|
|
} |
1157 |
✓✓ |
15738 |
if (exptag >= 0) { |
1158 |
✓✓✗✓
|
13588 |
if ((exptag != ptag) || (expclass != pclass)) { |
1159 |
|
|
/* If type is OPTIONAL, not an error: |
1160 |
|
|
* indicate missing type. |
1161 |
|
|
*/ |
1162 |
✓✗ |
703 |
if (opt) |
1163 |
|
703 |
return -1; |
1164 |
|
|
asn1_tlc_clear(ctx); |
1165 |
|
|
ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); |
1166 |
|
|
return 0; |
1167 |
|
|
} |
1168 |
|
|
/* We have a tag and class match: |
1169 |
|
|
* assume we are going to do something with it */ |
1170 |
✓✗ |
12885 |
asn1_tlc_clear(ctx); |
1171 |
|
|
} |
1172 |
|
|
|
1173 |
✗✓ |
15035 |
if (i & 1) |
1174 |
|
|
plen = len - (p - q); |
1175 |
✓✓ |
15035 |
if (inf) |
1176 |
|
12885 |
*inf = i & 1; |
1177 |
✓✓ |
15035 |
if (cst) |
1178 |
|
11016 |
*cst = i & V_ASN1_CONSTRUCTED; |
1179 |
✓✓ |
15035 |
if (olen) |
1180 |
|
12885 |
*olen = plen; |
1181 |
✓✓ |
15035 |
if (oclass) |
1182 |
|
2150 |
*oclass = pclass; |
1183 |
✓✓ |
15035 |
if (otag) |
1184 |
|
2150 |
*otag = ptag; |
1185 |
|
|
|
1186 |
|
15035 |
*in = p; |
1187 |
|
15035 |
return 1; |
1188 |
|
|
} |