asn1_lib.c revision 68651
1142215Sglebius/* crypto/asn1/asn1_lib.c */ 2142215Sglebius/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3142215Sglebius * All rights reserved. 4142215Sglebius * 5142215Sglebius * This package is an SSL implementation written 6142215Sglebius * by Eric Young (eay@cryptsoft.com). 7142215Sglebius * The implementation was written so as to conform with Netscapes SSL. 8142215Sglebius * 9142215Sglebius * This library is free for commercial and non-commercial use as long as 10142215Sglebius * the following conditions are aheared to. The following conditions 11142215Sglebius * apply to all code found in this distribution, be it the RC4, RSA, 12142215Sglebius * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13142215Sglebius * included with this distribution is covered by the same copyright terms 14142215Sglebius * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15142215Sglebius * 16142215Sglebius * Copyright remains Eric Young's, and as such any Copyright notices in 17142215Sglebius * the code are not to be removed. 18142215Sglebius * If this package is used in a product, Eric Young should be given attribution 19142215Sglebius * as the author of the parts of the library used. 20142215Sglebius * This can be in the form of a textual message at program startup or 21142215Sglebius * in documentation (online or textual) provided with the package. 22142215Sglebius * 23142215Sglebius * Redistribution and use in source and binary forms, with or without 24142215Sglebius * modification, are permitted provided that the following conditions 25142215Sglebius * are met: 26142215Sglebius * 1. Redistributions of source code must retain the copyright 27172467Ssilby * notice, this list of conditions and the following disclaimer. 28172467Ssilby * 2. Redistributions in binary form must reproduce the above copyright 29172467Ssilby * notice, this list of conditions and the following disclaimer in the 30142215Sglebius * documentation and/or other materials provided with the distribution. 31142215Sglebius * 3. All advertising materials mentioning features or use of this software 32142215Sglebius * must display the following acknowledgement: 33142215Sglebius * "This product includes cryptographic software written by 34142215Sglebius * Eric Young (eay@cryptsoft.com)" 35142215Sglebius * The word 'cryptographic' can be left out if the rouines from the library 36142215Sglebius * being used are not cryptographic related :-). 37142215Sglebius * 4. If you include any Windows specific code (or a derivative thereof) from 38142215Sglebius * the apps directory (application code) you must include an acknowledgement: 39142215Sglebius * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40142215Sglebius * 41142215Sglebius * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42142215Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43142215Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44142215Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45164033Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46142215Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47142215Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48142215Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49142215Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50142215Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51142215Sglebius * SUCH DAMAGE. 52142215Sglebius * 53142215Sglebius * The licence and distribution terms for any publically available version or 54142215Sglebius * derivative of this code cannot be changed. i.e. this code cannot simply be 55181803Sbz * copied and put under another distribution licence 56142215Sglebius * [including the GNU Public Licence.] 57142215Sglebius */ 58142215Sglebius 59142215Sglebius#include <stdio.h> 60142215Sglebius#include "cryptlib.h" 61142215Sglebius#include <openssl/asn1.h> 62142215Sglebius#include <openssl/asn1_mac.h> 63142215Sglebius 64142215Sglebiusstatic int asn1_get_length(unsigned char **pp,int *inf,long *rl,int max); 65152410Srustatic void asn1_put_length(unsigned char **pp, int length); 66142215Sglebiusconst char *ASN1_version="ASN.1" OPENSSL_VERSION_PTEXT; 67142215Sglebius 68142215Sglebiusint ASN1_check_infinite_end(unsigned char **p, long len) 69142215Sglebius { 70142215Sglebius /* If there is 0 or 1 byte left, the length check should pick 71142215Sglebius * things up */ 72142215Sglebius if (len <= 0) 73142215Sglebius return(1); 74142215Sglebius else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) 75142215Sglebius { 76142215Sglebius (*p)+=2; 77142215Sglebius return(1); 78142215Sglebius } 79142215Sglebius return(0); 80142215Sglebius } 81142215Sglebius 82142215Sglebius 83148387Sumeint ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass, 84142215Sglebius long omax) 85142215Sglebius { 86142215Sglebius int i,ret; 87142215Sglebius long l; 88142215Sglebius unsigned char *p= *pp; 89142215Sglebius int tag,xclass,inf; 90142215Sglebius long max=omax; 91142215Sglebius 92142215Sglebius if (!max) goto err; 93142215Sglebius ret=(*p&V_ASN1_CONSTRUCTED); 94142215Sglebius xclass=(*p&V_ASN1_PRIVATE); 95147256Sbrooks i= *p&V_ASN1_PRIMITIVE_TAG; 96142901Sglebius if (i == V_ASN1_PRIMITIVE_TAG) 97142215Sglebius { /* high-tag */ 98142215Sglebius p++; 99142215Sglebius if (--max == 0) goto err; 100142215Sglebius l=0; 101142215Sglebius while (*p&0x80) 102142215Sglebius { 103142215Sglebius l<<=7L; 104142215Sglebius l|= *(p++)&0x7f; 105142215Sglebius if (--max == 0) goto err; 106142215Sglebius } 107142215Sglebius l<<=7L; 108142215Sglebius l|= *(p++)&0x7f; 109142215Sglebius tag=(int)l; 110142215Sglebius } 111142215Sglebius else 112142215Sglebius { 113142215Sglebius tag=i; 114142215Sglebius p++; 115142215Sglebius if (--max == 0) goto err; 116142215Sglebius } 117142215Sglebius *ptag=tag; 118142215Sglebius *pclass=xclass; 119142215Sglebius if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err; 120142215Sglebius 121142215Sglebius#if 0 122142215Sglebius fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", 123142215Sglebius (int)p,*plength,omax,(int)*pp,(int)(p+ *plength), 124142215Sglebius (int)(omax+ *pp)); 125142215Sglebius 126142215Sglebius#endif 127142215Sglebius#if 0 128142215Sglebius if ((p+ *plength) > (omax+ *pp)) 129142215Sglebius { 130142215Sglebius ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); 131142215Sglebius /* Set this so that even if things are not long enough 132142215Sglebius * the values are set correctly */ 133142215Sglebius ret|=0x80; 134142215Sglebius } 135147256Sbrooks#endif 136142215Sglebius *pp=p; 137142215Sglebius return(ret|inf); 138142215Sglebiuserr: 139142215Sglebius ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG); 140142215Sglebius return(0x80); 141142215Sglebius } 142142215Sglebius 143142215Sglebiusstatic int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) 144142215Sglebius { 145142215Sglebius unsigned char *p= *pp; 146142215Sglebius long ret=0; 147146226Sglebius int i; 148146226Sglebius 149142215Sglebius if (max-- < 1) return(0); 150142215Sglebius if (*p == 0x80) 151142215Sglebius { 152142215Sglebius *inf=1; 153142215Sglebius ret=0; 154142215Sglebius p++; 155142215Sglebius } 156142215Sglebius else 157142215Sglebius { 158142215Sglebius *inf=0; 159142215Sglebius i= *p&0x7f; 160142215Sglebius if (*(p++) & 0x80) 161142215Sglebius { 162142914Sglebius if (max-- == 0) return(0); 163142914Sglebius while (i-- > 0) 164142914Sglebius { 165142914Sglebius ret<<=8L; 166142215Sglebius ret|= *(p++); 167142914Sglebius if (max-- == 0) return(0); 168142215Sglebius } 169142914Sglebius } 170142215Sglebius else 171142215Sglebius ret=i; 172142215Sglebius } 173142215Sglebius *pp=p; 174142914Sglebius *rl=ret; 175142914Sglebius return(1); 176142914Sglebius } 177142914Sglebius 178142451Sglebius/* class 0 is constructed 179142446Sglebius * constructed == 2 for indefinite length constructed */ 180142446Sglebiusvoid ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, 181142451Sglebius int xclass) 182142215Sglebius { 183142451Sglebius unsigned char *p= *pp; 184142446Sglebius int i, ttag; 185142446Sglebius 186142451Sglebius i=(constructed)?V_ASN1_CONSTRUCTED:0; 187142446Sglebius i|=(xclass&V_ASN1_PRIVATE); 188142559Sglebius if (tag < 31) 189142559Sglebius *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG); 190142559Sglebius else 191142559Sglebius { 192142559Sglebius *(p++)=i|V_ASN1_PRIMITIVE_TAG; 193142559Sglebius for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7; 194142559Sglebius ttag = i; 195160195Ssam while(i-- > 0) 196142559Sglebius { 197166228Sglebius p[i] = tag & 0x7f; 198142559Sglebius if(i != (ttag - 1)) p[i] |= 0x80; 199142559Sglebius tag >>= 7; 200142559Sglebius } 201142559Sglebius p += ttag; 202142914Sglebius } 203142559Sglebius if ((constructed == 2) && (length == 0)) 204142559Sglebius *(p++)=0x80; /* der_put_length would output 0 instead */ 205142914Sglebius else 206142559Sglebius asn1_put_length(&p,length); 207142559Sglebius *pp=p; 208191148Skmacy } 209142559Sglebius 210142559Sglebiusstatic void asn1_put_length(unsigned char **pp, int length) 211142559Sglebius { 212142559Sglebius unsigned char *p= *pp; 213142215Sglebius int i,l; 214142215Sglebius if (length <= 127) 215156947Sglebius *(p++)=(unsigned char)length; 216142559Sglebius else 217142559Sglebius { 218142914Sglebius l=length; 219144329Sglebius for (i=0; l > 0; i++) 220142215Sglebius l>>=8; 221142559Sglebius *(p++)=i|0x80; 222142559Sglebius l=i; 223142559Sglebius while (i-- > 0) 224166423Sglebius { 225142215Sglebius p[i]=length&0xff; 226142215Sglebius length>>=8; 227142215Sglebius } 228142911Sglebius p+=l; 229142215Sglebius } 230142215Sglebius *pp=p; 231156947Sglebius } 232156947Sglebius 233142215Sglebiusint ASN1_object_size(int constructed, int length, int tag) 234142215Sglebius { 235142215Sglebius int ret; 236142215Sglebius 237142215Sglebius ret=length; 238142215Sglebius ret++; 239142559Sglebius if (tag >= 31) 240142215Sglebius { 241142215Sglebius while (tag > 0) 242142215Sglebius { 243142215Sglebius tag>>=7; 244142215Sglebius ret++; 245179490Smlaier } 246179490Smlaier } 247179490Smlaier if ((length == 0) && (constructed == 2)) 248179490Smlaier ret+=2; 249142215Sglebius ret++; 250179490Smlaier if (length > 127) 251142215Sglebius { 252142215Sglebius while (length > 0) 253142914Sglebius { 254142914Sglebius length>>=8; 255142914Sglebius ret++; 256142914Sglebius } 257142914Sglebius } 258142215Sglebius return(ret); 259142215Sglebius } 260142215Sglebius 261142215Sglebiusint asn1_Finish(ASN1_CTX *c) 262142215Sglebius { 263142215Sglebius if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos)) 264142215Sglebius { 265142215Sglebius if (!ASN1_check_infinite_end(&c->p,c->slen)) 266142215Sglebius { 267142215Sglebius c->error=ERR_R_MISSING_ASN1_EOS; 268142215Sglebius return(0); 269142215Sglebius } 270142215Sglebius } 271179490Smlaier if ( ((c->slen != 0) && !(c->inf & 1)) || 272179490Smlaier ((c->slen < 0) && (c->inf & 1))) 273179490Smlaier { 274179490Smlaier c->error=ERR_R_ASN1_LENGTH_MISMATCH; 275179490Smlaier return(0); 276191528Srwatson } 277179490Smlaier return(1); 278179490Smlaier } 279179490Smlaier 280179490Smlaierint asn1_GetSequence(ASN1_CTX *c, long *length) 281179490Smlaier { 282179490Smlaier unsigned char *q; 283179490Smlaier 284179490Smlaier q=c->p; 285179490Smlaier c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass), 286191528Srwatson *length); 287179490Smlaier if (c->inf & 0x80) 288179490Smlaier { 289179490Smlaier c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL; 290142215Sglebius return(0); 291142215Sglebius } 292179490Smlaier if (c->tag != V_ASN1_SEQUENCE) 293179490Smlaier { 294179490Smlaier c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE; 295179490Smlaier return(0); 296179490Smlaier } 297191528Srwatson (*length)-=(c->p-q); 298179490Smlaier if (c->max && (*length < 0)) 299142215Sglebius { 300179490Smlaier c->error=ERR_R_ASN1_LENGTH_MISMATCH; 301179490Smlaier return(0); 302179490Smlaier } 303179490Smlaier if (c->inf == (1|V_ASN1_CONSTRUCTED)) 304179490Smlaier c->slen= *length+ *(c->pp)-c->p; 305179490Smlaier c->eos=0; 306179490Smlaier return(1); 307179490Smlaier } 308142215Sglebius 309191528SrwatsonASN1_STRING *ASN1_STRING_dup(ASN1_STRING *str) 310179490Smlaier { 311179490Smlaier ASN1_STRING *ret; 312179490Smlaier 313142215Sglebius if (str == NULL) return(NULL); 314142215Sglebius if ((ret=ASN1_STRING_type_new(str->type)) == NULL) 315142215Sglebius return(NULL); 316142215Sglebius if (!ASN1_STRING_set(ret,str->data,str->length)) 317142215Sglebius { 318142914Sglebius ASN1_STRING_free(ret); 319142914Sglebius return(NULL); 320142914Sglebius } 321142215Sglebius ret->flags = str->flags; 322142215Sglebius return(ret); 323142559Sglebius } 324142215Sglebius 325142215Sglebiusint ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) 326142215Sglebius { 327142215Sglebius unsigned char *c; 328142215Sglebius const char *data=_data; 329142215Sglebius 330142215Sglebius if (len < 0) 331142215Sglebius { 332142215Sglebius if (data == NULL) 333142215Sglebius return(0); 334142215Sglebius else 335142215Sglebius len=strlen(data); 336142215Sglebius } 337142215Sglebius if ((str->length < len) || (str->data == NULL)) 338142215Sglebius { 339142215Sglebius c=str->data; 340142215Sglebius if (c == NULL) 341142215Sglebius str->data=OPENSSL_malloc(len+1); 342142559Sglebius else 343142215Sglebius str->data=OPENSSL_realloc(c,len+1); 344142215Sglebius 345142215Sglebius if (str->data == NULL) 346142215Sglebius { 347142215Sglebius str->data=c; 348142914Sglebius return(0); 349142914Sglebius } 350142215Sglebius } 351142215Sglebius str->length=len; 352142215Sglebius if (data != NULL) 353142215Sglebius { 354142215Sglebius memcpy(str->data,data,len); 355142559Sglebius /* an allowance for strings :-) */ 356142215Sglebius str->data[len]='\0'; 357142215Sglebius } 358142215Sglebius return(1); 359142215Sglebius } 360142215Sglebius 361142914SglebiusASN1_STRING *ASN1_STRING_new(void) 362142914Sglebius { 363142914Sglebius return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); 364142215Sglebius } 365147256Sbrooks 366142914Sglebius 367142914SglebiusASN1_STRING *ASN1_STRING_type_new(int type) 368142215Sglebius { 369142564Sglebius ASN1_STRING *ret; 370142215Sglebius 371142215Sglebius ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); 372142215Sglebius if (ret == NULL) 373142215Sglebius { 374142215Sglebius ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE); 375142215Sglebius return(NULL); 376142215Sglebius } 377142215Sglebius ret->length=0; 378142215Sglebius ret->type=type; 379142215Sglebius ret->data=NULL; 380142559Sglebius ret->flags=0; 381160195Ssam return(ret); 382142215Sglebius } 383142215Sglebius 384142215Sglebiusvoid ASN1_STRING_free(ASN1_STRING *a) 385142215Sglebius { 386142215Sglebius if (a == NULL) return; 387184205Sdes if (a->data != NULL) OPENSSL_free(a->data); 388147256Sbrooks OPENSSL_free(a); 389147256Sbrooks } 390184205Sdes 391147256Sbrooksint ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b) 392147256Sbrooks { 393142215Sglebius int i; 394142215Sglebius 395142215Sglebius i=(a->length-b->length); 396142215Sglebius if (i == 0) 397142215Sglebius { 398142215Sglebius i=memcmp(a->data,b->data,a->length); 399142215Sglebius if (i == 0) 400142215Sglebius return(a->type-b->type); 401160164Smlaier else 402160164Smlaier return(i); 403160164Smlaier } 404170613Sbms else 405160164Smlaier return(i); 406162627Sbms } 407191672Sbms 408191672Sbmsvoid asn1_add_error(unsigned char *address, int offset) 409191672Sbms { 410191672Sbms char buf1[16],buf2[16]; 411191672Sbms 412191672Sbms sprintf(buf1,"%lu",(unsigned long)address); 413191672Sbms sprintf(buf2,"%d",offset); 414191672Sbms ERR_add_error_data(4,"address=",buf1," offset=",buf2); 415142215Sglebius } 416171637Srwatson 417171637Srwatsonint ASN1_STRING_length(ASN1_STRING *x) 418171637Srwatson{ return M_ASN1_STRING_length(x); } 419142215Sglebius 420142215Sglebiusvoid ASN1_STRING_length_set(ASN1_STRING *x, int len) 421142215Sglebius{ M_ASN1_STRING_length_set(x, len); return; } 422142215Sglebius 423151688Syarint ASN1_STRING_type(ASN1_STRING *x) 424142215Sglebius{ return M_ASN1_STRING_type(x); } 425142215Sglebius 426142215Sglebiusunsigned char * ASN1_STRING_data(ASN1_STRING *x) 427142215Sglebius{ return M_ASN1_STRING_data(x); } 428142215Sglebius