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. 8280297Sjkim * 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). 15280297Sjkim * 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. 22280297Sjkim * 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 :-). 37280297Sjkim * 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)" 40280297Sjkim * 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. 52280297Sjkim * 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 68280297Sjkim# ifndef OPENSSL_NO_FP_API 69109998Smarkm 70280297Sjkimvoid *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) 71280297Sjkim{ 72280297Sjkim BIO *b; 73280297Sjkim void *ret; 7455714Skris 75280297Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 76280297Sjkim ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB); 77280297Sjkim return (NULL); 78280297Sjkim } 79280297Sjkim BIO_set_fp(b, in, BIO_NOCLOSE); 80280297Sjkim ret = ASN1_d2i_bio(xnew, d2i, b, x); 81280297Sjkim BIO_free(b); 82280297Sjkim return (ret); 83280297Sjkim} 84280297Sjkim# endif 8555714Skris 86280297Sjkimvoid *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) 87280297Sjkim{ 88280297Sjkim BUF_MEM *b = NULL; 89280297Sjkim const unsigned char *p; 90280297Sjkim void *ret = NULL; 91280297Sjkim int len; 92109998Smarkm 93280297Sjkim len = asn1_d2i_read_bio(in, &b); 94280297Sjkim if (len < 0) 95280297Sjkim goto err; 96109998Smarkm 97280297Sjkim p = (unsigned char *)b->data; 98280297Sjkim ret = d2i(x, &p, len); 99280297Sjkim err: 100280297Sjkim if (b != NULL) 101280297Sjkim BUF_MEM_free(b); 102280297Sjkim return (ret); 103280297Sjkim} 104109998Smarkm 105109998Smarkm#endif 106109998Smarkm 107109998Smarkmvoid *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) 108280297Sjkim{ 109280297Sjkim BUF_MEM *b = NULL; 110280297Sjkim const unsigned char *p; 111280297Sjkim void *ret = NULL; 112280297Sjkim int len; 113109998Smarkm 114280297Sjkim len = asn1_d2i_read_bio(in, &b); 115280297Sjkim if (len < 0) 116280297Sjkim goto err; 117109998Smarkm 118280297Sjkim p = (const unsigned char *)b->data; 119280297Sjkim ret = ASN1_item_d2i(x, &p, len, it); 120280297Sjkim err: 121280297Sjkim if (b != NULL) 122280297Sjkim BUF_MEM_free(b); 123280297Sjkim return (ret); 124280297Sjkim} 125109998Smarkm 126109998Smarkm#ifndef OPENSSL_NO_FP_API 127109998Smarkmvoid *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) 128280297Sjkim{ 129280297Sjkim BIO *b; 130280297Sjkim char *ret; 131109998Smarkm 132280297Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 133280297Sjkim ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB); 134280297Sjkim return (NULL); 135280297Sjkim } 136280297Sjkim BIO_set_fp(b, in, BIO_NOCLOSE); 137280297Sjkim ret = ASN1_item_d2i_bio(it, b, x); 138280297Sjkim BIO_free(b); 139280297Sjkim return (ret); 140280297Sjkim} 141109998Smarkm#endif 142109998Smarkm 143109998Smarkm#define HEADER_SIZE 8 144298998Sjkim#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) 145109998Smarkmstatic int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) 146280297Sjkim{ 147280297Sjkim BUF_MEM *b; 148280297Sjkim unsigned char *p; 149280297Sjkim int i; 150280297Sjkim ASN1_const_CTX c; 151280297Sjkim size_t want = HEADER_SIZE; 152280297Sjkim int eos = 0; 153280297Sjkim size_t off = 0; 154280297Sjkim size_t len = 0; 15555714Skris 156280297Sjkim b = BUF_MEM_new(); 157280297Sjkim if (b == NULL) { 158280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 159280297Sjkim return -1; 160280297Sjkim } 16155714Skris 162280297Sjkim ERR_clear_error(); 163280297Sjkim for (;;) { 164280297Sjkim if (want >= (len - off)) { 165280297Sjkim want -= (len - off); 16655714Skris 167280297Sjkim if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { 168280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 169280297Sjkim goto err; 170280297Sjkim } 171280297Sjkim i = BIO_read(in, &(b->data[len]), want); 172280297Sjkim if ((i < 0) && ((len - off) == 0)) { 173280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); 174280297Sjkim goto err; 175280297Sjkim } 176280297Sjkim if (i > 0) { 177280297Sjkim if (len + i < len) { 178280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 179280297Sjkim goto err; 180280297Sjkim } 181280297Sjkim len += i; 182280297Sjkim } 183280297Sjkim } 184280297Sjkim /* else data already loaded */ 18555714Skris 186280297Sjkim p = (unsigned char *)&(b->data[off]); 187280297Sjkim c.p = p; 188280297Sjkim c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass), 189280297Sjkim len - off); 190280297Sjkim if (c.inf & 0x80) { 191280297Sjkim unsigned long e; 19255714Skris 193280297Sjkim e = ERR_GET_REASON(ERR_peek_error()); 194280297Sjkim if (e != ASN1_R_TOO_LONG) 195280297Sjkim goto err; 196280297Sjkim else 197280297Sjkim ERR_clear_error(); /* clear error */ 198280297Sjkim } 199280297Sjkim i = c.p - p; /* header length */ 200280297Sjkim off += i; /* end of data */ 20155714Skris 202280297Sjkim if (c.inf & 1) { 203280297Sjkim /* no data body so go round again */ 204280297Sjkim eos++; 205280297Sjkim if (eos < 0) { 206280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); 207280297Sjkim goto err; 208280297Sjkim } 209280297Sjkim want = HEADER_SIZE; 210280297Sjkim } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { 211280297Sjkim /* eos value, so go back and read another header */ 212280297Sjkim eos--; 213280297Sjkim if (eos <= 0) 214280297Sjkim break; 215280297Sjkim else 216280297Sjkim want = HEADER_SIZE; 217280297Sjkim } else { 218280297Sjkim /* suck in c.slen bytes of data */ 219280297Sjkim want = c.slen; 220280297Sjkim if (want > (len - off)) { 221298998Sjkim size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; 222298998Sjkim 223280297Sjkim want -= (len - off); 224280297Sjkim if (want > INT_MAX /* BIO_read takes an int length */ || 225280297Sjkim len + want < len) { 226280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 227280297Sjkim goto err; 228280297Sjkim } 229280297Sjkim while (want > 0) { 230298998Sjkim /* 231298998Sjkim * Read content in chunks of increasing size 232298998Sjkim * so we can return an error for EOF without 233298998Sjkim * having to allocate the entire content length 234298998Sjkim * in one go. 235298998Sjkim */ 236298998Sjkim size_t chunk = want > chunk_max ? chunk_max : want; 237298998Sjkim 238298998Sjkim if (!BUF_MEM_grow_clean(b, len + chunk)) { 239298998Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 240280297Sjkim goto err; 241280297Sjkim } 242298998Sjkim want -= chunk; 243298998Sjkim while (chunk > 0) { 244298998Sjkim i = BIO_read(in, &(b->data[len]), chunk); 245298998Sjkim if (i <= 0) { 246298998Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, 247298998Sjkim ASN1_R_NOT_ENOUGH_DATA); 248298998Sjkim goto err; 249298998Sjkim } 250280297Sjkim /* 251280297Sjkim * This can't overflow because |len+want| didn't 252280297Sjkim * overflow. 253280297Sjkim */ 254298998Sjkim len += i; 255298998Sjkim chunk -= i; 256298998Sjkim } 257298998Sjkim if (chunk_max < INT_MAX/2) 258298998Sjkim chunk_max *= 2; 259280297Sjkim } 260280297Sjkim } 261280297Sjkim if (off + c.slen < off) { 262280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 263280297Sjkim goto err; 264280297Sjkim } 265280297Sjkim off += c.slen; 266280297Sjkim if (eos <= 0) { 267280297Sjkim break; 268280297Sjkim } else 269280297Sjkim want = HEADER_SIZE; 270280297Sjkim } 271280297Sjkim } 27255714Skris 273280297Sjkim if (off > INT_MAX) { 274280297Sjkim ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 275280297Sjkim goto err; 276280297Sjkim } 277234954Sbz 278280297Sjkim *pb = b; 279280297Sjkim return off; 280280297Sjkim err: 281280297Sjkim if (b != NULL) 282280297Sjkim BUF_MEM_free(b); 283280297Sjkim return -1; 284280297Sjkim} 285