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