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