]>
git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/unBER/unBER.cpp
2 * Decodes and prints ASN.1 BER.
4 * Written by Henning Schulzrinne, Columbia University, (c) 1997.
5 * Updated by Doug Mitchell 9/6/00 to use oidParser
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <security_cdsa_utils/cuOidParser.h>
15 static void usage(char **argv
)
17 printf("Usage: %s berfile [o (parse octet strings)] "
18 "[b (parse bit strings) ]\n", argv
[0]);
22 #define PARSE_BIT_STR 0x01
23 #define PARSE_OCTET_STR 0x02
25 /* bogus infinite length loop index target */
26 #define INDEFINITE 1000000
28 typedef unsigned char uchar
;
30 #define CLASS_MASK 0xc0
31 #define CLASS_UNIV 0x00
32 #define CLASS_APPL 0x40
33 #define CLASS_CONTEXT 0x80
34 #define CLASS_PRIVATE 0xc0
35 #define CONSTRUCT_BIT 0x20
37 static int sequence(int t
, const char *tag
, uchar
*b
, int length
,
38 OidParser
&parser
, unsigned parseFlags
);
39 static int value(int t
, uchar
*b
, int length
, OidParser
&parser
,
42 static void indent(int t
)
45 for (i
= 0; i
< t
; i
++) putchar(' ');
48 static int oid(int t
, uchar
*b
, int length
, OidParser
&parser
)
51 char oidStr
[OID_PARSER_STRING_SIZE
];
52 parser
.oidParse(b
, length
, oidStr
);
53 printf("OID <%d>: %s\n", length
, oidStr
);
58 static int integer(int t
, const char *type
, uchar
*b
, int length
)
63 printf("%s <%d>:", type
, length
);
64 for (i
= 0; i
< length
; i
++) {
65 printf("%02x ", b
[i
]);
72 static int bitstring(int t
, uchar
*b
, int length
)
77 printf("BIT STRING <%d, %d>:", length
, b
[0]);
78 for (i
= 1; i
< length
; i
++) {
83 printf("%02x ", b
[i
]);
90 static int octetstring(int t
, uchar
*b
, int length
)
95 printf("OCTET STRING <%d>:", length
);
96 for (i
= 0; i
< length
; i
++) {
101 printf("%02x ", b
[i
]);
107 static int bmpstring(int t
, uchar
*b
, int length
)
109 /* enventually convert via unicode to printable */
113 printf("BMP STRING <%d>:", length
);
114 for (i
= 0; i
< length
; i
++) {
119 printf("%02x ", b
[i
]);
127 static int string(int t
, const char *tag
, uchar
*b
, int length
)
130 printf("%s <%d>: %*.*s\n", tag
, length
, length
, length
, b
);
134 static int unparsed(int t
, uchar
*b
, int length
)
139 printf("UNPARSED DATA <%d>:", length
);
140 for (i
= 0; i
< length
; i
++) {
145 printf("%02x ", b
[i
]);
152 static int metaClass(int t
, // indent
154 uchar
*b
, // start of contents
155 int length
, // content length
156 const char *className
,
160 uchar underlyingTag
= tag
& ~(CLASS_MASK
| CONSTRUCT_BIT
);
163 printf("%s (tag %d) <indefinite> {\n", className
, underlyingTag
);
166 printf("%s (tag %d) <%d> {\n", className
, underlyingTag
, length
);
168 /* just print uninterpreted bytes if !constructed, !universal */
169 if( ( ( tag
& CLASS_MASK
) != CLASS_UNIV
) &&
170 !(tag
& CONSTRUCT_BIT
) ) {
171 /* fixme - can't do this for indefinite length */
172 unparsed(t
+3, b
, length
);
175 length
= value(t
+ 3, b
, length
, parser
, parseFlags
);
184 int t
, // indent depth
185 uchar
*b
, // start of item (at tag)
186 int length
, // length if item, -1 ==> indefinite
188 unsigned parseFlags
) // PARSE_BIT_STR, etc.
191 int tag_length
, length_length
, len
;
194 const char *parseStr
= NULL
; // name of recursively parsed bit/octet string
195 uchar
*parseVal
= NULL
; // contents to parse
196 unsigned parseLen
= 0;
198 if (length
== -1) length
= INDEFINITE
;
200 for (i
= 0; i
< length
; ) {
204 /* get length: short form (single byte) or 0x8b or 0x80 (indefinite) */
205 if (b
[i
+1] == 0x80) {
209 else if (b
[i
+1] & 0x80) {
210 /* long length of n bytes */
211 length_length
= (b
[i
+1] & 0x7f) + 1;
213 for (j
= 1; j
< length_length
; j
++) {
214 len
= len
* 256 + b
[i
+1+j
];
218 /* short length form */
224 * i is index of current tag
225 * len is content length of current item
226 * set k as index to start of content
228 k
= i
+ tag_length
+ length_length
;
230 if(length
!= INDEFINITE
) {
231 if((k
+ len
) > length
) {
232 printf("***content overflow\n");
235 /* handle special case classes */
236 classId
= b
[i
] & CLASS_MASK
;
237 constructBit
= b
[i
] & CONSTRUCT_BIT
;
240 case CLASS_UNIV
: // normal case handled below
243 i
+= metaClass(t
, b
[i
], &b
[k
], len
, "CONTEXT SPECIFIC",
247 i
+= metaClass(t
, b
[i
], &b
[k
], len
, "APPLICATION SPECIFIC",
251 i
+= metaClass(t
, b
[i
], &b
[k
], len
, "PRIVATE",
258 goto done
; // this item already parsed per class
261 parseVal
= b
+ k
; // default recursively parsed value
265 case 0x0: /* end of indefinite length */
266 i
+= tag_length
+ length_length
;
269 case 0x01: /* BOOLEAN, a one-byte integer */
270 i
+= integer(t
, "BOOLEAN", &b
[k
], len
);
273 case 0x02: /* INTEGER */
274 i
+= integer(t
, "INTEGER", &b
[k
], len
);
277 case 0x03: /* BIT STRING */
278 i
+= bitstring(t
, &b
[k
], len
);
279 if(parseFlags
& PARSE_OCTET_STR
) {
280 parseStr
= "BIT STRING";
281 parseVal
++; // skip reminder byte
286 case 0x04: /* OCTET STRING */
287 i
+= octetstring(t
, &b
[k
], len
);
288 if(parseFlags
& PARSE_OCTET_STR
) {
289 parseStr
= "OCTET STRING";
298 case 0x06: /* OBJECT IDENTIFIER */
299 i
+= oid(t
, &b
[k
], len
, parser
);
302 case 0x0A: /* enumerated */
303 i
+= integer(t
, "ENUM", &b
[k
], len
);
306 case 0xc: /* UTF8 string */
307 i
+= string(t
, "UTF8String", &b
[k
], len
);
310 case 0x13: /* PrintableString */
311 i
+= string(t
, "PrintableString", &b
[k
], len
);
314 case 0x14: /* T61String */
315 i
+= string(t
, "T61String", &b
[k
], len
);
318 case 0x16: /* IA5String */
319 i
+= string(t
, "IA5String", &b
[k
], len
);
322 case 0x17: /* UTCTime */
323 i
+= string(t
, "UTCTime", &b
[k
], len
);
326 case 0x18: /* generalized Time */
327 i
+= string(t
, "GenTime", &b
[k
], len
);
330 case 0x19: /* SEC_ASN1_GRAPHIC_STRING */
331 i
+= string(t
, "Graphic", &b
[k
], len
);
334 case 0x1a: /* SEC_ASN1_VISIBLE_STRING */
335 i
+= string(t
, "Visible", &b
[k
], len
);
338 case 0x1b: /* SEC_ASN1_GENERAL_STRING */
339 i
+= string(t
, "General", &b
[k
], len
);
342 case 0x1e: /* BMP string, unicode */
343 i
+= bmpstring(t
, &b
[k
], len
);
346 case 0xA0: /* SIGNED? */
347 i
+= sequence(t
, "EXPLICIT", &b
[k
], len
, parser
,
351 case 0x30: /* SEQUENCE OF */
352 i
+= sequence(t
, "SEQUENCE OF", &b
[k
], len
, parser
,
356 case 0x31: /* SET OF */
357 i
+= sequence(t
, "SET OF", &b
[k
], len
, parser
,
361 case 0x39: /* SET OF */
362 i
+= sequence(t
, "structured", &b
[k
], len
, parser
,
366 case 0x24: /* CONSTRUCTED octet string */
367 i
+= sequence(t
, "CONSTR OCTET STRING", &b
[k
], len
,
369 if(parseFlags
& PARSE_OCTET_STR
) {
370 parseStr
= "OCTET STRING";
375 printf("ACK! Unknown tag (0x%x); aborting\n", b
[i
]);
382 printf("Parse contents (y/anything)? ");
383 char resp
= getchar();
386 printf("Parsed %s contents {\n", parseStr
);
387 value(t
+6, parseVal
, parseLen
, parser
, parseFlags
);
389 printf("} end of Parsed %s\n", parseStr
);
392 i
+= tag_length
+ length_length
;
393 } /* main loop for i to length */
398 static int sequence(int t
, const char *tag
, uchar
*b
, int length
,
399 OidParser
&parser
, unsigned parseFlags
)
405 printf("%s <indefinite> {\n", tag
);
408 printf("%s <%d> {\n", tag
, length
);
410 len
= value(t
+ 3, b
, length
, parser
, parseFlags
);
417 int main(int argc
, char *argv
[])
424 if(readFile(argv
[1], &bfr
, (unsigned int *)&i
)) {
425 printf("Error reading %s\n", argv
[1]);
429 unsigned parseFlags
= 0;
431 for(int dex
=2; dex
<argc
; dex
++) {
432 switch(argv
[dex
][0]) {
434 parseFlags
|= PARSE_BIT_STR
;
437 parseFlags
|= PARSE_OCTET_STR
;
445 value(0, bfr
, i
, parser
, parseFlags
);