#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <security_cdsa_utils/cuOidParser.h>
static void usage(char **argv)
{
printf("Usage: %s berfile [o (parse octet strings)] "
"[b (parse bit strings) ]\n", argv[0]);
exit(1);
}
#define PARSE_BIT_STR 0x01
#define PARSE_OCTET_STR 0x02
#define INDEFINITE 1000000
typedef unsigned char uchar;
#define CLASS_MASK 0xc0
#define CLASS_UNIV 0x00
#define CLASS_APPL 0x40
#define CLASS_CONTEXT 0x80
#define CLASS_PRIVATE 0xc0
#define CONSTRUCT_BIT 0x20
static int sequence(int t, const char *tag, uchar *b, int length,
OidParser &parser, unsigned parseFlags);
static int value(int t, uchar *b, int length, OidParser &parser,
unsigned parseFlags);
static void indent(int t)
{
int i;
for (i = 0; i < t; i++) putchar(' ');
}
static int oid(int t, uchar *b, int length, OidParser &parser)
{
indent(t);
char oidStr[OID_PARSER_STRING_SIZE];
parser.oidParse(b, length, oidStr);
printf("OID <%d>: %s\n", length, oidStr);
return length;
}
static int integer(int t, const char *type, uchar *b, int length)
{
int i;
indent(t);
printf("%s <%d>:", type, length);
for (i = 0; i < length; i++) {
printf("%02x ", b[i]);
}
printf("\n");
return length;
}
static int bitstring(int t, uchar *b, int length)
{
int i;
indent(t);
printf("BIT STRING <%d, %d>:", length, b[0]);
for (i = 1; i < length; i++) {
if ((i % 16) == 0) {
printf("\n");
indent(t+3);
}
printf("%02x ", b[i]);
}
printf("\n");
return length;
}
static int octetstring(int t, uchar *b, int length)
{
int i;
indent(t);
printf("OCTET STRING <%d>:", length);
for (i = 0; i < length; i++) {
if ((i % 16) == 0) {
printf("\n");
indent(t+3);
}
printf("%02x ", b[i]);
}
printf("\n");
return length;
}
static int bmpstring(int t, uchar *b, int length)
{
int i;
indent(t);
printf("BMP STRING <%d>:", length);
for (i = 0; i < length; i++) {
if ((i % 16) == 0) {
printf("\n");
indent(t+3);
}
printf("%02x ", b[i]);
}
printf("\n");
return length;
}
static int string(int t, const char *tag, uchar *b, int length)
{
indent(t);
printf("%s <%d>: %*.*s\n", tag, length, length, length, b);
return length;
}
static int unparsed(int t, uchar *b, int length)
{
int i;
indent(t);
printf("UNPARSED DATA <%d>:", length);
for (i = 0; i < length; i++) {
if ((i % 16) == 0) {
printf("\n");
indent(t+3);
}
printf("%02x ", b[i]);
}
printf("\n");
return length;
}
static int metaClass(int t, uchar tag, uchar *b, int length, const char *className,
OidParser &parser,
unsigned parseFlags)
{
uchar underlyingTag = tag & ~(CLASS_MASK | CONSTRUCT_BIT);
indent(t);
if(length == -1) {
printf("%s (tag %d) <indefinite> {\n", className, underlyingTag);
}
else {
printf("%s (tag %d) <%d> {\n", className, underlyingTag, length);
}
if( ( ( tag & CLASS_MASK) != CLASS_UNIV) &&
!(tag & CONSTRUCT_BIT) ) {
unparsed(t+3, b, length);
}
else {
length = value(t + 3, b, length, parser, parseFlags);
}
indent(t);
printf("}\n");
return length;
}
static int value(
int t, uchar *b, int length, OidParser &parser,
unsigned parseFlags) {
int i, j, k;
int tag_length, length_length, len;
uchar classId;
uchar constructBit;
const char *parseStr = NULL; uchar *parseVal = NULL; unsigned parseLen = 0;
if (length == -1) length = INDEFINITE;
for (i = 0; i < length; ) {
tag_length = 1;
if (b[i+1] == 0x80) {
len = -1;
length_length = 1;
}
else if (b[i+1] & 0x80) {
length_length = (b[i+1] & 0x7f) + 1;
len = 0;
for (j = 1; j < length_length; j++) {
len = len * 256 + b[i+1+j];
}
}
else {
len = b[i+1];
length_length = 1;
}
k = i + tag_length + length_length;
if(length != INDEFINITE) {
if((k + len) > length) {
printf("***content overflow\n");
}
}
classId = b[i] & CLASS_MASK;
constructBit = b[i] & CONSTRUCT_BIT;
switch(classId) {
case CLASS_UNIV: goto parseTag;
case CLASS_CONTEXT:
i += metaClass(t, b[i], &b[k], len, "CONTEXT SPECIFIC",
parser, parseFlags);
break;
case CLASS_APPL:
i += metaClass(t, b[i], &b[k], len, "APPLICATION SPECIFIC",
parser, parseFlags);
break;
case CLASS_PRIVATE:
i += metaClass(t, b[i], &b[k], len, "PRIVATE",
parser, parseFlags);
break;
default:
break;
}
goto done; parseTag:
parseStr = NULL;
parseVal = b + k; parseLen = len;
switch(b[i]) {
case 0x0:
i += tag_length + length_length;
return i;
case 0x01:
i += integer(t, "BOOLEAN", &b[k], len);
break;
case 0x02:
i += integer(t, "INTEGER", &b[k], len);
break;
case 0x03:
i += bitstring(t, &b[k], len);
if(parseFlags & PARSE_OCTET_STR) {
parseStr = "BIT STRING";
parseVal++; parseLen--;
}
break;
case 0x04:
i += octetstring(t, &b[k], len);
if(parseFlags & PARSE_OCTET_STR) {
parseStr = "OCTET STRING";
}
break;
case 0x5:
indent(t);
printf("NULL\n");
break;
case 0x06:
i += oid(t, &b[k], len, parser);
break;
case 0x0A:
i += integer(t, "ENUM", &b[k], len);
break;
case 0xc:
i += string(t, "UTF8String", &b[k], len);
break;
case 0x13:
i += string(t, "PrintableString", &b[k], len);
break;
case 0x14:
i += string(t, "T61String", &b[k], len);
break;
case 0x16:
i += string(t, "IA5String", &b[k], len);
break;
case 0x17:
i += string(t, "UTCTime", &b[k], len);
break;
case 0x18:
i += string(t, "GenTime", &b[k], len);
break;
case 0x19:
i += string(t, "Graphic", &b[k], len);
break;
case 0x1a:
i += string(t, "Visible", &b[k], len);
break;
case 0x1b:
i += string(t, "General", &b[k], len);
break;
case 0x1e:
i += bmpstring(t, &b[k], len);
break;
case 0xA0:
i += sequence(t, "EXPLICIT", &b[k], len, parser,
parseFlags);
break;
case 0x30:
i += sequence(t, "SEQUENCE OF", &b[k], len, parser,
parseFlags);
break;
case 0x31:
i += sequence(t, "SET OF", &b[k], len, parser,
parseFlags);
break;
case 0x39:
i += sequence(t, "structured", &b[k], len, parser,
parseFlags);
break;
case 0x24:
i += sequence(t, "CONSTR OCTET STRING", &b[k], len,
parser, parseFlags);
if(parseFlags & PARSE_OCTET_STR) {
parseStr = "OCTET STRING";
}
break;
default:
printf("ACK! Unknown tag (0x%x); aborting\n", b[i]);
exit(1);
}
done:
if(parseStr) {
indent(t);
fpurge(stdin);
printf("Parse contents (y/anything)? ");
char resp = getchar();
if(resp == 'y') {
indent(t+3);
printf("Parsed %s contents {\n", parseStr);
value(t+6, parseVal, parseLen, parser, parseFlags);
indent(t+3);
printf("} end of Parsed %s\n", parseStr);
}
}
i += tag_length + length_length;
}
return i;
}
static int sequence(int t, const char *tag, uchar *b, int length,
OidParser &parser, unsigned parseFlags)
{
int len;
indent(t);
if (length < 0) {
printf("%s <indefinite> {\n", tag);
}
else {
printf("%s <%d> {\n", tag, length);
}
len = value(t + 3, b, length, parser, parseFlags);
indent(t);
printf("}\n");
return len;
}
int main(int argc, char *argv[])
{
uchar* bfr;
int i = 0;
if(argc < 2) {
usage(argv);
}
if(readFile(argv[1], &bfr, (unsigned int *)&i)) {
printf("Error reading %s\n", argv[1]);
exit(1);
}
unsigned parseFlags = 0;
for(int dex=2; dex<argc; dex++) {
switch(argv[dex][0]) {
case 'b':
parseFlags |= PARSE_BIT_STR;
break;
case 'o':
parseFlags |= PARSE_OCTET_STR;
break;
default:
usage(argv);
}
}
OidParser parser;
value(0, bfr, i, parser, parseFlags);
free(bfr);
return 0;
}