Line data Source code
1 : /* tasn_prn.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 2000.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2000,2005 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stddef.h>
61 : #include "cryptlib.h"
62 : #include <openssl/asn1.h>
63 : #include <openssl/asn1t.h>
64 : #include <openssl/objects.h>
65 : #include <openssl/buffer.h>
66 : #include <openssl/err.h>
67 : #include <openssl/x509v3.h>
68 : #include "asn1_locl.h"
69 :
70 : /*
71 : * Print routines.
72 : */
73 :
74 : /* ASN1_PCTX routines */
75 :
76 : ASN1_PCTX default_pctx = {
77 : ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
78 : 0, /* nm_flags */
79 : 0, /* cert_flags */
80 : 0, /* oid_flags */
81 : 0 /* str_flags */
82 : };
83 :
84 0 : ASN1_PCTX *ASN1_PCTX_new(void)
85 : {
86 : ASN1_PCTX *ret;
87 0 : ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
88 0 : if (ret == NULL) {
89 0 : ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
90 0 : return NULL;
91 : }
92 0 : ret->flags = 0;
93 0 : ret->nm_flags = 0;
94 0 : ret->cert_flags = 0;
95 0 : ret->oid_flags = 0;
96 0 : ret->str_flags = 0;
97 0 : return ret;
98 : }
99 :
100 0 : void ASN1_PCTX_free(ASN1_PCTX *p)
101 : {
102 0 : OPENSSL_free(p);
103 0 : }
104 :
105 0 : unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
106 : {
107 0 : return p->flags;
108 : }
109 :
110 0 : void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
111 : {
112 0 : p->flags = flags;
113 0 : }
114 :
115 0 : unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
116 : {
117 0 : return p->nm_flags;
118 : }
119 :
120 0 : void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
121 : {
122 0 : p->nm_flags = flags;
123 0 : }
124 :
125 0 : unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
126 : {
127 0 : return p->cert_flags;
128 : }
129 :
130 0 : void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
131 : {
132 0 : p->cert_flags = flags;
133 0 : }
134 :
135 0 : unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
136 : {
137 0 : return p->oid_flags;
138 : }
139 :
140 0 : void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
141 : {
142 0 : p->oid_flags = flags;
143 0 : }
144 :
145 0 : unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
146 : {
147 0 : return p->str_flags;
148 : }
149 :
150 0 : void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
151 : {
152 0 : p->str_flags = flags;
153 0 : }
154 :
155 : /* Main print routines */
156 :
157 : static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
158 : const ASN1_ITEM *it,
159 : const char *fname, const char *sname,
160 : int nohdr, const ASN1_PCTX *pctx);
161 :
162 : int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
163 : const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
164 :
165 : static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
166 : const ASN1_ITEM *it, int indent,
167 : const char *fname, const char *sname,
168 : const ASN1_PCTX *pctx);
169 :
170 : static int asn1_print_fsname(BIO *out, int indent,
171 : const char *fname, const char *sname,
172 : const ASN1_PCTX *pctx);
173 :
174 0 : int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
175 : const ASN1_ITEM *it, const ASN1_PCTX *pctx)
176 : {
177 : const char *sname;
178 0 : if (pctx == NULL)
179 : pctx = &default_pctx;
180 0 : if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
181 : sname = NULL;
182 : else
183 0 : sname = it->sname;
184 0 : return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
185 : }
186 :
187 0 : static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
188 : const ASN1_ITEM *it,
189 : const char *fname, const char *sname,
190 : int nohdr, const ASN1_PCTX *pctx)
191 : {
192 : const ASN1_TEMPLATE *tt;
193 : const ASN1_EXTERN_FUNCS *ef;
194 : ASN1_VALUE **tmpfld;
195 0 : const ASN1_AUX *aux = it->funcs;
196 : ASN1_aux_cb *asn1_cb;
197 : ASN1_PRINT_ARG parg;
198 : int i;
199 0 : if (aux && aux->asn1_cb) {
200 0 : parg.out = out;
201 0 : parg.indent = indent;
202 0 : parg.pctx = pctx;
203 0 : asn1_cb = aux->asn1_cb;
204 : } else
205 : asn1_cb = 0;
206 :
207 0 : if (*fld == NULL) {
208 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
209 0 : if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
210 : return 0;
211 0 : if (BIO_puts(out, "<ABSENT>\n") <= 0)
212 : return 0;
213 : }
214 : return 1;
215 : }
216 :
217 0 : switch (it->itype) {
218 : case ASN1_ITYPE_PRIMITIVE:
219 0 : if (it->templates) {
220 0 : if (!asn1_template_print_ctx(out, fld, indent,
221 : it->templates, pctx))
222 : return 0;
223 : break;
224 : }
225 : /* fall thru */
226 : case ASN1_ITYPE_MSTRING:
227 0 : if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx))
228 : return 0;
229 : break;
230 :
231 : case ASN1_ITYPE_EXTERN:
232 0 : if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
233 : return 0;
234 : /* Use new style print routine if possible */
235 0 : ef = it->funcs;
236 0 : if (ef && ef->asn1_ex_print) {
237 0 : i = ef->asn1_ex_print(out, fld, indent, "", pctx);
238 0 : if (!i)
239 : return 0;
240 0 : if ((i == 2) && (BIO_puts(out, "\n") <= 0))
241 : return 0;
242 : return 1;
243 0 : } else if (sname &&
244 0 : BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
245 : return 0;
246 : break;
247 :
248 : case ASN1_ITYPE_CHOICE:
249 : #if 0
250 : if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
251 : return 0;
252 : #endif
253 : /* CHOICE type, get selector */
254 0 : i = asn1_get_choice_selector(fld, it);
255 : /* This should never happen... */
256 0 : if ((i < 0) || (i >= it->tcount)) {
257 0 : if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
258 : return 0;
259 0 : return 1;
260 : }
261 0 : tt = it->templates + i;
262 0 : tmpfld = asn1_get_field_ptr(fld, tt);
263 0 : if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
264 : return 0;
265 : break;
266 :
267 : case ASN1_ITYPE_SEQUENCE:
268 : case ASN1_ITYPE_NDEF_SEQUENCE:
269 0 : if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
270 : return 0;
271 0 : if (fname || sname) {
272 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
273 0 : if (BIO_puts(out, " {\n") <= 0)
274 : return 0;
275 : } else {
276 0 : if (BIO_puts(out, "\n") <= 0)
277 : return 0;
278 : }
279 : }
280 :
281 0 : if (asn1_cb) {
282 0 : i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
283 0 : if (i == 0)
284 : return 0;
285 0 : if (i == 2)
286 : return 1;
287 : }
288 :
289 : /* Print each field entry */
290 0 : for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
291 : const ASN1_TEMPLATE *seqtt;
292 0 : seqtt = asn1_do_adb(fld, tt, 1);
293 0 : if (!seqtt)
294 : return 0;
295 0 : tmpfld = asn1_get_field_ptr(fld, seqtt);
296 0 : if (!asn1_template_print_ctx(out, tmpfld,
297 : indent + 2, seqtt, pctx))
298 : return 0;
299 : }
300 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
301 0 : if (BIO_printf(out, "%*s}\n", indent, "") < 0)
302 : return 0;
303 : }
304 :
305 0 : if (asn1_cb) {
306 0 : i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
307 0 : if (i == 0)
308 : return 0;
309 : }
310 : break;
311 :
312 : default:
313 0 : BIO_printf(out, "Unprocessed type %d\n", it->itype);
314 0 : return 0;
315 : }
316 :
317 : return 1;
318 : }
319 :
320 0 : int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
321 : const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
322 : {
323 : int i, flags;
324 : const char *sname, *fname;
325 0 : flags = tt->flags;
326 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
327 0 : sname = ASN1_ITEM_ptr(tt->item)->sname;
328 : else
329 : sname = NULL;
330 0 : if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
331 : fname = NULL;
332 : else
333 0 : fname = tt->field_name;
334 0 : if (flags & ASN1_TFLG_SK_MASK) {
335 : char *tname;
336 : ASN1_VALUE *skitem;
337 : STACK_OF(ASN1_VALUE) *stack;
338 :
339 : /* SET OF, SEQUENCE OF */
340 0 : if (fname) {
341 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
342 0 : if (flags & ASN1_TFLG_SET_OF)
343 : tname = "SET";
344 : else
345 : tname = "SEQUENCE";
346 0 : if (BIO_printf(out, "%*s%s OF %s {\n",
347 : indent, "", tname, tt->field_name) <= 0)
348 : return 0;
349 0 : } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
350 : return 0;
351 : }
352 0 : stack = (STACK_OF(ASN1_VALUE) *)*fld;
353 0 : for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
354 0 : if ((i > 0) && (BIO_puts(out, "\n") <= 0))
355 : return 0;
356 :
357 0 : skitem = sk_ASN1_VALUE_value(stack, i);
358 0 : if (!asn1_item_print_ctx(out, &skitem, indent + 2,
359 0 : ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
360 : pctx))
361 : return 0;
362 : }
363 0 : if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
364 : return 0;
365 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
366 0 : if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
367 : return 0;
368 : }
369 : return 1;
370 : }
371 0 : return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
372 : fname, sname, 0, pctx);
373 : }
374 :
375 0 : static int asn1_print_fsname(BIO *out, int indent,
376 : const char *fname, const char *sname,
377 : const ASN1_PCTX *pctx)
378 : {
379 : static char spaces[] = " ";
380 : const int nspaces = sizeof(spaces) - 1;
381 :
382 : #if 0
383 : if (!sname && !fname)
384 : return 1;
385 : #endif
386 :
387 0 : while (indent > nspaces) {
388 0 : if (BIO_write(out, spaces, nspaces) != nspaces)
389 : return 0;
390 0 : indent -= nspaces;
391 : }
392 0 : if (BIO_write(out, spaces, indent) != indent)
393 : return 0;
394 0 : if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
395 : sname = NULL;
396 0 : if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
397 : fname = NULL;
398 0 : if (!sname && !fname)
399 : return 1;
400 0 : if (fname) {
401 0 : if (BIO_puts(out, fname) <= 0)
402 : return 0;
403 : }
404 0 : if (sname) {
405 0 : if (fname) {
406 0 : if (BIO_printf(out, " (%s)", sname) <= 0)
407 : return 0;
408 : } else {
409 0 : if (BIO_puts(out, sname) <= 0)
410 : return 0;
411 : }
412 : }
413 0 : if (BIO_write(out, ": ", 2) != 2)
414 : return 0;
415 : return 1;
416 : }
417 :
418 0 : static int asn1_print_boolean_ctx(BIO *out, int boolval,
419 : const ASN1_PCTX *pctx)
420 : {
421 : const char *str;
422 0 : switch (boolval) {
423 : case -1:
424 : str = "BOOL ABSENT";
425 : break;
426 :
427 : case 0:
428 : str = "FALSE";
429 : break;
430 :
431 : default:
432 : str = "TRUE";
433 : break;
434 :
435 : }
436 :
437 0 : if (BIO_puts(out, str) <= 0)
438 : return 0;
439 : return 1;
440 :
441 : }
442 :
443 0 : static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
444 : const ASN1_PCTX *pctx)
445 : {
446 : char *s;
447 : int ret = 1;
448 0 : s = i2s_ASN1_INTEGER(NULL, str);
449 0 : if (BIO_puts(out, s) <= 0)
450 : ret = 0;
451 0 : OPENSSL_free(s);
452 0 : return ret;
453 : }
454 :
455 0 : static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
456 : const ASN1_PCTX *pctx)
457 : {
458 : char objbuf[80];
459 : const char *ln;
460 0 : ln = OBJ_nid2ln(OBJ_obj2nid(oid));
461 0 : if (!ln)
462 : ln = "";
463 0 : OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
464 0 : if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
465 : return 0;
466 : return 1;
467 : }
468 :
469 0 : static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
470 : const ASN1_PCTX *pctx)
471 : {
472 0 : if (str->type == V_ASN1_BIT_STRING) {
473 0 : if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0)
474 : return 0;
475 0 : } else if (BIO_puts(out, "\n") <= 0)
476 : return 0;
477 0 : if ((str->length > 0)
478 0 : && BIO_dump_indent(out, (char *)str->data, str->length,
479 : indent + 2) <= 0)
480 : return 0;
481 : return 1;
482 : }
483 :
484 0 : static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
485 : const ASN1_ITEM *it, int indent,
486 : const char *fname, const char *sname,
487 : const ASN1_PCTX *pctx)
488 : {
489 : long utype;
490 : ASN1_STRING *str;
491 : int ret = 1, needlf = 1;
492 : const char *pname;
493 : const ASN1_PRIMITIVE_FUNCS *pf;
494 0 : pf = it->funcs;
495 0 : if (!asn1_print_fsname(out, indent, fname, sname, pctx))
496 : return 0;
497 0 : if (pf && pf->prim_print)
498 0 : return pf->prim_print(out, fld, it, indent, pctx);
499 0 : str = (ASN1_STRING *)*fld;
500 0 : if (it->itype == ASN1_ITYPE_MSTRING)
501 0 : utype = str->type & ~V_ASN1_NEG;
502 : else
503 0 : utype = it->utype;
504 0 : if (utype == V_ASN1_ANY) {
505 : ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
506 0 : utype = atype->type;
507 0 : fld = &atype->value.asn1_value;
508 0 : str = (ASN1_STRING *)*fld;
509 0 : if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
510 : pname = NULL;
511 : else
512 0 : pname = ASN1_tag2str(utype);
513 : } else {
514 0 : if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
515 0 : pname = ASN1_tag2str(utype);
516 : else
517 : pname = NULL;
518 : }
519 :
520 0 : if (utype == V_ASN1_NULL) {
521 0 : if (BIO_puts(out, "NULL\n") <= 0)
522 : return 0;
523 0 : return 1;
524 : }
525 :
526 0 : if (pname) {
527 0 : if (BIO_puts(out, pname) <= 0)
528 : return 0;
529 0 : if (BIO_puts(out, ":") <= 0)
530 : return 0;
531 : }
532 :
533 0 : switch (utype) {
534 : case V_ASN1_BOOLEAN:
535 : {
536 0 : int boolval = *(int *)fld;
537 0 : if (boolval == -1)
538 0 : boolval = it->size;
539 0 : ret = asn1_print_boolean_ctx(out, boolval, pctx);
540 : }
541 0 : break;
542 :
543 : case V_ASN1_INTEGER:
544 : case V_ASN1_ENUMERATED:
545 0 : ret = asn1_print_integer_ctx(out, str, pctx);
546 0 : break;
547 :
548 : case V_ASN1_UTCTIME:
549 0 : ret = ASN1_UTCTIME_print(out, str);
550 0 : break;
551 :
552 : case V_ASN1_GENERALIZEDTIME:
553 0 : ret = ASN1_GENERALIZEDTIME_print(out, str);
554 0 : break;
555 :
556 : case V_ASN1_OBJECT:
557 0 : ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
558 0 : break;
559 :
560 : case V_ASN1_OCTET_STRING:
561 : case V_ASN1_BIT_STRING:
562 0 : ret = asn1_print_obstring_ctx(out, str, indent, pctx);
563 : needlf = 0;
564 0 : break;
565 :
566 : case V_ASN1_SEQUENCE:
567 : case V_ASN1_SET:
568 : case V_ASN1_OTHER:
569 0 : if (BIO_puts(out, "\n") <= 0)
570 : return 0;
571 0 : if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0)
572 : ret = 0;
573 : needlf = 0;
574 : break;
575 :
576 : default:
577 0 : ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
578 :
579 : }
580 0 : if (!ret)
581 : return 0;
582 0 : if (needlf && BIO_puts(out, "\n") <= 0)
583 : return 0;
584 : return 1;
585 : }
|