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