1 /* crypto/asn1/asn1_lib.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 <limits.h>
  61 #include "cryptlib.h"
  62 #include <openssl/asn1.h>
  63 #include <openssl/asn1_mac.h>
  64 
  65 static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
  66 static void asn1_put_length(unsigned char **pp, int length);
  67 const char ASN1_version[]="ASN.1" OPENSSL_VERSION_PTEXT;
  68 
  69 static int _asn1_check_infinite_end(const unsigned char **p, long len)
  70         {
  71         /* If there is 0 or 1 byte left, the length check should pick
  72          * things up */
  73         if (len <= 0)
  74                 return(1);
  75         else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
  76                 {
  77                 (*p)+=2;
  78                 return(1);
  79                 }
  80         return(0);
  81         }
  82 
  83 int ASN1_check_infinite_end(unsigned char **p, long len)
  84         {
  85         return _asn1_check_infinite_end((const unsigned char **)p, len);
  86         }
  87 
  88 int ASN1_const_check_infinite_end(const unsigned char **p, long len)
  89         {
  90         return _asn1_check_infinite_end(p, len);
  91         }
  92 
  93 
  94 int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
  95         int *pclass, long omax)
  96         {
  97         int i,ret;
  98         long l;
  99         const unsigned char *p= *pp;
 100         int tag,xclass,inf;
 101         long max=omax;
 102 
 103         if (!max) goto err;
 104         ret=(*p&V_ASN1_CONSTRUCTED);
 105         xclass=(*p&V_ASN1_PRIVATE);
 106         i= *p&V_ASN1_PRIMITIVE_TAG;
 107         if (i == V_ASN1_PRIMITIVE_TAG)
 108                 {               /* high-tag */
 109                 p++;
 110                 if (--max == 0) goto err;
 111                 l=0;
 112                 while (*p&0x80)
 113                         {
 114                         l<<=7L;
 115                         l|= *(p++)&0x7f;
 116                         if (--max == 0) goto err;
 117                         if (l > (INT_MAX >> 7L)) goto err;
 118                         }
 119                 l<<=7L;
 120                 l|= *(p++)&0x7f;
 121                 tag=(int)l;
 122                 if (--max == 0) goto err;
 123                 }
 124         else
 125                 { 
 126                 tag=i;
 127                 p++;
 128                 if (--max == 0) goto err;
 129                 }
 130         *ptag=tag;
 131         *pclass=xclass;
 132         if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
 133 
 134 #if 0
 135         fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n", 
 136                 (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
 137                 (int)(omax+ *pp));
 138 
 139 #endif
 140         if (*plength > (omax - (p - *pp)))
 141                 {
 142                 ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG);
 143                 /* Set this so that even if things are not long enough
 144                  * the values are set correctly */
 145                 ret|=0x80;
 146                 }
 147         *pp=p;
 148         return(ret|inf);
 149 err:
 150         ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG);
 151         return(0x80);
 152         }
 153 
 154 static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
 155         {
 156         const unsigned char *p= *pp;
 157         unsigned long ret=0;
 158         unsigned int i;
 159 
 160         if (max-- < 1) return(0);
 161         if (*p == 0x80)
 162                 {
 163                 *inf=1;
 164                 ret=0;
 165                 p++;
 166                 }
 167         else
 168                 {
 169                 *inf=0;
 170                 i= *p&0x7f;
 171                 if (*(p++) & 0x80)
 172                         {
 173                         if (i > sizeof(long))
 174                                 return 0;
 175                         if (max-- == 0) return(0);
 176                         while (i-- > 0)
 177                                 {
 178                                 ret<<=8L;
 179                                 ret|= *(p++);
 180                                 if (max-- == 0) return(0);
 181                                 }
 182                         }
 183                 else
 184                         ret=i;
 185                 }
 186         if (ret > LONG_MAX)
 187                 return 0;
 188         *pp=p;
 189         *rl=(long)ret;
 190         return(1);
 191         }
 192 
 193 /* class 0 is constructed
 194  * constructed == 2 for indefinite length constructed */
 195 void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
 196              int xclass)
 197         {
 198         unsigned char *p= *pp;
 199         int i, ttag;
 200 
 201         i=(constructed)?V_ASN1_CONSTRUCTED:0;
 202         i|=(xclass&V_ASN1_PRIVATE);
 203         if (tag < 31)
 204                 *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
 205         else
 206                 {
 207                 *(p++)=i|V_ASN1_PRIMITIVE_TAG;
 208                 for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
 209                 ttag = i;
 210                 while(i-- > 0)
 211                         {
 212                         p[i] = tag & 0x7f;
 213                         if(i != (ttag - 1)) p[i] |= 0x80;
 214                         tag >>= 7;
 215                         }
 216                 p += ttag;
 217                 }
 218         if (constructed == 2)
 219                 *(p++)=0x80;
 220         else
 221                 asn1_put_length(&p,length);
 222         *pp=p;
 223         }
 224 
 225 int ASN1_put_eoc(unsigned char **pp)
 226         {
 227         unsigned char *p = *pp;
 228         *p++ = 0;
 229         *p++ = 0;
 230         *pp = p;
 231         return 2;
 232         }
 233 
 234 static void asn1_put_length(unsigned char **pp, int length)
 235         {
 236         unsigned char *p= *pp;
 237         int i,l;
 238         if (length <= 127)
 239                 *(p++)=(unsigned char)length;
 240         else
 241                 {
 242                 l=length;
 243                 for (i=0; l > 0; i++)
 244                         l>>=8;
 245                 *(p++)=i|0x80;
 246                 l=i;
 247                 while (i-- > 0)
 248                         {
 249                         p[i]=length&0xff;
 250                         length>>=8;
 251                         }
 252                 p+=l;
 253                 }
 254         *pp=p;
 255         }
 256 
 257 int ASN1_object_size(int constructed, int length, int tag)
 258         {
 259         int ret;
 260 
 261         ret=length;
 262         ret++;
 263         if (tag >= 31)
 264                 {
 265                 while (tag > 0)
 266                         {
 267                         tag>>=7;
 268                         ret++;
 269                         }
 270                 }
 271         if (constructed == 2)
 272                 return ret + 3;
 273         ret++;
 274         if (length > 127)
 275                 {
 276                 while (length > 0)
 277                         {
 278                         length>>=8;
 279                         ret++;
 280                         }
 281                 }
 282         return(ret);
 283         }
 284 
 285 static int _asn1_Finish(ASN1_const_CTX *c)
 286         {
 287         if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
 288                 {
 289                 if (!ASN1_const_check_infinite_end(&c->p,c->slen))
 290                         {
 291                         c->error=ERR_R_MISSING_ASN1_EOS;
 292                         return(0);
 293                         }
 294                 }
 295         if (    ((c->slen != 0) && !(c->inf & 1)) ||
 296                 ((c->slen < 0) && (c->inf & 1)))
 297                 {
 298                 c->error=ERR_R_ASN1_LENGTH_MISMATCH;
 299                 return(0);
 300                 }
 301         return(1);
 302         }
 303 
 304 int asn1_Finish(ASN1_CTX *c)
 305         {
 306         return _asn1_Finish((ASN1_const_CTX *)c);
 307         }
 308 
 309 int asn1_const_Finish(ASN1_const_CTX *c)
 310         {
 311         return _asn1_Finish(c);
 312         }
 313 
 314 int asn1_GetSequence(ASN1_const_CTX *c, long *length)
 315         {
 316         const unsigned char *q;
 317 
 318         q=c->p;
 319         c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
 320                 *length);
 321         if (c->inf & 0x80)
 322                 {
 323                 c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL;
 324                 return(0);
 325                 }
 326         if (c->tag != V_ASN1_SEQUENCE)
 327                 {
 328                 c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE;
 329                 return(0);
 330                 }
 331         (*length)-=(c->p-q);
 332         if (c->max && (*length < 0))
 333                 {
 334                 c->error=ERR_R_ASN1_LENGTH_MISMATCH;
 335                 return(0);
 336                 }
 337         if (c->inf == (1|V_ASN1_CONSTRUCTED))
 338                 c->slen= *length+ *(c->pp)-c->p;
 339         c->eos=0;
 340         return(1);
 341         }
 342 
 343 int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
 344         {
 345         if (str == NULL)
 346                 return 0;
 347         dst->type = str->type;
 348         if (!ASN1_STRING_set(dst,str->data,str->length))
 349                 return 0;
 350         dst->flags = str->flags;
 351         return 1;
 352         }
 353 
 354 ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
 355         {
 356         ASN1_STRING *ret;
 357         if (!str)
 358                  return NULL;
 359         ret=ASN1_STRING_new();
 360         if (!ret)
 361                 return NULL;
 362         if (!ASN1_STRING_copy(ret,str))
 363                 {
 364                 ASN1_STRING_free(ret);
 365                 return NULL;
 366                 }
 367         return ret;
 368         }
 369 
 370 int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
 371         {
 372         unsigned char *c;
 373         const char *data=_data;
 374 
 375         if (len < 0)
 376                 {
 377                 if (data == NULL)
 378                         return(0);
 379                 else
 380                         len=strlen(data);
 381                 }
 382         if ((str->length < len) || (str->data == NULL))
 383                 {
 384                 c=str->data;
 385                 if (c == NULL)
 386                         str->data=OPENSSL_malloc(len+1);
 387                 else
 388                         str->data=OPENSSL_realloc(c,len+1);
 389 
 390                 if (str->data == NULL)
 391                         {
 392                         ASN1err(ASN1_F_ASN1_STRING_SET,ERR_R_MALLOC_FAILURE);
 393                         str->data=c;
 394                         return(0);
 395                         }
 396                 }
 397         str->length=len;
 398         if (data != NULL)
 399                 {
 400                 memcpy(str->data,data,len);
 401                 /* an allowance for strings :-) */
 402                 str->data[len]='\0';
 403                 }
 404         return(1);
 405         }
 406 
 407 void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
 408         {
 409         if (str->data)
 410                 OPENSSL_free(str->data);
 411         str->data = data;
 412         str->length = len;
 413         }
 414 
 415 ASN1_STRING *ASN1_STRING_new(void)
 416         {
 417         return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
 418         }
 419 
 420 
 421 ASN1_STRING *ASN1_STRING_type_new(int type)
 422         {
 423         ASN1_STRING *ret;
 424 
 425         ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
 426         if (ret == NULL)
 427                 {
 428                 ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE);
 429                 return(NULL);
 430                 }
 431         ret->length=0;
 432         ret->type=type;
 433         ret->data=NULL;
 434         ret->flags=0;
 435         return(ret);
 436         }
 437 
 438 void ASN1_STRING_free(ASN1_STRING *a)
 439         {
 440         if (a == NULL) return;
 441         if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
 442                 OPENSSL_free(a->data);
 443         OPENSSL_free(a);
 444         }
 445 
 446 int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
 447         {
 448         int i;
 449 
 450         i=(a->length-b->length);
 451         if (i == 0)
 452                 {
 453                 i=memcmp(a->data,b->data,a->length);
 454                 if (i == 0)
 455                         return(a->type-b->type);
 456                 else
 457                         return(i);
 458                 }
 459         else
 460                 return(i);
 461         }
 462 
 463 void asn1_add_error(const unsigned char *address, int offset)
 464         {
 465         char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1];
 466 
 467         BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address);
 468         BIO_snprintf(buf2,sizeof buf2,"%d",offset);
 469         ERR_add_error_data(4,"address=",buf1," offset=",buf2);
 470         }
 471 
 472 int ASN1_STRING_length(const ASN1_STRING *x)
 473 { return M_ASN1_STRING_length(x); }
 474 
 475 void ASN1_STRING_length_set(ASN1_STRING *x, int len)
 476 { M_ASN1_STRING_length_set(x, len); return; }
 477 
 478 int ASN1_STRING_type(ASN1_STRING *x)
 479 { return M_ASN1_STRING_type(x); }
 480 
 481 unsigned char * ASN1_STRING_data(ASN1_STRING *x)
 482 { return M_ASN1_STRING_data(x); }