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