Home | History | Annotate | Download | only in evp
      1 /* crypto/evp/bio_ok.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 /*
     60 	From: Arne Ansper <arne (at) cyber.ee>
     61 
     62 	Why BIO_f_reliable?
     63 
     64 	I wrote function which took BIO* as argument, read data from it
     65 	and processed it. Then I wanted to store the input file in
     66 	encrypted form. OK I pushed BIO_f_cipher to the BIO stack
     67 	and everything was OK. BUT if user types wrong password
     68 	BIO_f_cipher outputs only garbage and my function crashes. Yes
     69 	I can and I should fix my function, but BIO_f_cipher is
     70 	easy way to add encryption support to many existing applications
     71 	and it's hard to debug and fix them all.
     72 
     73 	So I wanted another BIO which would catch the incorrect passwords and
     74 	file damages which cause garbage on BIO_f_cipher's output.
     75 
     76 	The easy way is to push the BIO_f_md and save the checksum at
     77 	the end of the file. However there are several problems with this
     78 	approach:
     79 
     80 	1) you must somehow separate checksum from actual data.
     81 	2) you need lot's of memory when reading the file, because you
     82 	must read to the end of the file and verify the checksum before
     83 	letting the application to read the data.
     84 
     85 	BIO_f_reliable tries to solve both problems, so that you can
     86 	read and write arbitrary long streams using only fixed amount
     87 	of memory.
     88 
     89 	BIO_f_reliable splits data stream into blocks. Each block is prefixed
     90 	with it's length and suffixed with it's digest. So you need only
     91 	several Kbytes of memory to buffer single block before verifying
     92 	it's digest.
     93 
     94 	BIO_f_reliable goes further and adds several important capabilities:
     95 
     96 	1) the digest of the block is computed over the whole stream
     97 	-- so nobody can rearrange the blocks or remove or replace them.
     98 
     99 	2) to detect invalid passwords right at the start BIO_f_reliable
    100 	adds special prefix to the stream. In order to avoid known plain-text
    101 	attacks this prefix is generated as follows:
    102 
    103 		*) digest is initialized with random seed instead of
    104 		standardized one.
    105 		*) same seed is written to output
    106 		*) well-known text is then hashed and the output
    107 		of the digest is also written to output.
    108 
    109 	reader can now read the seed from stream, hash the same string
    110 	and then compare the digest output.
    111 
    112 	Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I
    113 	initially wrote and tested this code on x86 machine and wrote the
    114 	digests out in machine-dependent order :( There are people using
    115 	this code and I cannot change this easily without making existing
    116 	data files unreadable.
    117 
    118 */
    119 
    120 #include <stdio.h>
    121 #include <errno.h>
    122 #include <assert.h>
    123 #include "cryptlib.h"
    124 #include <openssl/buffer.h>
    125 #include <openssl/bio.h>
    126 #include <openssl/evp.h>
    127 #include <openssl/rand.h>
    128 
    129 static int ok_write(BIO *h, const char *buf, int num);
    130 static int ok_read(BIO *h, char *buf, int size);
    131 static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
    132 static int ok_new(BIO *h);
    133 static int ok_free(BIO *data);
    134 static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
    135 
    136 static void sig_out(BIO* b);
    137 static void sig_in(BIO* b);
    138 static void block_out(BIO* b);
    139 static void block_in(BIO* b);
    140 #define OK_BLOCK_SIZE	(1024*4)
    141 #define OK_BLOCK_BLOCK	4
    142 #define IOBS		(OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
    143 #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
    144 
    145 typedef struct ok_struct
    146 	{
    147 	size_t buf_len;
    148 	size_t buf_off;
    149 	size_t buf_len_save;
    150 	size_t buf_off_save;
    151 	int cont;		/* <= 0 when finished */
    152 	int finished;
    153 	EVP_MD_CTX md;
    154 	int blockout;		/* output block is ready */
    155 	int sigio;		/* must process signature */
    156 	unsigned char buf[IOBS];
    157 	} BIO_OK_CTX;
    158 
    159 static BIO_METHOD methods_ok=
    160 	{
    161 	BIO_TYPE_CIPHER,"reliable",
    162 	ok_write,
    163 	ok_read,
    164 	NULL, /* ok_puts, */
    165 	NULL, /* ok_gets, */
    166 	ok_ctrl,
    167 	ok_new,
    168 	ok_free,
    169 	ok_callback_ctrl,
    170 	};
    171 
    172 BIO_METHOD *BIO_f_reliable(void)
    173 	{
    174 	return(&methods_ok);
    175 	}
    176 
    177 static int ok_new(BIO *bi)
    178 	{
    179 	BIO_OK_CTX *ctx;
    180 
    181 	ctx=(BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_CTX));
    182 	if (ctx == NULL) return(0);
    183 
    184 	ctx->buf_len=0;
    185 	ctx->buf_off=0;
    186 	ctx->buf_len_save=0;
    187 	ctx->buf_off_save=0;
    188 	ctx->cont=1;
    189 	ctx->finished=0;
    190 	ctx->blockout= 0;
    191 	ctx->sigio=1;
    192 
    193 	EVP_MD_CTX_init(&ctx->md);
    194 
    195 	bi->init=0;
    196 	bi->ptr=(char *)ctx;
    197 	bi->flags=0;
    198 	return(1);
    199 	}
    200 
    201 static int ok_free(BIO *a)
    202 	{
    203 	if (a == NULL) return(0);
    204 	EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md);
    205 	OPENSSL_cleanse(a->ptr,sizeof(BIO_OK_CTX));
    206 	OPENSSL_free(a->ptr);
    207 	a->ptr=NULL;
    208 	a->init=0;
    209 	a->flags=0;
    210 	return(1);
    211 	}
    212 
    213 static int ok_read(BIO *b, char *out, int outl)
    214 	{
    215 	int ret=0,i,n;
    216 	BIO_OK_CTX *ctx;
    217 
    218 	if (out == NULL) return(0);
    219 	ctx=(BIO_OK_CTX *)b->ptr;
    220 
    221 	if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
    222 
    223 	while(outl > 0)
    224 		{
    225 
    226 		/* copy clean bytes to output buffer */
    227 		if (ctx->blockout)
    228 			{
    229 			i=ctx->buf_len-ctx->buf_off;
    230 			if (i > outl) i=outl;
    231 			memcpy(out,&(ctx->buf[ctx->buf_off]),i);
    232 			ret+=i;
    233 			out+=i;
    234 			outl-=i;
    235 			ctx->buf_off+=i;
    236 
    237 			/* all clean bytes are out */
    238 			if (ctx->buf_len == ctx->buf_off)
    239 				{
    240 				ctx->buf_off=0;
    241 
    242 				/* copy start of the next block into proper place */
    243 				if(ctx->buf_len_save- ctx->buf_off_save > 0)
    244 					{
    245 					ctx->buf_len= ctx->buf_len_save- ctx->buf_off_save;
    246 					memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
    247 							ctx->buf_len);
    248 					}
    249 				else
    250 					{
    251 					ctx->buf_len=0;
    252 					}
    253 				ctx->blockout= 0;
    254 				}
    255 			}
    256 
    257 		/* output buffer full -- cancel */
    258 		if (outl == 0) break;
    259 
    260 		/* no clean bytes in buffer -- fill it */
    261 		n=IOBS- ctx->buf_len;
    262 		i=BIO_read(b->next_bio,&(ctx->buf[ctx->buf_len]),n);
    263 
    264 		if (i <= 0) break;	/* nothing new */
    265 
    266 		ctx->buf_len+= i;
    267 
    268 		/* no signature yet -- check if we got one */
    269 		if (ctx->sigio == 1) sig_in(b);
    270 
    271 		/* signature ok -- check if we got block */
    272 		if (ctx->sigio == 0) block_in(b);
    273 
    274 		/* invalid block -- cancel */
    275 		if (ctx->cont <= 0) break;
    276 
    277 		}
    278 
    279 	BIO_clear_retry_flags(b);
    280 	BIO_copy_next_retry(b);
    281 	return(ret);
    282 	}
    283 
    284 static int ok_write(BIO *b, const char *in, int inl)
    285 	{
    286 	int ret=0,n,i;
    287 	BIO_OK_CTX *ctx;
    288 
    289 	if (inl <= 0) return inl;
    290 
    291 	ctx=(BIO_OK_CTX *)b->ptr;
    292 	ret=inl;
    293 
    294 	if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
    295 
    296 	if(ctx->sigio) sig_out(b);
    297 
    298 	do{
    299 		BIO_clear_retry_flags(b);
    300 		n=ctx->buf_len-ctx->buf_off;
    301 		while (ctx->blockout && n > 0)
    302 			{
    303 			i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
    304 			if (i <= 0)
    305 				{
    306 				BIO_copy_next_retry(b);
    307 				if(!BIO_should_retry(b))
    308 					ctx->cont= 0;
    309 				return(i);
    310 				}
    311 			ctx->buf_off+=i;
    312 			n-=i;
    313 			}
    314 
    315 		/* at this point all pending data has been written */
    316 		ctx->blockout= 0;
    317 		if (ctx->buf_len == ctx->buf_off)
    318 			{
    319 			ctx->buf_len=OK_BLOCK_BLOCK;
    320 			ctx->buf_off=0;
    321 			}
    322 
    323 		if ((in == NULL) || (inl <= 0)) return(0);
    324 
    325 		n= (inl+ ctx->buf_len > OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) ?
    326 			(int)(OK_BLOCK_SIZE+OK_BLOCK_BLOCK-ctx->buf_len) : inl;
    327 
    328 		memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),(unsigned char *)in,n);
    329 		ctx->buf_len+= n;
    330 		inl-=n;
    331 		in+=n;
    332 
    333 		if(ctx->buf_len >= OK_BLOCK_SIZE+ OK_BLOCK_BLOCK)
    334 			{
    335 			block_out(b);
    336 			}
    337 	}while(inl > 0);
    338 
    339 	BIO_clear_retry_flags(b);
    340 	BIO_copy_next_retry(b);
    341 	return(ret);
    342 	}
    343 
    344 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
    345 	{
    346 	BIO_OK_CTX *ctx;
    347 	EVP_MD *md;
    348 	const EVP_MD **ppmd;
    349 	long ret=1;
    350 	int i;
    351 
    352 	ctx=b->ptr;
    353 
    354 	switch (cmd)
    355 		{
    356 	case BIO_CTRL_RESET:
    357 		ctx->buf_len=0;
    358 		ctx->buf_off=0;
    359 		ctx->buf_len_save=0;
    360 		ctx->buf_off_save=0;
    361 		ctx->cont=1;
    362 		ctx->finished=0;
    363 		ctx->blockout= 0;
    364 		ctx->sigio=1;
    365 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    366 		break;
    367 	case BIO_CTRL_EOF:	/* More to read */
    368 		if (ctx->cont <= 0)
    369 			ret=1;
    370 		else
    371 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    372 		break;
    373 	case BIO_CTRL_PENDING: /* More to read in buffer */
    374 	case BIO_CTRL_WPENDING: /* More to read in buffer */
    375 		ret=ctx->blockout ? ctx->buf_len-ctx->buf_off : 0;
    376 		if (ret <= 0)
    377 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    378 		break;
    379 	case BIO_CTRL_FLUSH:
    380 		/* do a final write */
    381 		if(ctx->blockout == 0)
    382 			block_out(b);
    383 
    384 		while (ctx->blockout)
    385 			{
    386 			i=ok_write(b,NULL,0);
    387 			if (i < 0)
    388 				{
    389 				ret=i;
    390 				break;
    391 				}
    392 			}
    393 
    394 		ctx->finished=1;
    395 		ctx->buf_off=ctx->buf_len=0;
    396 		ctx->cont=(int)ret;
    397 
    398 		/* Finally flush the underlying BIO */
    399 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    400 		break;
    401 	case BIO_C_DO_STATE_MACHINE:
    402 		BIO_clear_retry_flags(b);
    403 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    404 		BIO_copy_next_retry(b);
    405 		break;
    406 	case BIO_CTRL_INFO:
    407 		ret=(long)ctx->cont;
    408 		break;
    409 	case BIO_C_SET_MD:
    410 		md=ptr;
    411 		EVP_DigestInit_ex(&ctx->md, md, NULL);
    412 		b->init=1;
    413 		break;
    414 	case BIO_C_GET_MD:
    415 		if (b->init)
    416 			{
    417 			ppmd=ptr;
    418 			*ppmd=ctx->md.digest;
    419 			}
    420 		else
    421 			ret=0;
    422 		break;
    423 	default:
    424 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    425 		break;
    426 		}
    427 	return(ret);
    428 	}
    429 
    430 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
    431 	{
    432 	long ret=1;
    433 
    434 	if (b->next_bio == NULL) return(0);
    435 	switch (cmd)
    436 		{
    437 	default:
    438 		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
    439 		break;
    440 		}
    441 	return(ret);
    442 	}
    443 
    444 static void longswap(void *_ptr, size_t len)
    445 {	const union { long one; char little; } is_endian = {1};
    446 
    447 	if (is_endian.little) {
    448 		size_t i;
    449 		unsigned char *p=_ptr,c;
    450 
    451 		for(i= 0;i < len;i+= 4) {
    452 			c=p[0],p[0]=p[3],p[3]=c;
    453 			c=p[1],p[1]=p[2],p[2]=c;
    454 		}
    455 	}
    456 }
    457 
    458 static void sig_out(BIO* b)
    459 	{
    460 	BIO_OK_CTX *ctx;
    461 	EVP_MD_CTX *md;
    462 
    463 	ctx=b->ptr;
    464 	md=&ctx->md;
    465 
    466 	if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return;
    467 
    468 	EVP_DigestInit_ex(md, md->digest, NULL);
    469 	/* FIXME: there's absolutely no guarantee this makes any sense at all,
    470 	 * particularly now EVP_MD_CTX has been restructured.
    471 	 */
    472 	RAND_pseudo_bytes(md->md_data, md->digest->md_size);
    473 	memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
    474 	longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
    475 	ctx->buf_len+= md->digest->md_size;
    476 
    477 	EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
    478 	EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
    479 	ctx->buf_len+= md->digest->md_size;
    480 	ctx->blockout= 1;
    481 	ctx->sigio= 0;
    482 	}
    483 
    484 static void sig_in(BIO* b)
    485 	{
    486 	BIO_OK_CTX *ctx;
    487 	EVP_MD_CTX *md;
    488 	unsigned char tmp[EVP_MAX_MD_SIZE];
    489 	int ret= 0;
    490 
    491 	ctx=b->ptr;
    492 	md=&ctx->md;
    493 
    494 	if((int)(ctx->buf_len-ctx->buf_off) < 2*md->digest->md_size) return;
    495 
    496 	EVP_DigestInit_ex(md, md->digest, NULL);
    497 	memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size);
    498 	longswap(md->md_data, md->digest->md_size);
    499 	ctx->buf_off+= md->digest->md_size;
    500 
    501 	EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
    502 	EVP_DigestFinal_ex(md, tmp, NULL);
    503 	ret= memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0;
    504 	ctx->buf_off+= md->digest->md_size;
    505 	if(ret == 1)
    506 		{
    507 		ctx->sigio= 0;
    508 		if(ctx->buf_len != ctx->buf_off)
    509 			{
    510 			memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), ctx->buf_len- ctx->buf_off);
    511 			}
    512 		ctx->buf_len-= ctx->buf_off;
    513 		ctx->buf_off= 0;
    514 		}
    515 	else
    516 		{
    517 		ctx->cont= 0;
    518 		}
    519 	}
    520 
    521 static void block_out(BIO* b)
    522 	{
    523 	BIO_OK_CTX *ctx;
    524 	EVP_MD_CTX *md;
    525 	unsigned long tl;
    526 
    527 	ctx=b->ptr;
    528 	md=&ctx->md;
    529 
    530 	tl= ctx->buf_len- OK_BLOCK_BLOCK;
    531 	ctx->buf[0]=(unsigned char)(tl>>24);
    532 	ctx->buf[1]=(unsigned char)(tl>>16);
    533 	ctx->buf[2]=(unsigned char)(tl>>8);
    534 	ctx->buf[3]=(unsigned char)(tl);
    535 	EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
    536 	EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
    537 	ctx->buf_len+= md->digest->md_size;
    538 	ctx->blockout= 1;
    539 	}
    540 
    541 static void block_in(BIO* b)
    542 	{
    543 	BIO_OK_CTX *ctx;
    544 	EVP_MD_CTX *md;
    545 	unsigned long tl= 0;
    546 	unsigned char tmp[EVP_MAX_MD_SIZE];
    547 
    548 	ctx=b->ptr;
    549 	md=&ctx->md;
    550 
    551 	assert(sizeof(tl)>=OK_BLOCK_BLOCK);	/* always true */
    552 	tl =ctx->buf[0]; tl<<=8;
    553 	tl|=ctx->buf[1]; tl<<=8;
    554 	tl|=ctx->buf[2]; tl<<=8;
    555 	tl|=ctx->buf[3];
    556 
    557 	if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return;
    558 
    559 	EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
    560 	EVP_DigestFinal_ex(md, tmp, NULL);
    561 	if(memcmp(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 0)
    562 		{
    563 		/* there might be parts from next block lurking around ! */
    564 		ctx->buf_off_save= tl+ OK_BLOCK_BLOCK+ md->digest->md_size;
    565 		ctx->buf_len_save= ctx->buf_len;
    566 		ctx->buf_off= OK_BLOCK_BLOCK;
    567 		ctx->buf_len= tl+ OK_BLOCK_BLOCK;
    568 		ctx->blockout= 1;
    569 		}
    570 	else
    571 		{
    572 		ctx->cont= 0;
    573 		}
    574 	}
    575 
    576