]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/unBER/unBER.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / unBER / unBER.cpp
1 /*
2 * Decodes and prints ASN.1 BER.
3 *
4 * Written by Henning Schulzrinne, Columbia University, (c) 1997.
5 * Updated by Doug Mitchell 9/6/00 to use oidParser
6 */
7
8 #include <stdio.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <security_cdsa_utils/cuOidParser.h>
14
15 static void usage(char **argv)
16 {
17 printf("Usage: %s berfile [o (parse octet strings)] "
18 "[b (parse bit strings) ]\n", argv[0]);
19 exit(1);
20 }
21
22 #define PARSE_BIT_STR 0x01
23 #define PARSE_OCTET_STR 0x02
24
25 /* bogus infinite length loop index target */
26 #define INDEFINITE 1000000
27
28 typedef unsigned char uchar;
29
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
36
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,
40 unsigned parseFlags);
41
42 static void indent(int t)
43 {
44 int i;
45 for (i = 0; i < t; i++) putchar(' ');
46 } /* indent */
47
48 static int oid(int t, uchar *b, int length, OidParser &parser)
49 {
50 indent(t);
51 char oidStr[OID_PARSER_STRING_SIZE];
52 parser.oidParse(b, length, oidStr);
53 printf("OID <%d>: %s\n", length, oidStr);
54 return length;
55 } /* oid */
56
57
58 static int integer(int t, const char *type, uchar *b, int length)
59 {
60 int i;
61
62 indent(t);
63 printf("%s <%d>:", type, length);
64 for (i = 0; i < length; i++) {
65 printf("%02x ", b[i]);
66 }
67 printf("\n");
68 return length;
69 } /* integer */
70
71
72 static int bitstring(int t, uchar *b, int length)
73 {
74 int i;
75
76 indent(t);
77 printf("BIT STRING <%d, %d>:", length, b[0]);
78 for (i = 1; i < length; i++) {
79 if ((i % 16) == 0) {
80 printf("\n");
81 indent(t+3);
82 }
83 printf("%02x ", b[i]);
84 }
85 printf("\n");
86 return length;
87 } /* bitstring */
88
89
90 static int octetstring(int t, uchar *b, int length)
91 {
92 int i;
93
94 indent(t);
95 printf("OCTET STRING <%d>:", length);
96 for (i = 0; i < length; i++) {
97 if ((i % 16) == 0) {
98 printf("\n");
99 indent(t+3);
100 }
101 printf("%02x ", b[i]);
102 }
103 printf("\n");
104 return length;
105 } /* bitstring */
106
107 static int bmpstring(int t, uchar *b, int length)
108 {
109 /* enventually convert via unicode to printable */
110 int i;
111
112 indent(t);
113 printf("BMP STRING <%d>:", length);
114 for (i = 0; i < length; i++) {
115 if ((i % 16) == 0) {
116 printf("\n");
117 indent(t+3);
118 }
119 printf("%02x ", b[i]);
120 }
121 printf("\n");
122 return length;
123 } /* bmpstring */
124
125
126
127 static int string(int t, const char *tag, uchar *b, int length)
128 {
129 indent(t);
130 printf("%s <%d>: %*.*s\n", tag, length, length, length, b);
131 return length;
132 } /* string */
133
134 static int unparsed(int t, uchar *b, int length)
135 {
136 int i;
137
138 indent(t);
139 printf("UNPARSED DATA <%d>:", length);
140 for (i = 0; i < length; i++) {
141 if ((i % 16) == 0) {
142 printf("\n");
143 indent(t+3);
144 }
145 printf("%02x ", b[i]);
146 }
147 printf("\n");
148 return length;
149 } /* unparsed */
150
151
152 static int metaClass(int t, // indent
153 uchar tag, // tag
154 uchar *b, // start of contents
155 int length, // content length
156 const char *className,
157 OidParser &parser,
158 unsigned parseFlags)
159 {
160 uchar underlyingTag = tag & ~(CLASS_MASK | CONSTRUCT_BIT);
161 indent(t);
162 if(length == -1) {
163 printf("%s (tag %d) <indefinite> {\n", className, underlyingTag);
164 }
165 else {
166 printf("%s (tag %d) <%d> {\n", className, underlyingTag, length);
167 }
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);
173 }
174 else {
175 length = value(t + 3, b, length, parser, parseFlags);
176 }
177 indent(t);
178 printf("}\n");
179 return length;
180 } /* metaClass */
181
182
183 static int value(
184 int t, // indent depth
185 uchar *b, // start of item (at tag)
186 int length, // length if item, -1 ==> indefinite
187 OidParser &parser,
188 unsigned parseFlags) // PARSE_BIT_STR, etc.
189 {
190 int i, j, k;
191 int tag_length, length_length, len;
192 uchar classId;
193 uchar constructBit;
194 const char *parseStr = NULL; // name of recursively parsed bit/octet string
195 uchar *parseVal = NULL; // contents to parse
196 unsigned parseLen = 0;
197
198 if (length == -1) length = INDEFINITE;
199
200 for (i = 0; i < length; ) {
201 /* tag length */
202 tag_length = 1;
203
204 /* get length: short form (single byte) or 0x8b or 0x80 (indefinite) */
205 if (b[i+1] == 0x80) {
206 len = -1;
207 length_length = 1;
208 }
209 else if (b[i+1] & 0x80) {
210 /* long length of n bytes */
211 length_length = (b[i+1] & 0x7f) + 1;
212 len = 0;
213 for (j = 1; j < length_length; j++) {
214 len = len * 256 + b[i+1+j];
215 }
216 }
217 else {
218 /* short length form */
219 len = b[i+1];
220 length_length = 1;
221 }
222
223 /*
224 * i is index of current tag
225 * len is content length of current item
226 * set k as index to start of content
227 */
228 k = i + tag_length + length_length;
229
230 if(length != INDEFINITE) {
231 if((k + len) > length) {
232 printf("***content overflow\n");
233 }
234 }
235 /* handle special case classes */
236 classId = b[i] & CLASS_MASK;
237 constructBit = b[i] & CONSTRUCT_BIT;
238
239 switch(classId) {
240 case CLASS_UNIV: // normal case handled below
241 goto parseTag;
242 case CLASS_CONTEXT:
243 i += metaClass(t, b[i], &b[k], len, "CONTEXT SPECIFIC",
244 parser, parseFlags);
245 break;
246 case CLASS_APPL:
247 i += metaClass(t, b[i], &b[k], len, "APPLICATION SPECIFIC",
248 parser, parseFlags);
249 break;
250 case CLASS_PRIVATE:
251 i += metaClass(t, b[i], &b[k], len, "PRIVATE",
252 parser, parseFlags);
253 break;
254 default:
255 /* not reached */
256 break;
257 }
258 goto done; // this item already parsed per class
259 parseTag:
260 parseStr = NULL;
261 parseVal = b + k; // default recursively parsed value
262 parseLen = len;
263
264 switch(b[i]) {
265 case 0x0: /* end of indefinite length */
266 i += tag_length + length_length;
267 return i;
268
269 case 0x01: /* BOOLEAN, a one-byte integer */
270 i += integer(t, "BOOLEAN", &b[k], len);
271 break;
272
273 case 0x02: /* INTEGER */
274 i += integer(t, "INTEGER", &b[k], len);
275 break;
276
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
282 parseLen--;
283 }
284 break;
285
286 case 0x04: /* OCTET STRING */
287 i += octetstring(t, &b[k], len);
288 if(parseFlags & PARSE_OCTET_STR) {
289 parseStr = "OCTET STRING";
290 }
291 break;
292
293 case 0x5: /* NULL */
294 indent(t);
295 printf("NULL\n");
296 break;
297
298 case 0x06: /* OBJECT IDENTIFIER */
299 i += oid(t, &b[k], len, parser);
300 break;
301
302 case 0x0A: /* enumerated */
303 i += integer(t, "ENUM", &b[k], len);
304 break;
305
306 case 0xc: /* UTF8 string */
307 i += string(t, "UTF8String", &b[k], len);
308 break;
309
310 case 0x13: /* PrintableString */
311 i += string(t, "PrintableString", &b[k], len);
312 break;
313
314 case 0x14: /* T61String */
315 i += string(t, "T61String", &b[k], len);
316 break;
317
318 case 0x16: /* IA5String */
319 i += string(t, "IA5String", &b[k], len);
320 break;
321
322 case 0x17: /* UTCTime */
323 i += string(t, "UTCTime", &b[k], len);
324 break;
325
326 case 0x18: /* generalized Time */
327 i += string(t, "GenTime", &b[k], len);
328 break;
329
330 case 0x19: /* SEC_ASN1_GRAPHIC_STRING */
331 i += string(t, "Graphic", &b[k], len);
332 break;
333
334 case 0x1a: /* SEC_ASN1_VISIBLE_STRING */
335 i += string(t, "Visible", &b[k], len);
336 break;
337
338 case 0x1b: /* SEC_ASN1_GENERAL_STRING */
339 i += string(t, "General", &b[k], len);
340 break;
341
342 case 0x1e: /* BMP string, unicode */
343 i += bmpstring(t, &b[k], len);
344 break;
345
346 case 0xA0: /* SIGNED? */
347 i += sequence(t, "EXPLICIT", &b[k], len, parser,
348 parseFlags);
349 break;
350
351 case 0x30: /* SEQUENCE OF */
352 i += sequence(t, "SEQUENCE OF", &b[k], len, parser,
353 parseFlags);
354 break;
355
356 case 0x31: /* SET OF */
357 i += sequence(t, "SET OF", &b[k], len, parser,
358 parseFlags);
359 break;
360
361 case 0x39: /* SET OF */
362 i += sequence(t, "structured", &b[k], len, parser,
363 parseFlags);
364 break;
365
366 case 0x24: /* CONSTRUCTED octet string */
367 i += sequence(t, "CONSTR OCTET STRING", &b[k], len,
368 parser, parseFlags);
369 if(parseFlags & PARSE_OCTET_STR) {
370 parseStr = "OCTET STRING";
371 }
372 break;
373
374 default:
375 printf("ACK! Unknown tag (0x%x); aborting\n", b[i]);
376 exit(1);
377 } /* switch tag */
378 done:
379 if(parseStr) {
380 indent(t);
381 fpurge(stdin);
382 printf("Parse contents (y/anything)? ");
383 char resp = getchar();
384 if(resp == 'y') {
385 indent(t+3);
386 printf("Parsed %s contents {\n", parseStr);
387 value(t+6, parseVal, parseLen, parser, parseFlags);
388 indent(t+3);
389 printf("} end of Parsed %s\n", parseStr);
390 }
391 }
392 i += tag_length + length_length;
393 } /* main loop for i to length */
394 return i;
395 } /* value */
396
397
398 static int sequence(int t, const char *tag, uchar *b, int length,
399 OidParser &parser, unsigned parseFlags)
400 {
401 int len;
402
403 indent(t);
404 if (length < 0) {
405 printf("%s <indefinite> {\n", tag);
406 }
407 else {
408 printf("%s <%d> {\n", tag, length);
409 }
410 len = value(t + 3, b, length, parser, parseFlags);
411 indent(t);
412 printf("}\n");
413 return len;
414 } /* sequence */
415
416
417 int main(int argc, char *argv[])
418 {
419 uchar* bfr;
420 int i = 0;
421 if(argc < 2) {
422 usage(argv);
423 }
424 if(readFile(argv[1], &bfr, (unsigned int *)&i)) {
425 printf("Error reading %s\n", argv[1]);
426 exit(1);
427 }
428
429 unsigned parseFlags = 0;
430
431 for(int dex=2; dex<argc; dex++) {
432 switch(argv[dex][0]) {
433 case 'b':
434 parseFlags |= PARSE_BIT_STR;
435 break;
436 case 'o':
437 parseFlags |= PARSE_OCTET_STR;
438 break;
439 default:
440 usage(argv);
441 }
442 }
443
444 OidParser parser;
445 value(0, bfr, i, parser, parseFlags);
446 free(bfr);
447 return 0;
448 } /* main */