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