[Redbutton-devel] SF.net SVN: redbutton: [436] redbutton-author/trunk
Brought to you by:
skilvington
|
From: <ski...@us...> - 2007-10-15 08:50:55
|
Revision: 436
http://redbutton.svn.sourceforge.net/redbutton/?rev=436&view=rev
Author: skilvington
Date: 2007-10-15 01:50:51 -0700 (Mon, 15 Oct 2007)
Log Message:
-----------
initial import of mhegd (opposite of mhegc) not finished yet
Modified Paths:
--------------
redbutton-author/trunk/Makefile
redbutton-author/trunk/asn1tag.h
redbutton-author/trunk/ccc.y
Added Paths:
-----------
redbutton-author/trunk/der_decode.c
redbutton-author/trunk/der_decode.h
redbutton-author/trunk/mhegd.c
Modified: redbutton-author/trunk/Makefile
===================================================================
--- redbutton-author/trunk/Makefile 2007-10-15 08:49:09 UTC (rev 435)
+++ redbutton-author/trunk/Makefile 2007-10-15 08:50:51 UTC (rev 436)
@@ -4,6 +4,8 @@
# for vasprintf
DEFS=-D_GNU_SOURCE
+LIBS=
+
LEX=flex
YACC=bison
#LEX=lex
@@ -11,18 +13,29 @@
DESTDIR=/usr/local
-OBJS= mhegc.o \
- lex.parser.o \
- parser.o \
- der_encode.o \
- asn1tag.o \
- utils.o
+MHEGC_OBJS= mhegc.o \
+ lex.parser.o \
+ parser.o \
+ der_encode.o \
+ asn1tag.o \
+ utils.o
+MHEGD_OBJS= mhegd.o \
+ asn1decode.o \
+ der_decode.o \
+ asn1tag.o \
+ utils.o
+
TARDIR=`basename ${PWD}`
-mhegc: parser.h ${OBJS}
- ${CC} ${CFLAGS} ${DEFS} -o mhegc ${OBJS} ${LIBS}
+all: mhegc mhegd
+mhegc: parser.h ${MHEGC_OBJS}
+ ${CC} ${CFLAGS} ${DEFS} -o mhegc ${MHEGC_OBJS} ${LIBS}
+
+mhegd: asn1decode.h ${MHEGD_OBJS}
+ ${CC} ${CFLAGS} ${DEFS} -o mhegd ${MHEGD_OBJS} ${LIBS}
+
ccc: ccc.y ccc.l asn1type.o
${LEX} -i -t ccc.l > lex.ccc.c
${YACC} -b ccc -d ccc.y
@@ -32,17 +45,21 @@
cat grammar | ./ccc -l parser.l -p parser.c -h parser.h -t tokens.h
${LEX} -i -t parser.l > lex.parser.c
+asn1decode.c asn1decode.h: asn1decode.c.* asn1decode.h.* grammar asn1tag.h ccc
+ cat grammar | ./ccc -d asn1decode.c -e asn1decode.h
+
.c.o:
${CC} ${CFLAGS} ${DEFS} -c $<
berdecode: berdecode.c
${CC} ${CFLAGS} ${DEFS} -o berdecode berdecode.c
-install: mhegc
+install: mhegc mhegd
install -m 755 mhegc ${DESTDIR}/bin
+ install -m 755 mhegd ${DESTDIR}/bin
clean:
- rm -f mhegc ccc lex.ccc.c ccc.tab.[ch] lex.parser.c parser.[lch] tokens.h *.o berdecode core
+ rm -f mhegc mhegd ccc lex.ccc.c ccc.tab.[ch] lex.parser.c parser.[lch] tokens.h asn1decode.[ch] *.o berdecode core
tar:
make clean
Modified: redbutton-author/trunk/asn1tag.h
===================================================================
--- redbutton-author/trunk/asn1tag.h 2007-10-15 08:49:09 UTC (rev 435)
+++ redbutton-author/trunk/asn1tag.h 2007-10-15 08:50:51 UTC (rev 436)
@@ -589,6 +589,8 @@
#define ASN1TAGCLASS_ENUMERATED ((ASN1CLASS_UNIVERSAL << 24) | ASN1TAG_ENUMERATED)
#define ASN1TAGCLASS_SEQUENCE ((ASN1CLASS_UNIVERSAL << 24) | ASN1TAG_SEQUENCE)
#define ASN1TAGCLASS_SET ((ASN1CLASS_UNIVERSAL << 24) | ASN1TAG_SET)
+/* alias */
+#define ASN1TAGCLASS_Null ASN1TAGCLASS_NULL
/* the ASN1 types in the grammar that are not CONTEXT class types */
#define ASN1TAGCLASS_JointIsoItuIdentifier ASN1TAGCLASS_INTEGER
Modified: redbutton-author/trunk/ccc.y
===================================================================
--- redbutton-author/trunk/ccc.y 2007-10-15 08:49:09 UTC (rev 435)
+++ redbutton-author/trunk/ccc.y 2007-10-15 08:50:51 UTC (rev 436)
@@ -58,6 +58,9 @@
struct buf parse_hdr; /* parse_Xxx() prototypes for the parser */
struct buf parse_enum_hdr; /* parse_Xxx() prototypes for enum values */
struct buf is_hdr; /* is_Xxx() prototypes for the parser */
+ struct buf decode_fns; /* asn1decode_Xxx() C functions for mhegd */
+ struct buf decode_is_fns; /* is_Xxx() C functions for mhegd */
+ struct buf decode_hdr; /* asn1decode_Xxx() prototypes for mhegd */
} state;
/* header for files we generate */
@@ -191,12 +194,14 @@
char *parser_name = NULL;
char *header_name = NULL;
char *tokens_name = NULL;
+ char *decode_name = NULL;
+ char *decode_hdr_name = NULL;
int arg;
struct str_list *t;
char header[PATH_MAX];
char footer[PATH_MAX];
- while((arg = getopt(argc, argv, "l:p:h:t:")) != EOF)
+ while((arg = getopt(argc, argv, "l:p:h:t:d:e:")) != EOF)
{
switch(arg)
{
@@ -216,6 +221,14 @@
tokens_name = optarg;
break;
+ case 'd':
+ decode_name = optarg;
+ break;
+
+ case 'e':
+ decode_hdr_name = optarg;
+ break;
+
default:
usage(prog_name);
break;
@@ -234,6 +247,9 @@
buf_init(&state.parse_hdr);
buf_init(&state.parse_enum_hdr);
buf_init(&state.is_hdr);
+ buf_init(&state.decode_fns);
+ buf_init(&state.decode_is_fns);
+ buf_init(&state.decode_hdr);
yyparse();
@@ -312,13 +328,46 @@
fclose(tokens_file);
}
+ /* output ASN1 decoder file */
+ if(decode_name != NULL)
+ {
+ FILE *decode_file = safe_fopen(decode_name, "w");
+ fprintf(decode_file, STANDARD_HEADER);
+ /* output the header if there is one */
+ snprintf(header, sizeof(header), "%s.header", decode_name);
+ file_append(decode_file, header);
+ /* output our stuff */
+ fprintf(decode_file, "%s", state.decode_fns.str);
+ fprintf(decode_file, "%s", state.decode_is_fns.str);
+ /* output the footer if there is one */
+ snprintf(footer, sizeof(footer), "%s.footer", decode_name);
+ file_append(decode_file, footer);
+ fclose(decode_file);
+ }
+
+ /* output ASN1 decoder header file */
+ if(decode_hdr_name != NULL)
+ {
+ FILE *decode_hdr_file = safe_fopen(decode_hdr_name, "w");
+ fprintf(decode_hdr_file, STANDARD_HEADER);
+ /* output the header if there is one */
+ snprintf(header, sizeof(header), "%s.header", decode_hdr_name);
+ file_append(decode_hdr_file, header);
+ /* output our stuff */
+ fprintf(decode_hdr_file, "%s", state.decode_hdr.str);
+ /* output the footer if there is one */
+ snprintf(footer, sizeof(footer), "%s.footer", decode_hdr_name);
+ file_append(decode_hdr_file, footer);
+ fclose(decode_hdr_file);
+ }
+
return EXIT_SUCCESS;
}
void
usage(char *prog_name)
{
- fprintf(stderr, "Syntax: %s [-l <lexer-file>] [-p <parser-c-file>] [-h <parser-h-file>] [-t <tokens-file>]\n", prog_name);
+ fprintf(stderr, "Syntax: %s [-l <lexer-file>] [-p <parser-c-file>] [-h <parser-h-file>] [-t <tokens-file>] [-d <decode-c-file>] [-e <decode-h-file>]\n", prog_name);
exit(EXIT_FAILURE);
}
@@ -371,6 +420,7 @@
struct item *next;
unsigned int nitems;
unsigned int enum_val;
+ bool first;
/* prototype for the parse_Xxx function */
buf_append(&state.parse_hdr, "void parse_%s(struct node *);\n", name);
@@ -727,6 +777,217 @@
}
buf_append(&state.is_fns, "}\n\n");
+ /* ASN1 decode prototypes */
+ buf_append(&state.decode_hdr, "int asn1decode_%s(FILE *, FILE *, int);\n", name);
+ buf_append(&state.decode_hdr, "bool is_%s(unsigned char, unsigned int);\n\n", name);
+
+ /* ASN1 decode_Xxx() functions */
+ buf_append(&state.decode_fns, "int asn1decode_%s(FILE *der, FILE *out, int length)\n{\n", name);
+ buf_append(&state.decode_fns, "\tint left = length;\n");
+ buf_append(&state.decode_fns, "\tint sublen;\n");
+ buf_append(&state.decode_fns, "\tstruct der_tag tag;\n\n");
+ buf_append(&state.decode_fns, "\tverbose(\"<%s>\\n\");\n\n", name);
+
+ /* ASN1 is_Xxx() functions */
+ buf_append(&state.decode_is_fns, "bool is_%s(unsigned char class, unsigned int number)\n{\n", name);
+
+ /* count how many non-literal items there are */
+ nitems = 0;
+ for(item=state.items; item; item=item->next)
+ if(item->type != IT_LITERAL)
+ nitems ++;
+
+ /* is it the special case */
+ if(strcmp(name, "OctetString") == 0)
+ {
+ /* decode_Xxx() function */
+ buf_append(&state.decode_fns, "\tif((sublen = der_decode_Tag(der, &tag)) < 0)\n");
+ buf_append(&state.decode_fns, "\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\tleft -= sublen;\n\n");
+ buf_append(&state.decode_fns, "\tif(is_%s(tag.class, tag.number))\n\t{\n", name);
+ buf_append(&state.decode_fns, "\t\tder_decode_%s(der, out, tag.length);\n", name);
+ buf_append(&state.decode_fns, "\t\tleft -= tag.length;\n");
+ buf_append(&state.decode_fns, "\t}\n\telse\n");
+ buf_append(&state.decode_fns, "\t{\n\t\treturn der_error(\"%s\");\n\t}\n\n", name);
+ /* is_Xxx() function */
+ buf_append(&state.decode_is_fns, "\treturn MATCH_TAGCLASS(class, number, ASN1TAGCLASS_OCTETSTRING);\n");
+ }
+ /* has it got only 1 non-literal item */
+ else if(nitems == 1)
+ {
+ /* output any literals at the start */
+ for(item=state.items; item && item->type==IT_LITERAL; item=item->next)
+ buf_append(&state.decode_fns, "\tfprintf(out, \"%%s \", %s);\n\n", item->name);
+ /* decode the item */
+ buf_append(&state.decode_fns, "\tif((sublen = der_decode_Tag(der, &tag)) < 0)\n");
+ buf_append(&state.decode_fns, "\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\tleft -= sublen;\n\n");
+ buf_append(&state.decode_fns, "\tif(is_%s(tag.class, tag.number))\n\t{\n", item->name);
+ buf_append(&state.decode_fns, "\t\tasn1decode_%s(der, out, tag.length);\n", item->name);
+ buf_append(&state.decode_fns, "\t\tleft -= tag.length;\n");
+ buf_append(&state.decode_fns, "\t}\n\telse\n");
+ buf_append(&state.decode_fns, "\t{\n\t\treturn der_error(\"%s\");\n\t}\n\n", name);
+ /* is_Xxx() function */
+ buf_append(&state.decode_is_fns, "\treturn is_%s(class, number);\n", item->name);
+ /* output any literals at the end */
+ item = item->next;
+ while(item)
+ {
+ /* assert */
+ if(item->type != IT_LITERAL)
+ fatal("Trailing non-literal");
+ buf_append(&state.decode_fns, "\tfprintf(out, %s);\n\n", item->name);
+ item = item->next;
+ }
+ }
+ /* is it a SEQUENCE or SET */
+ else if(state.and_items)
+ {
+ /* output any literals at the start */
+ for(item=state.items; item && item->type==IT_LITERAL; item=item->next)
+ buf_append(&state.decode_fns, "\tfprintf(out, \"%%s \", %s);\n\n", item->name);
+ /* items must be in the order they are defined for SEQUENCE types */
+ switch(asn1type(name))
+ {
+ case ASN1TYPE_SEQUENCE:
+ /* assert */
+ if(item->type != IT_IDENTIFIER)
+ fatal("not Identifier");
+ /* is_Xxx() - just match the first item */
+ buf_append(&state.decode_is_fns, "\treturn is_%s(class, number);\n", item->name);
+ /* decode_Xxx() - examine each non-literal item in turn */
+ while(item && item->type != IT_LITERAL)
+ {
+/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+ item = item->next;
+ }
+ break;
+
+ case ASN1TYPE_SET:
+ /* while there is data left in the current object */
+ buf_append(&state.decode_fns, "\twhile(left > 0)\n\t{\n");
+ /* decode the next tag */
+ buf_append(&state.decode_fns, "\t\tif((sublen = der_decode_Tag(der, &tag)) < 0)\n");
+ buf_append(&state.decode_fns, "\t\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\t\tleft -= sublen;\n");
+ /* the non-literal items may appear in any order */
+ first = true;
+ while(item && item->type != IT_LITERAL)
+ {
+ /* is_Xxx() */
+ if(first)
+ buf_append(&state.decode_is_fns, "\treturn ");
+ else
+ buf_append(&state.decode_is_fns, "\t || ");
+ buf_append(&state.decode_is_fns, "is_%s(class, number)", item->name);
+ /* is it the last */
+ if(item->next == NULL || item->next->type == IT_LITERAL)
+ buf_append(&state.decode_is_fns, ";");
+ buf_append(&state.decode_is_fns, "\n");
+ /* decode_Xxx() */
+ if(first)
+ buf_append(&state.decode_fns, "\t\t");
+ else
+ buf_append(&state.decode_fns, "\t\telse ");
+ first = false;
+ buf_append(&state.decode_fns, "if(is_%s(tag.class, tag.number))\n\t\t{\n", item->name);
+ buf_append(&state.decode_fns, "\t\t\tasn1decode_%s(der, out, tag.length);\n", item->name);
+ buf_append(&state.decode_fns, "\t\t\tleft -= tag.length;\n");
+ buf_append(&state.decode_fns, "\t\t}\n");
+ item = item->next;
+ }
+ /* decode_Xxx() */
+ buf_append(&state.decode_fns, "\t\telse\n");
+ buf_append(&state.decode_fns, "\t\t{\n\t\t\treturn der_error(\"%s: unexpected tag [%%s %%u]\", asn1class_name(tag.class), tag.number);\n\t}\n", name);
+ buf_append(&state.decode_fns, "\t\t}\n\n");
+ break;
+
+ default:
+ /* assert */
+ fatal("and_items set but not a SEQUENCE or SET");
+ break;
+ }
+ /* output any literals at the end */
+ while(item)
+ {
+ /* assert */
+ if(item->type != IT_LITERAL)
+ fatal("Trailing non-literal");
+ buf_append(&state.decode_fns, "\tfprintf(out, %s);\n\n", item->name);
+ item = item->next;
+ }
+ }
+ /* is it ENUMERATED */
+ else if(asn1type(name) == ASN1TYPE_ENUMERATED)
+ {
+ /* an ENUMERATED type */
+ buf_append(&state.decode_fns, "\t/* ENUMERATED */\n");
+ buf_append(&state.decode_fns, "\tchar *enum_names[] = {\n");
+ enum_val = 0;
+ for(item=state.items; item; item=item->next)
+ {
+ buf_append(&state.decode_fns, "\t\t%s,\n", item->name);
+ enum_val ++;
+ }
+ buf_append(&state.decode_fns, "\t};\n\n");
+ buf_append(&state.decode_fns, "\tif((sublen = der_decode_Tag(der, &tag)) < 0)\n");
+ buf_append(&state.decode_fns, "\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\tleft -= sublen;\n\n");
+ /* the ENUMERATED value is encoded as an INTEGER */
+ buf_append(&state.decode_fns, "\tif(is_%s(tag.class, tag.number))\n\t{\n", name);
+ buf_append(&state.decode_fns, "\t\tder_decode_ENUMERATED(der, out, tag.length, %u, enum_names);\n", enum_val);
+ buf_append(&state.decode_fns, "\t\tleft -= tag.length;\n");
+ buf_append(&state.decode_fns, "\t}\n\telse\n");
+ buf_append(&state.decode_fns, "\t{\n\t\treturn der_error(\"%s\");\n\t}\n\n", name);
+ /* is_Xxx() function */
+ buf_append(&state.decode_is_fns, "\treturn MATCH_TAGCLASS(class, number, ASN1TAGCLASS_ENUMERATED);\n");
+ }
+ /* must be a CHOICE */
+ else
+ {
+ /* a CHOICE type */
+ buf_append(&state.decode_fns, "\t/* CHOICE */\n");
+ buf_append(&state.decode_fns, "\tif((sublen = der_decode_Tag(der, &tag)) < 0)\n");
+ buf_append(&state.decode_fns, "\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\tleft -= sublen;\n\n");
+ /* see which item we chose */
+ for(item=state.items; item; item=item->next)
+ {
+ /* is_Xxx() function */
+ if(item == state.items)
+ buf_append(&state.decode_is_fns, "\treturn ");
+ else
+ buf_append(&state.decode_is_fns, "\t || ");
+ buf_append(&state.decode_is_fns, "MATCH_TAGCLASS(class, number, ASN1TAGCLASS_%s)", item->name);
+ /* is it the last */
+ if(item->next == NULL)
+ buf_append(&state.decode_is_fns, ";");
+ buf_append(&state.decode_is_fns, "\n");
+ /* decode_Xxx() function */
+ if(item == state.items)
+ buf_append(&state.decode_fns, "\t");
+ else
+ buf_append(&state.decode_fns, "\telse ");
+ buf_append(&state.decode_fns, "if(MATCH_TAGCLASS(tag.class, tag.number, ASN1TAGCLASS_%s))\n\t{\n", item->name);
+ buf_append(&state.decode_fns, "\t\tif((sublen = asn1decode_%s(der, out, tag.length)) < 0)\n", item->name);
+ buf_append(&state.decode_fns, "\t\t\treturn der_error(\"%s\");\n", name);
+ buf_append(&state.decode_fns, "\t\tleft -= sublen;\n");
+ buf_append(&state.decode_fns, "\t}\n");
+ }
+ buf_append(&state.decode_fns, "\telse\n");
+ buf_append(&state.decode_fns, "\t{\n\t\treturn der_error(\"%s\");\n\t}\n\n", name);
+ }
+
+ /* end decode_Xxx() function */
+ buf_append(&state.decode_fns, "\tfprintf(out, \"\\n\");\n\n");
+ buf_append(&state.decode_fns, "\tif(left != 0)\n");
+ buf_append(&state.decode_fns, "\t\treturn der_error(\"%s: %%d bytes left\", left);\n\n", name);
+ buf_append(&state.decode_fns, "\tverbose(\"</%s>\\n\");\n\n", name);
+ buf_append(&state.decode_fns, "\treturn length;\n}\n\n");
+
+ /* end is_Xxx() function */
+ buf_append(&state.decode_is_fns, "}\n\n");
+
/* free the items */
item = state.items;
while(item)
@@ -850,6 +1111,9 @@
if((b->str = malloc(b->nalloced)) == NULL)
fatal("Out of memory");
+ /* in case it never gets any data put in it */
+ b->str[0] = '\0';
+
return;
}
Added: redbutton-author/trunk/der_decode.c
===================================================================
--- redbutton-author/trunk/der_decode.c (rev 0)
+++ redbutton-author/trunk/der_decode.c 2007-10-15 08:50:51 UTC (rev 436)
@@ -0,0 +1,240 @@
+/*
+ * der_decode.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <ctype.h>
+
+#include "der_decode.h"
+
+void verbose(char *, ...);
+char hexdigit(unsigned char);
+
+/* DER does not allow indefinite lengths */
+
+int
+der_decode_Tag(FILE *der, struct der_tag *tag)
+{
+ unsigned int type;
+ unsigned int len;
+ unsigned char byte;
+ unsigned int longtype;
+ int nlens;
+ int nbytes = 0;
+
+ /* type */
+ if(der_read_file(der, 1, &byte) != 1)
+ return der_error("DER tag");
+ nbytes ++;
+ type = byte;
+ longtype = 0;
+ if((type & 0x1f) == 0x1f)
+ {
+ /* multi byte type */
+ do
+ {
+ if(der_read_file(der, 1, &byte) != 1)
+ return der_error("DER tag");
+ nbytes ++;
+ longtype <<= 7;
+ longtype += byte & 0x7f;
+ }
+ while((byte & 0x80) != 0);
+ }
+ tag->class = type & 0xc0;
+ tag->number = ((type & 0x1f) == 0x1f) ? longtype : type & 0x1f;
+
+ /* length */
+ if(der_read_file(der, 1, &byte) != 1)
+ return der_error("DER tag");
+ nbytes ++;
+ len = byte;
+ if(len == 0 && type == 0)
+ {
+ return der_error("Found EOC; indefinite lengths not allowed in DER");
+ }
+ else if(len == 0x80)
+ {
+ return der_error("Indefinite lengths not allowed in DER");
+ }
+ else if((len & 0x80) == 0x80)
+ {
+ /* multibyte length field */
+ nlens = len & 0x7f;
+ len = 0;
+ while(nlens > 0)
+ {
+ if(der_read_file(der, 1, &byte) != 1)
+ return der_error("DER tag");
+ nbytes ++;
+ len <<= 8;
+ len += byte;
+ nlens --;
+ }
+ }
+ tag->length = len;
+
+ return nbytes;
+}
+
+int
+der_decode_BOOLEAN(FILE *der, FILE *out, int length)
+{
+ unsigned char val;
+
+ if(length != 1)
+ return der_error("Boolean: length=%d", length);
+
+ if(der_read_file(der, length, &val) < 0)
+ return der_error("Boolean");
+
+ verbose("<Boolean value=\"%s\"/>\n", val ? "true" : "false");
+
+ fprintf(out, "%s", val ? "true" : "false");
+
+ return length;
+}
+
+int
+der_decode_INTEGER(FILE *der, FILE *out, int length)
+{
+ int val = get_der_int(der, length);
+
+ verbose("<Integer value=\"%d\"/>\n", val);
+
+ fprintf(out, "%d", val);
+
+ return length;
+}
+
+/* DER does not allow constructed OCTET-STRINGs */
+
+int
+der_decode_OctetString(FILE *der, FILE *out, int length)
+{
+ int left = length;
+ unsigned char byte;
+
+ verbose("<OctetString size=\"%d\">\n", length);
+
+ fprintf(out, "'");
+ while(left > 0)
+ {
+ if(der_read_file(der, 1, &byte) < 0)
+ return der_error("OctetString");
+ if(byte != '\'' && byte >= 0x20 && byte < 0x7f)
+ fprintf(out, "%c", byte);
+ else
+ fprintf(out, "=%c%c", hexdigit((byte >> 4) & 0xf), hexdigit(byte & 0xf));
+ left --;
+ }
+ fprintf(out, "'");
+
+ verbose("</OctetString>\n");
+
+ return length;
+}
+
+int
+der_decode_Null(FILE *der, FILE *out, int length)
+{
+ if(length != 0)
+ return der_error("Null: length=%d", length);
+
+ verbose("<Null/>");
+
+ return length;
+}
+
+int
+der_decode_ENUMERATED(FILE *der, FILE *out, int length, unsigned int max, char *names[])
+{
+ int val = get_der_int(der, length);
+
+ if(val < 1 || val > max)
+ return der_error("Enumerated: %d; not in range 1-%d", val, max);
+
+ verbose("<Enumerated value=\"%d\"/>\n", val);
+
+ fprintf(out, "%s", names[val - 1]);
+
+ return length;
+}
+
+char
+hexdigit(unsigned char nibble)
+{
+ if(nibble < 10)
+ return '0' + nibble;
+ else if(nibble < 16)
+ return 'a' + nibble;
+ else
+ return '?';
+}
+
+int
+get_der_int(FILE *der, int length)
+{
+ unsigned char byte;
+ unsigned int uval;
+ int val;
+ bool negative;
+ int i;
+
+ if(length > sizeof(int))
+ fatal("Integer: length=%d", length);
+
+ /* is it -ve */
+ if(der_read_file(der, 1, &byte) < 0)
+ fatal("Integer: EOF");
+ negative = ((byte & 0x80) == 0x80);
+
+ /* big endian */
+ uval = byte;
+ for(i=1; i<length; i++)
+ {
+ if(der_read_file(der, 1, &byte) < 0)
+ fatal("Integer: EOF");
+ uval <<= 8;
+ uval += byte;
+ }
+
+ /* sign extend if negative */
+ if(negative)
+ {
+ /* byte order neutral */
+ for(i=length; i<sizeof(int); i++)
+ uval += (0xff << (i * 8));
+ }
+
+ val = (int) uval;
+
+ return val;
+}
+
+int
+der_read_file(FILE *in, unsigned int nbytes, void *buf)
+{
+ int nread;
+
+ if((nread = fread(buf, 1, nbytes, in)) != nbytes)
+ return der_error("Unexpected EOF");
+
+ return nread;
+}
+
+int
+der_error(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+
+ return -1;
+}
+
Added: redbutton-author/trunk/der_decode.h
===================================================================
--- redbutton-author/trunk/der_decode.h (rev 0)
+++ redbutton-author/trunk/der_decode.h 2007-10-15 08:50:51 UTC (rev 436)
@@ -0,0 +1,47 @@
+/*
+ * der_decode.h
+ */
+
+#ifndef __DER_DECODE_H__
+#define __DER_DECODE_H__
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "utils.h"
+
+#define der_alloc(N) safe_malloc(N)
+#define der_realloc(P, N) safe_realloc(P, N)
+#define der_free(P) safe_free(P)
+
+struct der_tag
+{
+ unsigned char class;
+ unsigned int number;
+ unsigned int length;
+};
+
+#define DER_CLASS_UNIVERSAL 0x00
+#define DER_CLASS_APPLICATION 0x40
+#define DER_CLASS_CONTEXT 0x80
+#define DER_CLASS_PRIVATE 0xc0
+
+/* top 8 bits are class, bottom 24 are the tag number */
+#define MATCH_TAGCLASS(CLASS, NUMBER, TAGCLASS) ((CLASS == ((TAGCLASS >> 24) & 0xff)) && (NUMBER == (TAGCLASS & 0xffffff)))
+
+int der_decode_Tag(FILE *, struct der_tag *);
+
+int der_decode_BOOLEAN(FILE *, FILE *, int);
+int der_decode_INTEGER(FILE *, FILE *, int);
+int der_decode_OctetString(FILE *, FILE *, int);
+int der_decode_Null(FILE *, FILE *, int);
+int der_decode_ENUMERATED(FILE *, FILE *, int, unsigned int, char **);
+
+int get_der_int(FILE *, int);
+
+int der_read_file(FILE *, unsigned int, void *);
+
+int der_error(char *, ...);
+
+#endif /* __DER_DECODE_H__ */
+
Added: redbutton-author/trunk/mhegd.c
===================================================================
--- redbutton-author/trunk/mhegd.c (rev 0)
+++ redbutton-author/trunk/mhegd.c 2007-10-15 08:50:51 UTC (rev 436)
@@ -0,0 +1,131 @@
+/*
+ * mhegd.c
+ */
+
+/*
+ * Copyright (C) 2007, Simon Kilvington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "asn1decode.h"
+#include "der_decode.h"
+#include "utils.h"
+
+void verbose(const char *, ...);
+void vverbose(const char *, ...);
+
+void usage(char *);
+
+static int _verbose = 0;
+
+int
+main(int argc, char *argv[])
+{
+ char *prog_name = argv[0];
+ int arg;
+ FILE *in_file;
+ FILE *out_file = stdout;
+ int filesize;
+
+ while((arg = getopt(argc, argv, "o:v")) != EOF)
+ {
+ switch(arg)
+ {
+ case 'o':
+ if((out_file = fopen(optarg, "w")) == NULL)
+ fatal("Unable to write '%s': %s", optarg, strerror(errno));
+ break;
+
+ case 'v':
+ _verbose ++;
+ break;
+
+ default:
+ usage(prog_name);
+ break;
+ }
+ }
+
+ /* the single param is the name of a DER file */
+ if(optind != argc - 1)
+ usage(prog_name);
+
+ if((in_file = fopen(argv[optind], "r")) == NULL)
+ fatal("Unable to open '%s': %s", argv[optind], strerror(errno));
+
+ verbose("Reading '%s':\n", argv[optind]);
+
+ /* see how long the file is */
+ fseek(in_file, 0, SEEK_END);
+ filesize = (int) ftell(in_file);
+ rewind(in_file);
+
+ /* write text form of DER encoded in_file to out_file */
+ if(asn1decode_InterchangedObject(in_file, out_file, filesize) != filesize)
+ fatal("Unexpected data after InterchangedObject");
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * verbose functions send output to stderr so error messages get interleaved correctly
+ */
+
+void
+verbose(const char *fmt, ...)
+{
+ va_list ap;
+
+ if(_verbose)
+ {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+ return;
+}
+
+void
+vverbose(const char *fmt, ...)
+{
+ va_list ap;
+
+ if(_verbose > 1)
+ {
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+ return;
+}
+
+void
+usage(char *prog_name)
+{
+ fprintf(stderr, "Usage: %s [-vv] [-o <output_file>] <input_file>\n", prog_name);
+
+ exit(EXIT_FAILURE);
+}
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|