Fix strange formatting by indent
[openssl.git] / crypto / asn1 / asn1_par.c
1 /* crypto/asn1/asn1_par.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 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/buffer.h>
62 #include <openssl/objects.h>
63 #include <openssl/asn1.h>
64
65 static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
66         int indent);
67 static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
68         int offset, int depth, int indent, int dump);
69 static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
70              int indent)
71         {
72         static const char fmt[]="%-18s";
73         char str[128];
74         const char *p;
75
76         if (constructed & V_ASN1_CONSTRUCTED)
77                 p="cons: ";
78         else
79                 p="prim: ";
80         if (BIO_write(bp,p,6) < 6) goto err;
81         BIO_indent(bp,indent,128);
82
83         p=str;
84         if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
85                 BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
86         else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
87                 BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
88         else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
89                 BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
90         else if (tag > 30)
91                 BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
92         else
93                 p = ASN1_tag2str(tag);
94
95         if (BIO_printf(bp,fmt,p) <= 0)
96                 goto err;
97         return(1);
98 err:
99         return(0);
100         }
101
102 int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
103         {
104         return(asn1_parse2(bp,&pp,len,0,0,indent,0));
105         }
106
107 int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
108         {
109         return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
110         }
111
112 static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
113              int depth, int indent, int dump)
114         {
115         const unsigned char *p,*ep,*tot,*op,*opp;
116         long len;
117         int tag,xclass,ret=0;
118         int nl,hl,j,r;
119         ASN1_OBJECT *o=NULL;
120         ASN1_OCTET_STRING *os=NULL;
121         /* ASN1_BMPSTRING *bmp=NULL;*/
122         int dump_indent;
123
124 #if 0
125         dump_indent = indent;
126 #else
127         dump_indent = 6;        /* Because we know BIO_dump_indent() */
128 #endif
129         p= *pp;
130         tot=p+length;
131         op=p-1;
132         while ((p < tot) && (op < p))
133                 {
134                 op=p;
135                 j=ASN1_get_object(&p,&len,&tag,&xclass,length);
136                 if (j & 0x80)
137                         {
138                         if (BIO_write(bp,"Error in encoding\n",18) <= 0)
139                                 goto end;
140                         ret=0;
141                         goto end;
142                         }
143                 hl=(p-op);
144                 length-=hl;
145                 /* if j == 0x21 it is a constructed indefinite length object */
146                 if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
147                         <= 0) goto end;
148
149                 if (j != (V_ASN1_CONSTRUCTED | 1))
150                         {
151                         if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
152                                 depth,(long)hl,len) <= 0)
153                                 goto end;
154                         }
155                 else
156                         {
157                         if (BIO_printf(bp,"d=%-2d hl=%ld l=inf  ",
158                                 depth,(long)hl) <= 0)
159                                 goto end;
160                         }
161                 if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
162                         goto end;
163                 if (j & V_ASN1_CONSTRUCTED)
164                         {
165                         ep=p+len;
166                         if (BIO_write(bp,"\n",1) <= 0) goto end;
167                         if (len > length)
168                                 {
169                                 BIO_printf(bp,
170                                         "length is greater than %ld\n",length);
171                                 ret=0;
172                                 goto end;
173                                 }
174                         if ((j == 0x21) && (len == 0))
175                                 {
176                                 for (;;)
177                                         {
178                                         r=asn1_parse2(bp,&p,(long)(tot-p),
179                                                 offset+(p - *pp),depth+1,
180                                                 indent,dump);
181                                         if (r == 0) { ret=0; goto end; }
182                                         if ((r == 2) || (p >= tot)) break;
183                                         }
184                                 }
185                         else
186                                 while (p < ep)
187                                         {
188                                         r=asn1_parse2(bp,&p,(long)len,
189                                                 offset+(p - *pp),depth+1,
190                                                 indent,dump);
191                                         if (r == 0) { ret=0; goto end; }
192                                         }
193                         }
194                 else if (xclass != 0)
195                         {
196                         p+=len;
197                         if (BIO_write(bp,"\n",1) <= 0) goto end;
198                         }
199                 else
200                         {
201                         nl=0;
202                         if (    (tag == V_ASN1_PRINTABLESTRING) ||
203                                 (tag == V_ASN1_T61STRING) ||
204                                 (tag == V_ASN1_IA5STRING) ||
205                                 (tag == V_ASN1_VISIBLESTRING) ||
206                                 (tag == V_ASN1_NUMERICSTRING) ||
207                                 (tag == V_ASN1_UTF8STRING) ||
208                                 (tag == V_ASN1_UTCTIME) ||
209                                 (tag == V_ASN1_GENERALIZEDTIME))
210                                 {
211                                 if (BIO_write(bp,":",1) <= 0) goto end;
212                                 if ((len > 0) &&
213                                         BIO_write(bp,(const char *)p,(int)len)
214                                         != (int)len)
215                                         goto end;
216                                 }
217                         else if (tag == V_ASN1_OBJECT)
218                                 {
219                                 opp=op;
220                                 if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
221                                         {
222                                         if (BIO_write(bp,":",1) <= 0) goto end;
223                                         i2a_ASN1_OBJECT(bp,o);
224                                         }
225                                 else
226                                         {
227                                         if (BIO_write(bp,":BAD OBJECT",11) <= 0)
228                                                 goto end;
229                                         }
230                                 }
231                         else if (tag == V_ASN1_BOOLEAN)
232                                 {
233                                 int ii;
234
235                                 opp=op;
236                                 ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
237                                 if (ii < 0)
238                                         {
239                                         if (BIO_write(bp,"Bad boolean\n",12) <= 0)
240                                                 goto end;
241                                         }
242                                 BIO_printf(bp,":%d",ii);
243                                 }
244                         else if (tag == V_ASN1_BMPSTRING)
245                                 {
246                                 /* do the BMP thang */
247                                 }
248                         else if (tag == V_ASN1_OCTET_STRING)
249                                 {
250                                 int i,printable=1;
251
252                                 opp=op;
253                                 os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
254                                 if (os != NULL && os->length > 0)
255                                         {
256                                         opp = os->data;
257                                         /* testing whether the octet string is
258                                          * printable */
259                                         for (i=0; i<os->length; i++)
260                                                 {
261                                                 if ((   (opp[i] < ' ') &&
262                                                         (opp[i] != '\n') &&
263                                                         (opp[i] != '\r') &&
264                                                         (opp[i] != '\t')) ||
265                                                         (opp[i] > '~'))
266                                                         {
267                                                         printable=0;
268                                                         break;
269                                                         }
270                                                 }
271                                         if (printable)
272                                         /* printable string */
273                                                 {
274                                                 if (BIO_write(bp,":",1) <= 0)
275                                                         goto end;
276                                                 if (BIO_write(bp,(const char *)opp,
277                                                         os->length) <= 0)
278                                                         goto end;
279                                                 }
280                                         else if (!dump)
281                                         /* not printable => print octet string
282                                          * as hex dump */
283                                                 {
284                                                 if (BIO_write(bp,"[HEX DUMP]:",11) <= 0)
285                                                         goto end;
286                                                 for (i=0; i<os->length; i++)
287                                                         {
288                                                         if (BIO_printf(bp,"%02X"
289                                                                 , opp[i]) <= 0)
290                                                                 goto end;
291                                                         }
292                                                 }
293                                         else
294                                         /* print the normal dump */
295                                                 {
296                                                 if (!nl) 
297                                                         {
298                                                         if (BIO_write(bp,"\n",1) <= 0)
299                                                                 goto end;
300                                                         }
301                                                 if (BIO_dump_indent(bp,
302                                                         (const char *)opp,
303                                                         ((dump == -1 || dump > 
304                                                         os->length)?os->length:dump),
305                                                         dump_indent) <= 0)
306                                                         goto end;
307                                                 nl=1;
308                                                 }
309                                         }
310                                 if (os != NULL)
311                                         {
312                                         M_ASN1_OCTET_STRING_free(os);
313                                         os=NULL;
314                                         }
315                                 }
316                         else if (tag == V_ASN1_INTEGER)
317                                 {
318                                 ASN1_INTEGER *bs;
319                                 int i;
320
321                                 opp=op;
322                                 bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
323                                 if (bs != NULL)
324                                         {
325                                         if (BIO_write(bp,":",1) <= 0) goto end;
326                                         if (bs->type == V_ASN1_NEG_INTEGER)
327                                                 if (BIO_write(bp,"-",1) <= 0)
328                                                         goto end;
329                                         for (i=0; i<bs->length; i++)
330                                                 {
331                                                 if (BIO_printf(bp,"%02X",
332                                                         bs->data[i]) <= 0)
333                                                         goto end;
334                                                 }
335                                         if (bs->length == 0)
336                                                 {
337                                                 if (BIO_write(bp,"00",2) <= 0)
338                                                         goto end;
339                                                 }
340                                         }
341                                 else
342                                         {
343                                         if (BIO_write(bp,"BAD INTEGER",11) <= 0)
344                                                 goto end;
345                                         }
346                                 M_ASN1_INTEGER_free(bs);
347                                 }
348                         else if (tag == V_ASN1_ENUMERATED)
349                                 {
350                                 ASN1_ENUMERATED *bs;
351                                 int i;
352
353                                 opp=op;
354                                 bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
355                                 if (bs != NULL)
356                                         {
357                                         if (BIO_write(bp,":",1) <= 0) goto end;
358                                         if (bs->type == V_ASN1_NEG_ENUMERATED)
359                                                 if (BIO_write(bp,"-",1) <= 0)
360                                                         goto end;
361                                         for (i=0; i<bs->length; i++)
362                                                 {
363                                                 if (BIO_printf(bp,"%02X",
364                                                         bs->data[i]) <= 0)
365                                                         goto end;
366                                                 }
367                                         if (bs->length == 0)
368                                                 {
369                                                 if (BIO_write(bp,"00",2) <= 0)
370                                                         goto end;
371                                                 }
372                                         }
373                                 else
374                                         {
375                                         if (BIO_write(bp,"BAD ENUMERATED",11) <= 0)
376                                                 goto end;
377                                         }
378                                 M_ASN1_ENUMERATED_free(bs);
379                                 }
380                         else if (len > 0 && dump)
381                                 {
382                                 if (!nl) 
383                                         {
384                                         if (BIO_write(bp,"\n",1) <= 0)
385                                                 goto end;
386                                         }
387                                 if (BIO_dump_indent(bp,(const char *)p,
388                                         ((dump == -1 || dump > len)?len:dump),
389                                         dump_indent) <= 0)
390                                         goto end;
391                                 nl=1;
392                                 }
393
394                         if (!nl) 
395                                 {
396                                 if (BIO_write(bp,"\n",1) <= 0) goto end;
397                                 }
398                         p+=len;
399                         if ((tag == V_ASN1_EOC) && (xclass == 0))
400                                 {
401                                 ret=2; /* End of sequence */
402                                 goto end;
403                                 }
404                         }
405                 length-=len;
406                 }
407         ret=1;
408 end:
409         if (o != NULL) ASN1_OBJECT_free(o);
410         if (os != NULL) M_ASN1_OCTET_STRING_free(os);
411         *pp=p;
412         return(ret);
413         }
414
415 const char *ASN1_tag2str(int tag)
416 {
417         static const char * const tag2str[] = {
418         /* 0-4 */
419          "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
420         /* 5-9 */ 
421          "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
422         /* 10-13 */
423          "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
424         /* 15-17 */ 
425         "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
426         /* 18-20 */  
427         "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
428         /* 21-24 */
429         "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME",
430         /* 25-27 */
431         "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
432         /* 28-30 */
433         "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
434         };
435
436         if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
437                                                         tag &= ~0x100;
438
439         if(tag < 0 || tag > 30) return "(unknown)";
440         return tag2str[tag];
441 }
442