155714Skris/* crypto/asn1/a_d2i_fp.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> 60234954Sbz#include <limits.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/buffer.h> 6355714Skris#include <openssl/asn1_mac.h> 6455714Skris 65109998Smarkmstatic int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); 6655714Skris 67109998Smarkm#ifndef NO_OLD_ASN1 68109998Smarkm#ifndef OPENSSL_NO_FP_API 69109998Smarkm 70160814Ssimonvoid *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x) 7155714Skris { 7255714Skris BIO *b; 73160814Ssimon void *ret; 7455714Skris 7555714Skris if ((b=BIO_new(BIO_s_file())) == NULL) 7655714Skris { 7755714Skris ASN1err(ASN1_F_ASN1_D2I_FP,ERR_R_BUF_LIB); 7855714Skris return(NULL); 7955714Skris } 8055714Skris BIO_set_fp(b,in,BIO_NOCLOSE); 8155714Skris ret=ASN1_d2i_bio(xnew,d2i,b,x); 8255714Skris BIO_free(b); 8355714Skris return(ret); 8455714Skris } 8555714Skris#endif 8655714Skris 87160814Ssimonvoid *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x) 8855714Skris { 89109998Smarkm BUF_MEM *b = NULL; 90160814Ssimon const unsigned char *p; 91160814Ssimon void *ret=NULL; 92109998Smarkm int len; 93109998Smarkm 94109998Smarkm len = asn1_d2i_read_bio(in, &b); 95109998Smarkm if(len < 0) goto err; 96109998Smarkm 97109998Smarkm p=(unsigned char *)b->data; 98109998Smarkm ret=d2i(x,&p,len); 99109998Smarkmerr: 100109998Smarkm if (b != NULL) BUF_MEM_free(b); 101109998Smarkm return(ret); 102109998Smarkm } 103109998Smarkm 104109998Smarkm#endif 105109998Smarkm 106109998Smarkmvoid *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) 107109998Smarkm { 108109998Smarkm BUF_MEM *b = NULL; 109160814Ssimon const unsigned char *p; 110109998Smarkm void *ret=NULL; 111109998Smarkm int len; 112109998Smarkm 113109998Smarkm len = asn1_d2i_read_bio(in, &b); 114109998Smarkm if(len < 0) goto err; 115109998Smarkm 116160814Ssimon p=(const unsigned char *)b->data; 117109998Smarkm ret=ASN1_item_d2i(x,&p,len, it); 118109998Smarkmerr: 119109998Smarkm if (b != NULL) BUF_MEM_free(b); 120109998Smarkm return(ret); 121109998Smarkm } 122109998Smarkm 123109998Smarkm#ifndef OPENSSL_NO_FP_API 124109998Smarkmvoid *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) 125109998Smarkm { 126109998Smarkm BIO *b; 127109998Smarkm char *ret; 128109998Smarkm 129109998Smarkm if ((b=BIO_new(BIO_s_file())) == NULL) 130109998Smarkm { 131160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_D2I_FP,ERR_R_BUF_LIB); 132109998Smarkm return(NULL); 133109998Smarkm } 134109998Smarkm BIO_set_fp(b,in,BIO_NOCLOSE); 135109998Smarkm ret=ASN1_item_d2i_bio(it,b,x); 136109998Smarkm BIO_free(b); 137109998Smarkm return(ret); 138109998Smarkm } 139109998Smarkm#endif 140109998Smarkm 141109998Smarkm#define HEADER_SIZE 8 142109998Smarkmstatic int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) 143109998Smarkm { 14455714Skris BUF_MEM *b; 14555714Skris unsigned char *p; 14655714Skris int i; 147160814Ssimon ASN1_const_CTX c; 148234954Sbz size_t want=HEADER_SIZE; 14955714Skris int eos=0; 150234954Sbz size_t off=0; 151234954Sbz size_t len=0; 15255714Skris 15355714Skris b=BUF_MEM_new(); 15455714Skris if (b == NULL) 15555714Skris { 156160814Ssimon ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); 157109998Smarkm return -1; 15855714Skris } 15955714Skris 16055714Skris ERR_clear_error(); 16155714Skris for (;;) 16255714Skris { 16355714Skris if (want >= (len-off)) 16455714Skris { 16555714Skris want-=(len-off); 16655714Skris 167234954Sbz if (len + want < len || !BUF_MEM_grow_clean(b,len+want)) 16855714Skris { 169160814Ssimon ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); 17055714Skris goto err; 17155714Skris } 17255714Skris i=BIO_read(in,&(b->data[len]),want); 17355714Skris if ((i < 0) && ((len-off) == 0)) 17455714Skris { 175160814Ssimon ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_NOT_ENOUGH_DATA); 17655714Skris goto err; 17755714Skris } 17855714Skris if (i > 0) 179234954Sbz { 180234954Sbz if (len+i < len) 181234954Sbz { 182234954Sbz ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); 183234954Sbz goto err; 184234954Sbz } 18555714Skris len+=i; 186234954Sbz } 18755714Skris } 18855714Skris /* else data already loaded */ 18955714Skris 19055714Skris p=(unsigned char *)&(b->data[off]); 19155714Skris c.p=p; 19255714Skris c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass), 19355714Skris len-off); 19455714Skris if (c.inf & 0x80) 19555714Skris { 19655714Skris unsigned long e; 19755714Skris 19855714Skris e=ERR_GET_REASON(ERR_peek_error()); 19955714Skris if (e != ASN1_R_TOO_LONG) 20055714Skris goto err; 20155714Skris else 202160814Ssimon ERR_clear_error(); /* clear error */ 20355714Skris } 20455714Skris i=c.p-p;/* header length */ 20555714Skris off+=i; /* end of data */ 20655714Skris 20755714Skris if (c.inf & 1) 20855714Skris { 20955714Skris /* no data body so go round again */ 21055714Skris eos++; 211234954Sbz if (eos < 0) 212234954Sbz { 213234954Sbz ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_HEADER_TOO_LONG); 214234954Sbz goto err; 215234954Sbz } 21655714Skris want=HEADER_SIZE; 21755714Skris } 21855714Skris else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) 21955714Skris { 22055714Skris /* eos value, so go back and read another header */ 22155714Skris eos--; 22255714Skris if (eos <= 0) 22355714Skris break; 22455714Skris else 22555714Skris want=HEADER_SIZE; 22655714Skris } 22755714Skris else 22855714Skris { 22955714Skris /* suck in c.slen bytes of data */ 230234954Sbz want=c.slen; 23155714Skris if (want > (len-off)) 23255714Skris { 23355714Skris want-=(len-off); 234234954Sbz if (want > INT_MAX /* BIO_read takes an int length */ || 235234954Sbz len+want < len) 236234954Sbz { 237234954Sbz ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); 238234954Sbz goto err; 239234954Sbz } 240109998Smarkm if (!BUF_MEM_grow_clean(b,len+want)) 24155714Skris { 242160814Ssimon ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE); 24355714Skris goto err; 24455714Skris } 245109998Smarkm while (want > 0) 24655714Skris { 247109998Smarkm i=BIO_read(in,&(b->data[len]),want); 248109998Smarkm if (i <= 0) 249109998Smarkm { 250160814Ssimon ASN1err(ASN1_F_ASN1_D2I_READ_BIO, 251109998Smarkm ASN1_R_NOT_ENOUGH_DATA); 252109998Smarkm goto err; 253109998Smarkm } 254234954Sbz /* This can't overflow because 255234954Sbz * |len+want| didn't overflow. */ 256109998Smarkm len+=i; 257234954Sbz want-=i; 25855714Skris } 25955714Skris } 260234954Sbz if (off + c.slen < off) 261234954Sbz { 262234954Sbz ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); 263234954Sbz goto err; 264234954Sbz } 265234954Sbz off+=c.slen; 26655714Skris if (eos <= 0) 26755714Skris { 26855714Skris break; 26955714Skris } 27055714Skris else 27155714Skris want=HEADER_SIZE; 27255714Skris } 27355714Skris } 27455714Skris 275234954Sbz if (off > INT_MAX) 276234954Sbz { 277234954Sbz ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG); 278234954Sbz goto err; 279234954Sbz } 280234954Sbz 281109998Smarkm *pb = b; 282109998Smarkm return off; 28355714Skriserr: 28455714Skris if (b != NULL) BUF_MEM_free(b); 285234954Sbz return -1; 28655714Skris } 287