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