LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - gen_encode.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 214 286 74.8 %
Date: 2023-11-21 12:31:41 Functions: 6 6 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             : 
      36             : /* XXX same as der_length_tag */
      37             : static size_t
      38         304 : length_tag(unsigned int tag)
      39             : {
      40         304 :     size_t len = 0;
      41             : 
      42         304 :     if(tag <= 30)
      43         288 :         return 1;
      44           0 :     while(tag) {
      45           0 :         tag /= 128;
      46           0 :         len++;
      47             :     }
      48           0 :     return len + 1;
      49             : }
      50             : 
      51             : static void
      52        1026 : encode_primitive (const char *typename, const char *name)
      53             : {
      54        1028 :     fprintf (codefile,
      55             :              "e = der_put_%s(p, len, %s, &l);\n"
      56             :              "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
      57             :              typename,
      58             :              name);
      59         992 : }
      60             : 
      61             : const char *
      62       29849 : classname(Der_class class)
      63             : {
      64       29849 :     const char *cn[] = { "ASN1_C_UNIV", "ASN1_C_APPL",
      65             :                          "ASN1_C_CONTEXT", "ASN1_C_PRIV" };
      66       29849 :     if ((int)class >= sizeof(cn) / sizeof(cn[0]))
      67           0 :         return "???";
      68       29849 :     return cn[class];
      69             : }
      70             : 
      71             : 
      72             : const char *
      73       29773 : valuename(Der_class class, int value)
      74             : {
      75        1567 :     static char s[32];
      76        1567 :     struct {
      77             :         int value;
      78             :         const char *s;
      79       29773 :     } *p, values[] = {
      80             : #define X(Y) { Y, #Y }
      81             :         X(UT_BMPString),
      82             :         X(UT_BitString),
      83             :         X(UT_Boolean),
      84             :         X(UT_EmbeddedPDV),
      85             :         X(UT_Enumerated),
      86             :         X(UT_External),
      87             :         X(UT_GeneralString),
      88             :         X(UT_GeneralizedTime),
      89             :         X(UT_GraphicString),
      90             :         X(UT_IA5String),
      91             :         X(UT_Integer),
      92             :         X(UT_Null),
      93             :         X(UT_NumericString),
      94             :         X(UT_OID),
      95             :         X(UT_ObjectDescriptor),
      96             :         X(UT_OctetString),
      97             :         X(UT_PrintableString),
      98             :         X(UT_Real),
      99             :         X(UT_RelativeOID),
     100             :         X(UT_Sequence),
     101             :         X(UT_Set),
     102             :         X(UT_TeletexString),
     103             :         X(UT_UTCTime),
     104             :         X(UT_UTF8String),
     105             :         X(UT_UniversalString),
     106             :         X(UT_VideotexString),
     107             :         X(UT_VisibleString),
     108             : #undef X
     109             :         { -1, NULL }
     110             :     };
     111       29773 :     if(class == ASN1_C_UNIV) {
     112      250059 :         for(p = values; p->value != -1; p++)
     113      250059 :             if(p->value == value)
     114       15732 :                 return p->s;
     115             :     }
     116       14041 :     snprintf(s, sizeof(s), "%d", value);
     117       14041 :     return s;
     118             : }
     119             : 
     120             : static int
     121        7486 : encode_type (const char *name, const Type *t, const char *tmpstr)
     122             : {
     123        7486 :     int constructed = 1;
     124             : 
     125        7486 :     switch (t->type) {
     126        1539 :     case TType:
     127             : #if 0
     128             :         encode_type (name, t->symbol->type);
     129             : #endif
     130        1620 :         fprintf (codefile,
     131             :                  "e = encode_%s(p, len, %s, &l);\n"
     132             :                  "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
     133        1539 :                  t->symbol->gen_name, name);
     134        1539 :         constructed = !is_primitive_type(t);
     135        1539 :         break;
     136         418 :     case TInteger:
     137         418 :         if(t->members) {
     138          38 :             fprintf(codefile,
     139             :                     "{\n"
     140             :                     "int enumint = (int)*%s;\n",
     141             :                     name);
     142          38 :             encode_primitive("integer", "&enumint");
     143          38 :             fprintf(codefile, "}\n;");
     144         380 :         } else if (t->range == NULL) {
     145          76 :             encode_primitive("heim_integer", name);
     146         304 :         } else if (t->range->min < 0 &&
     147          56 :                    (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
     148          19 :             encode_primitive("integer64", name);
     149         285 :         } else if (t->range->min < 0) {
     150          38 :             encode_primitive("integer", name);
     151         247 :         } else if (t->range->max > UINT_MAX) {
     152           0 :             encode_primitive("unsigned64", name);
     153             :         } else {
     154         247 :             encode_primitive("unsigned", name);
     155             :         }
     156             : 
     157         396 :         constructed = 0;
     158         396 :         break;
     159          36 :     case TBoolean:
     160          38 :         encode_primitive ("boolean", name);
     161          38 :         constructed = 0;
     162          38 :         break;
     163         252 :     case TOctetString:
     164         266 :         encode_primitive ("octet_string", name);
     165         266 :         constructed = 0;
     166         266 :         break;
     167         190 :     case TBitString: {
     168          10 :         Member *m;
     169          10 :         int pos;
     170             : 
     171         190 :         if (HEIM_TAILQ_EMPTY(t->members)) {
     172         133 :             encode_primitive("bit_string", name);
     173         133 :             constructed = 0;
     174         133 :             break;
     175             :         }
     176             : 
     177          57 :         fprintf (codefile, "{\n"
     178             :                  "unsigned char c = 0;\n");
     179          57 :         if (!rfc1510_bitstring)
     180          57 :             fprintf (codefile,
     181             :                      "int rest = 0;\n"
     182             :                      "int bit_set = 0;\n");
     183             : #if 0
     184             :         pos = t->members->prev->val;
     185             :         /* fix for buggy MIT (and OSF?) code */
     186             :         if (pos > 31)
     187             :             abort ();
     188             : #endif
     189             :         /*
     190             :          * It seems that if we do not always set pos to 31 here, the MIT
     191             :          * code will do the wrong thing.
     192             :          *
     193             :          * I hate ASN.1 (and DER), but I hate it even more when everybody
     194             :          * has to screw it up differently.
     195             :          */
     196          57 :         pos = HEIM_TAILQ_LAST(t->members, memhead)->val;
     197          57 :         if (rfc1510_bitstring) {
     198           0 :             if (pos < 31)
     199           0 :                 pos = 31;
     200             :         }
     201             : 
     202         741 :         HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
     203         741 :             while (m->val / 8 < pos / 8) {
     204          57 :                 if (!rfc1510_bitstring)
     205          57 :                     fprintf (codefile,
     206             :                              "if (c != 0 || bit_set) {\n");
     207          57 :                 fprintf (codefile,
     208             :                          "if (len < 1) return ASN1_OVERFLOW;\n"
     209             :                          "*p-- = c; len--; ret++;\n");
     210          57 :                 if (!rfc1510_bitstring)
     211          57 :                     fprintf (codefile,
     212             :                              "if (!bit_set) {\n"
     213             :                              "rest = 0;\n"
     214             :                              "while(c) { \n"
     215             :                              "if (c & 1) break;\n"
     216             :                              "c = c >> 1;\n"
     217             :                              "rest++;\n"
     218             :                              "}\n"
     219             :                              "bit_set = 1;\n"
     220             :                              "}\n"
     221             :                              "}\n");
     222          57 :                 fprintf (codefile,
     223             :                          "c = 0;\n");
     224          57 :                 pos -= 8;
     225             :             }
     226         720 :             fprintf (codefile,
     227             :                      "if((%s)->%s) {\n"
     228             :                      "c |= 1<<%d;\n",
     229         684 :                      name, m->gen_name, (int)(7 - m->val % 8));
     230         684 :             fprintf (codefile,
     231             :                      "}\n");
     232             :         }
     233             : 
     234          57 :         if (!rfc1510_bitstring)
     235          57 :             fprintf (codefile,
     236             :                      "if (c != 0 || bit_set) {\n");
     237          57 :         fprintf (codefile,
     238             :                  "if (len < 1) return ASN1_OVERFLOW;\n"
     239             :                  "*p-- = c; len--; ret++;\n");
     240          57 :         if (!rfc1510_bitstring)
     241          57 :             fprintf (codefile,
     242             :                      "if (!bit_set) {\n"
     243             :                      "rest = 0;\n"
     244             :                      "if(c) { \n"
     245             :                      "while(c) { \n"
     246             :                      "if (c & 1) break;\n"
     247             :                      "c = c >> 1;\n"
     248             :                      "rest++;\n"
     249             :                      "}\n"
     250             :                      "}\n"
     251             :                      "}\n"
     252             :                      "}\n");
     253             : 
     254          57 :         fprintf (codefile,
     255             :                  "if (len < 1) return ASN1_OVERFLOW;\n"
     256             :                  "*p-- = %s;\n"
     257             :                  "len -= 1;\n"
     258             :                  "ret += 1;\n"
     259             :                  "}\n\n",
     260          57 :                  rfc1510_bitstring ? "0" : "rest");
     261          57 :         constructed = 0;
     262          57 :         break;
     263             :     }
     264           0 :     case TEnumerated : {
     265           0 :         encode_primitive ("enumerated", name);
     266           0 :         constructed = 0;
     267           0 :         break;
     268             :     }
     269             : 
     270         551 :     case TSet:
     271             :     case TSequence: {
     272          29 :         Member *m;
     273             : 
     274         551 :         if (t->members == NULL)
     275           0 :             break;
     276             : 
     277        2470 :         HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
     278        1919 :             char *s = NULL;
     279             : 
     280        1919 :             if (m->ellipsis)
     281          95 :                 continue;
     282             : 
     283        1920 :             if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
     284           0 :                 errx(1, "malloc");
     285        1824 :             fprintf(codefile, "/* %s */\n", m->name);
     286        1824 :             if (m->optional)
     287         950 :                 fprintf (codefile,
     288             :                          "if(%s) ",
     289             :                          s);
     290         874 :             else if(m->defval)
     291           0 :                 gen_compare_defval(s + 1, m->defval);
     292        1824 :             fprintf (codefile, "{\n");
     293        1824 :             fprintf (codefile, "size_t %s_oldret HEIMDAL_UNUSED_ATTRIBUTE = ret;\n", tmpstr);
     294        1824 :             fprintf (codefile, "ret = 0;\n");
     295        1824 :             encode_type (s, m->type, m->gen_name);
     296        1824 :             fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
     297        1824 :             fprintf (codefile, "}\n");
     298        1824 :             free (s);
     299             :         }
     300         522 :         break;
     301             :     }
     302           0 :     case TSetOf: {
     303             : 
     304           0 :         fprintf(codefile,
     305             :                 "{\n"
     306             :                 "heim_octet_string *val;\n"
     307             :                 "size_t elen = 0, totallen = 0;\n"
     308             :                 "int eret = 0;\n");
     309             : 
     310           0 :         fprintf(codefile,
     311             :                 "if ((%s)->len > UINT_MAX/sizeof(val[0]))\n"
     312             :                 "return ERANGE;\n",
     313             :                 name);
     314             : 
     315           0 :         fprintf(codefile,
     316             :                 "val = calloc(1, sizeof(val[0]) * (%s)->len);\n"
     317             :                 "if (val == NULL && (%s)->len != 0) return ENOMEM;\n",
     318             :                 name, name);
     319             : 
     320           0 :         fprintf(codefile,
     321             :                 "for(i = 0; i < (int)(%s)->len; i++) {\n",
     322             :                 name);
     323             : 
     324           0 :         fprintf(codefile,
     325             :                 "ASN1_MALLOC_ENCODE(%s, val[i].data, "
     326             :                 "val[i].length, &(%s)->val[i], &elen, eret);\n",
     327           0 :                 t->subtype->symbol->gen_name,
     328             :                 name);
     329             : 
     330           0 :         fprintf(codefile,
     331             :                 "if(eret) {\n"
     332             :                 "i--;\n"
     333             :                 "while (i >= 0) {\n"
     334             :                 "free(val[i].data);\n"
     335             :                 "i--;\n"
     336             :                 "}\n"
     337             :                 "free(val);\n"
     338             :                 "return eret;\n"
     339             :                 "}\n"
     340             :                 "totallen += elen;\n"
     341             :                 "}\n");
     342             : 
     343           0 :         fprintf(codefile,
     344             :                 "if (totallen > len) {\n"
     345             :                 "for (i = 0; i < (int)(%s)->len; i++) {\n"
     346             :                 "free(val[i].data);\n"
     347             :                 "}\n"
     348             :                 "free(val);\n"
     349             :                 "return ASN1_OVERFLOW;\n"
     350             :                 "}\n",
     351             :                 name);
     352             : 
     353           0 :         fprintf(codefile,
     354             :                 "qsort(val, (%s)->len, sizeof(val[0]), _heim_der_set_sort);\n",
     355             :                 name);
     356             : 
     357           0 :         fprintf (codefile,
     358             :                  "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
     359             :                  "p -= val[i].length;\n"
     360             :                  "ret += val[i].length;\n"
     361             :                  "memcpy(p + 1, val[i].data, val[i].length);\n"
     362             :                  "free(val[i].data);\n"
     363             :                  "}\n"
     364             :                  "free(val);\n"
     365             :                  "}\n",
     366             :                  name);
     367           0 :         break;
     368             :     }
     369         304 :     case TSequenceOf: {
     370         304 :         char *sname = NULL;
     371         304 :         char *n = NULL;
     372             : 
     373         304 :         fprintf (codefile,
     374             :                  "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
     375             :                  "size_t %s_for_oldret = ret;\n"
     376             :                  "ret = 0;\n",
     377             :                  name, tmpstr);
     378         304 :         if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL)
     379           0 :             errx(1, "malloc");
     380         304 :         if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
     381           0 :             errx(1, "malloc");
     382         304 :         encode_type (n, t->subtype, sname);
     383         304 :         fprintf (codefile,
     384             :                  "ret += %s_for_oldret;\n"
     385             :                  "}\n",
     386             :                  tmpstr);
     387         304 :         free (n);
     388         304 :         free (sname);
     389         304 :         break;
     390             :     }
     391           0 :     case TGeneralizedTime:
     392           0 :         encode_primitive ("generalized_time", name);
     393           0 :         constructed = 0;
     394           0 :         break;
     395          18 :     case TGeneralString:
     396          19 :         encode_primitive ("general_string", name);
     397          19 :         constructed = 0;
     398          19 :         break;
     399           0 :     case TTeletexString:
     400           0 :         encode_primitive ("general_string", name);
     401           0 :         constructed = 0;
     402           0 :         break;
     403        3819 :     case TTag: {
     404        3819 :         char *tname = NULL;
     405        3819 :         int replace_tag = 0;
     406        9595 :         int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
     407        5852 :                      t->tag.tagenv == TE_EXPLICIT) &&
     408        2033 :             is_primitive_type(t->subtype);
     409         201 :         int c;
     410        3819 :         if (asprintf (&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
     411           0 :             errx(1, "malloc");
     412             :         /*
     413             :          * HACK HACK HACK
     414             :          *
     415             :          * This is part of the fix to the bug where we treated IMPLICIT tags of
     416             :          * named types as EXPLICIT.  I.e.
     417             :          *
     418             :          *  Foo ::= SEQUENCE { ... }
     419             :          *  Bar ::= SEQUENCE { foo [0] IMPLICIT Foo }
     420             :          *
     421             :          * would get a context [0] constructed tag *and* a universal sequence
     422             :          * constructed tag when it should get only the first tag.
     423             :          *
     424             :          * Properly fixing this would require changing the signatures of the
     425             :          * encode, length, and decode functions we generate to take an optional
     426             :          * tag to replace the one the encoder would generate / decoder would
     427             :          * expect.  That would change the ABI, which... isn't stable, but it's
     428             :          * a bit soon to make that change.
     429             :          *
     430             :          * So, we're looking for IMPLICIT, and if we see any, we generate code
     431             :          * to replace the tag.
     432             :          *
     433             :          * On the decode side we need to know what tag to restore.  For this we
     434             :          * generate enums in the generated header.
     435             :          *
     436             :          * NOTE: We *do* "replace" the tags of IMPLICIT-tagged primitive types,
     437             :          *       but our primitive codec functions leave those tags out, which
     438             :          *       is why we don't have to der_replace_tag() them here.
     439             :          */
     440             :         /*
     441             :          * If the tag is IMPLICIT and it's not primitive and the subtype is not
     442             :          * any kind of structure...
     443             :          */
     444        3819 :         if (t->tag.tagenv == TE_IMPLICIT && !prim &&
     445         114 :             t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
     446          90 :             t->subtype->type != TChoice) {
     447             :             /* If it is a named type for a structured thing */
     448          95 :             if (t->subtype->symbol &&
     449          57 :                 (t->subtype->type == TSequence ||
     450          54 :                  t->subtype->type == TSet))
     451           0 :                 replace_tag = 1;
     452          95 :             else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "heim_any"))
     453          54 :                 replace_tag = 1;
     454        3724 :         } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
     455             :             /*
     456             :              * Because the subtype is named we are generating its codec
     457             :              * functions, and those will be adding their UNIVERSAL or whatever
     458             :              * tags unlike our raw primtive codec library.
     459             :              */
     460          19 :             replace_tag = is_tagged_type(t->subtype->symbol->type);
     461             : 
     462        3619 :         if (replace_tag)
     463         277 :             fprintf(codefile,
     464             :                     "{ unsigned char *psave_%s = p, *pfree_%s = NULL;\n"
     465             :                     "size_t l2_%s, lensave_%s = len;\n"
     466             :                     "len = length_%s(%s);\n"
     467             :                     /* Allocate a temp buffer for the encoder */
     468             :                     "if ((p = pfree_%s = calloc(1, len)) == NULL) return ENOMEM;\n"
     469             :                     /* Make p point to the last byte of the allocated buf */
     470             :                     "p += len - 1;\n",
     471             :                     tmpstr, tmpstr, tmpstr, tmpstr,
     472          76 :                     t->subtype->symbol->gen_name, name, tmpstr);
     473             : 
     474             :         /* XXX Currently we generate code that leaks `pfree_%s` here.  */
     475        3819 :         c = encode_type (name, t->subtype, tname);
     476             :         /* Explicit non-UNIVERSAL tags are always constructed */
     477        3819 :         if (!c && t->tag.tagclass != ASN1_C_UNIV && t->tag.tagenv == TE_EXPLICIT)
     478         874 :             c = 1;
     479        3819 :         if (replace_tag)
     480          76 :             fprintf(codefile,
     481             :                     "if (len) { free(pfree_%s); return EINVAL; }\n"
     482             :                     /*
     483             :                      * Here we have `p' pointing to one byte before the buffer
     484             :                      * we allocated above.
     485             :                      *
     486             :                      *     [ T_wrong | LL | VVVV ] // temp buffer
     487             :                      *   ^   ^
     488             :                      *   |   |
     489             :                      *   |   \
     490             :                      *   \    +-- p + 1
     491             :                      *    +-- p
     492             :                      *
     493             :                      * psave_<fieldName> still points to the last byte in the
     494             :                      * original buffer passed in where we should write the
     495             :                      * encoding of <fieldName>.
     496             :                      *
     497             :                      * We adjust psave_<fieldName> to point to before the TLV
     498             :                      * encoding of <fieldName> (with wrong tag) in the original
     499             :                      * buffer (this may NOT be a valid pointer, but we won't
     500             :                      * dereference it):
     501             :                      *
     502             :                      * [ ... | T_wrong | LL | VVVVV | ... ] // original buffer
     503             :                      *      ^
     504             :                      *      |
     505             :                      *      \
     506             :                      *       +-- psave_<fieldName>
     507             :                      */
     508             :                     "psave_%s -= l;\n"
     509             :                     /*
     510             :                      * We further adjust psave_<fieldName> to point to the last
     511             :                      * byte of what should be the T(ag) of the TLV encoding of
     512             :                      * <fieldName> (this is now a valid pointer), then...
     513             :                      *
     514             :                      *         |<--->| (not written yet)
     515             :                      *         |     | |<-------->| (not written yet)
     516             :                      * [ ... | T_right | LL | VVVVV | ... ] // original buffer
     517             :                      *                ^
     518             :                      *                |
     519             :                      *                \
     520             :                      *                 +-- psave_<fieldName>
     521             :                      */
     522             :                     "psave_%s += asn1_tag_length_%s;\n"
     523             :                     /*
     524             :                      * ...copy the L(ength)V(alue) of the TLV encoding of
     525             :                      * <fieldName>.
     526             :                      *
     527             :                      * [ ... | T_right | LL | VVVVV | ... ] // original buffer
     528             :                      *                   ^
     529             :                      *                   |
     530             :                      *                   \
     531             :                      *                    +-- psave_<fieldName> + 1
     532             :                      *
     533             :                      *             |<----->| length is
     534             :                      *             |       | `l' - asn1_tag_length_<fieldName>
     535             :                      * [ T_wrong | LL | VVVV ] // temp buffer
     536             :                      *   ^         ^
     537             :                      *   |         |
     538             :                      *   |         \
     539             :                      *   \          +-- p + 1 + asn1_tag_length_%s
     540             :                      *    +-- p + 1
     541             :                      */
     542             :                     "memcpy(psave_%s + 1, p + 1 + asn1_tag_length_%s, l - asn1_tag_length_%s);\n"
     543             :                     /*
     544             :                      * Encode the IMPLICIT tag.  Recall that encoders like
     545             :                      * der_put_tag() take a pointer to the last byte they
     546             :                      * should write to, and a length of bytes to the left of
     547             :                      * that that they are allowed to write into.
     548             :                      *
     549             :                      * [ ... | T_right | LL | VVVVV | ... ] // original buffer
     550             :                      *                ^
     551             :                      *                |
     552             :                      *                \
     553             :                      *                 +-- psave_<fieldName>
     554             :                      */
     555             :                     "e = der_put_tag(psave_%s, %zu, %s, %s, %d, &l2_%s);\n"
     556             :                     "if (e) { free(pfree_%s); return e; }\n"
     557             :                     /* Restore `len' and adjust it (see `p' below) */
     558             :                     "len = lensave_%s - (l + %zu - asn1_tag_length_%s);\n"
     559             :                     /*
     560             :                      * Adjust `ret' to account for the difference in size
     561             :                      * between the length of the right and wrong tags.
     562             :                      */
     563             :                     "ret += %zu - asn1_tag_length_%s;\n"
     564             :                     /* Free the buffer and restore `p' */
     565             :                     "free(pfree_%s);\n"
     566             :                     /*
     567             :                      * Make `p' point into the original buffer again, to one
     568             :                      * byte before the bytes we wrote:
     569             :                      *
     570             :                      * [ ... | T_right | LL | VVVVV | ... ] // original buffer
     571             :                      *      ^
     572             :                      *      |
     573             :                      *      \
     574             :                      *       +-- p
     575             :                      */
     576             :                     "p = psave_%s - (1 + %zu - asn1_tag_length_%s); }\n",
     577          72 :                     tmpstr, tmpstr, tmpstr, t->subtype->symbol->name,
     578          76 :                     tmpstr, t->subtype->symbol->name, t->subtype->symbol->name,
     579          76 :                     tmpstr, length_tag(t->tag.tagvalue),
     580          76 :                     classname(t->tag.tagclass),
     581             :                     c ? "CONS" : "PRIM",
     582          72 :                     t->tag.tagvalue,
     583             :                     tmpstr,
     584             : 
     585          72 :                     tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name,
     586          72 :                     length_tag(t->tag.tagvalue), t->subtype->symbol->name,
     587          76 :                     tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name);
     588             :         else
     589        7486 :             fprintf(codefile,
     590             :                     "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n"
     591             :                     "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
     592        3743 :                     classname(t->tag.tagclass),
     593             :                     c ? "CONS" : "PRIM",
     594        3743 :                     valuename(t->tag.tagclass, t->tag.tagvalue));
     595        3819 :         free(tname);
     596        3819 :         constructed = c;
     597        3819 :         break;
     598             :     }
     599         171 :     case TChoice:{
     600         171 :         Member *m, *have_ellipsis = NULL;
     601         171 :         char *s = NULL;
     602             : 
     603         171 :         if (t->members == NULL)
     604           0 :             break;
     605             : 
     606         171 :         fprintf(codefile, "\n");
     607             : 
     608         171 :         if (asprintf (&s, "(%s)", name) < 0 || s == NULL)
     609           0 :             errx(1, "malloc");
     610         171 :         fprintf(codefile, "switch(%s->element) {\n", s);
     611             : 
     612         817 :         HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
     613         646 :             char *s2 = NULL;
     614             : 
     615         646 :             if (m->ellipsis) {
     616          19 :                 have_ellipsis = m;
     617          19 :                 continue;
     618             :             }
     619             : 
     620         627 :             fprintf (codefile, "case %s: {", m->label);
     621         660 :             if (asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&",
     622         627 :                          s, m->gen_name) < 0 || s2 == NULL)
     623           0 :                 errx(1, "malloc");
     624         627 :             if (m->optional)
     625           0 :                 fprintf (codefile, "if(%s) {\n", s2);
     626         627 :             fprintf (codefile, "size_t %s_oldret = ret;\n", tmpstr);
     627         627 :             fprintf (codefile, "ret = 0;\n");
     628         627 :             constructed = encode_type (s2, m->type, m->gen_name);
     629         627 :             fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
     630         627 :             if(m->optional)
     631           0 :                 fprintf (codefile, "}\n");
     632         627 :             fprintf(codefile, "break;\n");
     633         627 :             fprintf(codefile, "}\n");
     634         627 :             free (s2);
     635             :         }
     636         171 :         free (s);
     637         171 :         if (have_ellipsis) {
     638          19 :             fprintf(codefile,
     639             :                     "case %s: {\n"
     640             :                     "if (len < (%s)->u.%s.length)\n"
     641             :                     "return ASN1_OVERFLOW;\n"
     642             :                     "p -= (%s)->u.%s.length;\n"
     643             :                     "ret += (%s)->u.%s.length;\n"
     644             :                     "memcpy(p + 1, (%s)->u.%s.data, (%s)->u.%s.length);\n"
     645             :                     "break;\n"
     646             :                     "}\n",
     647             :                     have_ellipsis->label,
     648             :                     name, have_ellipsis->gen_name,
     649             :                     name, have_ellipsis->gen_name,
     650             :                     name, have_ellipsis->gen_name,
     651             :                     name, have_ellipsis->gen_name,
     652             :                     name, have_ellipsis->gen_name);
     653             :         }
     654         171 :         fprintf(codefile, "};\n");
     655         162 :         break;
     656             :     }
     657          72 :     case TOID:
     658          76 :         encode_primitive ("oid", name);
     659          76 :         constructed = 0;
     660          76 :         break;
     661           0 :     case TUTCTime:
     662           0 :         encode_primitive ("utctime", name);
     663           0 :         constructed = 0;
     664           0 :         break;
     665          72 :     case TUTF8String:
     666          76 :         encode_primitive ("utf8string", name);
     667          76 :         constructed = 0;
     668          76 :         break;
     669           0 :     case TPrintableString:
     670           0 :         encode_primitive ("printable_string", name);
     671           0 :         constructed = 0;
     672           0 :         break;
     673           0 :     case TIA5String:
     674           0 :         encode_primitive ("ia5_string", name);
     675           0 :         constructed = 0;
     676           0 :         break;
     677           0 :     case TBMPString:
     678           0 :         encode_primitive ("bmp_string", name);
     679           0 :         constructed = 0;
     680           0 :         break;
     681           0 :     case TUniversalString:
     682           0 :         encode_primitive ("universal_string", name);
     683           0 :         constructed = 0;
     684           0 :         break;
     685           0 :     case TVisibleString:
     686           0 :         encode_primitive ("visible_string", name);
     687           0 :         constructed = 0;
     688           0 :         break;
     689          19 :     case TNull:
     690          19 :         fprintf (codefile, "/* NULL */\n");
     691          19 :         constructed = 0;
     692          19 :         break;
     693           0 :     default:
     694           0 :         abort ();
     695             :     }
     696        7486 :     return constructed;
     697             : }
     698             : 
     699             : void
     700         912 : generate_type_encode (const Symbol *s)
     701             : {
     702         960 :     fprintf (codefile, "int ASN1CALL\n"
     703             :              "encode_%s(unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE, size_t len HEIMDAL_UNUSED_ATTRIBUTE,"
     704             :              " const %s *data, size_t *size)\n"
     705             :              "{\n",
     706         912 :              s->gen_name, s->gen_name);
     707             : 
     708         912 :     switch (s->type->type) {
     709         912 :     case TInteger:
     710             :     case TBoolean:
     711             :     case TOctetString:
     712             :     case TGeneralizedTime:
     713             :     case TGeneralString:
     714             :     case TTeletexString:
     715             :     case TUTCTime:
     716             :     case TUTF8String:
     717             :     case TPrintableString:
     718             :     case TIA5String:
     719             :     case TBMPString:
     720             :     case TUniversalString:
     721             :     case TVisibleString:
     722             :     case TNull:
     723             :     case TBitString:
     724             :     case TEnumerated:
     725             :     case TOID:
     726             :     case TSequence:
     727             :     case TSequenceOf:
     728             :     case TSet:
     729             :     case TSetOf:
     730             :     case TTag:
     731             :     case TType:
     732             :     case TChoice:
     733         912 :         fprintf (codefile,
     734             :                  "size_t ret HEIMDAL_UNUSED_ATTRIBUTE = 0;\n"
     735             :                  "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
     736             :                  "int i HEIMDAL_UNUSED_ATTRIBUTE, e HEIMDAL_UNUSED_ATTRIBUTE;\n\n");
     737             : 
     738         912 :         encode_type("data", s->type, "Top");
     739             : 
     740         912 :         fprintf (codefile, "*size = ret;\n"
     741             :                  "return 0;\n");
     742         912 :         break;
     743           0 :     default:
     744           0 :         abort ();
     745             :     }
     746         912 :     fprintf (codefile, "}\n\n");
     747         912 : }

Generated by: LCOV version 1.14