155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 755682Smarkm * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 1155682Smarkm * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 1455682Smarkm * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 1855682Smarkm * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 3455682Smarkm */ 3555682Smarkm 3655682Smarkm#include "der_locl.h" 37102644Snectar#include <com_err.h> 3855682Smarkm#include <sys/types.h> 3955682Smarkm#include <sys/stat.h> 4055682Smarkm#include <getarg.h> 4155682Smarkm#include <err.h> 42178825Sdfr#include <der.h> 4355682Smarkm 44178825Sdfrstatic int indent_flag = 1; 45233294Sstasstatic int inner_flag = 0; 4655682Smarkm 47178825Sdfrstatic unsigned long indefinite_form_loop; 48178825Sdfrstatic unsigned long indefinite_form_loop_max = 10000; 4955682Smarkm 50178825Sdfrstatic size_t 5155682Smarkmloop (unsigned char *buf, size_t len, int indent) 5255682Smarkm{ 53178825Sdfr unsigned char *start_buf = buf; 54178825Sdfr 5555682Smarkm while (len > 0) { 5655682Smarkm int ret; 5755682Smarkm Der_class class; 5855682Smarkm Der_type type; 59178825Sdfr unsigned int tag; 6055682Smarkm size_t sz; 6155682Smarkm size_t length; 62178825Sdfr size_t loop_length = 0; 63178825Sdfr int end_tag = 0; 64178825Sdfr const char *tagname; 6555682Smarkm 6655682Smarkm ret = der_get_tag (buf, len, &class, &type, &tag, &sz); 6755682Smarkm if (ret) 68102644Snectar errx (1, "der_get_tag: %s", error_message (ret)); 6972445Sassar if (sz > len) 7072445Sassar errx (1, "unreasonable length (%u) > %u", 7172445Sassar (unsigned)sz, (unsigned)len); 7255682Smarkm buf += sz; 7355682Smarkm len -= sz; 74178825Sdfr if (indent_flag) { 75178825Sdfr int i; 76178825Sdfr for (i = 0; i < indent; ++i) 77178825Sdfr printf (" "); 78178825Sdfr } 79178825Sdfr printf ("%s %s ", der_get_class_name(class), der_get_type_name(type)); 80178825Sdfr tagname = der_get_tag_name(tag); 81178825Sdfr if (class == ASN1_C_UNIV && tagname != NULL) 82178825Sdfr printf ("%s = ", tagname); 8355682Smarkm else 8455682Smarkm printf ("tag %d = ", tag); 8555682Smarkm ret = der_get_length (buf, len, &length, &sz); 8655682Smarkm if (ret) 87102644Snectar errx (1, "der_get_tag: %s", error_message (ret)); 88178825Sdfr if (sz > len) 89178825Sdfr errx (1, "unreasonable tag length (%u) > %u", 90178825Sdfr (unsigned)sz, (unsigned)len); 9155682Smarkm buf += sz; 9255682Smarkm len -= sz; 93178825Sdfr if (length == ASN1_INDEFINITE) { 94178825Sdfr if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) || 95178825Sdfr (class == ASN1_C_CONTEXT && type == CONS) || 96178825Sdfr (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) || 97178825Sdfr (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) { 98178825Sdfr printf("*INDEFINITE FORM*"); 99178825Sdfr } else { 100178825Sdfr fflush(stdout); 101178825Sdfr errx(1, "indef form used on unsupported object"); 102178825Sdfr } 103178825Sdfr end_tag = 1; 104178825Sdfr if (indefinite_form_loop > indefinite_form_loop_max) 105178825Sdfr errx(1, "indefinite form used recursively more then %lu " 106178825Sdfr "times, aborting", indefinite_form_loop_max); 107178825Sdfr indefinite_form_loop++; 108178825Sdfr length = len; 109178825Sdfr } else if (length > len) { 110178825Sdfr printf("\n"); 111178825Sdfr fflush(stdout); 112178825Sdfr errx (1, "unreasonable inner length (%u) > %u", 113178825Sdfr (unsigned)length, (unsigned)len); 114178825Sdfr } 115178825Sdfr if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) { 116178825Sdfr printf ("%lu bytes [%u]", (unsigned long)length, tag); 117178825Sdfr if (type == CONS) { 118178825Sdfr printf("\n"); 119178825Sdfr loop_length = loop (buf, length, indent + 2); 120178825Sdfr } else { 121178825Sdfr printf(" IMPLICIT content\n"); 122178825Sdfr } 123178825Sdfr } else if (class == ASN1_C_UNIV) { 12455682Smarkm switch (tag) { 125178825Sdfr case UT_EndOfContent: 126178825Sdfr printf (" INDEFINITE length was %lu\n", 127178825Sdfr (unsigned long)(buf - start_buf)); 128178825Sdfr break; 129178825Sdfr case UT_Set : 13055682Smarkm case UT_Sequence : 131178825Sdfr printf ("%lu bytes {\n", (unsigned long)length); 132178825Sdfr loop_length = loop (buf, length, indent + 2); 133178825Sdfr if (indent_flag) { 134178825Sdfr int i; 135178825Sdfr for (i = 0; i < indent; ++i) 136178825Sdfr printf (" "); 137178825Sdfr printf ("}\n"); 138178825Sdfr } else 139178825Sdfr printf ("} indent = %d\n", indent / 2); 14055682Smarkm break; 14155682Smarkm case UT_Integer : { 14255682Smarkm int val; 14355682Smarkm 144178825Sdfr if (length <= sizeof(val)) { 145178825Sdfr ret = der_get_integer (buf, length, &val, NULL); 146178825Sdfr if (ret) 147178825Sdfr errx (1, "der_get_integer: %s", error_message (ret)); 148178825Sdfr printf ("integer %d\n", val); 149178825Sdfr } else { 150178825Sdfr heim_integer vali; 151178825Sdfr char *p; 152178825Sdfr 153178825Sdfr ret = der_get_heim_integer(buf, length, &vali, NULL); 154178825Sdfr if (ret) 155233294Sstas errx (1, "der_get_heim_integer: %s", 156178825Sdfr error_message (ret)); 157178825Sdfr ret = der_print_hex_heim_integer(&vali, &p); 158178825Sdfr if (ret) 159233294Sstas errx (1, "der_print_hex_heim_integer: %s", 160178825Sdfr error_message (ret)); 161233294Sstas printf ("BIG NUM integer: length %lu %s\n", 162178825Sdfr (unsigned long)length, p); 163178825Sdfr free(p); 164178825Sdfr } 16555682Smarkm break; 16655682Smarkm } 16755682Smarkm case UT_OctetString : { 168178825Sdfr heim_octet_string str; 169233294Sstas size_t i; 17055682Smarkm 17155682Smarkm ret = der_get_octet_string (buf, length, &str, NULL); 17255682Smarkm if (ret) 173102644Snectar errx (1, "der_get_octet_string: %s", error_message (ret)); 17490926Snectar printf ("(length %lu), ", (unsigned long)length); 175233294Sstas 176233294Sstas if (inner_flag) { 177233294Sstas Der_class class; 178233294Sstas Der_type type; 179233294Sstas unsigned int tag; 180233294Sstas 181233294Sstas ret = der_get_tag(str.data, str.length, 182233294Sstas &class, &type, &tag, &sz); 183233294Sstas if (ret || sz > str.length || 184233294Sstas type != CONS || tag != UT_Sequence) 185233294Sstas goto just_an_octet_string; 186233294Sstas 187233294Sstas printf("{\n"); 188233294Sstas loop (str.data, str.length, indent + 2); 189233294Sstas for (i = 0; i < indent; ++i) 190233294Sstas printf (" "); 191233294Sstas printf ("}\n"); 192233294Sstas 193233294Sstas } else { 194233294Sstas unsigned char *uc; 195233294Sstas 196233294Sstas just_an_octet_string: 197233294Sstas uc = (unsigned char *)str.data; 198233294Sstas for (i = 0; i < min(16,length); ++i) 199233294Sstas printf ("%02x", uc[i]); 200233294Sstas printf ("\n"); 201233294Sstas } 20255682Smarkm free (str.data); 20355682Smarkm break; 20455682Smarkm } 205233294Sstas case UT_IA5String : 206233294Sstas case UT_PrintableString : { 207233294Sstas heim_printable_string str; 208233294Sstas unsigned char *s; 209233294Sstas size_t n; 210233294Sstas 211233294Sstas memset(&str, 0, sizeof(str)); 212233294Sstas 213233294Sstas ret = der_get_printable_string (buf, length, &str, NULL); 214233294Sstas if (ret) 215233294Sstas errx (1, "der_get_general_string: %s", 216233294Sstas error_message (ret)); 217233294Sstas s = str.data; 218233294Sstas printf("\""); 219233294Sstas for (n = 0; n < str.length; n++) { 220233294Sstas if (isprint((int)s[n])) 221233294Sstas printf ("%c", s[n]); 222233294Sstas else 223233294Sstas printf ("#%02x", s[n]); 224233294Sstas } 225233294Sstas printf("\"\n"); 226233294Sstas der_free_printable_string(&str); 227233294Sstas break; 228233294Sstas } 22955682Smarkm case UT_GeneralizedTime : 230178825Sdfr case UT_GeneralString : 231233294Sstas case UT_VisibleString : 232233294Sstas case UT_UTF8String : { 233178825Sdfr heim_general_string str; 23455682Smarkm 23555682Smarkm ret = der_get_general_string (buf, length, &str, NULL); 23655682Smarkm if (ret) 23755682Smarkm errx (1, "der_get_general_string: %s", 238102644Snectar error_message (ret)); 23955682Smarkm printf ("\"%s\"\n", str); 24055682Smarkm free (str); 24155682Smarkm break; 24255682Smarkm } 243102644Snectar case UT_OID: { 244178825Sdfr heim_oid o; 245178825Sdfr char *p; 246102644Snectar 247102644Snectar ret = der_get_oid(buf, length, &o, NULL); 248102644Snectar if (ret) 249102644Snectar errx (1, "der_get_oid: %s", error_message (ret)); 250178825Sdfr ret = der_print_heim_oid(&o, '.', &p); 251178825Sdfr der_free_oid(&o); 252178825Sdfr if (ret) 253178825Sdfr errx (1, "der_print_heim_oid: %s", error_message (ret)); 254178825Sdfr printf("%s\n", p); 255178825Sdfr free(p); 256178825Sdfr 257178825Sdfr break; 258178825Sdfr } 259178825Sdfr case UT_Enumerated: { 260178825Sdfr int num; 261178825Sdfr 262178825Sdfr ret = der_get_integer (buf, length, &num, NULL); 263178825Sdfr if (ret) 264178825Sdfr errx (1, "der_get_enum: %s", error_message (ret)); 265233294Sstas 266178825Sdfr printf("%u\n", num); 267102644Snectar break; 268102644Snectar } 26955682Smarkm default : 27090926Snectar printf ("%lu bytes\n", (unsigned long)length); 27155682Smarkm break; 27255682Smarkm } 27355682Smarkm } 274178825Sdfr if (end_tag) { 275178825Sdfr if (loop_length == 0) 276233294Sstas errx(1, "zero length INDEFINITE data ? indent = %d\n", 277178825Sdfr indent / 2); 278178825Sdfr if (loop_length < length) 279178825Sdfr length = loop_length; 280178825Sdfr if (indefinite_form_loop == 0) 281178825Sdfr errx(1, "internal error in indefinite form loop detection"); 282178825Sdfr indefinite_form_loop--; 283178825Sdfr } else if (loop_length) 284178825Sdfr errx(1, "internal error for INDEFINITE form"); 28555682Smarkm buf += length; 28655682Smarkm len -= length; 28755682Smarkm } 28855682Smarkm return 0; 28955682Smarkm} 29055682Smarkm 29155682Smarkmstatic int 29255682Smarkmdoit (const char *filename) 29355682Smarkm{ 29455682Smarkm int fd = open (filename, O_RDONLY); 29555682Smarkm struct stat sb; 29655682Smarkm unsigned char *buf; 29755682Smarkm size_t len; 29855682Smarkm int ret; 29955682Smarkm 30055682Smarkm if(fd < 0) 30155682Smarkm err (1, "opening %s for read", filename); 30255682Smarkm if (fstat (fd, &sb) < 0) 30355682Smarkm err (1, "stat %s", filename); 30455682Smarkm len = sb.st_size; 305178825Sdfr buf = emalloc (len); 30655682Smarkm if (read (fd, buf, len) != len) 30755682Smarkm errx (1, "read failed"); 30855682Smarkm close (fd); 30955682Smarkm ret = loop (buf, len, 0); 31055682Smarkm free (buf); 311233294Sstas return ret; 31255682Smarkm} 31355682Smarkm 31455682Smarkm 31555682Smarkmstatic int version_flag; 31655682Smarkmstatic int help_flag; 31755682Smarkmstruct getargs args[] = { 318178825Sdfr { "indent", 0, arg_negative_flag, &indent_flag }, 319233294Sstas { "inner", 0, arg_flag, &inner_flag, "try to parse inner structures of OCTET STRING" }, 32055682Smarkm { "version", 0, arg_flag, &version_flag }, 32155682Smarkm { "help", 0, arg_flag, &help_flag } 32255682Smarkm}; 32355682Smarkmint num_args = sizeof(args) / sizeof(args[0]); 32455682Smarkm 32555682Smarkmstatic void 32655682Smarkmusage(int code) 32755682Smarkm{ 32855682Smarkm arg_printusage(args, num_args, NULL, "dump-file"); 32955682Smarkm exit(code); 33055682Smarkm} 33155682Smarkm 33255682Smarkmint 33355682Smarkmmain(int argc, char **argv) 33455682Smarkm{ 335178825Sdfr int optidx = 0; 33655682Smarkm 33778527Sassar setprogname (argv[0]); 338102644Snectar initialize_asn1_error_table (); 339178825Sdfr if(getarg(args, num_args, argc, argv, &optidx)) 34055682Smarkm usage(1); 34155682Smarkm if(help_flag) 34255682Smarkm usage(0); 34355682Smarkm if(version_flag) { 34455682Smarkm print_version(NULL); 34555682Smarkm exit(0); 34655682Smarkm } 347178825Sdfr argv += optidx; 348178825Sdfr argc -= optidx; 34955682Smarkm if (argc != 1) 35055682Smarkm usage (1); 35155682Smarkm return doit (argv[0]); 35255682Smarkm} 353