asn1_par.c revision 160815
1204076Spjd/* crypto/asn1/asn1_par.c */ 2204076Spjd/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3211877Spjd * All rights reserved. 4204076Spjd * 5204076Spjd * This package is an SSL implementation written 6204076Spjd * by Eric Young (eay@cryptsoft.com). 7204076Spjd * The implementation was written so as to conform with Netscapes SSL. 8204076Spjd * 9204076Spjd * This library is free for commercial and non-commercial use as long as 10204076Spjd * the following conditions are aheared to. The following conditions 11204076Spjd * apply to all code found in this distribution, be it the RC4, RSA, 12204076Spjd * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13204076Spjd * included with this distribution is covered by the same copyright terms 14204076Spjd * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15204076Spjd * 16204076Spjd * Copyright remains Eric Young's, and as such any Copyright notices in 17204076Spjd * the code are not to be removed. 18204076Spjd * If this package is used in a product, Eric Young should be given attribution 19204076Spjd * as the author of the parts of the library used. 20204076Spjd * This can be in the form of a textual message at program startup or 21204076Spjd * in documentation (online or textual) provided with the package. 22204076Spjd * 23204076Spjd * Redistribution and use in source and binary forms, with or without 24204076Spjd * modification, are permitted provided that the following conditions 25204076Spjd * are met: 26204076Spjd * 1. Redistributions of source code must retain the copyright 27204076Spjd * notice, this list of conditions and the following disclaimer. 28204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 29204076Spjd * notice, this list of conditions and the following disclaimer in the 30204076Spjd * documentation and/or other materials provided with the distribution. 31204076Spjd * 3. All advertising materials mentioning features or use of this software 32204076Spjd * must display the following acknowledgement: 33204076Spjd * "This product includes cryptographic software written by 34204076Spjd * Eric Young (eay@cryptsoft.com)" 35204076Spjd * The word 'cryptographic' can be left out if the rouines from the library 36204076Spjd * being used are not cryptographic related :-). 37204076Spjd * 4. If you include any Windows specific code (or a derivative thereof) from 38204076Spjd * the apps directory (application code) you must include an acknowledgement: 39204076Spjd * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40204076Spjd * 41204076Spjd * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46213009Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51204076Spjd * SUCH DAMAGE. 52204076Spjd * 53204076Spjd * The licence and distribution terms for any publically available version or 54204076Spjd * derivative of this code cannot be changed. i.e. this code cannot simply be 55204076Spjd * copied and put under another distribution licence 56204076Spjd * [including the GNU Public Licence.] 57204076Spjd */ 58212038Spjd 59204076Spjd#include <stdio.h> 60204076Spjd#include "cryptlib.h" 61204076Spjd#include <openssl/buffer.h> 62211977Spjd#include <openssl/objects.h> 63204076Spjd#include <openssl/asn1.h> 64204076Spjd 65204076Spjdstatic int asn1_print_info(BIO *bp, int tag, int xclass,int constructed, 66204076Spjd int indent); 67204076Spjdstatic int asn1_parse2(BIO *bp, const unsigned char **pp, long length, 68204076Spjd int offset, int depth, int indent, int dump); 69204076Spjdstatic int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, 70204076Spjd int indent) 71204076Spjd { 72204076Spjd static const char fmt[]="%-18s"; 73204076Spjd static const char fmt2[]="%2d %-15s"; 74204076Spjd char str[128]; 75204076Spjd const char *p,*p2=NULL; 76204076Spjd 77204076Spjd if (constructed & V_ASN1_CONSTRUCTED) 78204076Spjd p="cons: "; 79211984Spjd else 80211984Spjd p="prim: "; 81204076Spjd if (BIO_write(bp,p,6) < 6) goto err; 82204076Spjd BIO_indent(bp,indent,128); 83204076Spjd 84204076Spjd p=str; 85204076Spjd if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) 86204076Spjd BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag); 87204076Spjd else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) 88204076Spjd BIO_snprintf(str,sizeof str,"cont [ %d ]",tag); 89204076Spjd else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) 90204076Spjd BIO_snprintf(str,sizeof str,"appl [ %d ]",tag); 91204076Spjd else if (tag > 30) 92204076Spjd BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag); 93204076Spjd else 94204076Spjd p = ASN1_tag2str(tag); 95204076Spjd 96204076Spjd if (p2 != NULL) 97204076Spjd { 98204076Spjd if (BIO_printf(bp,fmt2,tag,p2) <= 0) goto err; 99204076Spjd } 100204076Spjd else 101204076Spjd { 102204076Spjd if (BIO_printf(bp,fmt,p) <= 0) goto err; 103204076Spjd } 104204076Spjd return(1); 105204076Spjderr: 106204076Spjd return(0); 107204076Spjd } 108204076Spjd 109204076Spjdint ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent) 110204076Spjd { 111211877Spjd return(asn1_parse2(bp,&pp,len,0,0,indent,0)); 112211877Spjd } 113211877Spjd 114211877Spjdint ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump) 115211877Spjd { 116211877Spjd return(asn1_parse2(bp,&pp,len,0,0,indent,dump)); 117211877Spjd } 118211877Spjd 119211877Spjdstatic int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset, 120211877Spjd int depth, int indent, int dump) 121211877Spjd { 122211877Spjd const unsigned char *p,*ep,*tot,*op,*opp; 123211877Spjd long len; 124211877Spjd int tag,xclass,ret=0; 125211877Spjd int nl,hl,j,r; 126211877Spjd ASN1_OBJECT *o=NULL; 127211877Spjd ASN1_OCTET_STRING *os=NULL; 128211877Spjd /* ASN1_BMPSTRING *bmp=NULL;*/ 129211877Spjd int dump_indent; 130211877Spjd 131204076Spjd#if 0 132204076Spjd dump_indent = indent; 133204076Spjd#else 134204076Spjd dump_indent = 6; /* Because we know BIO_dump_indent() */ 135204076Spjd#endif 136204076Spjd p= *pp; 137204076Spjd tot=p+length; 138204076Spjd op=p-1; 139204076Spjd while ((p < tot) && (op < p)) 140204076Spjd { 141204076Spjd op=p; 142204076Spjd j=ASN1_get_object(&p,&len,&tag,&xclass,length); 143204076Spjd#ifdef LINT 144204076Spjd j=j; 145204076Spjd#endif 146204076Spjd if (j & 0x80) 147204076Spjd { 148204076Spjd if (BIO_write(bp,"Error in encoding\n",18) <= 0) 149204076Spjd goto end; 150204076Spjd ret=0; 151204076Spjd goto end; 152204076Spjd } 153204076Spjd hl=(p-op); 154204076Spjd length-=hl; 155204076Spjd /* if j == 0x21 it is a constructed indefinite length object */ 156210879Spjd if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp)) 157210879Spjd <= 0) goto end; 158210879Spjd 159204076Spjd if (j != (V_ASN1_CONSTRUCTED | 1)) 160204076Spjd { 161204076Spjd if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ", 162204076Spjd depth,(long)hl,len) <= 0) 163210879Spjd goto end; 164210879Spjd } 165210879Spjd else 166204076Spjd { 167204076Spjd if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ", 168204076Spjd depth,(long)hl) <= 0) 169204076Spjd goto end; 170204076Spjd } 171204076Spjd if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0)) 172204076Spjd goto end; 173204076Spjd if (j & V_ASN1_CONSTRUCTED) 174204076Spjd { 175204076Spjd ep=p+len; 176204076Spjd if (BIO_write(bp,"\n",1) <= 0) goto end; 177204076Spjd if (len > length) 178204076Spjd { 179204076Spjd BIO_printf(bp, 180204076Spjd "length is greater than %ld\n",length); 181204076Spjd ret=0; 182204076Spjd goto end; 183204076Spjd } 184204076Spjd if ((j == 0x21) && (len == 0)) 185204076Spjd { 186204076Spjd for (;;) 187204076Spjd { 188204076Spjd r=asn1_parse2(bp,&p,(long)(tot-p), 189204076Spjd offset+(p - *pp),depth+1, 190204076Spjd indent,dump); 191204076Spjd if (r == 0) { ret=0; goto end; } 192204076Spjd if ((r == 2) || (p >= tot)) break; 193204076Spjd } 194204076Spjd } 195204076Spjd else 196204076Spjd while (p < ep) 197204076Spjd { 198204076Spjd r=asn1_parse2(bp,&p,(long)len, 199204076Spjd offset+(p - *pp),depth+1, 200204076Spjd indent,dump); 201204076Spjd if (r == 0) { ret=0; goto end; } 202204076Spjd } 203204076Spjd } 204204076Spjd else if (xclass != 0) 205204076Spjd { 206204076Spjd p+=len; 207204076Spjd if (BIO_write(bp,"\n",1) <= 0) goto end; 208204076Spjd } 209204076Spjd else 210204076Spjd { 211204076Spjd nl=0; 212204076Spjd if ( (tag == V_ASN1_PRINTABLESTRING) || 213204076Spjd (tag == V_ASN1_T61STRING) || 214204076Spjd (tag == V_ASN1_IA5STRING) || 215204076Spjd (tag == V_ASN1_VISIBLESTRING) || 216204076Spjd (tag == V_ASN1_UTCTIME) || 217204076Spjd (tag == V_ASN1_GENERALIZEDTIME)) 218204076Spjd { 219204076Spjd if (BIO_write(bp,":",1) <= 0) goto end; 220204076Spjd if ((len > 0) && 221204076Spjd BIO_write(bp,(const char *)p,(int)len) 222204076Spjd != (int)len) 223204076Spjd goto end; 224204076Spjd } 225204076Spjd else if (tag == V_ASN1_OBJECT) 226204076Spjd { 227204076Spjd opp=op; 228204076Spjd if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL) 229204076Spjd { 230204076Spjd if (BIO_write(bp,":",1) <= 0) goto end; 231204076Spjd i2a_ASN1_OBJECT(bp,o); 232204076Spjd } 233204076Spjd else 234204076Spjd { 235204076Spjd if (BIO_write(bp,":BAD OBJECT",11) <= 0) 236204076Spjd goto end; 237204076Spjd } 238204076Spjd } 239204076Spjd else if (tag == V_ASN1_BOOLEAN) 240204076Spjd { 241204076Spjd int ii; 242204076Spjd 243204076Spjd opp=op; 244204076Spjd ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl); 245204076Spjd if (ii < 0) 246204076Spjd { 247204076Spjd if (BIO_write(bp,"Bad boolean\n",12)) 248204076Spjd goto end; 249204076Spjd } 250204076Spjd BIO_printf(bp,":%d",ii); 251204076Spjd } 252204076Spjd else if (tag == V_ASN1_BMPSTRING) 253204076Spjd { 254204076Spjd /* do the BMP thang */ 255204076Spjd } 256204076Spjd else if (tag == V_ASN1_OCTET_STRING) 257204076Spjd { 258204076Spjd int i,printable=1; 259204076Spjd 260204076Spjd opp=op; 261204076Spjd os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl); 262204076Spjd if (os != NULL && os->length > 0) 263204076Spjd { 264204076Spjd opp = os->data; 265204076Spjd /* testing whether the octet string is 266204076Spjd * printable */ 267204076Spjd for (i=0; i<os->length; i++) 268204076Spjd { 269204076Spjd if (( (opp[i] < ' ') && 270204076Spjd (opp[i] != '\n') && 271204076Spjd (opp[i] != '\r') && 272204076Spjd (opp[i] != '\t')) || 273204076Spjd (opp[i] > '~')) 274204076Spjd { 275204076Spjd printable=0; 276204076Spjd break; 277204076Spjd } 278204076Spjd } 279204076Spjd if (printable) 280204076Spjd /* printable string */ 281204076Spjd { 282204076Spjd if (BIO_write(bp,":",1) <= 0) 283204076Spjd goto end; 284204076Spjd if (BIO_write(bp,(const char *)opp, 285204076Spjd os->length) <= 0) 286204076Spjd goto end; 287204076Spjd } 288204076Spjd else if (!dump) 289204076Spjd /* not printable => print octet string 290204076Spjd * as hex dump */ 291204076Spjd { 292204076Spjd if (BIO_write(bp,"[HEX DUMP]:",11) <= 0) 293204076Spjd goto end; 294204076Spjd for (i=0; i<os->length; i++) 295204076Spjd { 296204076Spjd if (BIO_printf(bp,"%02X" 297204076Spjd , opp[i]) <= 0) 298204076Spjd goto end; 299204076Spjd } 300204076Spjd } 301204076Spjd else 302204076Spjd /* print the normal dump */ 303204076Spjd { 304204076Spjd if (!nl) 305204076Spjd { 306204076Spjd if (BIO_write(bp,"\n",1) <= 0) 307204076Spjd goto end; 308204076Spjd } 309204076Spjd if (BIO_dump_indent(bp, 310204076Spjd (const char *)opp, 311204076Spjd ((dump == -1 || dump > 312204076Spjd os->length)?os->length:dump), 313204076Spjd dump_indent) <= 0) 314204076Spjd goto end; 315204076Spjd nl=1; 316204076Spjd } 317204076Spjd } 318204076Spjd if (os != NULL) 319204076Spjd { 320204076Spjd M_ASN1_OCTET_STRING_free(os); 321214276Spjd os=NULL; 322204076Spjd } 323204076Spjd } 324214275Spjd else if (tag == V_ASN1_INTEGER) 325214275Spjd { 326209182Spjd ASN1_INTEGER *bs; 327204076Spjd int i; 328204076Spjd 329204076Spjd opp=op; 330212038Spjd bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl); 331204076Spjd if (bs != NULL) 332204076Spjd { 333204076Spjd if (BIO_write(bp,":",1) <= 0) goto end; 334204076Spjd if (bs->type == V_ASN1_NEG_INTEGER) 335204076Spjd if (BIO_write(bp,"-",1) <= 0) 336204076Spjd goto end; 337204076Spjd for (i=0; i<bs->length; i++) 338213009Spjd { 339204076Spjd if (BIO_printf(bp,"%02X", 340204076Spjd bs->data[i]) <= 0) 341204076Spjd goto end; 342204076Spjd } 343204076Spjd if (bs->length == 0) 344204076Spjd { 345204076Spjd if (BIO_write(bp,"00",2) <= 0) 346204076Spjd goto end; 347204076Spjd } 348204076Spjd } 349204076Spjd else 350204076Spjd { 351212038Spjd if (BIO_write(bp,"BAD INTEGER",11) <= 0) 352212038Spjd goto end; 353212038Spjd } 354212038Spjd M_ASN1_INTEGER_free(bs); 355212038Spjd } 356212038Spjd else if (tag == V_ASN1_ENUMERATED) 357212038Spjd { 358212038Spjd ASN1_ENUMERATED *bs; 359204076Spjd int i; 360204076Spjd 361204076Spjd opp=op; 362204076Spjd bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl); 363204076Spjd if (bs != NULL) 364204076Spjd { 365204076Spjd if (BIO_write(bp,":",1) <= 0) goto end; 366204076Spjd if (bs->type == V_ASN1_NEG_ENUMERATED) 367204076Spjd if (BIO_write(bp,"-",1) <= 0) 368204076Spjd goto end; 369204076Spjd for (i=0; i<bs->length; i++) 370204076Spjd { 371204076Spjd if (BIO_printf(bp,"%02X", 372212038Spjd bs->data[i]) <= 0) 373212038Spjd goto end; 374204076Spjd } 375204076Spjd if (bs->length == 0) 376204076Spjd { 377211977Spjd if (BIO_write(bp,"00",2) <= 0) 378211984Spjd goto end; 379211984Spjd } 380204076Spjd } 381211977Spjd else 382204076Spjd { 383204076Spjd if (BIO_write(bp,"BAD ENUMERATED",11) <= 0) 384204076Spjd goto end; 385213009Spjd } 386213009Spjd M_ASN1_ENUMERATED_free(bs); 387210880Spjd } 388212038Spjd else if (len > 0 && dump) 389212038Spjd { 390212038Spjd if (!nl) 391207371Spjd { 392207371Spjd if (BIO_write(bp,"\n",1) <= 0) 393207371Spjd goto end; 394207371Spjd } 395207371Spjd if (BIO_dump_indent(bp,(const char *)p, 396207371Spjd ((dump == -1 || dump > len)?len:dump), 397204076Spjd dump_indent) <= 0) 398213007Spjd goto end; 399213007Spjd nl=1; 400213007Spjd } 401213007Spjd 402213007Spjd if (!nl) 403213007Spjd { 404213007Spjd if (BIO_write(bp,"\n",1) <= 0) goto end; 405213007Spjd } 406213007Spjd p+=len; 407213007Spjd if ((tag == V_ASN1_EOC) && (xclass == 0)) 408213007Spjd { 409213007Spjd ret=2; /* End of sequence */ 410213007Spjd goto end; 411204076Spjd } 412212038Spjd } 413204076Spjd length-=len; 414204076Spjd } 415204076Spjd ret=1; 416204076Spjdend: 417204076Spjd if (o != NULL) ASN1_OBJECT_free(o); 418213007Spjd if (os != NULL) M_ASN1_OCTET_STRING_free(os); 419204076Spjd *pp=p; 420204076Spjd return(ret); 421204076Spjd } 422204076Spjd 423204076Spjdconst char *ASN1_tag2str(int tag) 424204076Spjd{ 425204076Spjd static const char *tag2str[] = { 426204076Spjd "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ 427204076Spjd "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ 428204076Spjd "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */ 429204076Spjd "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */ 430204076Spjd "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ 431204076Spjd "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */ 432204076Spjd "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ 433204076Spjd "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */ 434204076Spjd }; 435204076Spjd 436204076Spjd if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) 437204076Spjd tag &= ~0x100; 438204076Spjd 439204076Spjd if(tag < 0 || tag > 30) return "(unknown)"; 440204076Spjd return tag2str[tag]; 441204076Spjd} 442204076Spjd 443204076Spjd