[BACK]Return to gen_decode.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / asn1_compile

Annotation of src/usr.bin/asn1_compile/gen_decode.c, Revision 1.2

1.1       hin         1: /*
                      2:  * Copyright (c) 1997 - 2001 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: /*
1.2     ! biorn      37: RCSID("$KTH: gen_decode.c,v 1.21 2005/05/29 14:23:01 lha Exp $");
1.1       hin        38: */
                     39:
                     40: static void
                     41: decode_primitive (const char *typename, const char *name)
                     42: {
                     43:     fprintf (codefile,
                     44:             "e = decode_%s(p, len, %s, &l);\n"
                     45:             "FORW;\n",
                     46:             typename,
                     47:             name);
                     48: }
                     49:
                     50: static void
                     51: decode_type (const char *name, const Type *t)
                     52: {
                     53:     switch (t->type) {
                     54:     case TType:
                     55: #if 0
                     56:        decode_type (name, t->symbol->type);
                     57: #endif
                     58:        fprintf (codefile,
                     59:                 "e = decode_%s(p, len, %s, &l);\n"
                     60:                 "FORW;\n",
                     61:                 t->symbol->gen_name, name);
                     62:        break;
                     63:     case TInteger:
                     64:        if(t->members == NULL)
                     65:            decode_primitive ("integer", name);
                     66:        else {
                     67:            char *s;
                     68:            asprintf(&s, "(int*)%s", name);
                     69:            if(s == NULL)
                     70:                errx (1, "out of memory");
                     71:            decode_primitive ("integer", s);
                     72:            free(s);
                     73:        }
                     74:        break;
                     75:     case TUInteger:
                     76:        decode_primitive ("unsigned", name);
                     77:        break;
                     78:     case TEnumerated:
                     79:        decode_primitive ("enumerated", name);
                     80:        break;
                     81:     case TOctetString:
                     82:        decode_primitive ("octet_string", name);
                     83:        break;
                     84:     case TOID :
                     85:        decode_primitive ("oid", name);
                     86:        break;
                     87:     case TBitString: {
                     88:        Member *m;
                     89:        int tag = -1;
                     90:        int pos;
                     91:
                     92:        fprintf (codefile,
1.2     ! biorn      93:                 "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, PRIM, UT_BitString,"
1.1       hin        94:                 "&reallen, &l);\n"
                     95:                 "FORW;\n"
                     96:                 "if(len < reallen)\n"
                     97:                 "return ASN1_OVERRUN;\n"
                     98:                 "p++;\n"
                     99:                 "len--;\n"
                    100:                 "reallen--;\n"
                    101:                 "ret++;\n");
                    102:        pos = 0;
                    103:        for (m = t->members; m && tag != m->val; m = m->next) {
                    104:            while (m->val / 8 > pos / 8) {
                    105:                fprintf (codefile,
                    106:                         "p++; len--; reallen--; ret++;\n");
                    107:                pos += 8;
                    108:            }
                    109:            fprintf (codefile,
                    110:                     "%s->%s = (*p >> %d) & 1;\n",
                    111:                     name, m->gen_name, 7 - m->val % 8);
                    112:            if (tag == -1)
                    113:                tag = m->val;
                    114:        }
                    115:        fprintf (codefile,
                    116:                 "p += reallen; len -= reallen; ret += reallen;\n");
                    117:        break;
                    118:     }
                    119:     case TSequence: {
                    120:        Member *m;
                    121:        int tag = -1;
                    122:
                    123:        if (t->members == NULL)
                    124:            break;
                    125:
                    126:        fprintf (codefile,
1.2     ! biorn     127:                 "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,"
1.1       hin       128:                 "&reallen, &l);\n"
                    129:                 "FORW;\n"
                    130:                 "{\n"
                    131:                 "int dce_fix;\n"
                    132:                 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
                    133:                 "return ASN1_BAD_FORMAT;\n");
                    134:
                    135:        for (m = t->members; m && tag != m->val; m = m->next) {
                    136:            char *s;
                    137:
                    138:            asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
                    139:            if (0 && m->type->type == TType){
                    140:                if(m->optional)
                    141:                    fprintf (codefile,
                    142:                             "%s = malloc(sizeof(*%s));\n"
                    143:                             "if(%s == NULL) return ENOMEM;\n", s, s, s);
                    144:                fprintf (codefile,
                    145:                         "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n",
                    146:                         m->type->symbol->gen_name,
                    147:                         m->val,
                    148:                         m->optional,
                    149:                         s);
                    150:                if(m->optional)
                    151:                    fprintf (codefile,
                    152:                             "if (e == ASN1_MISSING_FIELD) {\n"
                    153:                             "free(%s);\n"
                    154:                             "%s = NULL;\n"
                    155:                             "e = l = 0;\n"
                    156:                             "}\n",
                    157:                             s, s);
                    158:
                    159:                fprintf (codefile, "FORW;\n");
                    160:
                    161:            }else{
                    162:                fprintf (codefile, "{\n"
                    163:                         "size_t newlen, oldlen;\n\n"
1.2     ! biorn     164:                         "e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, %d, &l);\n",
1.1       hin       165:                         m->val);
                    166:                fprintf (codefile,
                    167:                         "if (e)\n");
                    168:                if(m->optional)
                    169:                    /* XXX should look at e */
                    170:                    fprintf (codefile,
                    171:                             "%s = NULL;\n", s);
                    172:                else
                    173:                    fprintf (codefile,
                    174:                             "return e;\n");
                    175:                fprintf (codefile,
                    176:                         "else {\n");
                    177:                fprintf (codefile,
                    178:                         "p += l;\n"
                    179:                         "len -= l;\n"
                    180:                         "ret += l;\n"
                    181:                         "e = der_get_length (p, len, &newlen, &l);\n"
                    182:                         "FORW;\n"
                    183:                         "{\n"
                    184:
                    185:                         "int dce_fix;\n"
                    186:                         "oldlen = len;\n"
                    187:                         "if((dce_fix = fix_dce(newlen, &len)) < 0)"
                    188:                         "return ASN1_BAD_FORMAT;\n");
                    189:                if (m->optional)
                    190:                    fprintf (codefile,
                    191:                             "%s = malloc(sizeof(*%s));\n"
                    192:                             "if(%s == NULL) return ENOMEM;\n", s, s, s);
                    193:                decode_type (s, m->type);
                    194:                fprintf (codefile,
                    195:                         "if(dce_fix){\n"
                    196:                         "e = der_match_tag_and_length (p, len, "
                    197:                         "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
                    198:                         "FORW;\n"
                    199:                         "}else \n"
                    200:                         "len = oldlen - newlen;\n"
                    201:                         "}\n"
                    202:                         "}\n");
                    203:                fprintf (codefile,
                    204:                         "}\n");
                    205:            }
                    206:            if (tag == -1)
                    207:                tag = m->val;
                    208:            free (s);
                    209:        }
                    210:        fprintf(codefile,
                    211:                "if(dce_fix){\n"
                    212:                "e = der_match_tag_and_length (p, len, "
                    213:                "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
                    214:                "FORW;\n"
                    215:                "}\n"
                    216:                "}\n");
                    217:
                    218:        break;
                    219:     }
                    220:     case TSequenceOf: {
                    221:        char *n;
                    222:
                    223:        fprintf (codefile,
1.2     ! biorn     224:                 "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,"
1.1       hin       225:                 "&reallen, &l);\n"
                    226:                 "FORW;\n"
                    227:                 "if(len < reallen)\n"
                    228:                 "return ASN1_OVERRUN;\n"
                    229:                 "len = reallen;\n");
                    230:
                    231:        fprintf (codefile,
                    232:                 "{\n"
                    233:                 "size_t origlen = len;\n"
                    234:                 "int oldret = ret;\n"
                    235:                 "ret = 0;\n"
                    236:                 "(%s)->len = 0;\n"
                    237:                 "(%s)->val = NULL;\n"
                    238:                 "while(ret < origlen) {\n"
                    239:                 "(%s)->len++;\n"
                    240:                 "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n",
                    241:                 name, name, name, name, name, name, name);
                    242:        asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name);
                    243:        decode_type (n, t->subtype);
                    244:        fprintf (codefile,
                    245:                 "len = origlen - ret;\n"
                    246:                 "}\n"
                    247:                 "ret += oldret;\n"
                    248:                 "}\n");
                    249:        free (n);
                    250:        break;
                    251:     }
                    252:     case TGeneralizedTime:
                    253:        decode_primitive ("generalized_time", name);
                    254:        break;
                    255:     case TGeneralString:
                    256:        decode_primitive ("general_string", name);
                    257:        break;
1.2     ! biorn     258:     case TUTF8String:
        !           259:        decode_primitive ("utf8string", name);
        !           260:        break;
        !           261:     case TNull:
        !           262:        fprintf (codefile,
        !           263:                 "e = decode_nulltype(p, len, &l);\n"
        !           264:                 "FORW;\n");
        !           265:        break;
1.1       hin       266:     case TApplication:
                    267:        fprintf (codefile,
1.2     ! biorn     268:                 "e = der_match_tag_and_length (p, len, ASN1_C_APPL, CONS, %d, "
1.1       hin       269:                 "&reallen, &l);\n"
                    270:                 "FORW;\n"
                    271:                 "{\n"
                    272:                 "int dce_fix;\n"
                    273:                 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
                    274:                 "return ASN1_BAD_FORMAT;\n",
                    275:                 t->application);
                    276:        decode_type (name, t->subtype);
                    277:        fprintf(codefile,
                    278:                "if(dce_fix){\n"
                    279:                "e = der_match_tag_and_length (p, len, "
                    280:                "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
                    281:                "FORW;\n"
                    282:                "}\n"
                    283:                "}\n");
                    284:
                    285:        break;
1.2     ! biorn     286:     case TBoolean:
        !           287:        decode_primitive ("boolean", name);
        !           288:        break;
1.1       hin       289:     default :
                    290:        abort ();
                    291:     }
                    292: }
                    293:
                    294: void
                    295: generate_type_decode (const Symbol *s)
                    296: {
                    297:   fprintf (headerfile,
                    298:           "int    "
                    299:           "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
                    300:           s->gen_name, s->gen_name);
                    301:
                    302:   fprintf (codefile, "#define FORW "
                    303:           "if(e) goto fail; "
                    304:           "p += l; "
                    305:           "len -= l; "
                    306:           "ret += l\n\n");
                    307:
                    308:
                    309:   fprintf (codefile, "int\n"
                    310:           "decode_%s(const unsigned char *p,"
                    311:           " size_t len, %s *data, size_t *size)\n"
                    312:           "{\n",
                    313:           s->gen_name, s->gen_name);
                    314:
                    315:   switch (s->type->type) {
                    316:   case TInteger:
                    317:   case TUInteger:
1.2     ! biorn     318:   case TBoolean:
1.1       hin       319:   case TOctetString:
                    320:   case TOID:
                    321:   case TGeneralizedTime:
                    322:   case TGeneralString:
1.2     ! biorn     323:   case TUTF8String:
        !           324:   case TNull:
        !           325:   case TEnumerated:
1.1       hin       326:   case TBitString:
                    327:   case TSequence:
                    328:   case TSequenceOf:
                    329:   case TApplication:
                    330:   case TType:
                    331:     fprintf (codefile,
                    332:             "size_t ret = 0, reallen;\n"
                    333:             "size_t l;\n"
                    334:             "int e;\n\n");
                    335:     fprintf (codefile, "memset(data, 0, sizeof(*data));\n");
                    336:     fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */
                    337:
                    338:     decode_type ("data", s->type);
                    339:     fprintf (codefile,
                    340:             "if(size) *size = ret;\n"
                    341:             "return 0;\n");
                    342:     fprintf (codefile,
                    343:             "fail:\n"
                    344:             "free_%s(data);\n"
                    345:             "return e;\n",
                    346:             s->gen_name);
                    347:     break;
                    348:   default:
                    349:     abort ();
                    350:   }
                    351:   fprintf (codefile, "}\n\n");
                    352: }
                    353:
                    354: void
                    355: generate_seq_type_decode (const Symbol *s)
                    356: {
                    357:     fprintf (headerfile,
                    358:             "int decode_seq_%s(const unsigned char *, size_t, int, int, "
                    359:             "%s *, size_t *);\n",
                    360:             s->gen_name, s->gen_name);
                    361:
                    362:     fprintf (codefile, "int\n"
                    363:             "decode_seq_%s(const unsigned char *p, size_t len, int tag, "
                    364:             "int optional, %s *data, size_t *size)\n"
                    365:             "{\n",
                    366:             s->gen_name, s->gen_name);
                    367:
                    368:     fprintf (codefile,
                    369:             "size_t newlen, oldlen;\n"
                    370:             "size_t l, ret = 0;\n"
                    371:             "int e;\n"
                    372:             "int dce_fix;\n");
                    373:
                    374:     fprintf (codefile,
1.2     ! biorn     375:             "e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, tag, &l);\n"
1.1       hin       376:             "if (e)\n"
                    377:             "return e;\n");
                    378:     fprintf (codefile,
                    379:             "p += l;\n"
                    380:             "len -= l;\n"
                    381:             "ret += l;\n"
                    382:             "e = der_get_length(p, len, &newlen, &l);\n"
                    383:             "if (e)\n"
                    384:             "return e;\n"
                    385:             "p += l;\n"
                    386:             "len -= l;\n"
                    387:             "ret += l;\n"
                    388:             "oldlen = len;\n"
                    389:             "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n"
                    390:             "return ASN1_BAD_FORMAT;\n"
                    391:             "e = decode_%s(p, len, data, &l);\n"
                    392:             "if (e)\n"
                    393:             "return e;\n"
                    394:             "p += l;\n"
                    395:             "len -= l;\n"
                    396:             "ret += l;\n"
                    397:             "if (dce_fix) {\n"
                    398:             "size_t reallen;\n\n"
                    399:             "e = der_match_tag_and_length(p, len, "
                    400:             "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
                    401:             "if (e)\n"
                    402:             "return e;\n"
                    403:             "ret += l;\n"
                    404:             "}\n",
                    405:             s->gen_name);
                    406:     fprintf (codefile,
                    407:             "if(size) *size = ret;\n"
                    408:             "return 0;\n");
                    409:
                    410:     fprintf (codefile, "}\n\n");
                    411: }