1 /* crypto/asn1/a_d2i_fp.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/buffer.h>
  63 #include <openssl/asn1_mac.h>
  64 
  65 static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
  66 
  67 #ifndef NO_OLD_ASN1
  68 #ifndef OPENSSL_NO_FP_API
  69 
  70 void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
  71         {
  72         BIO *b;
  73         void *ret;
  74 
  75         if ((b=BIO_new(BIO_s_file())) == NULL)
  76                 {
  77                 ASN1err(ASN1_F_ASN1_D2I_FP,ERR_R_BUF_LIB);
  78                 return(NULL);
  79                 }
  80         BIO_set_fp(b,in,BIO_NOCLOSE);
  81         ret=ASN1_d2i_bio(xnew,d2i,b,x);
  82         BIO_free(b);
  83         return(ret);
  84         }
  85 #endif
  86 
  87 void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
  88         {
  89         BUF_MEM *b = NULL;
  90         const unsigned char *p;
  91         void *ret=NULL;
  92         int len;
  93 
  94         len = asn1_d2i_read_bio(in, &b);
  95         if(len < 0) goto err;
  96 
  97         p=(unsigned char *)b->data;
  98         ret=d2i(x,&p,len);
  99 err:
 100         if (b != NULL) BUF_MEM_free(b);
 101         return(ret);
 102         }
 103 
 104 #endif
 105 
 106 void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
 107         {
 108         BUF_MEM *b = NULL;
 109         const unsigned char *p;
 110         void *ret=NULL;
 111         int len;
 112 
 113         len = asn1_d2i_read_bio(in, &b);
 114         if(len < 0) goto err;
 115 
 116         p=(const unsigned char *)b->data;
 117         ret=ASN1_item_d2i(x,&p,len, it);
 118 err:
 119         if (b != NULL) BUF_MEM_free(b);
 120         return(ret);
 121         }
 122 
 123 #ifndef OPENSSL_NO_FP_API
 124 void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
 125         {
 126         BIO *b;
 127         char *ret;
 128 
 129         if ((b=BIO_new(BIO_s_file())) == NULL)
 130                 {
 131                 ASN1err(ASN1_F_ASN1_ITEM_D2I_FP,ERR_R_BUF_LIB);
 132                 return(NULL);
 133                 }
 134         BIO_set_fp(b,in,BIO_NOCLOSE);
 135         ret=ASN1_item_d2i_bio(it,b,x);
 136         BIO_free(b);
 137         return(ret);
 138         }
 139 #endif
 140 
 141 #define HEADER_SIZE   8
 142 static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
 143         {
 144         BUF_MEM *b;
 145         unsigned char *p;
 146         int i;
 147         ASN1_const_CTX c;
 148         size_t want=HEADER_SIZE;
 149         int eos=0;
 150         size_t off=0;
 151         size_t len=0;
 152 
 153         b=BUF_MEM_new();
 154         if (b == NULL)
 155                 {
 156                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
 157                 return -1;
 158                 }
 159 
 160         ERR_clear_error();
 161         for (;;)
 162                 {
 163                 if (want >= (len-off))
 164                         {
 165                         want-=(len-off);
 166 
 167                         if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
 168                                 {
 169                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
 170                                 goto err;
 171                                 }
 172                         i=BIO_read(in,&(b->data[len]),want);
 173                         if ((i < 0) && ((len-off) == 0))
 174                                 {
 175                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_NOT_ENOUGH_DATA);
 176                                 goto err;
 177                                 }
 178                         if (i > 0)
 179                                 {
 180                                 if (len+i < len)
 181                                         {
 182                                         ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
 183                                         goto err;
 184                                         }
 185                                 len+=i;
 186                                 }
 187                         }
 188                 /* else data already loaded */
 189 
 190                 p=(unsigned char *)&(b->data[off]);
 191                 c.p=p;
 192                 c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
 193                         len-off);
 194                 if (c.inf & 0x80)
 195                         {
 196                         unsigned long e;
 197 
 198                         e=ERR_GET_REASON(ERR_peek_error());
 199                         if (e != ASN1_R_TOO_LONG)
 200                                 goto err;
 201                         else
 202                                 ERR_clear_error(); /* clear error */
 203                         }
 204                 i=c.p-p;/* header length */
 205                 off+=i; /* end of data */
 206 
 207                 if (c.inf & 1)
 208                         {
 209                         /* no data body so go round again */
 210                         eos++;
 211                         if (eos < 0)
 212                                 {
 213                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_HEADER_TOO_LONG);
 214                                 goto err;
 215                                 }
 216                         want=HEADER_SIZE;
 217                         }
 218                 else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
 219                         {
 220                         /* eos value, so go back and read another header */
 221                         eos--;
 222                         if (eos <= 0)
 223                                 break;
 224                         else
 225                                 want=HEADER_SIZE;
 226                         }
 227                 else
 228                         {
 229                         /* suck in c.slen bytes of data */
 230                         want=c.slen;
 231                         if (want > (len-off))
 232                                 {
 233                                 want-=(len-off);
 234                                 if (want > INT_MAX /* BIO_read takes an int length */ ||
 235                                         len+want < len)
 236                                                 {
 237                                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
 238                                                 goto err;
 239                                                 }
 240                                 if (!BUF_MEM_grow_clean(b,len+want))
 241                                         {
 242                                         ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
 243                                         goto err;
 244                                         }
 245                                 while (want > 0)
 246                                         {
 247                                         i=BIO_read(in,&(b->data[len]),want);
 248                                         if (i <= 0)
 249                                                 {
 250                                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
 251                                                     ASN1_R_NOT_ENOUGH_DATA);
 252                                                 goto err;
 253                                                 }
 254                                         /* This can't overflow because
 255                                          * |len+want| didn't overflow. */
 256                                         len+=i;
 257                                         want-=i;
 258                                         }
 259                                 }
 260                         if (off + c.slen < off)
 261                                 {
 262                                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
 263                                 goto err;
 264                                 }
 265                         off+=c.slen;
 266                         if (eos <= 0)
 267                                 {
 268                                 break;
 269                                 }
 270                         else
 271                                 want=HEADER_SIZE;
 272                         }
 273                 }
 274 
 275         if (off > INT_MAX)
 276                 {
 277                 ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
 278                 goto err;
 279                 }
 280 
 281         *pb = b;
 282         return off;
 283 err:
 284         if (b != NULL) BUF_MEM_free(b);
 285         return -1;
 286         }