asn1_par.c revision 68651
155714Skris/* crypto/asn1/asn1_par.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/buffer.h> 6255714Skris#include <openssl/objects.h> 6355714Skris#include <openssl/asn1.h> 6455714Skris 6555714Skrisstatic int asn1_print_info(BIO *bp, int tag, int xclass,int constructed, 6655714Skris int indent); 6755714Skrisstatic int asn1_parse2(BIO *bp, unsigned char **pp, long length, 6868651Skris int offset, int depth, int indent, int dump); 6955714Skrisstatic int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, 7055714Skris int indent) 7155714Skris { 7255714Skris static const char fmt[]="%-18s"; 7355714Skris static const char fmt2[]="%2d %-15s"; 7455714Skris char str[128]; 7555714Skris const char *p,*p2=NULL; 7655714Skris 7755714Skris if (constructed & V_ASN1_CONSTRUCTED) 7855714Skris p="cons: "; 7955714Skris else 8055714Skris p="prim: "; 8155714Skris if (BIO_write(bp,p,6) < 6) goto err; 8255714Skris if (indent) 8355714Skris { 8455714Skris if (indent > 128) indent=128; 8555714Skris memset(str,' ',indent); 8655714Skris if (BIO_write(bp,str,indent) < indent) goto err; 8755714Skris } 8855714Skris 8955714Skris p=str; 9055714Skris if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) 9155714Skris sprintf(str,"priv [ %d ] ",tag); 9255714Skris else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) 9355714Skris sprintf(str,"cont [ %d ]",tag); 9455714Skris else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) 9555714Skris sprintf(str,"appl [ %d ]",tag); 9659191Skris else p = ASN1_tag2str(tag); 9755714Skris 9855714Skris if (p2 != NULL) 9955714Skris { 10055714Skris if (BIO_printf(bp,fmt2,tag,p2) <= 0) goto err; 10155714Skris } 10255714Skris else 10355714Skris { 10455714Skris if (BIO_printf(bp,fmt,p) <= 0) goto err; 10555714Skris } 10655714Skris return(1); 10755714Skriserr: 10855714Skris return(0); 10955714Skris } 11055714Skris 11155714Skrisint ASN1_parse(BIO *bp, unsigned char *pp, long len, int indent) 11255714Skris { 11368651Skris return(asn1_parse2(bp,&pp,len,0,0,indent,0)); 11455714Skris } 11555714Skris 11668651Skrisint ASN1_parse_dump(BIO *bp, unsigned char *pp, long len, int indent, int dump) 11768651Skris { 11868651Skris return(asn1_parse2(bp,&pp,len,0,0,indent,dump)); 11968651Skris } 12068651Skris 12155714Skrisstatic int asn1_parse2(BIO *bp, unsigned char **pp, long length, int offset, 12268651Skris int depth, int indent, int dump) 12355714Skris { 12455714Skris unsigned char *p,*ep,*tot,*op,*opp; 12555714Skris long len; 12655714Skris int tag,xclass,ret=0; 12755714Skris int nl,hl,j,r; 12855714Skris ASN1_OBJECT *o=NULL; 12955714Skris ASN1_OCTET_STRING *os=NULL; 13055714Skris /* ASN1_BMPSTRING *bmp=NULL;*/ 13168651Skris int dump_indent; 13255714Skris 13368651Skris#if 0 13468651Skris dump_indent = indent; 13568651Skris#else 13668651Skris dump_indent = 6; /* Because we know BIO_dump_indent() */ 13768651Skris#endif 13855714Skris p= *pp; 13955714Skris tot=p+length; 14055714Skris op=p-1; 14155714Skris while ((p < tot) && (op < p)) 14255714Skris { 14355714Skris op=p; 14455714Skris j=ASN1_get_object(&p,&len,&tag,&xclass,length); 14555714Skris#ifdef LINT 14655714Skris j=j; 14755714Skris#endif 14855714Skris if (j & 0x80) 14955714Skris { 15055714Skris if (BIO_write(bp,"Error in encoding\n",18) <= 0) 15155714Skris goto end; 15255714Skris ret=0; 15355714Skris goto end; 15455714Skris } 15555714Skris hl=(p-op); 15655714Skris length-=hl; 15755714Skris /* if j == 0x21 it is a constructed indefinite length object */ 15855714Skris if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp)) 15955714Skris <= 0) goto end; 16055714Skris 16155714Skris if (j != (V_ASN1_CONSTRUCTED | 1)) 16255714Skris { 16355714Skris if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ", 16455714Skris depth,(long)hl,len) <= 0) 16555714Skris goto end; 16655714Skris } 16755714Skris else 16855714Skris { 16955714Skris if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ", 17055714Skris depth,(long)hl) <= 0) 17155714Skris goto end; 17255714Skris } 17355714Skris if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0)) 17455714Skris goto end; 17555714Skris if (j & V_ASN1_CONSTRUCTED) 17655714Skris { 17755714Skris ep=p+len; 17855714Skris if (BIO_write(bp,"\n",1) <= 0) goto end; 17955714Skris if (len > length) 18055714Skris { 18155714Skris BIO_printf(bp, 18255714Skris "length is greater than %ld\n",length); 18355714Skris ret=0; 18455714Skris goto end; 18555714Skris } 18655714Skris if ((j == 0x21) && (len == 0)) 18755714Skris { 18855714Skris for (;;) 18955714Skris { 19055714Skris r=asn1_parse2(bp,&p,(long)(tot-p), 19155714Skris offset+(p - *pp),depth+1, 19268651Skris indent,dump); 19355714Skris if (r == 0) { ret=0; goto end; } 19455714Skris if ((r == 2) || (p >= tot)) break; 19555714Skris } 19655714Skris } 19755714Skris else 19855714Skris while (p < ep) 19955714Skris { 20055714Skris r=asn1_parse2(bp,&p,(long)len, 20155714Skris offset+(p - *pp),depth+1, 20268651Skris indent,dump); 20355714Skris if (r == 0) { ret=0; goto end; } 20455714Skris } 20555714Skris } 20655714Skris else if (xclass != 0) 20755714Skris { 20855714Skris p+=len; 20955714Skris if (BIO_write(bp,"\n",1) <= 0) goto end; 21055714Skris } 21155714Skris else 21255714Skris { 21355714Skris nl=0; 21455714Skris if ( (tag == V_ASN1_PRINTABLESTRING) || 21555714Skris (tag == V_ASN1_T61STRING) || 21655714Skris (tag == V_ASN1_IA5STRING) || 21755714Skris (tag == V_ASN1_VISIBLESTRING) || 21855714Skris (tag == V_ASN1_UTCTIME) || 21955714Skris (tag == V_ASN1_GENERALIZEDTIME)) 22055714Skris { 22155714Skris if (BIO_write(bp,":",1) <= 0) goto end; 22255714Skris if ((len > 0) && 22355714Skris BIO_write(bp,(char *)p,(int)len) 22455714Skris != (int)len) 22555714Skris goto end; 22655714Skris } 22755714Skris else if (tag == V_ASN1_OBJECT) 22855714Skris { 22955714Skris opp=op; 23055714Skris if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL) 23155714Skris { 23255714Skris if (BIO_write(bp,":",1) <= 0) goto end; 23355714Skris i2a_ASN1_OBJECT(bp,o); 23455714Skris } 23555714Skris else 23655714Skris { 23755714Skris if (BIO_write(bp,":BAD OBJECT",11) <= 0) 23855714Skris goto end; 23955714Skris } 24055714Skris } 24155714Skris else if (tag == V_ASN1_BOOLEAN) 24255714Skris { 24355714Skris int ii; 24455714Skris 24555714Skris opp=op; 24655714Skris ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl); 24755714Skris if (ii < 0) 24855714Skris { 24955714Skris if (BIO_write(bp,"Bad boolean\n",12)) 25055714Skris goto end; 25155714Skris } 25255714Skris BIO_printf(bp,":%d",ii); 25355714Skris } 25455714Skris else if (tag == V_ASN1_BMPSTRING) 25555714Skris { 25655714Skris /* do the BMP thang */ 25755714Skris } 25855714Skris else if (tag == V_ASN1_OCTET_STRING) 25955714Skris { 26055714Skris int i,printable=1; 26155714Skris 26255714Skris opp=op; 26355714Skris os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl); 26455714Skris if (os != NULL) 26555714Skris { 26655714Skris opp=os->data; 26755714Skris for (i=0; i<os->length; i++) 26855714Skris { 26955714Skris if (( (opp[i] < ' ') && 27055714Skris (opp[i] != '\n') && 27155714Skris (opp[i] != '\r') && 27255714Skris (opp[i] != '\t')) || 27355714Skris (opp[i] > '~')) 27455714Skris { 27555714Skris printable=0; 27655714Skris break; 27755714Skris } 27855714Skris } 27955714Skris if (printable && (os->length > 0)) 28055714Skris { 28155714Skris if (BIO_write(bp,":",1) <= 0) 28255714Skris goto end; 28355714Skris if (BIO_write(bp,(char *)opp, 28455714Skris os->length) <= 0) 28555714Skris goto end; 28655714Skris } 28768651Skris if (!printable && (os->length > 0) 28868651Skris && dump) 28968651Skris { 29068651Skris if (!nl) 29168651Skris { 29268651Skris if (BIO_write(bp,"\n",1) <= 0) 29368651Skris goto end; 29468651Skris } 29568651Skris if (BIO_dump_indent(bp,(char *)opp, 29668651Skris ((dump == -1 || dump > os->length)?os->length:dump), 29768651Skris dump_indent) <= 0) 29868651Skris goto end; 29968651Skris nl=1; 30068651Skris } 30159191Skris M_ASN1_OCTET_STRING_free(os); 30255714Skris os=NULL; 30355714Skris } 30455714Skris } 30555714Skris else if (tag == V_ASN1_INTEGER) 30655714Skris { 30755714Skris ASN1_INTEGER *bs; 30855714Skris int i; 30955714Skris 31055714Skris opp=op; 31155714Skris bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl); 31255714Skris if (bs != NULL) 31355714Skris { 31455714Skris if (BIO_write(bp,":",1) <= 0) goto end; 31555714Skris if (bs->type == V_ASN1_NEG_INTEGER) 31655714Skris if (BIO_write(bp,"-",1) <= 0) 31755714Skris goto end; 31855714Skris for (i=0; i<bs->length; i++) 31955714Skris { 32055714Skris if (BIO_printf(bp,"%02X", 32155714Skris bs->data[i]) <= 0) 32255714Skris goto end; 32355714Skris } 32455714Skris if (bs->length == 0) 32555714Skris { 32655714Skris if (BIO_write(bp,"00",2) <= 0) 32755714Skris goto end; 32855714Skris } 32955714Skris } 33055714Skris else 33155714Skris { 33255714Skris if (BIO_write(bp,"BAD INTEGER",11) <= 0) 33355714Skris goto end; 33455714Skris } 33559191Skris M_ASN1_INTEGER_free(bs); 33655714Skris } 33755714Skris else if (tag == V_ASN1_ENUMERATED) 33855714Skris { 33955714Skris ASN1_ENUMERATED *bs; 34055714Skris int i; 34155714Skris 34255714Skris opp=op; 34355714Skris bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl); 34455714Skris if (bs != NULL) 34555714Skris { 34655714Skris if (BIO_write(bp,":",1) <= 0) goto end; 34755714Skris if (bs->type == V_ASN1_NEG_ENUMERATED) 34855714Skris if (BIO_write(bp,"-",1) <= 0) 34955714Skris goto end; 35055714Skris for (i=0; i<bs->length; i++) 35155714Skris { 35255714Skris if (BIO_printf(bp,"%02X", 35355714Skris bs->data[i]) <= 0) 35455714Skris goto end; 35555714Skris } 35655714Skris if (bs->length == 0) 35755714Skris { 35855714Skris if (BIO_write(bp,"00",2) <= 0) 35955714Skris goto end; 36055714Skris } 36155714Skris } 36255714Skris else 36355714Skris { 36455714Skris if (BIO_write(bp,"BAD ENUMERATED",11) <= 0) 36555714Skris goto end; 36655714Skris } 36759191Skris M_ASN1_ENUMERATED_free(bs); 36855714Skris } 36968651Skris else if (len > 0 && dump) 37068651Skris { 37168651Skris if (!nl) 37268651Skris { 37368651Skris if (BIO_write(bp,"\n",1) <= 0) 37468651Skris goto end; 37568651Skris } 37668651Skris if (BIO_dump_indent(bp,(char *)p, 37768651Skris ((dump == -1 || dump > len)?len:dump), 37868651Skris dump_indent) <= 0) 37968651Skris goto end; 38068651Skris nl=1; 38168651Skris } 38255714Skris 38355714Skris if (!nl) 38455714Skris { 38555714Skris if (BIO_write(bp,"\n",1) <= 0) goto end; 38655714Skris } 38755714Skris p+=len; 38855714Skris if ((tag == V_ASN1_EOC) && (xclass == 0)) 38955714Skris { 39055714Skris ret=2; /* End of sequence */ 39155714Skris goto end; 39255714Skris } 39355714Skris } 39455714Skris length-=len; 39555714Skris } 39655714Skris ret=1; 39755714Skrisend: 39855714Skris if (o != NULL) ASN1_OBJECT_free(o); 39959191Skris if (os != NULL) M_ASN1_OCTET_STRING_free(os); 40055714Skris *pp=p; 40155714Skris return(ret); 40255714Skris } 40359191Skris 40459191Skrisconst char *ASN1_tag2str(int tag) 40559191Skris{ 40659191Skris const static char *tag2str[] = { 40759191Skris "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ 40859191Skris "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ 40959191Skris "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */ 41059191Skris "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */ 41159191Skris "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ 41259191Skris "VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */ 41359191Skris "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ 41459191Skris "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */ 41559191Skris }; 41659191Skris 41759191Skris if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) 41859191Skris tag &= ~0x100; 41959191Skris 42059191Skris if(tag < 0 || tag > 30) return "(unknown)"; 42159191Skris return tag2str[tag]; 42259191Skris} 42359191Skris 424