xref: /dflybsd-src/crypto/libressl/apps/openssl/asn1pars.c (revision f5b1c8a1e6dbe9333aed363dba27c2ff58be6174)
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