Annotation of src/usr.bin/asn1_compile/gen_decode.c, Revision 1.1
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: /*
! 37: RCSID("$KTH: gen_decode.c,v 1.18 2002/08/09 15:37:34 joda Exp $");
! 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,
! 93: "e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString,"
! 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,
! 127: "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,"
! 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"
! 164: "e = der_match_tag (p, len, CONTEXT, CONS, %d, &l);\n",
! 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,
! 224: "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,"
! 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;
! 258: case TApplication:
! 259: fprintf (codefile,
! 260: "e = der_match_tag_and_length (p, len, APPL, CONS, %d, "
! 261: "&reallen, &l);\n"
! 262: "FORW;\n"
! 263: "{\n"
! 264: "int dce_fix;\n"
! 265: "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
! 266: "return ASN1_BAD_FORMAT;\n",
! 267: t->application);
! 268: decode_type (name, t->subtype);
! 269: fprintf(codefile,
! 270: "if(dce_fix){\n"
! 271: "e = der_match_tag_and_length (p, len, "
! 272: "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
! 273: "FORW;\n"
! 274: "}\n"
! 275: "}\n");
! 276:
! 277: break;
! 278: default :
! 279: abort ();
! 280: }
! 281: }
! 282:
! 283: void
! 284: generate_type_decode (const Symbol *s)
! 285: {
! 286: fprintf (headerfile,
! 287: "int "
! 288: "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
! 289: s->gen_name, s->gen_name);
! 290:
! 291: fprintf (codefile, "#define FORW "
! 292: "if(e) goto fail; "
! 293: "p += l; "
! 294: "len -= l; "
! 295: "ret += l\n\n");
! 296:
! 297:
! 298: fprintf (codefile, "int\n"
! 299: "decode_%s(const unsigned char *p,"
! 300: " size_t len, %s *data, size_t *size)\n"
! 301: "{\n",
! 302: s->gen_name, s->gen_name);
! 303:
! 304: switch (s->type->type) {
! 305: case TInteger:
! 306: case TUInteger:
! 307: case TOctetString:
! 308: case TOID:
! 309: case TGeneralizedTime:
! 310: case TGeneralString:
! 311: case TBitString:
! 312: case TSequence:
! 313: case TSequenceOf:
! 314: case TApplication:
! 315: case TType:
! 316: fprintf (codefile,
! 317: "size_t ret = 0, reallen;\n"
! 318: "size_t l;\n"
! 319: "int e;\n\n");
! 320: fprintf (codefile, "memset(data, 0, sizeof(*data));\n");
! 321: fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */
! 322:
! 323: decode_type ("data", s->type);
! 324: fprintf (codefile,
! 325: "if(size) *size = ret;\n"
! 326: "return 0;\n");
! 327: fprintf (codefile,
! 328: "fail:\n"
! 329: "free_%s(data);\n"
! 330: "return e;\n",
! 331: s->gen_name);
! 332: break;
! 333: default:
! 334: abort ();
! 335: }
! 336: fprintf (codefile, "}\n\n");
! 337: }
! 338:
! 339: void
! 340: generate_seq_type_decode (const Symbol *s)
! 341: {
! 342: fprintf (headerfile,
! 343: "int decode_seq_%s(const unsigned char *, size_t, int, int, "
! 344: "%s *, size_t *);\n",
! 345: s->gen_name, s->gen_name);
! 346:
! 347: fprintf (codefile, "int\n"
! 348: "decode_seq_%s(const unsigned char *p, size_t len, int tag, "
! 349: "int optional, %s *data, size_t *size)\n"
! 350: "{\n",
! 351: s->gen_name, s->gen_name);
! 352:
! 353: fprintf (codefile,
! 354: "size_t newlen, oldlen;\n"
! 355: "size_t l, ret = 0;\n"
! 356: "int e;\n"
! 357: "int dce_fix;\n");
! 358:
! 359: fprintf (codefile,
! 360: "e = der_match_tag(p, len, CONTEXT, CONS, tag, &l);\n"
! 361: "if (e)\n"
! 362: "return e;\n");
! 363: fprintf (codefile,
! 364: "p += l;\n"
! 365: "len -= l;\n"
! 366: "ret += l;\n"
! 367: "e = der_get_length(p, len, &newlen, &l);\n"
! 368: "if (e)\n"
! 369: "return e;\n"
! 370: "p += l;\n"
! 371: "len -= l;\n"
! 372: "ret += l;\n"
! 373: "oldlen = len;\n"
! 374: "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n"
! 375: "return ASN1_BAD_FORMAT;\n"
! 376: "e = decode_%s(p, len, data, &l);\n"
! 377: "if (e)\n"
! 378: "return e;\n"
! 379: "p += l;\n"
! 380: "len -= l;\n"
! 381: "ret += l;\n"
! 382: "if (dce_fix) {\n"
! 383: "size_t reallen;\n\n"
! 384: "e = der_match_tag_and_length(p, len, "
! 385: "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
! 386: "if (e)\n"
! 387: "return e;\n"
! 388: "ret += l;\n"
! 389: "}\n",
! 390: s->gen_name);
! 391: fprintf (codefile,
! 392: "if(size) *size = ret;\n"
! 393: "return 0;\n");
! 394:
! 395: fprintf (codefile, "}\n\n");
! 396: }