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