Update ASN1 printing code. Highly experimental, not working properly (neither
[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 #define ASN1_PCTX_FLAGS_SHOW_ABSENT     0x1
70 #define ASN1_PCTX_FLAGS_SHOW_SEQUENCE   0x2
71 #define ASN1_PCTX_FLAGS_SHOW_TYPE       0x4
72 #define ASN1_PCTX_FLAGS_NO_FIELD_NAME   0x8
73 #define ASN1_PCTX_FLAGS_NO_STRUCT_NAME  0x10
74
75 /* Print routines.
76  */
77
78 /* ASN1_PCTX routines */
79
80 ASN1_PCTX default_pctx = 
81         {
82         ASN1_PCTX_FLAGS_SHOW_ABSENT,    /* flags */
83         0,      /* nm_flags */
84         0,      /* cert_flags */
85         0,      /* oid_flags */
86         0       /* str_flags */
87         };
88         
89
90 ASN1_PCTX *ASN1_PCTX_new(void)
91         {
92         ASN1_PCTX *ret;
93         ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
94         if (ret == NULL)
95                 {
96                 ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
97                 return NULL;
98                 }
99         ret->flags = 0;
100         ret->nm_flags = 0;
101         ret->cert_flags = 0;
102         ret->oid_flags = 0;
103         ret->str_flags = 0;
104         return ret;
105         }
106
107 void ASN1_PCTX_free(ASN1_PCTX *p)
108         {
109         OPENSSL_free(p);
110         }
111
112 unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
113         {
114         return p->flags;
115         }
116
117 void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
118         {
119         p->flags = flags;
120         }
121
122 unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
123         {
124         return p->nm_flags;
125         }
126
127 void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
128         {
129         p->nm_flags = flags;
130         }
131
132 unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
133         {
134         return p->cert_flags;
135         }
136
137 void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
138         {
139         p->cert_flags = flags;
140         }
141
142 unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
143         {
144         return p->oid_flags;
145         }
146
147 void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
148         {
149         p->oid_flags = flags;
150         }
151
152 unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
153         {
154         return p->str_flags;
155         }
156
157 void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
158         {
159         p->str_flags = flags;
160         }
161
162 /* Main print routines */
163
164 static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
165                                 const ASN1_ITEM *it, const ASN1_PCTX *pctx);
166 int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
167                                 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
168 static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
169                                 const ASN1_ITEM *it, int indent,
170                                 const ASN1_PCTX *pctx);
171
172 int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
173                                 const ASN1_ITEM *it, const ASN1_PCTX *pctx)
174         {
175         if (pctx == NULL)
176                 pctx = &default_pctx;
177         return asn1_item_print_ctx(out, &ifld, indent, it, pctx);
178         }
179
180 static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
181                                 const ASN1_ITEM *it, const ASN1_PCTX *pctx)
182         {
183         const ASN1_TEMPLATE *tt;
184         const ASN1_EXTERN_FUNCS *ef;
185         ASN1_VALUE **tmpfld;
186         int i;
187         if (BIO_printf(out, "%s:", it->sname) <= 0)
188                 return 0;
189         if(*fld == NULL)
190                 {
191                 if (!(pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT))
192                         {
193                         if (BIO_puts(out, "\n") <= 0)
194                                 return 0;
195                         }
196                 else
197                         {
198                         if (BIO_puts(out, "<ABSENT>\n") <= 0)
199                                 return 0;
200                         }
201                 return 1;
202                 }
203
204         switch(it->itype)
205                 {
206                 case ASN1_ITYPE_PRIMITIVE:
207                 if(it->templates)
208                         {
209                         if (!asn1_template_print_ctx(out, fld, indent,
210                                                         it->templates, pctx))
211                                 return 0;
212                         }
213                 /* fall thru */
214                 case ASN1_ITYPE_MSTRING:
215                 if (!asn1_primitive_print(out, fld, it, indent, pctx))
216                         return 0;
217                 break;
218
219                 case ASN1_ITYPE_EXTERN:
220                 /* Use new style print routine if possible */
221                 ef = it->funcs;
222                 if (ef && ef->asn1_ex_print)
223                         {
224                         if (!ef->asn1_ex_print(out, fld, indent, "", pctx))
225                                 return 0;
226                         }
227                 else if (BIO_printf(out, ":EXTERNAL TYPE %s\n", it->sname) <= 0)
228                         return 0;
229                 break;
230
231                 case ASN1_ITYPE_CHOICE:
232                 /* CHOICE type, get selector */
233                 i = asn1_get_choice_selector(fld, it);
234                 /* This should never happen... */
235                 if((i < 0) || (i >= it->tcount))
236                         {
237                         if (BIO_printf(out,
238                                 "ERROR: selector [%d] invalid\n", i) <= 0)
239                                 return 0;
240                         return 1;
241                         }
242                 tt = it->templates + i;
243                 tmpfld = asn1_get_field_ptr(fld, tt);
244                 if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
245                         return 0;
246                 break;
247
248                 case ASN1_ITYPE_SEQUENCE:
249                 case ASN1_ITYPE_NDEF_SEQUENCE:
250                 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
251                         {
252                         if (BIO_puts(out, " {\n") <= 0)
253                                 return 0;
254                         }
255                 else
256                         {
257                         if (BIO_puts(out, "\n") <= 0)
258                                 return 0;
259                         }
260
261                 /* Print each field entry */
262                 for(i = 0, tt = it->templates; i < it->tcount; i++, tt++)
263                         {
264                         const ASN1_TEMPLATE *seqtt;
265                         seqtt = asn1_do_adb(fld, tt, 1);
266                         tmpfld = asn1_get_field_ptr(fld, seqtt);
267                         if (!asn1_template_print_ctx(out, tmpfld,
268                                                 indent + 2, seqtt, pctx))
269                                 return 0;
270                         }
271                 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
272                         {
273                         if (BIO_printf(out, "%*s}\n", indent, "") < 0)
274                                 return 0;
275                         }
276                 break;
277
278                 default:
279                 BIO_printf(out, "Unprocessed type %d\n", it->itype);
280                 return 0;
281                 }
282         if (BIO_puts(out, "\n") <= 0)
283                 return 0;
284         return 1;
285         }
286
287 int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
288                                 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
289         {
290         int i, flags;
291         flags = tt->flags;
292         if(flags & ASN1_TFLG_SK_MASK)
293                 {
294                 char *tname;
295                 ASN1_VALUE *skitem;
296                 /* SET OF, SEQUENCE OF */
297                 if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
298                         {
299                         if(flags & ASN1_TFLG_SET_OF)
300                                 tname = "SET";
301                         else
302                                 tname = "SEQUENCE";
303                         if (BIO_printf(out, "%*s%s OF %s {\n",
304                                 indent, "", tname, tt->field_name) <= 0)
305                                 return 0;
306                         }
307                 else if (BIO_printf(out, "%*s%s:\n", indent, "",
308                                         tt->field_name) <= 0)
309                                 return 0;
310                 for(i = 0; i < sk_num((STACK *)*fld); i++)
311                         {
312                         if (BIO_printf(out, "%*s", indent + 2, "") <= 0)
313                                 return 0;
314                         skitem = (ASN1_VALUE *)sk_value((STACK *)*fld, i);
315                         if (!asn1_item_print_ctx(out, &skitem, indent + 2,
316                                         tt->item, pctx))
317                                 return 0;
318                         }
319                 if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
320                         {
321                         if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
322                                 return 0;
323                         }
324                 return 1;
325                 }
326         else if (BIO_printf(out, "%*s%s:", indent, "", tt->field_name) <= 0)
327                                 return 0;
328         return asn1_item_print_ctx(out, fld, indent, tt->item, pctx);
329         }
330
331 int asn1_print_fsname(BIO *out, int indent,
332                         const char *fname, const char *sname,
333                         const ASN1_PCTX *pctx)
334         {
335         static char spaces[] = "                    ";
336         const int nspaces = sizeof(spaces) - 1;
337         while (indent > nspaces)
338                 {
339                 if (BIO_write(out, spaces, nspaces) != nspaces)
340                         return 0;
341                 indent -= nspaces;
342                 }
343         if (BIO_write(out, spaces, indent) != indent)
344                 return 0;
345         if (!(pctx->flags &
346                 (ASN1_PCTX_FLAGS_NO_FIELD_NAME|ASN1_PCTX_FLAGS_NO_STRUCT_NAME)))
347                 return 1;
348         if (fname && !(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME))
349                 {
350                 if (BIO_puts(out, fname) <= 0)
351                         return 0;
352                 }
353         if (sname && !(pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME))
354                 {
355                 if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
356                         {
357                         if (BIO_puts(out, sname) <= 0)
358                                 return 0;
359                         }
360                 else if (BIO_printf(out, " (%s)", sname) <= 0)
361                         return 0;
362                 }
363         if (BIO_write(out, ":", 1) != 1)
364                 return 0;
365         return 1;
366         }
367
368 int asn1_print_boolean_ctx(BIO *out, const int bool, const ASN1_PCTX *pctx)
369         {
370         const char *str;
371         switch (bool)
372                 {
373                 case -1:
374                 str = "BOOL ABSENT";
375                 break;
376
377                 case 0:
378                 str = "FALSE";
379                 break;
380
381                 default:
382                 str = "TRUE";
383                 break;
384
385                 }
386
387         if (BIO_puts(out, str) <= 0)
388                 return 0;
389         return 1;
390
391         }
392
393 static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
394                                                 const ASN1_PCTX *pctx)
395         {
396         char *s;
397         int ret = 1;
398         s = i2s_ASN1_INTEGER(NULL, str);
399         if (BIO_printf(out, "%s", s) <= 0)
400                 ret = 0;
401         OPENSSL_free(s);
402         return ret;
403         }
404
405 static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
406                                                 const ASN1_PCTX *pctx)
407         {
408         char objbuf[80];
409         const char *ln;
410         ln = OBJ_nid2ln(OBJ_obj2nid(oid));
411         if(!ln)
412                 ln = "";
413         OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
414         if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
415                 return 0;
416         return 1;
417         }
418
419 static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
420                                                 const ASN1_PCTX *pctx)
421         {
422         if (str->type == V_ASN1_BIT_STRING)
423                 {
424                 if (BIO_printf(out, " (%ld unused bits)\n",
425                                         str->flags & 0x7) <= 0)
426                                 return 0;
427                 }
428         else if (BIO_puts(out, "\n") <= 0)
429                 return 0;
430         if (BIO_dump_indent(out, (char *)str->data, str->length,
431                                 indent + 2) <= 0)
432                 return 0;
433         return 1;
434         }
435
436 static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
437                                 const ASN1_ITEM *it, int indent,
438                                 const ASN1_PCTX *pctx)
439         {
440         long utype;
441         ASN1_STRING *str;
442         int ret = 1;
443         str = (ASN1_STRING *)*fld;
444         if (it->itype == ASN1_ITYPE_MSTRING)
445                 utype = str->type & ~V_ASN1_NEG;
446         else
447                 utype = it->utype;
448         if (utype == V_ASN1_ANY)
449                 {
450                 ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
451                 utype = atype->type;
452                 fld = (ASN1_VALUE **)&atype->value.ptr;
453                 str = (ASN1_STRING *)*fld;
454                 }
455         if (BIO_puts(out, ASN1_tag2str(utype)) <= 0)
456                 return 0;
457         if (utype != V_ASN1_NULL && BIO_puts(out, ":") <= 0)
458                 return 0;
459
460         switch (utype)
461                 {
462                 case V_ASN1_BOOLEAN:
463                         {
464                         int bool = *(int *)fld;
465                         if (bool == -1)
466                                 bool = it->size;
467                         ret = asn1_print_boolean_ctx(out, bool, pctx);
468                         }
469                 break;
470
471                 case V_ASN1_INTEGER:
472                 case V_ASN1_ENUMERATED:
473                 ret = asn1_print_integer_ctx(out, str, pctx);
474                 break;
475
476                 case V_ASN1_NULL:
477                 break;
478
479                 case V_ASN1_UTCTIME:
480                 ret = ASN1_UTCTIME_print(out, str);
481                 break;
482
483                 case V_ASN1_GENERALIZEDTIME:
484                 ret = ASN1_GENERALIZEDTIME_print(out, str);
485                 break;
486
487                 case V_ASN1_OBJECT:
488                 ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
489                 break;
490
491                 case V_ASN1_OCTET_STRING:
492                 case V_ASN1_BIT_STRING:
493                 ret = asn1_print_obstring_ctx(out, str, indent, pctx);
494                 break;
495
496                 case V_ASN1_SEQUENCE:
497                 case V_ASN1_SET:
498                 if (ASN1_parse_dump(out, str->data, str->length,
499                                                 indent, 0) <= 0)
500                         ret = 0;
501                 break;
502
503                 default:
504                 ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
505
506                 }
507         if (!ret)
508                 return 0;
509         return 1;
510         }