LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - gen_decode.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 223 441 50.6 %
Date: 2024-04-21 15:09:00 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "gen_locl.h"
      35             : #include "lex.h"
      36             : 
      37             : RCSID("$Id$");
      38             : 
      39             : static void
      40        1026 : decode_primitive (const char *typename, const char *name, const char *forwstr)
      41             : {
      42             : #if 0
      43             :     fprintf (codefile,
      44             :              "e = decode_%s(p, len, %s, &l);\n"
      45             :              "%s;\n",
      46             :              typename,
      47             :              name,
      48             :              forwstr);
      49             : #else
      50        1042 :     fprintf (codefile,
      51             :              "e = der_get_%s(p, len, %s, &l);\n"
      52             :              "if(e) %s;\np += l; len -= l; ret += l;\n",
      53             :              typename,
      54             :              name,
      55             :              forwstr);
      56             : #endif
      57        1010 : }
      58             : 
      59             : static void
      60         717 : find_tag (const Type *t,
      61             :           Der_class *cl, Der_type *ty, unsigned *tag)
      62             : {
      63         722 :     switch (t->type) {
      64           0 :     case TBitString:
      65           0 :         *cl  = ASN1_C_UNIV;
      66           0 :         *ty  = PRIM;
      67           0 :         *tag = UT_BitString;
      68           0 :         break;
      69           0 :     case TBoolean:
      70           0 :         *cl  = ASN1_C_UNIV;
      71           0 :         *ty  = PRIM;
      72           0 :         *tag = UT_Boolean;
      73           0 :         break;
      74           0 :     case TChoice:
      75           0 :         errx(1, "Cannot have recursive CHOICE");
      76           0 :     case TEnumerated:
      77           0 :         *cl  = ASN1_C_UNIV;
      78           0 :         *ty  = PRIM;
      79           0 :         *tag = UT_Enumerated;
      80           0 :         break;
      81           0 :     case TGeneralString:
      82           0 :         *cl  = ASN1_C_UNIV;
      83           0 :         *ty  = PRIM;
      84           0 :         *tag = UT_GeneralString;
      85           0 :         break;
      86           0 :     case TTeletexString:
      87           0 :         *cl  = ASN1_C_UNIV;
      88           0 :         *ty  = PRIM;
      89           0 :         *tag = UT_TeletexString;
      90           0 :         break;
      91           0 :     case TGeneralizedTime:
      92           0 :         *cl  = ASN1_C_UNIV;
      93           0 :         *ty  = PRIM;
      94           0 :         *tag = UT_GeneralizedTime;
      95           0 :         break;
      96           0 :     case TIA5String:
      97           0 :         *cl  = ASN1_C_UNIV;
      98           0 :         *ty  = PRIM;
      99           0 :         *tag = UT_IA5String;
     100           0 :         break;
     101           0 :     case TInteger:
     102           0 :         *cl  = ASN1_C_UNIV;
     103           0 :         *ty  = PRIM;
     104           0 :         *tag = UT_Integer;
     105           0 :         break;
     106           0 :     case TNull:
     107           0 :         *cl  = ASN1_C_UNIV;
     108           0 :         *ty  = PRIM;
     109           0 :         *tag = UT_Null;
     110           0 :         break;
     111           0 :     case TOID:
     112           0 :         *cl  = ASN1_C_UNIV;
     113           0 :         *ty  = PRIM;
     114           0 :         *tag = UT_OID;
     115           0 :         break;
     116           0 :     case TOctetString:
     117           0 :         *cl  = ASN1_C_UNIV;
     118           0 :         *ty  = PRIM;
     119           0 :         *tag = UT_OctetString;
     120           0 :         break;
     121           0 :     case TPrintableString:
     122           0 :         *cl  = ASN1_C_UNIV;
     123           0 :         *ty  = PRIM;
     124           0 :         *tag = UT_PrintableString;
     125           0 :         break;
     126           0 :     case TSequence:
     127             :     case TSequenceOf:
     128           0 :         *cl  = ASN1_C_UNIV;
     129           0 :         *ty  = CONS;
     130           0 :         *tag = UT_Sequence;
     131           0 :         break;
     132           0 :     case TSet:
     133             :     case TSetOf:
     134           0 :         *cl  = ASN1_C_UNIV;
     135           0 :         *ty  = CONS;
     136           0 :         *tag = UT_Set;
     137           0 :         break;
     138         627 :     case TTag:
     139         627 :         *cl  = t->tag.tagclass;
     140        1805 :         *ty  = !(t->tag.tagclass != ASN1_C_UNIV &&
     141         551 :                  t->tag.tagenv == TE_EXPLICIT) &&
     142        1152 :             is_primitive_type(t->subtype) ? PRIM : CONS;
     143         627 :         *tag = t->tag.tagvalue; /* XXX is this correct? */
     144         627 :         break;
     145          95 :     case TType:
     146          95 :         if ((t->symbol->stype == Stype && t->symbol->type == NULL)
     147          95 :             || t->symbol->stype == SUndefined) {
     148           0 :             lex_error_message("%s is imported or still undefined, "
     149             :                               " can't generate tag checking data in CHOICE "
     150             :                               "without this information",
     151           0 :                               t->symbol->name);
     152           0 :             exit(1);
     153             :         }
     154          95 :         find_tag(t->symbol->type, cl, ty, tag);
     155          95 :         return;
     156           0 :     case TUTCTime:
     157           0 :         *cl  = ASN1_C_UNIV;
     158           0 :         *ty  = PRIM;
     159           0 :         *tag = UT_UTCTime;
     160           0 :         break;
     161           0 :     case TUTF8String:
     162           0 :         *cl  = ASN1_C_UNIV;
     163           0 :         *ty  = PRIM;
     164           0 :         *tag = UT_UTF8String;
     165           0 :         break;
     166           0 :     case TBMPString:
     167           0 :         *cl  = ASN1_C_UNIV;
     168           0 :         *ty  = PRIM;
     169           0 :         *tag = UT_BMPString;
     170           0 :         break;
     171           0 :     case TUniversalString:
     172           0 :         *cl  = ASN1_C_UNIV;
     173           0 :         *ty  = PRIM;
     174           0 :         *tag = UT_UniversalString;
     175           0 :         break;
     176           0 :     case TVisibleString:
     177           0 :         *cl  = ASN1_C_UNIV;
     178           0 :         *ty  = PRIM;
     179           0 :         *tag = UT_VisibleString;
     180           0 :         break;
     181           0 :     default:
     182           0 :         abort();
     183             :     }
     184             : }
     185             : 
     186             : static void
     187          19 : range_check(const char *name,
     188             :             const char *length,
     189             :             const char *forwstr,
     190             :             struct range *r)
     191             : {
     192          19 :     if (r->min == r->max + 2 || r->min < r->max)
     193          19 :         fprintf (codefile,
     194             :                  "if ((%s)->%s > %lld) {\n"
     195             :                  "e = ASN1_MAX_CONSTRAINT; %s;\n"
     196             :                  "}\n",
     197          18 :                  name, length, (long long)r->max, forwstr);
     198          19 :     if ((r->min - 1 == r->max || r->min < r->max) && r->min > 0)
     199          19 :         fprintf (codefile,
     200             :                  "if ((%s)->%s < %lld) {\n"
     201             :                  "e = ASN1_MIN_CONSTRAINT; %s;\n"
     202             :                  "}\n",
     203          18 :                  name, length, (long long)r->min, forwstr);
     204          19 :     if (r->max == r->min)
     205           0 :         fprintf (codefile,
     206             :                  "if ((%s)->%s != %lld) {\n"
     207             :                  "e = ASN1_EXACT_CONSTRAINT; %s;\n"
     208             :                  "}\n",
     209           0 :                  name, length, (long long)r->min, forwstr);
     210          19 : }
     211             : 
     212             : static int
     213        7486 : decode_type(const char *name, const Type *t, int optional, struct value *defval,
     214             :             const char *forwstr, const char *tmpstr, const char *dertype,
     215             :             unsigned int depth)
     216             : {
     217        7486 :     switch (t->type) {
     218        1539 :     case TType: {
     219        1539 :         if (optional)
     220          57 :             fprintf(codefile,
     221             :                     "%s = calloc(1, sizeof(*%s));\n"
     222             :                     "if (%s == NULL) %s;\n",
     223             :                     name, name, name, forwstr);
     224        1620 :         fprintf (codefile,
     225             :                  "e = decode_%s(p, len, %s, &l);\n",
     226        1539 :                  t->symbol->gen_name, name);
     227        1539 :         if (optional) {
     228          57 :             fprintf (codefile,
     229             :                      "if(e == ASN1_MISSING_FIELD) {\n"
     230             :                      "free(%s);\n"
     231             :                      "%s = NULL;\n"
     232             :                      "} else if (e) { %s; \n"
     233             :                      "} else {\n"
     234             :                      "p += l; len -= l; ret += l;\n"
     235             :                      "}\n",
     236             :                      name, name, forwstr);
     237        1482 :         } else if (defval) {
     238           0 :             fprintf(codefile,
     239             :                     "if (e == ASN1_MISSING_FIELD) {\n");
     240             :             /*
     241             :              * `name' starts with an ampersand here and is not an lvalue.
     242             :              * We skip the ampersand and then it is an lvalue.
     243             :              */
     244           0 :             gen_assign_defval(name + 1, defval);
     245           0 :             fprintf(codefile,
     246             :                     "} else if (e) { %s;\n"
     247             :                     "} else { p += l; len -= l; ret += l; }\n",
     248             :                     forwstr);
     249             :         } else {
     250        1482 :             fprintf (codefile,
     251             :                      "if(e) %s;\n",
     252             :                      forwstr);
     253        1482 :             fprintf (codefile,
     254             :                      "p += l; len -= l; ret += l;\n");
     255             :         }
     256        1458 :         break;
     257             :     }
     258         418 :     case TInteger:
     259         418 :         if(t->members) {
     260             :             /*
     261             :              * This will produce a worning, how its hard to fix since:
     262             :              * if its enum to an NameType, we can add appriate
     263             :              * type-cast. If its not though, we have to figure out if
     264             :              * there is negative enum enum and use appropriate
     265             :              * signness and size on the intertype we cast the result
     266             :              * too.
     267             :              */
     268          38 :             fprintf(codefile,
     269             :                     "{\n"
     270             :                     "int enumint;\n");
     271          38 :             decode_primitive ("integer", "&enumint", forwstr);
     272          38 :             fprintf(codefile,
     273             :                     "*%s = enumint;\n"
     274             :                     "}\n",
     275             :                     name);
     276         380 :         } else if (t->range == NULL) {
     277          76 :             decode_primitive ("heim_integer", name, forwstr);
     278         304 :         } else if (t->range->min < 0 &&
     279          56 :                    (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
     280          19 :             decode_primitive ("integer64", name, forwstr);
     281         285 :         } else if (t->range->min < 0) {
     282          38 :             decode_primitive ("integer", name, forwstr);
     283         247 :         } else if (t->range->max > UINT_MAX) {
     284           0 :             decode_primitive ("unsigned64", name, forwstr);
     285             :         } else {
     286         247 :             decode_primitive ("unsigned", name, forwstr);
     287             :         }
     288         396 :         break;
     289          36 :     case TBoolean:
     290          38 :       decode_primitive ("boolean", name, forwstr);
     291          36 :       break;
     292           0 :     case TEnumerated:
     293           0 :         decode_primitive ("enumerated", name, forwstr);
     294           0 :         break;
     295         266 :     case TOctetString:
     296         266 :         if (dertype) {
     297           0 :             fprintf(codefile,
     298             :                     "if (%s == CONS) {\n",
     299             :                     dertype);
     300           0 :             decode_primitive("octet_string_ber", name, forwstr);
     301           0 :             fprintf(codefile,
     302             :                     "} else {\n");
     303             :         }
     304         266 :         decode_primitive ("octet_string", name, forwstr);
     305         266 :         if (dertype)
     306           0 :             fprintf(codefile, "}\n");
     307         266 :         if (t->range)
     308           0 :             range_check(name, "length", forwstr, t->range);
     309         252 :         break;
     310         190 :     case TBitString: {
     311          10 :         Member *m;
     312         190 :         int pos = 0;
     313             : 
     314         190 :         if (HEIM_TAILQ_EMPTY(t->members)) {
     315         133 :             decode_primitive ("bit_string", name, forwstr);
     316         126 :             break;
     317             :         }
     318          57 :         fprintf(codefile,
     319             :                 "if (len < 1) return ASN1_OVERRUN;\n"
     320             :                 "p++; len--; ret++;\n");
     321          57 :         fprintf(codefile,
     322             :                 "do {\n"
     323             :                 "if (len < 1) break;\n");
     324         741 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     325         741 :             while (m->val / 8 > pos / 8) {
     326          57 :                 fprintf (codefile,
     327             :                          "p++; len--; ret++;\n"
     328             :                          "if (len < 1) break;\n");
     329          57 :                 pos += 8;
     330             :             }
     331         684 :             fprintf(codefile,
     332             :                     "(%s)->%s = (*p >> %d) & 1;\n",
     333         684 :                     name, m->gen_name, (int)(7 - m->val % 8));
     334             :         }
     335          57 :         fprintf(codefile,
     336             :                 "} while(0);\n");
     337          57 :         fprintf (codefile,
     338             :                  "p += len; ret += len;\n");
     339          54 :         break;
     340             :     }
     341         551 :     case TSequence: {
     342          29 :         Member *m;
     343             : 
     344         551 :         if (t->members == NULL)
     345           0 :             break;
     346             : 
     347        2470 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     348        1919 :             char *s = NULL;
     349             : 
     350        1919 :             if (m->ellipsis)
     351          95 :                 continue;
     352             : 
     353        1920 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
     354        1824 :                           name, m->gen_name) < 0 || s == NULL)
     355           0 :                 errx(1, "malloc");
     356        1824 :             decode_type(s, m->type, m->optional, m->defval, forwstr,
     357        1824 :                         m->gen_name, NULL, depth + 1);
     358        1824 :             free (s);
     359             :         }
     360             : 
     361         522 :         break;
     362             :     }
     363           0 :     case TSet: {
     364             :         /*
     365             :          * SET { ... } is the dumbest construct in ASN.1.  It's semantically
     366             :          * indistinguishable from SEQUENCE { ... } but in BER you can write the
     367             :          * fields in any order you wish, and in DER you have to write them in
     368             :          * lexicographic order.  If you want a reason to hate ASN.1, this is
     369             :          * certainly one, though the real reason to hate ASN.1 is BER/DER/CER,
     370             :          * and, really, all tag-length-value (TLV) encodings ever invented,
     371             :          * including Protocol Buffers.  Fortunately not all ASN.1 encoding
     372             :          * rules are TLV or otherwise self-describing.  "Self-describing"
     373             :          * encoding rules other than those meant to be [somewhat] readable by
     374             :          * humans, such as XML and JSON, are simply dumb.  But SET { ... } is a
     375             :          * truly special sort of dumb.  The only possible use of SET { ... }
     376             :          * might well be for ASN.1 mappings of XML schemas(?).
     377             :          */
     378           0 :         Member *m;
     379           0 :         unsigned int memno;
     380             : 
     381           0 :         if(t->members == NULL)
     382           0 :             break;
     383             : 
     384           0 :         fprintf(codefile, "{\n");
     385           0 :         fprintf(codefile, "uint64_t members = 0;\n");
     386           0 :         fprintf(codefile, "while(len > 0) {\n");
     387           0 :         fprintf(codefile,
     388             :                 "Der_class class;\n"
     389             :                 "Der_type type;\n"
     390             :                 "unsigned int tag;\n"
     391             :                 "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
     392             :                 "if(e) %s;\n", forwstr);
     393           0 :         fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
     394           0 :         memno = 0;
     395           0 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     396           0 :             Type *mst = m->type; /* Member sub-type */
     397           0 :             char *s;
     398             : 
     399           0 :             while (mst->type == TType) {
     400           0 :                 assert(mst->subtype || (mst->symbol && mst->symbol->type));
     401           0 :                 mst = mst->subtype ? mst->subtype : mst->symbol->type;
     402             :             }
     403           0 :             assert(mst->type == TTag);
     404             : 
     405           0 :             fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
     406           0 :                     classname(mst->tag.tagclass),
     407           0 :                     (mst->tag.tagclass == ASN1_C_UNIV || mst->tag.tagenv == TE_IMPLICIT) &&
     408           0 :                     is_primitive_type(mst->subtype) ? "PRIM" : "CONS",
     409           0 :                     valuename(mst->tag.tagclass, mst->tag.tagvalue));
     410             : 
     411           0 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
     412           0 :                 errx(1, "malloc");
     413           0 :             if(m->optional)
     414           0 :                 fprintf(codefile,
     415             :                         "%s = calloc(1, sizeof(*%s));\n"
     416             :                         "if (%s == NULL) { e = ENOMEM; %s; }\n",
     417             :                         s, s, s, forwstr);
     418           0 :             decode_type (s, mst, 0, NULL, forwstr, m->gen_name, NULL, depth + 1);
     419           0 :             free (s);
     420             : 
     421           0 :             fprintf(codefile, "members |= (1ULL << %u);\n", memno);
     422           0 :             memno++;
     423           0 :             fprintf(codefile, "break;\n");
     424             :         }
     425           0 :         fprintf(codefile,
     426             :                 "default:\n"
     427             :                 "return ASN1_MISPLACED_FIELD;\n"
     428             :                 "break;\n");
     429           0 :         fprintf(codefile, "}\n");
     430           0 :         fprintf(codefile, "}\n");
     431           0 :         memno = 0;
     432           0 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     433           0 :             char *s;
     434             : 
     435           0 :             if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL)
     436           0 :                 errx(1, "malloc");
     437           0 :             fprintf(codefile, "if((members & (1ULL << %u)) == 0)\n", memno);
     438           0 :             if(m->optional)
     439           0 :                 fprintf(codefile, "%s = NULL;\n", s);
     440           0 :             else if(m->defval)
     441           0 :                 gen_assign_defval(s, m->defval);
     442             :             else
     443           0 :                 fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
     444           0 :             free(s);
     445           0 :             memno++;
     446             :         }
     447           0 :         fprintf(codefile, "}\n");
     448           0 :         break;
     449             :     }
     450         304 :     case TSetOf:
     451             :     case TSequenceOf: {
     452         304 :         char *n = NULL;
     453         304 :         char *sname = NULL;
     454             : 
     455         304 :         fprintf (codefile,
     456             :                  "{\n"
     457             :                  "size_t %s_origlen = len;\n"
     458             :                  "size_t %s_oldret = ret;\n"
     459             :                  "size_t %s_olen = 0;\n"
     460             :                  "void *%s_tmp;\n"
     461             :                  "ret = 0;\n"
     462             :                  "(%s)->len = 0;\n"
     463             :                  "(%s)->val = NULL;\n",
     464             :                  tmpstr,
     465             :                  tmpstr,
     466             :                  tmpstr,
     467             :                  tmpstr,
     468             :                  name,
     469             :                  name);
     470             : 
     471         304 :         fprintf (codefile,
     472             :                  "while(ret < %s_origlen) {\n"
     473             :                  "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
     474             :                  "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
     475             :                  "%s_olen = %s_nlen;\n"
     476             :                  "%s_tmp = realloc((%s)->val, %s_olen);\n"
     477             :                  "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
     478             :                  "(%s)->val = %s_tmp;\n",
     479             :                  tmpstr,
     480             :                  tmpstr, tmpstr, name,
     481             :                  tmpstr, tmpstr, forwstr,
     482             :                  tmpstr, tmpstr,
     483             :                  tmpstr, name, tmpstr,
     484             :                  tmpstr, forwstr,
     485             :                  name, tmpstr);
     486             : 
     487         304 :         if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
     488           0 :             errx(1, "malloc");
     489         304 :         if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
     490           0 :             errx(1, "malloc");
     491         304 :         decode_type(n, t->subtype, 0, NULL, forwstr, sname, NULL, depth + 1);
     492         304 :         fprintf (codefile,
     493             :                  "(%s)->len++;\n"
     494             :                  "len = %s_origlen - ret;\n"
     495             :                  "}\n"
     496             :                  "ret += %s_oldret;\n"
     497             :                  "}\n",
     498             :                  name,
     499             :                  tmpstr, tmpstr);
     500         304 :         if (t->range)
     501          19 :             range_check(name, "len", forwstr, t->range);
     502         304 :         free (n);
     503         304 :         free (sname);
     504         304 :         break;
     505             :     }
     506           0 :     case TGeneralizedTime:
     507           0 :         decode_primitive ("generalized_time", name, forwstr);
     508           0 :         break;
     509          18 :     case TGeneralString:
     510          19 :         decode_primitive ("general_string", name, forwstr);
     511          18 :         break;
     512           0 :     case TTeletexString:
     513           0 :         decode_primitive ("general_string", name, forwstr);
     514           0 :         break;
     515        3819 :     case TTag:{
     516        3819 :         char *tname = NULL, *typestring = NULL;
     517        3819 :         char *ide = NULL;
     518        3819 :         int replace_tag = 0;
     519        9595 :         int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
     520        5852 :                      t->tag.tagenv == TE_EXPLICIT) &&
     521        2033 :             is_primitive_type(t->subtype);
     522             : 
     523             :         /*
     524             :          * XXX See the comments in gen_encode() about this.
     525             :          */
     526        3819 :         if (t->tag.tagenv == TE_IMPLICIT && !prim &&
     527         114 :             t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
     528          90 :             t->subtype->type != TChoice) {
     529          95 :             if (t->subtype->symbol &&
     530          57 :                 (t->subtype->type == TSequence ||
     531          54 :                  t->subtype->type == TSet))
     532           0 :                 replace_tag = 1;
     533          95 :             else if (t->subtype->symbol &&
     534          57 :                      strcmp(t->subtype->symbol->name, "HEIM_ANY") != 0)
     535          57 :                 replace_tag = 1;
     536        3724 :         } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
     537          19 :             replace_tag = is_tagged_type(t->subtype->symbol->type);
     538             : 
     539        3819 :         if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
     540           0 :             errx(1, "malloc");
     541             : 
     542        3819 :         fprintf(codefile,
     543             :                 "{\n"
     544             :                 "size_t %s_datalen;\n"
     545             :                 "Der_type %s;\n",
     546             :                 tmpstr, typestring);
     547        3819 :         if (replace_tag)
     548          76 :             fprintf(codefile,
     549             :                     "const unsigned char *psave%u = p;\n"
     550             :                     "unsigned char *pcopy%u;\n"
     551             :                     "size_t lensave%u, lsave%u;\n",
     552             :                     depth, depth, depth, depth);
     553        3743 :         else if (support_ber)
     554           0 :             fprintf(codefile,
     555             :                     "int is_indefinite%u;\n", depth);
     556        3819 :         if (!replace_tag)
     557        3743 :             fprintf(codefile,
     558             :                     "size_t %s_oldlen;\n", tmpstr);
     559             : 
     560        3819 :         fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
     561             :                 "&%s_datalen, &l);\n",
     562        3819 :                 classname(t->tag.tagclass),
     563             :                 typestring,
     564        3819 :                 valuename(t->tag.tagclass, t->tag.tagvalue),
     565             :                 tmpstr);
     566             : 
     567             :         /* XXX hardcode for now */
     568        3819 :         if (!replace_tag && support_ber && t->subtype->type == TOctetString) {
     569           0 :             ide = typestring;
     570             :         } else {
     571        3961 :             fprintf(codefile,
     572             :                     "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
     573             :                     typestring,
     574             :                     prim ? "PRIM" : "CONS");
     575             :         }
     576             : 
     577        3819 :         if(optional) {
     578         893 :             fprintf(codefile,
     579             :                     "if(e) {\n"
     580             :                     "%s = NULL;\n"
     581             :                     "} else {\n"
     582             :                      "%s = calloc(1, sizeof(*%s));\n"
     583             :                      "if (%s == NULL) { e = ENOMEM; %s; }\n",
     584             :                      name, name, name, name, forwstr);
     585        2926 :         } else if (defval) {
     586           0 :             char *s;
     587             : 
     588           0 :             if (asprintf(&s, "*(%s)", name) == -1 || s == NULL)
     589           0 :                 return ENOMEM;
     590           0 :             fprintf(codefile, "if (e && e != ASN1_MISSING_FIELD) %s;\n", forwstr);
     591           0 :             fprintf(codefile, "if (e == ASN1_MISSING_FIELD) {\n");
     592           0 :             gen_assign_defval(s, defval);
     593           0 :             free(s);
     594           0 :             fprintf(codefile, "e = 0; l= 0;\n} else {\n");
     595             :         } else {
     596        2926 :             fprintf(codefile, "if (e) %s;\n", forwstr);
     597             :         }
     598             : 
     599        3819 :         if (replace_tag)
     600          76 :             fprintf(codefile,
     601             :                     "lsave%u = %s_datalen + l;\n"
     602             :                     "lensave%u = len;\n"
     603             :                     "e = der_replace_tag(p, len, &pcopy%u, &len, asn1_tag_class_%s, %s, asn1_tag_tag_%s);\n"
     604             :                     "if (e) %s;\n"
     605             :                     "p = pcopy%u;\n",
     606          72 :                     depth, tmpstr, depth, depth, t->subtype->symbol->gen_name,
     607             :                     prim ? "PRIM" : "CONS",
     608          76 :                     t->subtype->symbol->gen_name,
     609             :                     forwstr, depth);
     610             :         else
     611        3743 :             fprintf(codefile,
     612             :                     "p += l; len -= l; ret += l;\n");
     613        3819 :         if (!replace_tag)
     614        3743 :             fprintf(codefile,
     615             :                     "%s_oldlen = len;\n",
     616             :                     tmpstr);
     617        3819 :         if (support_ber && !replace_tag)
     618           0 :             fprintf (codefile,
     619             :                      "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
     620             :                      "{ e = ASN1_BAD_FORMAT; %s; }\n"
     621             :                      "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
     622             :                      depth, tmpstr, forwstr, depth, forwstr);
     623        3819 :         else if (!replace_tag)
     624        3743 :             fprintf(codefile,
     625             :                     "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
     626             :                     "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
     627        3819 :         if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
     628           0 :             errx(1, "malloc");
     629             :         /*
     630             :          * If `replace_tag' then here `p' and `len' will be the copy mutated by
     631             :          * der_replace_tag().
     632             :          */
     633        3819 :         decode_type(name, t->subtype, 0, NULL, forwstr, tname, ide, depth + 1);
     634        3819 :         if (replace_tag)
     635          76 :             fprintf(codefile,
     636             :                     "p = psave%u + lsave%u;\n"
     637             :                     "len = lensave%u - lsave%u;\n"
     638             :                     "ret += lsave%u - l;\n"
     639             :                     "free(pcopy%u);\n",
     640             :                     depth, depth, depth, depth, depth, depth);
     641        3743 :         else if(support_ber)
     642           0 :             fprintf(codefile,
     643             :                     "if(is_indefinite%u){\n"
     644             :                     "len += 2;\n"
     645             :                     "e = der_match_tag_and_length(p, len, "
     646             :                     "(Der_class)0, &%s, UT_EndOfContent, "
     647             :                     "&%s_datalen, &l);\n"
     648             :                     "if(e) %s;\n"
     649             :                     "p += l; len -= l; ret += l;\n"
     650             :                     "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
     651             :                     "} else \n",
     652             :                     depth,
     653             :                     typestring,
     654             :                     tmpstr,
     655             :                     forwstr,
     656             :                     typestring, forwstr);
     657        3819 :         if (!replace_tag)
     658        3743 :             fprintf(codefile,
     659             :                     "len = %s_oldlen - %s_datalen;\n",
     660             :                     tmpstr, tmpstr);
     661        3819 :         if (optional)
     662         893 :             fprintf(codefile, "}\n");
     663        2926 :         else if (defval)
     664           0 :             fprintf(codefile, "}\n");
     665        3819 :         fprintf(codefile, "}\n");
     666        3819 :         free(tname);
     667        3819 :         free(typestring);
     668        3819 :         break;
     669             :     }
     670         171 :     case TChoice: {
     671         171 :         Member *m, *have_ellipsis = NULL;
     672         171 :         const char *els = "";
     673             : 
     674         171 :         if (t->members == NULL)
     675           0 :             break;
     676             : 
     677         817 :         HEIM_TAILQ_FOREACH(m, t->members, members) {
     678         646 :             const Type *tt = m->type;
     679         646 :             char *s = NULL;
     680          34 :             Der_class cl;
     681          34 :             Der_type  ty;
     682          34 :             unsigned  tag;
     683             : 
     684         646 :             if (m->ellipsis) {
     685          19 :                 have_ellipsis = m;
     686          19 :                 continue;
     687             :             }
     688             : 
     689         627 :             find_tag(tt, &cl, &ty, &tag);
     690             : 
     691        1254 :             fprintf(codefile,
     692             :                     "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
     693             :                     els,
     694             :                     classname(cl),
     695         627 :                     ty ? "CONS" : "PRIM",
     696             :                     valuename(cl, tag));
     697         627 :             fprintf(codefile,
     698             :                     "(%s)->element = %s;\n",
     699             :                     name, m->label);
     700         660 :             if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
     701         627 :                           name, m->gen_name) < 0 || s == NULL)
     702           0 :                 errx(1, "malloc");
     703         627 :             decode_type(s, m->type, m->optional, NULL, forwstr, m->gen_name,
     704             :                         NULL, depth + 1);
     705         627 :             free(s);
     706         627 :             fprintf(codefile,
     707             :                     "}\n");
     708         627 :             els = "else ";
     709             :         }
     710         171 :         if (have_ellipsis) {
     711          19 :             fprintf(codefile,
     712             :                     "else {\n"
     713             :                     "(%s)->element = %s;\n"
     714             :                     "(%s)->u.%s.data = calloc(1, len);\n"
     715             :                     "if ((%s)->u.%s.data == NULL) {\n"
     716             :                     "e = ENOMEM; %s;\n"
     717             :                     "}\n"
     718             :                     "(%s)->u.%s.length = len;\n"
     719             :                     "memcpy((%s)->u.%s.data, p, len);\n"
     720             :                     "p += len;\n"
     721             :                     "ret += len;\n"
     722             :                     "len = 0;\n"
     723             :                     "}\n",
     724             :                     name, have_ellipsis->label,
     725             :                     name, have_ellipsis->gen_name,
     726             :                     name, have_ellipsis->gen_name,
     727             :                     forwstr,
     728             :                     name, have_ellipsis->gen_name,
     729             :                     name, have_ellipsis->gen_name);
     730             :         } else {
     731         152 :             fprintf(codefile,
     732             :                     "else {\n"
     733             :                     "e = ASN1_PARSE_ERROR;\n"
     734             :                     "%s;\n"
     735             :                     "}\n",
     736             :                     forwstr);
     737             :         }
     738         162 :         break;
     739             :     }
     740           0 :     case TUTCTime:
     741           0 :         decode_primitive ("utctime", name, forwstr);
     742           0 :         break;
     743          72 :     case TUTF8String:
     744          76 :         decode_primitive ("utf8string", name, forwstr);
     745          72 :         break;
     746           0 :     case TPrintableString:
     747           0 :         decode_primitive ("printable_string", name, forwstr);
     748           0 :         break;
     749           0 :     case TIA5String:
     750           0 :         decode_primitive ("ia5_string", name, forwstr);
     751           0 :         break;
     752           0 :     case TBMPString:
     753           0 :         decode_primitive ("bmp_string", name, forwstr);
     754           0 :         break;
     755           0 :     case TUniversalString:
     756           0 :         decode_primitive ("universal_string", name, forwstr);
     757           0 :         break;
     758           0 :     case TVisibleString:
     759           0 :         decode_primitive ("visible_string", name, forwstr);
     760           0 :         break;
     761          19 :     case TNull:
     762          19 :         fprintf (codefile, "/* NULL */\n");
     763          18 :         break;
     764          72 :     case TOID:
     765          76 :         decode_primitive ("oid", name, forwstr);
     766          72 :         break;
     767           0 :     default :
     768           0 :         abort ();
     769             :     }
     770        7092 :     return 0;
     771             : }
     772             : 
     773             : void
     774         912 : generate_type_decode (const Symbol *s)
     775             : {
     776         912 :     int preserve = preserve_type(s->name) ? TRUE : FALSE;
     777             : 
     778         960 :     fprintf (codefile, "int ASN1CALL\n"
     779             :              "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE,"
     780             :              " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n"
     781             :              "{\n",
     782         912 :              s->gen_name, s->gen_name);
     783             : 
     784         912 :     switch (s->type->type) {
     785         912 :     case TInteger:
     786             :     case TBoolean:
     787             :     case TOctetString:
     788             :     case TOID:
     789             :     case TGeneralizedTime:
     790             :     case TGeneralString:
     791             :     case TTeletexString:
     792             :     case TUTF8String:
     793             :     case TPrintableString:
     794             :     case TIA5String:
     795             :     case TBMPString:
     796             :     case TUniversalString:
     797             :     case TVisibleString:
     798             :     case TUTCTime:
     799             :     case TNull:
     800             :     case TEnumerated:
     801             :     case TBitString:
     802             :     case TSequence:
     803             :     case TSequenceOf:
     804             :     case TSet:
     805             :     case TSetOf:
     806             :     case TTag:
     807             :     case TType:
     808             :     case TChoice:
     809         912 :         fprintf (codefile,
     810             :                  "size_t ret = 0;\n"
     811             :                  "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
     812             :                  "int e HEIMDAL_UNUSED_ATTRIBUTE;\n");
     813         912 :         if (preserve)
     814           0 :             fprintf (codefile, "const unsigned char *begin = p;\n");
     815             : 
     816         912 :         fprintf (codefile, "\n");
     817         912 :         fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
     818             : 
     819         912 :         decode_type("data", s->type, 0, NULL, "goto fail", "Top", NULL, 1);
     820         912 :         if (preserve)
     821           0 :             fprintf (codefile,
     822             :                      "data->_save.data = calloc(1, ret);\n"
     823             :                      "if (data->_save.data == NULL) { \n"
     824             :                      "e = ENOMEM; goto fail; \n"
     825             :                      "}\n"
     826             :                      "data->_save.length = ret;\n"
     827             :                      "memcpy(data->_save.data, begin, ret);\n");
     828         912 :         fprintf (codefile,
     829             :                  "if(size) *size = ret;\n"
     830             :                  "return 0;\n");
     831         960 :         fprintf (codefile,
     832             :                  "fail:\n"
     833             :                  "free_%s(data);\n"
     834             :                  "return e;\n",
     835         912 :                  s->gen_name);
     836         912 :         break;
     837           0 :     default:
     838           0 :         abort ();
     839             :     }
     840         912 :     fprintf (codefile, "}\n\n");
     841         912 : }

Generated by: LCOV version 1.14