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