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. 8296465Sdelphij * 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). 15296465Sdelphij * 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. 22296465Sdelphij * 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 :-). 37296465Sdelphij * 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)" 40296465Sdelphij * 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. 52296465Sdelphij * 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 68296465Sdelphij# ifndef OPENSSL_NO_FP_API 69109998Smarkm 70296465Sdelphijvoid *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) 71296465Sdelphij{ 72296465Sdelphij BIO *b; 73296465Sdelphij void *ret; 7455714Skris 75296465Sdelphij if ((b = BIO_new(BIO_s_file())) == NULL) { 76296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB); 77296465Sdelphij return (NULL); 78296465Sdelphij } 79296465Sdelphij BIO_set_fp(b, in, BIO_NOCLOSE); 80296465Sdelphij ret = ASN1_d2i_bio(xnew, d2i, b, x); 81296465Sdelphij BIO_free(b); 82296465Sdelphij return (ret); 83296465Sdelphij} 84296465Sdelphij# endif 8555714Skris 86296465Sdelphijvoid *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) 87296465Sdelphij{ 88296465Sdelphij BUF_MEM *b = NULL; 89296465Sdelphij const unsigned char *p; 90296465Sdelphij void *ret = NULL; 91296465Sdelphij int len; 92109998Smarkm 93296465Sdelphij len = asn1_d2i_read_bio(in, &b); 94296465Sdelphij if (len < 0) 95296465Sdelphij goto err; 96109998Smarkm 97296465Sdelphij p = (unsigned char *)b->data; 98296465Sdelphij ret = d2i(x, &p, len); 99296465Sdelphij err: 100296465Sdelphij if (b != NULL) 101296465Sdelphij BUF_MEM_free(b); 102296465Sdelphij return (ret); 103296465Sdelphij} 104109998Smarkm 105109998Smarkm#endif 106109998Smarkm 107109998Smarkmvoid *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) 108296465Sdelphij{ 109296465Sdelphij BUF_MEM *b = NULL; 110296465Sdelphij const unsigned char *p; 111296465Sdelphij void *ret = NULL; 112296465Sdelphij int len; 113109998Smarkm 114296465Sdelphij len = asn1_d2i_read_bio(in, &b); 115296465Sdelphij if (len < 0) 116296465Sdelphij goto err; 117109998Smarkm 118296465Sdelphij p = (const unsigned char *)b->data; 119296465Sdelphij ret = ASN1_item_d2i(x, &p, len, it); 120296465Sdelphij err: 121296465Sdelphij if (b != NULL) 122296465Sdelphij BUF_MEM_free(b); 123296465Sdelphij return (ret); 124296465Sdelphij} 125109998Smarkm 126109998Smarkm#ifndef OPENSSL_NO_FP_API 127109998Smarkmvoid *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) 128296465Sdelphij{ 129296465Sdelphij BIO *b; 130296465Sdelphij char *ret; 131109998Smarkm 132296465Sdelphij if ((b = BIO_new(BIO_s_file())) == NULL) { 133296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB); 134296465Sdelphij return (NULL); 135296465Sdelphij } 136296465Sdelphij BIO_set_fp(b, in, BIO_NOCLOSE); 137296465Sdelphij ret = ASN1_item_d2i_bio(it, b, x); 138296465Sdelphij BIO_free(b); 139296465Sdelphij return (ret); 140296465Sdelphij} 141109998Smarkm#endif 142109998Smarkm 143109998Smarkm#define HEADER_SIZE 8 144109998Smarkmstatic int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) 145296465Sdelphij{ 146296465Sdelphij BUF_MEM *b; 147296465Sdelphij unsigned char *p; 148296465Sdelphij int i; 149296465Sdelphij ASN1_const_CTX c; 150296465Sdelphij size_t want = HEADER_SIZE; 151296465Sdelphij int eos = 0; 152296465Sdelphij size_t off = 0; 153296465Sdelphij size_t len = 0; 15455714Skris 155296465Sdelphij b = BUF_MEM_new(); 156296465Sdelphij if (b == NULL) { 157296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 158296465Sdelphij return -1; 159296465Sdelphij } 16055714Skris 161296465Sdelphij ERR_clear_error(); 162296465Sdelphij for (;;) { 163296465Sdelphij if (want >= (len - off)) { 164296465Sdelphij want -= (len - off); 16555714Skris 166296465Sdelphij if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { 167296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 168296465Sdelphij goto err; 169296465Sdelphij } 170296465Sdelphij i = BIO_read(in, &(b->data[len]), want); 171296465Sdelphij if ((i < 0) && ((len - off) == 0)) { 172296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); 173296465Sdelphij goto err; 174296465Sdelphij } 175296465Sdelphij if (i > 0) { 176296465Sdelphij if (len + i < len) { 177296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 178296465Sdelphij goto err; 179296465Sdelphij } 180296465Sdelphij len += i; 181296465Sdelphij } 182296465Sdelphij } 183296465Sdelphij /* else data already loaded */ 18455714Skris 185296465Sdelphij p = (unsigned char *)&(b->data[off]); 186296465Sdelphij c.p = p; 187296465Sdelphij c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass), 188296465Sdelphij len - off); 189296465Sdelphij if (c.inf & 0x80) { 190296465Sdelphij unsigned long e; 19155714Skris 192296465Sdelphij e = ERR_GET_REASON(ERR_peek_error()); 193296465Sdelphij if (e != ASN1_R_TOO_LONG) 194296465Sdelphij goto err; 195296465Sdelphij else 196296465Sdelphij ERR_clear_error(); /* clear error */ 197296465Sdelphij } 198296465Sdelphij i = c.p - p; /* header length */ 199296465Sdelphij off += i; /* end of data */ 20055714Skris 201296465Sdelphij if (c.inf & 1) { 202296465Sdelphij /* no data body so go round again */ 203296465Sdelphij eos++; 204296465Sdelphij if (eos < 0) { 205296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); 206296465Sdelphij goto err; 207296465Sdelphij } 208296465Sdelphij want = HEADER_SIZE; 209296465Sdelphij } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { 210296465Sdelphij /* eos value, so go back and read another header */ 211296465Sdelphij eos--; 212296465Sdelphij if (eos <= 0) 213296465Sdelphij break; 214296465Sdelphij else 215296465Sdelphij want = HEADER_SIZE; 216296465Sdelphij } else { 217296465Sdelphij /* suck in c.slen bytes of data */ 218296465Sdelphij want = c.slen; 219296465Sdelphij if (want > (len - off)) { 220296465Sdelphij want -= (len - off); 221296465Sdelphij if (want > INT_MAX /* BIO_read takes an int length */ || 222296465Sdelphij len + want < len) { 223296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 224296465Sdelphij goto err; 225296465Sdelphij } 226296465Sdelphij if (!BUF_MEM_grow_clean(b, len + want)) { 227296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); 228296465Sdelphij goto err; 229296465Sdelphij } 230296465Sdelphij while (want > 0) { 231296465Sdelphij i = BIO_read(in, &(b->data[len]), want); 232296465Sdelphij if (i <= 0) { 233296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, 234296465Sdelphij ASN1_R_NOT_ENOUGH_DATA); 235296465Sdelphij goto err; 236296465Sdelphij } 237296465Sdelphij /* 238296465Sdelphij * This can't overflow because |len+want| didn't 239296465Sdelphij * overflow. 240296465Sdelphij */ 241296465Sdelphij len += i; 242296465Sdelphij want -= i; 243296465Sdelphij } 244296465Sdelphij } 245296465Sdelphij if (off + c.slen < off) { 246296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 247296465Sdelphij goto err; 248296465Sdelphij } 249296465Sdelphij off += c.slen; 250296465Sdelphij if (eos <= 0) { 251296465Sdelphij break; 252296465Sdelphij } else 253296465Sdelphij want = HEADER_SIZE; 254296465Sdelphij } 255296465Sdelphij } 25655714Skris 257296465Sdelphij if (off > INT_MAX) { 258296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); 259296465Sdelphij goto err; 260296465Sdelphij } 261234954Sbz 262296465Sdelphij *pb = b; 263296465Sdelphij return off; 264296465Sdelphij err: 265296465Sdelphij if (b != NULL) 266296465Sdelphij BUF_MEM_free(b); 267296465Sdelphij return -1; 268296465Sdelphij} 269