1*f5b1c8a1SJohn Marino /* $OpenBSD: asn1pars.c,v 1.5 2015/10/10 22:28:51 doug Exp $ */ 2*f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*f5b1c8a1SJohn Marino * All rights reserved. 4*f5b1c8a1SJohn Marino * 5*f5b1c8a1SJohn Marino * This package is an SSL implementation written 6*f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com). 7*f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL. 8*f5b1c8a1SJohn Marino * 9*f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as 10*f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions 11*f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA, 12*f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms 14*f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*f5b1c8a1SJohn Marino * 16*f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in 17*f5b1c8a1SJohn Marino * the code are not to be removed. 18*f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution 19*f5b1c8a1SJohn Marino * as the author of the parts of the library used. 20*f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or 21*f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package. 22*f5b1c8a1SJohn Marino * 23*f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 24*f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 25*f5b1c8a1SJohn Marino * are met: 26*f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright 27*f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 28*f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 29*f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the 30*f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution. 31*f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software 32*f5b1c8a1SJohn Marino * must display the following acknowledgement: 33*f5b1c8a1SJohn Marino * "This product includes cryptographic software written by 34*f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)" 35*f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library 36*f5b1c8a1SJohn Marino * being used are not cryptographic related :-). 37*f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from 38*f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement: 39*f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*f5b1c8a1SJohn Marino * 41*f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*f5b1c8a1SJohn Marino * SUCH DAMAGE. 52*f5b1c8a1SJohn Marino * 53*f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or 54*f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be 55*f5b1c8a1SJohn Marino * copied and put under another distribution licence 56*f5b1c8a1SJohn Marino * [including the GNU Public Licence.] 57*f5b1c8a1SJohn Marino */ 58*f5b1c8a1SJohn Marino 59*f5b1c8a1SJohn Marino /* A nice addition from Dr Stephen Henson <steve@openssl.org> to 60*f5b1c8a1SJohn Marino * add the -strparse option which parses nested binary structures 61*f5b1c8a1SJohn Marino */ 62*f5b1c8a1SJohn Marino 63*f5b1c8a1SJohn Marino #include <stdio.h> 64*f5b1c8a1SJohn Marino #include <stdlib.h> 65*f5b1c8a1SJohn Marino #include <limits.h> 66*f5b1c8a1SJohn Marino #include <string.h> 67*f5b1c8a1SJohn Marino 68*f5b1c8a1SJohn Marino #include "apps.h" 69*f5b1c8a1SJohn Marino #include "progs.h" 70*f5b1c8a1SJohn Marino 71*f5b1c8a1SJohn Marino #include <openssl/err.h> 72*f5b1c8a1SJohn Marino #include <openssl/evp.h> 73*f5b1c8a1SJohn Marino #include <openssl/pem.h> 74*f5b1c8a1SJohn Marino #include <openssl/x509.h> 75*f5b1c8a1SJohn Marino 76*f5b1c8a1SJohn Marino static struct { 77*f5b1c8a1SJohn Marino char *derfile; 78*f5b1c8a1SJohn Marino int dump; 79*f5b1c8a1SJohn Marino char *genconf; 80*f5b1c8a1SJohn Marino char *genstr; 81*f5b1c8a1SJohn Marino int indent; 82*f5b1c8a1SJohn Marino char *infile; 83*f5b1c8a1SJohn Marino int informat; 84*f5b1c8a1SJohn Marino unsigned int length; 85*f5b1c8a1SJohn Marino int noout; 86*f5b1c8a1SJohn Marino int offset; 87*f5b1c8a1SJohn Marino char *oidfile; 88*f5b1c8a1SJohn Marino STACK_OF(OPENSSL_STRING) *osk; 89*f5b1c8a1SJohn Marino } asn1pars_config; 90*f5b1c8a1SJohn Marino 91*f5b1c8a1SJohn Marino static int 92*f5b1c8a1SJohn Marino asn1pars_opt_dlimit(char *arg) 93*f5b1c8a1SJohn Marino { 94*f5b1c8a1SJohn Marino const char *errstr; 95*f5b1c8a1SJohn Marino 96*f5b1c8a1SJohn Marino asn1pars_config.dump = strtonum(arg, 1, INT_MAX, &errstr); 97*f5b1c8a1SJohn Marino if (errstr) { 98*f5b1c8a1SJohn Marino fprintf(stderr, "-dlimit must be from 1 to INT_MAX: %s\n", 99*f5b1c8a1SJohn Marino errstr); 100*f5b1c8a1SJohn Marino return (-1); 101*f5b1c8a1SJohn Marino } 102*f5b1c8a1SJohn Marino return (0); 103*f5b1c8a1SJohn Marino } 104*f5b1c8a1SJohn Marino 105*f5b1c8a1SJohn Marino static int 106*f5b1c8a1SJohn Marino asn1pars_opt_length(char *arg) 107*f5b1c8a1SJohn Marino { 108*f5b1c8a1SJohn Marino const char *errstr; 109*f5b1c8a1SJohn Marino 110*f5b1c8a1SJohn Marino asn1pars_config.length = strtonum(arg, 1, UINT_MAX, &errstr); 111*f5b1c8a1SJohn Marino if (errstr) { 112*f5b1c8a1SJohn Marino fprintf(stderr, "-length must be from 1 to UINT_MAX: %s\n", 113*f5b1c8a1SJohn Marino errstr); 114*f5b1c8a1SJohn Marino return (-1); 115*f5b1c8a1SJohn Marino } 116*f5b1c8a1SJohn Marino return (0); 117*f5b1c8a1SJohn Marino } 118*f5b1c8a1SJohn Marino 119*f5b1c8a1SJohn Marino static int 120*f5b1c8a1SJohn Marino asn1pars_opt_strparse(char *arg) 121*f5b1c8a1SJohn Marino { 122*f5b1c8a1SJohn Marino if (sk_OPENSSL_STRING_push(asn1pars_config.osk, arg) == 0) { 123*f5b1c8a1SJohn Marino fprintf(stderr, "-strparse cannot add argument\n"); 124*f5b1c8a1SJohn Marino return (-1); 125*f5b1c8a1SJohn Marino } 126*f5b1c8a1SJohn Marino return (0); 127*f5b1c8a1SJohn Marino } 128*f5b1c8a1SJohn Marino 129*f5b1c8a1SJohn Marino static struct option asn1pars_options[] = { 130*f5b1c8a1SJohn Marino { 131*f5b1c8a1SJohn Marino .name = "dump", 132*f5b1c8a1SJohn Marino .desc = "Dump unknown data in hex form", 133*f5b1c8a1SJohn Marino .type = OPTION_VALUE, 134*f5b1c8a1SJohn Marino .value = -1, 135*f5b1c8a1SJohn Marino .opt.value = &asn1pars_config.dump, 136*f5b1c8a1SJohn Marino }, 137*f5b1c8a1SJohn Marino { 138*f5b1c8a1SJohn Marino .name = "dlimit", 139*f5b1c8a1SJohn Marino .argname = "num", 140*f5b1c8a1SJohn Marino .desc = "Dump the first num bytes of unknown data in hex form", 141*f5b1c8a1SJohn Marino .type = OPTION_ARG_FUNC, 142*f5b1c8a1SJohn Marino .opt.argfunc = asn1pars_opt_dlimit, 143*f5b1c8a1SJohn Marino }, 144*f5b1c8a1SJohn Marino { 145*f5b1c8a1SJohn Marino .name = "genconf", 146*f5b1c8a1SJohn Marino .argname = "file", 147*f5b1c8a1SJohn Marino .desc = "File to generate ASN.1 structure from", 148*f5b1c8a1SJohn Marino .type = OPTION_ARG, 149*f5b1c8a1SJohn Marino .opt.arg = &asn1pars_config.genconf, 150*f5b1c8a1SJohn Marino }, 151*f5b1c8a1SJohn Marino { 152*f5b1c8a1SJohn Marino .name = "genstr", 153*f5b1c8a1SJohn Marino .argname = "string", 154*f5b1c8a1SJohn Marino .desc = "String to generate ASN.1 structure from", 155*f5b1c8a1SJohn Marino .type = OPTION_ARG, 156*f5b1c8a1SJohn Marino .opt.arg = &asn1pars_config.genstr, 157*f5b1c8a1SJohn Marino }, 158*f5b1c8a1SJohn Marino { 159*f5b1c8a1SJohn Marino .name = "i", 160*f5b1c8a1SJohn Marino .desc = "Indent output according to depth of structures", 161*f5b1c8a1SJohn Marino .type = OPTION_FLAG, 162*f5b1c8a1SJohn Marino .opt.flag = &asn1pars_config.indent, 163*f5b1c8a1SJohn Marino }, 164*f5b1c8a1SJohn Marino { 165*f5b1c8a1SJohn Marino .name = "in", 166*f5b1c8a1SJohn Marino .argname = "file", 167*f5b1c8a1SJohn Marino .desc = "The input file (default stdin)", 168*f5b1c8a1SJohn Marino .type = OPTION_ARG, 169*f5b1c8a1SJohn Marino .opt.arg = &asn1pars_config.infile, 170*f5b1c8a1SJohn Marino }, 171*f5b1c8a1SJohn Marino { 172*f5b1c8a1SJohn Marino .name = "inform", 173*f5b1c8a1SJohn Marino .argname = "fmt", 174*f5b1c8a1SJohn Marino .desc = "Input format (DER, TXT or PEM (default))", 175*f5b1c8a1SJohn Marino .type = OPTION_ARG_FORMAT, 176*f5b1c8a1SJohn Marino .opt.value = &asn1pars_config.informat, 177*f5b1c8a1SJohn Marino }, 178*f5b1c8a1SJohn Marino { 179*f5b1c8a1SJohn Marino .name = "length", 180*f5b1c8a1SJohn Marino .argname = "num", 181*f5b1c8a1SJohn Marino .desc = "Number of bytes to parse (default until EOF)", 182*f5b1c8a1SJohn Marino .type = OPTION_ARG_FUNC, 183*f5b1c8a1SJohn Marino .opt.argfunc = asn1pars_opt_length, 184*f5b1c8a1SJohn Marino }, 185*f5b1c8a1SJohn Marino { 186*f5b1c8a1SJohn Marino .name = "noout", 187*f5b1c8a1SJohn Marino .desc = "Do not produce any output", 188*f5b1c8a1SJohn Marino .type = OPTION_FLAG, 189*f5b1c8a1SJohn Marino .opt.flag = &asn1pars_config.noout, 190*f5b1c8a1SJohn Marino }, 191*f5b1c8a1SJohn Marino { 192*f5b1c8a1SJohn Marino .name = "offset", 193*f5b1c8a1SJohn Marino .argname = "num", 194*f5b1c8a1SJohn Marino .desc = "Offset to begin parsing", 195*f5b1c8a1SJohn Marino .type = OPTION_ARG_INT, 196*f5b1c8a1SJohn Marino .opt.value = &asn1pars_config.offset, 197*f5b1c8a1SJohn Marino }, 198*f5b1c8a1SJohn Marino { 199*f5b1c8a1SJohn Marino .name = "oid", 200*f5b1c8a1SJohn Marino .argname = "file", 201*f5b1c8a1SJohn Marino .desc = "File containing additional object identifiers (OIDs)", 202*f5b1c8a1SJohn Marino .type = OPTION_ARG, 203*f5b1c8a1SJohn Marino .opt.arg = &asn1pars_config.oidfile, 204*f5b1c8a1SJohn Marino }, 205*f5b1c8a1SJohn Marino { 206*f5b1c8a1SJohn Marino .name = "out", 207*f5b1c8a1SJohn Marino .argname = "file", 208*f5b1c8a1SJohn Marino .desc = "Output file in DER format", 209*f5b1c8a1SJohn Marino .type = OPTION_ARG, 210*f5b1c8a1SJohn Marino .opt.arg = &asn1pars_config.derfile, 211*f5b1c8a1SJohn Marino }, 212*f5b1c8a1SJohn Marino { 213*f5b1c8a1SJohn Marino .name = "strparse", 214*f5b1c8a1SJohn Marino .argname = "offset", 215*f5b1c8a1SJohn Marino .desc = "Parse the content octets of ASN.1 object starting at" 216*f5b1c8a1SJohn Marino " offset", 217*f5b1c8a1SJohn Marino .type = OPTION_ARG_FUNC, 218*f5b1c8a1SJohn Marino .opt.argfunc = asn1pars_opt_strparse, 219*f5b1c8a1SJohn Marino }, 220*f5b1c8a1SJohn Marino { NULL }, 221*f5b1c8a1SJohn Marino }; 222*f5b1c8a1SJohn Marino 223*f5b1c8a1SJohn Marino static void 224*f5b1c8a1SJohn Marino asn1pars_usage() 225*f5b1c8a1SJohn Marino { 226*f5b1c8a1SJohn Marino fprintf(stderr, 227*f5b1c8a1SJohn Marino "usage: asn1parse [-i] [-dlimit num] [-dump] [-genconf file] " 228*f5b1c8a1SJohn Marino "[-genstr string]\n" 229*f5b1c8a1SJohn Marino " [-in file] [-inform fmt] [-length num] [-noout] [-offset num] " 230*f5b1c8a1SJohn Marino "[-oid file]\n" 231*f5b1c8a1SJohn Marino " [-out file] [-strparse offset]\n\n"); 232*f5b1c8a1SJohn Marino options_usage(asn1pars_options); 233*f5b1c8a1SJohn Marino } 234*f5b1c8a1SJohn Marino 235*f5b1c8a1SJohn Marino static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf); 236*f5b1c8a1SJohn Marino 237*f5b1c8a1SJohn Marino int 238*f5b1c8a1SJohn Marino asn1parse_main(int argc, char **argv) 239*f5b1c8a1SJohn Marino { 240*f5b1c8a1SJohn Marino int i, j, ret = 1; 241*f5b1c8a1SJohn Marino long num, tmplen; 242*f5b1c8a1SJohn Marino BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL; 243*f5b1c8a1SJohn Marino char *str = NULL; 244*f5b1c8a1SJohn Marino const char *errstr = NULL; 245*f5b1c8a1SJohn Marino unsigned char *tmpbuf; 246*f5b1c8a1SJohn Marino const unsigned char *ctmpbuf; 247*f5b1c8a1SJohn Marino BUF_MEM *buf = NULL; 248*f5b1c8a1SJohn Marino ASN1_TYPE *at = NULL; 249*f5b1c8a1SJohn Marino 250*f5b1c8a1SJohn Marino if (single_execution) { 251*f5b1c8a1SJohn Marino if (pledge("stdio rpath wpath cpath", NULL) == -1) { 252*f5b1c8a1SJohn Marino perror("pledge"); 253*f5b1c8a1SJohn Marino exit(1); 254*f5b1c8a1SJohn Marino } 255*f5b1c8a1SJohn Marino } 256*f5b1c8a1SJohn Marino 257*f5b1c8a1SJohn Marino memset(&asn1pars_config, 0, sizeof(asn1pars_config)); 258*f5b1c8a1SJohn Marino 259*f5b1c8a1SJohn Marino asn1pars_config.informat = FORMAT_PEM; 260*f5b1c8a1SJohn Marino if ((asn1pars_config.osk = sk_OPENSSL_STRING_new_null()) == NULL) { 261*f5b1c8a1SJohn Marino BIO_printf(bio_err, "Memory allocation failure\n"); 262*f5b1c8a1SJohn Marino goto end; 263*f5b1c8a1SJohn Marino } 264*f5b1c8a1SJohn Marino 265*f5b1c8a1SJohn Marino if (options_parse(argc, argv, asn1pars_options, NULL, NULL) != 0) { 266*f5b1c8a1SJohn Marino asn1pars_usage(); 267*f5b1c8a1SJohn Marino return (1); 268*f5b1c8a1SJohn Marino } 269*f5b1c8a1SJohn Marino 270*f5b1c8a1SJohn Marino in = BIO_new(BIO_s_file()); 271*f5b1c8a1SJohn Marino out = BIO_new(BIO_s_file()); 272*f5b1c8a1SJohn Marino if ((in == NULL) || (out == NULL)) { 273*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 274*f5b1c8a1SJohn Marino goto end; 275*f5b1c8a1SJohn Marino } 276*f5b1c8a1SJohn Marino BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); 277*f5b1c8a1SJohn Marino 278*f5b1c8a1SJohn Marino if (asn1pars_config.oidfile != NULL) { 279*f5b1c8a1SJohn Marino if (BIO_read_filename(in, asn1pars_config.oidfile) <= 0) { 280*f5b1c8a1SJohn Marino BIO_printf(bio_err, "problems opening %s\n", 281*f5b1c8a1SJohn Marino asn1pars_config.oidfile); 282*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 283*f5b1c8a1SJohn Marino goto end; 284*f5b1c8a1SJohn Marino } 285*f5b1c8a1SJohn Marino OBJ_create_objects(in); 286*f5b1c8a1SJohn Marino } 287*f5b1c8a1SJohn Marino if (asn1pars_config.infile == NULL) 288*f5b1c8a1SJohn Marino BIO_set_fp(in, stdin, BIO_NOCLOSE); 289*f5b1c8a1SJohn Marino else { 290*f5b1c8a1SJohn Marino if (BIO_read_filename(in, asn1pars_config.infile) <= 0) { 291*f5b1c8a1SJohn Marino perror(asn1pars_config.infile); 292*f5b1c8a1SJohn Marino goto end; 293*f5b1c8a1SJohn Marino } 294*f5b1c8a1SJohn Marino } 295*f5b1c8a1SJohn Marino 296*f5b1c8a1SJohn Marino if (asn1pars_config.derfile) { 297*f5b1c8a1SJohn Marino if (!(derout = BIO_new_file(asn1pars_config.derfile, "wb"))) { 298*f5b1c8a1SJohn Marino BIO_printf(bio_err, "problems opening %s\n", 299*f5b1c8a1SJohn Marino asn1pars_config.derfile); 300*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 301*f5b1c8a1SJohn Marino goto end; 302*f5b1c8a1SJohn Marino } 303*f5b1c8a1SJohn Marino } 304*f5b1c8a1SJohn Marino if ((buf = BUF_MEM_new()) == NULL) 305*f5b1c8a1SJohn Marino goto end; 306*f5b1c8a1SJohn Marino if (!BUF_MEM_grow(buf, BUFSIZ * 8)) 307*f5b1c8a1SJohn Marino goto end; /* Pre-allocate :-) */ 308*f5b1c8a1SJohn Marino 309*f5b1c8a1SJohn Marino if (asn1pars_config.genstr || asn1pars_config.genconf) { 310*f5b1c8a1SJohn Marino num = do_generate(bio_err, asn1pars_config.genstr, 311*f5b1c8a1SJohn Marino asn1pars_config.genconf, buf); 312*f5b1c8a1SJohn Marino if (num < 0) { 313*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 314*f5b1c8a1SJohn Marino goto end; 315*f5b1c8a1SJohn Marino } 316*f5b1c8a1SJohn Marino } else { 317*f5b1c8a1SJohn Marino 318*f5b1c8a1SJohn Marino if (asn1pars_config.informat == FORMAT_PEM) { 319*f5b1c8a1SJohn Marino BIO *tmp; 320*f5b1c8a1SJohn Marino 321*f5b1c8a1SJohn Marino if ((b64 = BIO_new(BIO_f_base64())) == NULL) 322*f5b1c8a1SJohn Marino goto end; 323*f5b1c8a1SJohn Marino BIO_push(b64, in); 324*f5b1c8a1SJohn Marino tmp = in; 325*f5b1c8a1SJohn Marino in = b64; 326*f5b1c8a1SJohn Marino b64 = tmp; 327*f5b1c8a1SJohn Marino } 328*f5b1c8a1SJohn Marino num = 0; 329*f5b1c8a1SJohn Marino for (;;) { 330*f5b1c8a1SJohn Marino if (!BUF_MEM_grow(buf, (int) num + BUFSIZ)) 331*f5b1c8a1SJohn Marino goto end; 332*f5b1c8a1SJohn Marino i = BIO_read(in, &(buf->data[num]), BUFSIZ); 333*f5b1c8a1SJohn Marino if (i <= 0) 334*f5b1c8a1SJohn Marino break; 335*f5b1c8a1SJohn Marino num += i; 336*f5b1c8a1SJohn Marino } 337*f5b1c8a1SJohn Marino } 338*f5b1c8a1SJohn Marino str = buf->data; 339*f5b1c8a1SJohn Marino 340*f5b1c8a1SJohn Marino /* If any structs to parse go through in sequence */ 341*f5b1c8a1SJohn Marino 342*f5b1c8a1SJohn Marino if (sk_OPENSSL_STRING_num(asn1pars_config.osk)) { 343*f5b1c8a1SJohn Marino tmpbuf = (unsigned char *) str; 344*f5b1c8a1SJohn Marino tmplen = num; 345*f5b1c8a1SJohn Marino for (i = 0; i < sk_OPENSSL_STRING_num(asn1pars_config.osk); 346*f5b1c8a1SJohn Marino i++) { 347*f5b1c8a1SJohn Marino ASN1_TYPE *atmp; 348*f5b1c8a1SJohn Marino int typ; 349*f5b1c8a1SJohn Marino j = strtonum( 350*f5b1c8a1SJohn Marino sk_OPENSSL_STRING_value(asn1pars_config.osk, i), 351*f5b1c8a1SJohn Marino 1, INT_MAX, &errstr); 352*f5b1c8a1SJohn Marino if (errstr) { 353*f5b1c8a1SJohn Marino BIO_printf(bio_err, 354*f5b1c8a1SJohn Marino "'%s' is an invalid number: %s\n", 355*f5b1c8a1SJohn Marino sk_OPENSSL_STRING_value(asn1pars_config.osk, 356*f5b1c8a1SJohn Marino i), errstr); 357*f5b1c8a1SJohn Marino continue; 358*f5b1c8a1SJohn Marino } 359*f5b1c8a1SJohn Marino tmpbuf += j; 360*f5b1c8a1SJohn Marino tmplen -= j; 361*f5b1c8a1SJohn Marino atmp = at; 362*f5b1c8a1SJohn Marino ctmpbuf = tmpbuf; 363*f5b1c8a1SJohn Marino at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); 364*f5b1c8a1SJohn Marino ASN1_TYPE_free(atmp); 365*f5b1c8a1SJohn Marino if (!at) { 366*f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error parsing structure\n"); 367*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 368*f5b1c8a1SJohn Marino goto end; 369*f5b1c8a1SJohn Marino } 370*f5b1c8a1SJohn Marino typ = ASN1_TYPE_get(at); 371*f5b1c8a1SJohn Marino if ((typ == V_ASN1_OBJECT) || 372*f5b1c8a1SJohn Marino (typ == V_ASN1_NULL)) { 373*f5b1c8a1SJohn Marino BIO_printf(bio_err, "Can't parse %s type\n", 374*f5b1c8a1SJohn Marino typ == V_ASN1_NULL ? "NULL" : "OBJECT"); 375*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 376*f5b1c8a1SJohn Marino goto end; 377*f5b1c8a1SJohn Marino } 378*f5b1c8a1SJohn Marino /* hmm... this is a little evil but it works */ 379*f5b1c8a1SJohn Marino tmpbuf = at->value.asn1_string->data; 380*f5b1c8a1SJohn Marino tmplen = at->value.asn1_string->length; 381*f5b1c8a1SJohn Marino } 382*f5b1c8a1SJohn Marino str = (char *) tmpbuf; 383*f5b1c8a1SJohn Marino num = tmplen; 384*f5b1c8a1SJohn Marino } 385*f5b1c8a1SJohn Marino if (asn1pars_config.offset >= num) { 386*f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error: offset too large\n"); 387*f5b1c8a1SJohn Marino goto end; 388*f5b1c8a1SJohn Marino } 389*f5b1c8a1SJohn Marino num -= asn1pars_config.offset; 390*f5b1c8a1SJohn Marino 391*f5b1c8a1SJohn Marino if ((asn1pars_config.length == 0) || 392*f5b1c8a1SJohn Marino ((long)asn1pars_config.length > num)) 393*f5b1c8a1SJohn Marino asn1pars_config.length = (unsigned int) num; 394*f5b1c8a1SJohn Marino if (derout) { 395*f5b1c8a1SJohn Marino if (BIO_write(derout, str + asn1pars_config.offset, 396*f5b1c8a1SJohn Marino asn1pars_config.length) != (int)asn1pars_config.length) { 397*f5b1c8a1SJohn Marino BIO_printf(bio_err, "Error writing output\n"); 398*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 399*f5b1c8a1SJohn Marino goto end; 400*f5b1c8a1SJohn Marino } 401*f5b1c8a1SJohn Marino } 402*f5b1c8a1SJohn Marino if (!asn1pars_config.noout && 403*f5b1c8a1SJohn Marino !ASN1_parse_dump(out, 404*f5b1c8a1SJohn Marino (unsigned char *)&(str[asn1pars_config.offset]), 405*f5b1c8a1SJohn Marino asn1pars_config.length, asn1pars_config.indent, 406*f5b1c8a1SJohn Marino asn1pars_config.dump)) { 407*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 408*f5b1c8a1SJohn Marino goto end; 409*f5b1c8a1SJohn Marino } 410*f5b1c8a1SJohn Marino ret = 0; 411*f5b1c8a1SJohn Marino end: 412*f5b1c8a1SJohn Marino BIO_free(derout); 413*f5b1c8a1SJohn Marino BIO_free(in); 414*f5b1c8a1SJohn Marino BIO_free_all(out); 415*f5b1c8a1SJohn Marino BIO_free(b64); 416*f5b1c8a1SJohn Marino if (ret != 0) 417*f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 418*f5b1c8a1SJohn Marino BUF_MEM_free(buf); 419*f5b1c8a1SJohn Marino if (at != NULL) 420*f5b1c8a1SJohn Marino ASN1_TYPE_free(at); 421*f5b1c8a1SJohn Marino sk_OPENSSL_STRING_free(asn1pars_config.osk); 422*f5b1c8a1SJohn Marino OBJ_cleanup(); 423*f5b1c8a1SJohn Marino 424*f5b1c8a1SJohn Marino return (ret); 425*f5b1c8a1SJohn Marino } 426*f5b1c8a1SJohn Marino 427*f5b1c8a1SJohn Marino static int 428*f5b1c8a1SJohn Marino do_generate(BIO * bio, char *genstr, char *genconf, BUF_MEM * buf) 429*f5b1c8a1SJohn Marino { 430*f5b1c8a1SJohn Marino CONF *cnf = NULL; 431*f5b1c8a1SJohn Marino int len; 432*f5b1c8a1SJohn Marino long errline; 433*f5b1c8a1SJohn Marino unsigned char *p; 434*f5b1c8a1SJohn Marino ASN1_TYPE *atyp = NULL; 435*f5b1c8a1SJohn Marino 436*f5b1c8a1SJohn Marino if (genconf) { 437*f5b1c8a1SJohn Marino cnf = NCONF_new(NULL); 438*f5b1c8a1SJohn Marino if (!NCONF_load(cnf, genconf, &errline)) 439*f5b1c8a1SJohn Marino goto conferr; 440*f5b1c8a1SJohn Marino if (!genstr) 441*f5b1c8a1SJohn Marino genstr = NCONF_get_string(cnf, "default", "asn1"); 442*f5b1c8a1SJohn Marino if (!genstr) { 443*f5b1c8a1SJohn Marino BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf); 444*f5b1c8a1SJohn Marino goto err; 445*f5b1c8a1SJohn Marino } 446*f5b1c8a1SJohn Marino } 447*f5b1c8a1SJohn Marino atyp = ASN1_generate_nconf(genstr, cnf); 448*f5b1c8a1SJohn Marino NCONF_free(cnf); 449*f5b1c8a1SJohn Marino cnf = NULL; 450*f5b1c8a1SJohn Marino 451*f5b1c8a1SJohn Marino if (!atyp) 452*f5b1c8a1SJohn Marino return -1; 453*f5b1c8a1SJohn Marino 454*f5b1c8a1SJohn Marino len = i2d_ASN1_TYPE(atyp, NULL); 455*f5b1c8a1SJohn Marino if (len <= 0) 456*f5b1c8a1SJohn Marino goto err; 457*f5b1c8a1SJohn Marino 458*f5b1c8a1SJohn Marino if (!BUF_MEM_grow(buf, len)) 459*f5b1c8a1SJohn Marino goto err; 460*f5b1c8a1SJohn Marino 461*f5b1c8a1SJohn Marino p = (unsigned char *) buf->data; 462*f5b1c8a1SJohn Marino 463*f5b1c8a1SJohn Marino i2d_ASN1_TYPE(atyp, &p); 464*f5b1c8a1SJohn Marino 465*f5b1c8a1SJohn Marino ASN1_TYPE_free(atyp); 466*f5b1c8a1SJohn Marino return len; 467*f5b1c8a1SJohn Marino 468*f5b1c8a1SJohn Marino conferr: 469*f5b1c8a1SJohn Marino 470*f5b1c8a1SJohn Marino if (errline > 0) 471*f5b1c8a1SJohn Marino BIO_printf(bio, "Error on line %ld of config file '%s'\n", 472*f5b1c8a1SJohn Marino errline, genconf); 473*f5b1c8a1SJohn Marino else 474*f5b1c8a1SJohn Marino BIO_printf(bio, "Error loading config file '%s'\n", genconf); 475*f5b1c8a1SJohn Marino 476*f5b1c8a1SJohn Marino err: 477*f5b1c8a1SJohn Marino NCONF_free(cnf); 478*f5b1c8a1SJohn Marino ASN1_TYPE_free(atyp); 479*f5b1c8a1SJohn Marino 480*f5b1c8a1SJohn Marino return -1; 481*f5b1c8a1SJohn Marino 482*f5b1c8a1SJohn Marino } 483