blob: 60f3a0362b411d0ac38ec701e9d4de7a926d67a7 [file] [log] [blame]
Lev Walkin12984672004-09-24 21:00:15 +00001/*-
2 * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id$
27 */
Lev Walkin06b8d7a2004-09-23 22:06:02 +000028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <sys/types.h>
32#include <unistd.h>
33#include <sysexits.h> /* for EX_USAGE */
34#include <assert.h>
35#include <errno.h>
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <asn1parser.h> /* For static string tables */
42
Lev Walkin12984672004-09-24 21:00:15 +000043#include <asn_application.h>
44#include <constraints.c>
Lev Walkin06b8d7a2004-09-23 22:06:02 +000045#include <ber_tlv_tag.c>
46#include <ber_tlv_length.c>
Lev Walkin12984672004-09-24 21:00:15 +000047#include <OBJECT_IDENTIFIER.c>
48#include <RELATIVE-OID.c>
49#include <INTEGER.c>
Lev Walkin06b8d7a2004-09-23 22:06:02 +000050
51static void usage(const char *av0); /* Print the Usage screen and exit */
52static int process(const char *fname); /* Perform the BER decoding */
53static int decode_tlv_from_string(const char *datastring);
54
55#undef COPYRIGHT
56#define COPYRIGHT \
57 "Copyright (c) 2004 Lev Walkin <vlm@lionet.info>\n"
58
Lev Walkin12984672004-09-24 21:00:15 +000059static int single_type_decoding = 0; /* -1 enables that */
60static int pretty_printing = 1; /* -p disables that */
61static char *indent_buffer = " "; /* -i controls that */
Lev Walkin06b8d7a2004-09-23 22:06:02 +000062
63int
64main(int ac, char **av) {
65 int ch; /* Command line character */
66 int i; /* Index in some loops */
67
68 /*
69 * Process command-line options.
70 */
Lev Walkin12984672004-09-24 21:00:15 +000071 while((ch = getopt(ac, av, "1hi:pt:v")) != -1)
Lev Walkin06b8d7a2004-09-23 22:06:02 +000072 switch(ch) {
Lev Walkin12984672004-09-24 21:00:15 +000073 case '1':
74 single_type_decoding = 1;
75 break;
Lev Walkin06b8d7a2004-09-23 22:06:02 +000076 case 't':
77 if(decode_tlv_from_string(optarg))
78 exit(EX_DATAERR);
79 exit(0);
Lev Walkin12984672004-09-24 21:00:15 +000080 case 'p':
81 pretty_printing = 0;
82 break;
Lev Walkin06b8d7a2004-09-23 22:06:02 +000083 case 'i':
84 i = atoi(optarg);
85 if(i >= 0 && i < 16) {
86 indent_buffer = alloca(i + 1);
87 memset(indent_buffer, ' ', i);
88 indent_buffer[i] = '\0';
89 } else {
90 fprintf(stderr, "-i %s: Invalid indent value\n",optarg);
91 exit(EX_USAGE);
92 }
93 break;
94 case 'v':
95 fprintf(stderr, "ASN.1 BER Decoder, v" VERSION "\n" COPYRIGHT);
96 exit(0);
97 break;
Lev Walkin12984672004-09-24 21:00:15 +000098 case 'h':
Lev Walkin06b8d7a2004-09-23 22:06:02 +000099 default:
100 usage(av[0]);
101 }
102
103 /*
104 * Ensure that there are some input files present.
105 */
106 if(ac > optind) {
107 ac -= optind;
108 av += optind;
109 } else {
110 fprintf(stderr, "%s: No input files specified\n", av[0]);
111 exit(1);
112 }
113
114 setvbuf(stdout, 0, _IOLBF, 0);
115
116 /*
117 * Iterate over input files and parse each.
118 * All syntax trees from all files will be bundled together.
119 */
120 for(i = 0; i < ac; i++) {
121 if(process(av[i]))
122 exit(EX_DATAERR);
123 }
124
125 return 0;
126}
127
128/*
129 * Print the usage screen and exit(EX_USAGE).
130 */
131static void
132usage(const char *av0) {
133 fprintf(stderr,
134"ASN.1 BER Decoder, v" VERSION "\n" COPYRIGHT
135"Usage: %s [options] [-] [file ...]\n"
136"Options:\n"
Lev Walkin12984672004-09-24 21:00:15 +0000137" -1 Decode only the first BER structure (otherwise, until EOF)\n"
138" -i <indent> Amount of spaces for output indentation (default is 4)\n"
139" -p Do not attempt pretty-printing of known ASN.1 types\n"
140" -t <data-string> Decode the given tag[/length] sequence (e.g. -t \"bf20\")\n"
141"\n"
142"The XML opening tag format is as follows:\n"
143" <tform T=\"tag\" TL=\"tl_len\" V=\"{Indefinite|v_len}\" [A=\"type\"] [F]>\n"
144"Where:\n"
145" tform Which form the value is in: constructed (\"C\", \"I\") or primitive (\"P\")\n"
146" tag The tag class and value\n"
147" tl_len The length of the TL (BER Tag and Length) encoding\n"
148" v_len The length of the value (V, encoded by the L), may be \"Indefinite\"\n"
149" type Likely name of the underlying ASN.1 type (for [UNIVERSAL n] tags)\n"
150" [F] Indicates that the value was reformatted (pretty-printed)\n"
151"See the manual page for details\n"
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000152 , av0);
153 exit(EX_USAGE);
154}
155
156typedef enum pd_code {
157 PD_FAILED = -1,
158 PD_FINISHED = 0,
159 PD_EOF = 1,
160} pd_code_e;
161static pd_code_e process_deeper(const char *fname, FILE *fp, int level, ssize_t limit);
162static void print_TL(int fin, int level, int constr, ssize_t tlen, ber_tlv_tag_t, ber_tlv_len_t);
163static int print_V(const char *fname, FILE *fp, ber_tlv_tag_t, ber_tlv_len_t);
164
165/*
166 * Open the file and initiate recursive processing.
167 */
168static int
169process(const char *fname) {
170 FILE *fp;
171 pd_code_e pdc;
172
173 if(strcmp(fname, "-")) {
174 fp = fopen(fname, "r");
175 if(!fp) {
176 perror(fname);
177 return -1;
178 }
179 } else {
180 fp = stdin;
181 }
182
183 /*
184 * Fetch out BER-encoded data until EOF or error.
185 */
186 do {
187 pdc = process_deeper(fname, fp, 0, -1);
Lev Walkin12984672004-09-24 21:00:15 +0000188 } while(pdc == PD_FINISHED && !single_type_decoding);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000189
190 if(fp != stdin)
191 fclose(fp);
192
193 if(pdc == PD_FAILED)
194 return -1;
195 return 0;
196}
197
198/*
199 * Process the TLV recursively.
200 */
201static pd_code_e process_deeper(const char *fname, FILE *fp, int level, ssize_t limit) {
202 unsigned char tagbuf[32];
203 ssize_t tblen = 0;
204 pd_code_e pdc = PD_FINISHED;
205 ber_tlv_tag_t tlv_tag;
206 ber_tlv_len_t tlv_len;
207 ssize_t t_len;
208 ssize_t l_len;
209
210 do {
211 int constr;
212 int ch;
213
214 if(limit == 0)
215 return PD_FINISHED;
216
217 if(limit >= 0 && tblen >= limit) {
218 fprintf(stderr,
219 "%s: Too long TL sequence (%ld >= %ld). "
220 "Dangerous file\n",
221 fname, (long)tblen, (long)limit);
222 return PD_FAILED;
223 }
224
225 ch = fgetc(fp);
226 if(ch == -1) {
227 if(tblen) {
228 fprintf(stderr,
229 "%s: Unexpected end of file (TL)\n",
230 fname);
231 return PD_FAILED;
232 } else {
233 return PD_EOF;
234 }
235 }
236
237 tagbuf[tblen++] = ch;
238
239 /*
240 * Decode the TLV tag.
241 */
242 t_len = ber_fetch_tag(tagbuf, tblen, &tlv_tag);
243 switch(t_len) {
244 case -1:
245 fprintf(stderr, "%s: Fatal error deciphering tag\n",
246 fname);
247 return PD_FAILED;
248 case 0:
249 /* More data expected */
250 continue;
251 }
252
253 /*
254 * Decode the TLV length.
255 */
256 constr = BER_TLV_CONSTRUCTED(tagbuf);
257 l_len = ber_fetch_length(constr,
258 tagbuf + t_len, tblen - t_len, &tlv_len);
259 switch(l_len) {
260 case -1:
261 fprintf(stderr, "%s: Fatal error deciphering length\n",
262 fname);
263 return PD_FAILED;
264 case 0:
265 /* More data expected */
266 continue;
267 }
268
Lev Walkin12984672004-09-24 21:00:15 +0000269 if(tagbuf[0] == '\0' && tagbuf[1] == '\0') {
270 /* End of content octets */
271 return PD_FINISHED;
272 }
273
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000274 /* Make sure the T & L decoders took exactly the whole buffer */
275 assert((t_len + l_len) == tblen);
276
277 print_TL(0, level, constr, tblen, tlv_tag, tlv_len);
278
279 if(limit != -1) {
280 /* If limit is set, account for the TL sequence */
281 limit -= (t_len + l_len);
282 assert(limit >= 0);
283 }
284
285 if(limit != -1) {
286 if(tlv_len > limit) {
287 fprintf(stderr,
288 "%s: Structure advertizes length (%ld) "
289 "greater than of a parent container (%ld)\n",
290 fname, (long)tlv_len, (long)limit);
291 return PD_FAILED;
292 } else if(tlv_len != -1) {
293 /* Account for the V */
294 limit -= tlv_len;
295 }
296 }
297
298 if(constr) {
299 /*
300 * This is a constructed type. Process recursively.
301 */
302
303 /* Get the new subframe limit from the structure tags */
304 if(tlv_len == -1)
305 tlv_len = limit;
306
Lev Walkin12984672004-09-24 21:00:15 +0000307 printf(">\n"); /* Close the opening tag */
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000308 pdc = process_deeper(fname, fp, level + 1, tlv_len);
309 if(pdc == PD_FAILED) return pdc;
310 } else {
311
312 assert(tlv_len >= 0);
313 if(print_V(fname, fp, tlv_tag, tlv_len))
314 return PD_FAILED;
315 }
316
317 print_TL(1, level, constr, tblen, tlv_tag, tlv_len);
318
319 tblen = 0;
320 } while(1);
321
322 return pdc;
323}
324
325static void
326print_TL(int fin, int level, int constr, ssize_t tlen, ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len) {
327
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000328 if(fin && !constr) {
329 printf("</P>\n");
330 return;
331 }
332
333 while(level-- > 0) printf(indent_buffer); /* Print indent */
334 printf(fin ? "</" : "<");
335
Lev Walkin12984672004-09-24 21:00:15 +0000336 printf(constr ? ((tlv_len == -1) ? "I" : "C") : "P");
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000337
338 printf(" T=\"");
339 ber_tlv_tag_fwrite(tlv_tag, stdout);
340 printf("\"");
341
342 if(!fin) {
Lev Walkin12984672004-09-24 21:00:15 +0000343 printf(" TL=\"%ld\"", (long)tlen);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000344
345 if(tlv_len == -1)
Lev Walkin12984672004-09-24 21:00:15 +0000346 printf(" V=\"Indefinite\"");
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000347 else
Lev Walkin12984672004-09-24 21:00:15 +0000348 printf(" V=\"%ld\"", (long)tlv_len);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000349 }
350
351 if(BER_TAG_CLASS(tlv_tag) == ASN_TAG_CLASS_UNIVERSAL) {
352 const char *str;
353 ber_tlv_tag_t tvalue = BER_TAG_VALUE(tlv_tag);
354 str = ASN_UNIVERSAL_TAG2STR(tvalue);
355 if(str) printf(" A=\"%s\"", str);
356 }
357
Lev Walkin12984672004-09-24 21:00:15 +0000358 if(fin) printf(">\n");
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000359}
360
Lev Walkin12984672004-09-24 21:00:15 +0000361/*
362 * Print the value in binary form, or reformat for pretty-printing.
363 */
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000364static int
365print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len) {
Lev Walkin12984672004-09-24 21:00:15 +0000366 asn1_integer_t *arcs = 0; /* Object identifier arcs */
367 unsigned char *vbuf = 0;
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000368 asn1p_expr_type_e etype = 0;
Lev Walkin12984672004-09-24 21:00:15 +0000369 asn1_integer_t collector = 0;
370 int special_format = 0;
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000371 ssize_t i;
372
373 /* Figure out what type is it */
Lev Walkin12984672004-09-24 21:00:15 +0000374 if(BER_TAG_CLASS(tlv_tag) == ASN_TAG_CLASS_UNIVERSAL
375 && pretty_printing) {
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000376 ber_tlv_tag_t tvalue = BER_TAG_VALUE(tlv_tag);
377 etype = ASN_UNIVERSAL_TAG2TYPE(tvalue);
378 }
379
380 /*
Lev Walkin12984672004-09-24 21:00:15 +0000381 * Determine how to print the value, either in its native binary form,
382 * encoded with &xNN characters, or using pretty-printing.
383 * The basic string types (including "useful types", like UTCTime)
384 * are excempt from this determination logic, because their alphabets
385 * are subsets of the XML's native UTF-8 encoding.
386 */
387 switch(etype) {
388 case ASN_BASIC_BOOLEAN:
389 if(tlv_len == 1)
390 special_format = 1;
391 else
392 etype = 0;
393 break;
394 case ASN_BASIC_INTEGER:
395 case ASN_BASIC_ENUMERATED:
396 if((size_t)tlv_len <= sizeof(collector))
397 special_format = 1;
398 else
399 etype = 0;
400 break;
401 case ASN_BASIC_OBJECT_IDENTIFIER:
402 case ASN_BASIC_RELATIVE_OID:
403 if(tlv_len > 0 && tlv_len < 128*1024 /* VERY long OID! */) {
404 arcs = malloc(sizeof(*arcs) * (tlv_len + 1));
405 if(arcs) {
406 vbuf = malloc(tlv_len + 1);
407 /* Not checking is intentional */
408 }
409 }
410 case ASN_BASIC_UTCTime:
411 case ASN_BASIC_GeneralizedTime:
412 case ASN_STRING_NumericString:
413 case ASN_STRING_PrintableString:
414 case ASN_STRING_VisibleString:
415 case ASN_STRING_IA5String:
416 case ASN_STRING_UTF8String:
417 break; /* Directly compatible with UTF-8 */
418 case ASN_STRING_BMPString:
419 case ASN_STRING_UniversalString:
420 break; /* Not directly compatible with UTF-8 */
421 default:
422 /* Conditionally compatible with UTF-8 */
423 if((
424 (etype & ASN_STRING_MASK)
425 ||
426 (etype == ASN_BASIC_OCTET_STRING)
427 ) && (tlv_len > 0 && tlv_len < 128 * 1024)) {
428 vbuf = malloc(tlv_len + 1);
429 /* Not checking is intentional */
430 }
431 break;
432 }
433
434 /* If collection vbuf is present, defer printing the F flag. */
435 if(!vbuf) printf(special_format ? " F>" : ">");
436
437 /*
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000438 * Print the value in binary or text form.
439 */
440 for(i = 0; i < tlv_len; i++) {
441 int ch = fgetc(fp);
442 if(ch == -1) {
443 fprintf(stderr,
444 "%s: Unexpected end of file (V)\n", fname);
Lev Walkin12984672004-09-24 21:00:15 +0000445 if(vbuf) free(vbuf);
446 if(arcs) free(arcs);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000447 return -1;
448 }
449 switch(etype) {
450 case ASN_BASIC_UTCTime:
451 case ASN_BASIC_GeneralizedTime:
452 case ASN_STRING_NumericString:
453 case ASN_STRING_PrintableString:
454 case ASN_STRING_VisibleString:
Lev Walkin12984672004-09-24 21:00:15 +0000455 case ASN_STRING_IA5String:
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000456 case ASN_STRING_UTF8String:
457 switch(ch) {
458 default:
459 if(((etype == ASN_STRING_UTF8String)
460 || !(ch & 0x80))
461 && (ch >= 0x20)
462 ) {
463 printf("%c", ch);
464 break;
465 }
466 /* Fall through */
467 case '<': case '>': case '&':
468 printf("&x%02x;", ch);
469 }
470 break;
471 case ASN_BASIC_BOOLEAN:
Lev Walkin12984672004-09-24 21:00:15 +0000472 switch(ch) {
473 case 0: printf("<false/>"); break;
474 case 0xff: printf("<true/>"); break;
475 default: printf("<true value=\"&x%02x\"/>", ch);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000476 }
Lev Walkin12984672004-09-24 21:00:15 +0000477 break;
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000478 case ASN_BASIC_INTEGER:
479 case ASN_BASIC_ENUMERATED:
Lev Walkin12984672004-09-24 21:00:15 +0000480 if(i) collector = collector * 256 + ch;
481 else collector = (int)(signed char)ch;
482 break;
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000483 default:
Lev Walkin12984672004-09-24 21:00:15 +0000484 if(vbuf) {
485 vbuf[i] = ch;
486 } else {
487 printf("&x%02x;", ch);
488 }
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000489 }
490 }
491
Lev Walkin12984672004-09-24 21:00:15 +0000492 /* Do post-processing */
493 switch(etype) {
494 case ASN_BASIC_INTEGER:
495 case ASN_BASIC_ENUMERATED:
496 printf("%" PRIdMAX, collector);
497 break;
498 case ASN_BASIC_OBJECT_IDENTIFIER:
499 if(vbuf) {
500 OBJECT_IDENTIFIER_t oid;
501 int arcno;
502
503 oid.buf = vbuf;
504 oid.size = tlv_len;
505
506 arcno = OBJECT_IDENTIFIER_get_arcs(&oid, arcs,
507 sizeof(*arcs), tlv_len + 1);
508 if(arcno >= 0) {
509 assert(arcno <= (tlv_len + 1));
510 printf(" F>");
511 for(i = 0; i < arcno; i++) {
512 if(i) printf(".");
513 printf("%" PRIuASN, arcs[i]);
514 }
515 free(vbuf);
516 vbuf = 0;
517 }
518 }
519 break;
520 case ASN_BASIC_RELATIVE_OID:
521 if(vbuf) {
522 RELATIVE_OID_t oid;
523 int arcno;
524
525 oid.buf = vbuf;
526 oid.size = tlv_len;
527
528 arcno = RELATIVE_OID_get_arcs(&oid, arcs,
529 sizeof(*arcs), tlv_len);
530 if(arcno >= 0) {
531 assert(arcno <= (tlv_len + 1));
532 printf(" F>");
533 for(i = 0; i < arcno; i++) {
534 if(i) printf(".");
535 printf("%" PRIuASN, arcs[i]);
536 }
537 free(vbuf);
538 vbuf = 0;
539 }
540 }
541 break;
542 default: break;
543 }
544
545 /*
546 * If the buffer was not consumed, print it out.
547 */
548 if(vbuf) {
549 int binary;
550
551 /*
552 * Check whether the data could be represented as text
553 */
554 binary = -1 * (tlv_len >> 2); /* Threshold is 25% binary */
555 for(i = 0; i < tlv_len; i++) {
556 switch(vbuf[i]) {
557 case 0x1b: binary = 1; break;
558 case 0x09: case 0x0a: case 0x0d: continue;
559 default:
560 if(vbuf[i] < 0x20 || (vbuf[i] & 0x80))
561 if(++binary > 0) /* Way too many */
562 break;
563 continue;
564 }
565 break;
566 }
567 printf(">");
568 for(i = 0; i < tlv_len; i++) {
569 if(binary > 0 || vbuf[i] < 0x20 || (vbuf[i] & 0x80))
570 printf("&x%02x;", vbuf[i]);
571 else
572 printf("%c", vbuf[i]);
573 }
574 free(vbuf);
575 }
576
577 if(arcs) free(arcs);
Lev Walkin06b8d7a2004-09-23 22:06:02 +0000578 return 0;
579}
580
581
582static int
583decode_tlv_from_string(const char *datastring) {
584 unsigned char *data, *dp;
585 size_t dsize; /* Data size */
586 ssize_t len;
587 ber_tlv_tag_t tlv_tag;
588 ber_tlv_len_t tlv_len;
589 const char *p;
590 int half;
591
592 dsize = strlen(datastring) + 1;
593 dp = data = calloc(1, dsize);
594 assert(data);
595
596 for(half = 0, p = datastring; *p; p++) {
597 switch(*p) {
598 case '0': case '1': case '2': case '3': case '4':
599 case '5': case '6': case '7': case '8': case '9':
600 *dp |= *p - '0'; break;
601 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
602 *dp |= *p - 'A' + 10; break;
603 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
604 *dp |= *p - 'a' + 10; break;
605 case ' ': case '\t': case '\r': case '\n':
606 continue;
607 default:
608 fprintf(stderr, "Unexpected symbols in data string:\n");
609 fprintf(stderr, "%s\n", datastring);
610 for(dp = data; datastring < p; datastring++, dp++)
611 *dp = ' ';
612 *dp = '\0';
613 fprintf(stderr, "%s^ <- here\n", (char *)data);
614 return -1;
615 }
616 if(half) dp++; else (*dp) <<= 4;
617 half = !half;
618 }
619
620 assert((size_t)(dp - data) <= dsize);
621 dsize = dp - data;
622
623 printf("BER: ");
624 for(dp = data; dp < data + dsize; dp++)
625 printf("%02X", *dp);
626 printf("\n");
627
628 len = ber_fetch_tag(data, dsize, &tlv_tag);
629 switch(len) {
630 case -1:
631 fprintf(stderr, "TAG: Fatal error deciphering tag\n");
632 return -1;
633 case 0:
634 fprintf(stderr, "TAG: More data expected\n");
635 return -1;
636 default:
637 printf("TAG: ");
638 ber_tlv_tag_fwrite(tlv_tag, stdout);
639 if(BER_TLV_CONSTRUCTED(data)) {
640 printf(" (constructed)");
641 } else if(dsize >= 2 && data[0] == 0 && data[1] == 0) {
642 printf(" (end-of-content)");
643 } else {
644 printf(" (primitive)");
645 }
646 if(BER_TAG_CLASS(tlv_tag) == ASN_TAG_CLASS_UNIVERSAL) {
647 const char *str;
648 ber_tlv_tag_t tvalue = BER_TAG_VALUE(tlv_tag);
649 str = ASN_UNIVERSAL_TAG2STR(tvalue);
650 if(str) printf(" \"%s\"", str);
651 }
652 printf("\n");
653 }
654
655 if(dsize > (size_t)len) {
656 len = ber_fetch_length(BER_TLV_CONSTRUCTED(data),
657 data + len, dsize - len, &tlv_len);
658 switch(len) {
659 case -1:
660 fprintf(stderr,
661 "LEN: Fatal error deciphering length\n");
662 return -1;
663 case 0:
664 fprintf(stderr, "LEN: More data expected\n");
665 return -1;
666 default:
667 if(tlv_len == (ber_tlv_len_t)-1)
668 printf("LEN: Indefinite length encoding\n");
669 else
670 printf("LEN: %ld bytes\n", (long)tlv_len);
671 }
672 }
673
674 return 0;
675}
Lev Walkin12984672004-09-24 21:00:15 +0000676
677/*
678 * Dummy functions.
679 */
680ber_dec_rval_t ber_check_tags(asn1_TYPE_descriptor_t *td, ber_dec_ctx_t *opt_ctx, void *ptr, size_t size, int tag_mode, ber_tlv_len_t *last_length, int *opt_tlv_form) { ber_dec_rval_t rv; (void)td; (void)opt_ctx; (void)ptr; (void)size; (void)tag_mode; (void)last_length; (void)opt_tlv_form; return rv; }
681ssize_t der_write_tags(asn1_TYPE_descriptor_t *td, size_t slen, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) { (void)td; (void)slen; (void)tag_mode; (void)tag; (void)cb; (void)app_key; return -1; }