1*0Sstevel@tonic-gate /* apps/asn1pars.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate /* A nice addition from Dr Stephen Henson <shenson@bigfoot.com> to 60*0Sstevel@tonic-gate * add the -strparse option which parses nested binary structures 61*0Sstevel@tonic-gate */ 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #include <stdio.h> 64*0Sstevel@tonic-gate #include <stdlib.h> 65*0Sstevel@tonic-gate #include <string.h> 66*0Sstevel@tonic-gate #include "apps.h" 67*0Sstevel@tonic-gate #include <openssl/err.h> 68*0Sstevel@tonic-gate #include <openssl/evp.h> 69*0Sstevel@tonic-gate #include <openssl/x509.h> 70*0Sstevel@tonic-gate #include <openssl/pem.h> 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* -inform arg - input format - default PEM (DER or PEM) 73*0Sstevel@tonic-gate * -in arg - input file - default stdin 74*0Sstevel@tonic-gate * -i - indent the details by depth 75*0Sstevel@tonic-gate * -offset - where in the file to start 76*0Sstevel@tonic-gate * -length - how many bytes to use 77*0Sstevel@tonic-gate * -oid file - extra oid description file 78*0Sstevel@tonic-gate */ 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate #undef PROG 81*0Sstevel@tonic-gate #define PROG asn1parse_main 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate int MAIN(int, char **); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate int MAIN(int argc, char **argv) 86*0Sstevel@tonic-gate { 87*0Sstevel@tonic-gate int i,badops=0,offset=0,ret=1,j; 88*0Sstevel@tonic-gate unsigned int length=0; 89*0Sstevel@tonic-gate long num,tmplen; 90*0Sstevel@tonic-gate BIO *in=NULL,*out=NULL,*b64=NULL, *derout = NULL; 91*0Sstevel@tonic-gate int informat,indent=0, noout = 0, dump = 0; 92*0Sstevel@tonic-gate char *infile=NULL,*str=NULL,*prog,*oidfile=NULL, *derfile=NULL; 93*0Sstevel@tonic-gate unsigned char *tmpbuf; 94*0Sstevel@tonic-gate BUF_MEM *buf=NULL; 95*0Sstevel@tonic-gate STACK *osk=NULL; 96*0Sstevel@tonic-gate ASN1_TYPE *at=NULL; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate informat=FORMAT_PEM; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate apps_startup(); 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate if (bio_err == NULL) 103*0Sstevel@tonic-gate if ((bio_err=BIO_new(BIO_s_file())) != NULL) 104*0Sstevel@tonic-gate BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate if (!load_config(bio_err, NULL)) 107*0Sstevel@tonic-gate goto end; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate prog=argv[0]; 110*0Sstevel@tonic-gate argc--; 111*0Sstevel@tonic-gate argv++; 112*0Sstevel@tonic-gate if ((osk=sk_new_null()) == NULL) 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate BIO_printf(bio_err,"Memory allocation failure\n"); 115*0Sstevel@tonic-gate goto end; 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate while (argc >= 1) 118*0Sstevel@tonic-gate { 119*0Sstevel@tonic-gate if (strcmp(*argv,"-inform") == 0) 120*0Sstevel@tonic-gate { 121*0Sstevel@tonic-gate if (--argc < 1) goto bad; 122*0Sstevel@tonic-gate informat=str2fmt(*(++argv)); 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate else if (strcmp(*argv,"-in") == 0) 125*0Sstevel@tonic-gate { 126*0Sstevel@tonic-gate if (--argc < 1) goto bad; 127*0Sstevel@tonic-gate infile= *(++argv); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate else if (strcmp(*argv,"-out") == 0) 130*0Sstevel@tonic-gate { 131*0Sstevel@tonic-gate if (--argc < 1) goto bad; 132*0Sstevel@tonic-gate derfile= *(++argv); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate else if (strcmp(*argv,"-i") == 0) 135*0Sstevel@tonic-gate { 136*0Sstevel@tonic-gate indent=1; 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate else if (strcmp(*argv,"-noout") == 0) noout = 1; 139*0Sstevel@tonic-gate else if (strcmp(*argv,"-oid") == 0) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate if (--argc < 1) goto bad; 142*0Sstevel@tonic-gate oidfile= *(++argv); 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate else if (strcmp(*argv,"-offset") == 0) 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate if (--argc < 1) goto bad; 147*0Sstevel@tonic-gate offset= atoi(*(++argv)); 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate else if (strcmp(*argv,"-length") == 0) 150*0Sstevel@tonic-gate { 151*0Sstevel@tonic-gate if (--argc < 1) goto bad; 152*0Sstevel@tonic-gate length= atoi(*(++argv)); 153*0Sstevel@tonic-gate if (length == 0) goto bad; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate else if (strcmp(*argv,"-dump") == 0) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate dump= -1; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate else if (strcmp(*argv,"-dlimit") == 0) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate if (--argc < 1) goto bad; 162*0Sstevel@tonic-gate dump= atoi(*(++argv)); 163*0Sstevel@tonic-gate if (dump <= 0) goto bad; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate else if (strcmp(*argv,"-strparse") == 0) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate if (--argc < 1) goto bad; 168*0Sstevel@tonic-gate sk_push(osk,*(++argv)); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate else 171*0Sstevel@tonic-gate { 172*0Sstevel@tonic-gate BIO_printf(bio_err,"unknown option %s\n",*argv); 173*0Sstevel@tonic-gate badops=1; 174*0Sstevel@tonic-gate break; 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate argc--; 177*0Sstevel@tonic-gate argv++; 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate if (badops) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate bad: 183*0Sstevel@tonic-gate BIO_printf(bio_err,"%s [options] <infile\n",prog); 184*0Sstevel@tonic-gate BIO_printf(bio_err,"where options are\n"); 185*0Sstevel@tonic-gate BIO_printf(bio_err," -inform arg input format - one of DER TXT PEM\n"); 186*0Sstevel@tonic-gate BIO_printf(bio_err," -in arg input file\n"); 187*0Sstevel@tonic-gate BIO_printf(bio_err," -out arg output file (output format is always DER\n"); 188*0Sstevel@tonic-gate BIO_printf(bio_err," -noout arg don't produce any output\n"); 189*0Sstevel@tonic-gate BIO_printf(bio_err," -offset arg offset into file\n"); 190*0Sstevel@tonic-gate BIO_printf(bio_err," -length arg length of section in file\n"); 191*0Sstevel@tonic-gate BIO_printf(bio_err," -i indent entries\n"); 192*0Sstevel@tonic-gate BIO_printf(bio_err," -dump dump unknown data in hex form\n"); 193*0Sstevel@tonic-gate BIO_printf(bio_err," -dlimit arg dump the first arg bytes of unknown data in hex form\n"); 194*0Sstevel@tonic-gate BIO_printf(bio_err," -oid file file of extra oid definitions\n"); 195*0Sstevel@tonic-gate BIO_printf(bio_err," -strparse offset\n"); 196*0Sstevel@tonic-gate BIO_printf(bio_err," a series of these can be used to 'dig' into multiple\n"); 197*0Sstevel@tonic-gate BIO_printf(bio_err," ASN1 blob wrappings\n"); 198*0Sstevel@tonic-gate goto end; 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate ERR_load_crypto_strings(); 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate in=BIO_new(BIO_s_file()); 204*0Sstevel@tonic-gate out=BIO_new(BIO_s_file()); 205*0Sstevel@tonic-gate if ((in == NULL) || (out == NULL)) 206*0Sstevel@tonic-gate { 207*0Sstevel@tonic-gate ERR_print_errors(bio_err); 208*0Sstevel@tonic-gate goto end; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); 211*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 212*0Sstevel@tonic-gate { 213*0Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 214*0Sstevel@tonic-gate out = BIO_push(tmpbio, out); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate #endif 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate if (oidfile != NULL) 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate if (BIO_read_filename(in,oidfile) <= 0) 221*0Sstevel@tonic-gate { 222*0Sstevel@tonic-gate BIO_printf(bio_err,"problems opening %s\n",oidfile); 223*0Sstevel@tonic-gate ERR_print_errors(bio_err); 224*0Sstevel@tonic-gate goto end; 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate OBJ_create_objects(in); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate if (infile == NULL) 230*0Sstevel@tonic-gate BIO_set_fp(in,stdin,BIO_NOCLOSE); 231*0Sstevel@tonic-gate else 232*0Sstevel@tonic-gate { 233*0Sstevel@tonic-gate if (BIO_read_filename(in,infile) <= 0) 234*0Sstevel@tonic-gate { 235*0Sstevel@tonic-gate perror(infile); 236*0Sstevel@tonic-gate goto end; 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate if (derfile) { 241*0Sstevel@tonic-gate if(!(derout = BIO_new_file(derfile, "wb"))) { 242*0Sstevel@tonic-gate BIO_printf(bio_err,"problems opening %s\n",derfile); 243*0Sstevel@tonic-gate ERR_print_errors(bio_err); 244*0Sstevel@tonic-gate goto end; 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if ((buf=BUF_MEM_new()) == NULL) goto end; 249*0Sstevel@tonic-gate if (!BUF_MEM_grow(buf,BUFSIZ*8)) goto end; /* Pre-allocate :-) */ 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (informat == FORMAT_PEM) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate BIO *tmp; 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate if ((b64=BIO_new(BIO_f_base64())) == NULL) 256*0Sstevel@tonic-gate goto end; 257*0Sstevel@tonic-gate BIO_push(b64,in); 258*0Sstevel@tonic-gate tmp=in; 259*0Sstevel@tonic-gate in=b64; 260*0Sstevel@tonic-gate b64=tmp; 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate num=0; 264*0Sstevel@tonic-gate for (;;) 265*0Sstevel@tonic-gate { 266*0Sstevel@tonic-gate if (!BUF_MEM_grow(buf,(int)num+BUFSIZ)) goto end; 267*0Sstevel@tonic-gate i=BIO_read(in,&(buf->data[num]),BUFSIZ); 268*0Sstevel@tonic-gate if (i <= 0) break; 269*0Sstevel@tonic-gate num+=i; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate str=buf->data; 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* If any structs to parse go through in sequence */ 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate if (sk_num(osk)) 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate tmpbuf=(unsigned char *)str; 278*0Sstevel@tonic-gate tmplen=num; 279*0Sstevel@tonic-gate for (i=0; i<sk_num(osk); i++) 280*0Sstevel@tonic-gate { 281*0Sstevel@tonic-gate ASN1_TYPE *atmp; 282*0Sstevel@tonic-gate j=atoi(sk_value(osk,i)); 283*0Sstevel@tonic-gate if (j == 0) 284*0Sstevel@tonic-gate { 285*0Sstevel@tonic-gate BIO_printf(bio_err,"'%s' is an invalid number\n",sk_value(osk,i)); 286*0Sstevel@tonic-gate continue; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate tmpbuf+=j; 289*0Sstevel@tonic-gate tmplen-=j; 290*0Sstevel@tonic-gate atmp = at; 291*0Sstevel@tonic-gate at = d2i_ASN1_TYPE(NULL,&tmpbuf,tmplen); 292*0Sstevel@tonic-gate ASN1_TYPE_free(atmp); 293*0Sstevel@tonic-gate if(!at) 294*0Sstevel@tonic-gate { 295*0Sstevel@tonic-gate BIO_printf(bio_err,"Error parsing structure\n"); 296*0Sstevel@tonic-gate ERR_print_errors(bio_err); 297*0Sstevel@tonic-gate goto end; 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate /* hmm... this is a little evil but it works */ 300*0Sstevel@tonic-gate tmpbuf=at->value.asn1_string->data; 301*0Sstevel@tonic-gate tmplen=at->value.asn1_string->length; 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate str=(char *)tmpbuf; 304*0Sstevel@tonic-gate num=tmplen; 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate if (offset >= num) 308*0Sstevel@tonic-gate { 309*0Sstevel@tonic-gate BIO_printf(bio_err, "Error: offset too large\n"); 310*0Sstevel@tonic-gate goto end; 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate num -= offset; 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate if ((length == 0) || ((long)length > num)) length=(unsigned int)num; 316*0Sstevel@tonic-gate if(derout) { 317*0Sstevel@tonic-gate if(BIO_write(derout, str + offset, length) != (int)length) { 318*0Sstevel@tonic-gate BIO_printf(bio_err, "Error writing output\n"); 319*0Sstevel@tonic-gate ERR_print_errors(bio_err); 320*0Sstevel@tonic-gate goto end; 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate if (!noout && 324*0Sstevel@tonic-gate !ASN1_parse_dump(out,(unsigned char *)&(str[offset]),length, 325*0Sstevel@tonic-gate indent,dump)) 326*0Sstevel@tonic-gate { 327*0Sstevel@tonic-gate ERR_print_errors(bio_err); 328*0Sstevel@tonic-gate goto end; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate ret=0; 331*0Sstevel@tonic-gate end: 332*0Sstevel@tonic-gate BIO_free(derout); 333*0Sstevel@tonic-gate if (in != NULL) BIO_free(in); 334*0Sstevel@tonic-gate if (out != NULL) BIO_free_all(out); 335*0Sstevel@tonic-gate if (b64 != NULL) BIO_free(b64); 336*0Sstevel@tonic-gate if (ret != 0) 337*0Sstevel@tonic-gate ERR_print_errors(bio_err); 338*0Sstevel@tonic-gate if (buf != NULL) BUF_MEM_free(buf); 339*0Sstevel@tonic-gate if (at != NULL) ASN1_TYPE_free(at); 340*0Sstevel@tonic-gate if (osk != NULL) sk_free(osk); 341*0Sstevel@tonic-gate OBJ_cleanup(); 342*0Sstevel@tonic-gate apps_shutdown(); 343*0Sstevel@tonic-gate OPENSSL_EXIT(ret); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346