os/ossrv/ssl/libcrypto/src/crypto/evp/bio_ok.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/evp/bio_ok.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
/*
sl@0
    60
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    61
 */
sl@0
    62
/*
sl@0
    63
	From: Arne Ansper <arne@cyber.ee>
sl@0
    64
sl@0
    65
	Why BIO_f_reliable?
sl@0
    66
sl@0
    67
	I wrote function which took BIO* as argument, read data from it
sl@0
    68
	and processed it. Then I wanted to store the input file in 
sl@0
    69
	encrypted form. OK I pushed BIO_f_cipher to the BIO stack
sl@0
    70
	and everything was OK. BUT if user types wrong password 
sl@0
    71
	BIO_f_cipher outputs only garbage and my function crashes. Yes
sl@0
    72
	I can and I should fix my function, but BIO_f_cipher is 
sl@0
    73
	easy way to add encryption support to many existing applications
sl@0
    74
	and it's hard to debug and fix them all. 
sl@0
    75
sl@0
    76
	So I wanted another BIO which would catch the incorrect passwords and
sl@0
    77
	file damages which cause garbage on BIO_f_cipher's output. 
sl@0
    78
sl@0
    79
	The easy way is to push the BIO_f_md and save the checksum at 
sl@0
    80
	the end of the file. However there are several problems with this
sl@0
    81
	approach:
sl@0
    82
sl@0
    83
	1) you must somehow separate checksum from actual data. 
sl@0
    84
	2) you need lot's of memory when reading the file, because you 
sl@0
    85
	must read to the end of the file and verify the checksum before
sl@0
    86
	letting the application to read the data. 
sl@0
    87
	
sl@0
    88
	BIO_f_reliable tries to solve both problems, so that you can 
sl@0
    89
	read and write arbitrary long streams using only fixed amount
sl@0
    90
	of memory.
sl@0
    91
sl@0
    92
	BIO_f_reliable splits data stream into blocks. Each block is prefixed
sl@0
    93
	with it's length and suffixed with it's digest. So you need only 
sl@0
    94
	several Kbytes of memory to buffer single block before verifying 
sl@0
    95
	it's digest. 
sl@0
    96
sl@0
    97
	BIO_f_reliable goes further and adds several important capabilities:
sl@0
    98
sl@0
    99
	1) the digest of the block is computed over the whole stream 
sl@0
   100
	-- so nobody can rearrange the blocks or remove or replace them.
sl@0
   101
sl@0
   102
	2) to detect invalid passwords right at the start BIO_f_reliable 
sl@0
   103
	adds special prefix to the stream. In order to avoid known plain-text
sl@0
   104
	attacks this prefix is generated as follows:
sl@0
   105
sl@0
   106
		*) digest is initialized with random seed instead of 
sl@0
   107
		standardized one.
sl@0
   108
		*) same seed is written to output
sl@0
   109
		*) well-known text is then hashed and the output 
sl@0
   110
		of the digest is also written to output.
sl@0
   111
sl@0
   112
	reader can now read the seed from stream, hash the same string
sl@0
   113
	and then compare the digest output.
sl@0
   114
sl@0
   115
	Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I 
sl@0
   116
	initially wrote and tested this code on x86 machine and wrote the
sl@0
   117
	digests out in machine-dependent order :( There are people using
sl@0
   118
	this code and I cannot change this easily without making existing
sl@0
   119
	data files unreadable.
sl@0
   120
sl@0
   121
*/
sl@0
   122
sl@0
   123
#include <stdio.h>
sl@0
   124
#include <errno.h>
sl@0
   125
#include <assert.h>
sl@0
   126
#include "cryptlib.h"
sl@0
   127
#include <openssl/buffer.h>
sl@0
   128
#include <openssl/bio.h>
sl@0
   129
#include <openssl/evp.h>
sl@0
   130
#include <openssl/rand.h>
sl@0
   131
#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
   132
#include "libcrypto_wsd_macros.h"
sl@0
   133
#include "libcrypto_wsd.h"
sl@0
   134
#endif
sl@0
   135
sl@0
   136
sl@0
   137
static int ok_write(BIO *h, const char *buf, int num);
sl@0
   138
static int ok_read(BIO *h, char *buf, int size);
sl@0
   139
static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2);
sl@0
   140
static int ok_new(BIO *h);
sl@0
   141
static int ok_free(BIO *data);
sl@0
   142
static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
sl@0
   143
sl@0
   144
static void sig_out(BIO* b);
sl@0
   145
static void sig_in(BIO* b);
sl@0
   146
static void block_out(BIO* b);
sl@0
   147
static void block_in(BIO* b);
sl@0
   148
#define OK_BLOCK_SIZE	(1024*4)
sl@0
   149
#define OK_BLOCK_BLOCK	4
sl@0
   150
#define IOBS		(OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE)
sl@0
   151
#define WELLKNOWN "The quick brown fox jumped over the lazy dog's back."
sl@0
   152
sl@0
   153
typedef struct ok_struct
sl@0
   154
	{
sl@0
   155
	size_t buf_len;
sl@0
   156
	size_t buf_off;
sl@0
   157
	size_t buf_len_save;
sl@0
   158
	size_t buf_off_save;
sl@0
   159
	int cont;		/* <= 0 when finished */
sl@0
   160
	int finished;
sl@0
   161
	EVP_MD_CTX md;
sl@0
   162
	int blockout;		/* output block is ready */ 
sl@0
   163
	int sigio;		/* must process signature */
sl@0
   164
	unsigned char buf[IOBS];
sl@0
   165
	} BIO_OK_CTX;
sl@0
   166
sl@0
   167
#ifndef EMULATOR
sl@0
   168
static BIO_METHOD methods_ok=
sl@0
   169
	{
sl@0
   170
	BIO_TYPE_CIPHER,"reliable",
sl@0
   171
	ok_write,
sl@0
   172
	ok_read,
sl@0
   173
	NULL, /* ok_puts, */
sl@0
   174
	NULL, /* ok_gets, */
sl@0
   175
	ok_ctrl,
sl@0
   176
	ok_new,
sl@0
   177
	ok_free,
sl@0
   178
	ok_callback_ctrl,
sl@0
   179
	};
sl@0
   180
#else
sl@0
   181
GET_STATIC_VAR_FROM_TLS(methods_ok,bio_ok,BIO_METHOD)
sl@0
   182
#define methods_ok (*GET_WSD_VAR_NAME(methods_ok,bio_ok, s)())
sl@0
   183
const BIO_METHOD temp_s_methods_ok=
sl@0
   184
	{
sl@0
   185
	BIO_TYPE_CIPHER,"reliable",
sl@0
   186
	ok_write,
sl@0
   187
	ok_read,
sl@0
   188
	NULL, /* ok_puts, */
sl@0
   189
	NULL, /* ok_gets, */
sl@0
   190
	ok_ctrl,
sl@0
   191
	ok_new,
sl@0
   192
	ok_free,
sl@0
   193
	ok_callback_ctrl,
sl@0
   194
	};
sl@0
   195
sl@0
   196
#endif	
sl@0
   197
sl@0
   198
EXPORT_C BIO_METHOD *BIO_f_reliable(void)
sl@0
   199
	{
sl@0
   200
	return(&methods_ok);
sl@0
   201
	}
sl@0
   202
sl@0
   203
static int ok_new(BIO *bi)
sl@0
   204
	{
sl@0
   205
	BIO_OK_CTX *ctx;
sl@0
   206
sl@0
   207
	ctx=(BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_CTX));
sl@0
   208
	if (ctx == NULL) return(0);
sl@0
   209
sl@0
   210
	ctx->buf_len=0;
sl@0
   211
	ctx->buf_off=0;
sl@0
   212
	ctx->buf_len_save=0;
sl@0
   213
	ctx->buf_off_save=0;
sl@0
   214
	ctx->cont=1;
sl@0
   215
	ctx->finished=0;
sl@0
   216
	ctx->blockout= 0;
sl@0
   217
	ctx->sigio=1;
sl@0
   218
sl@0
   219
	EVP_MD_CTX_init(&ctx->md);
sl@0
   220
sl@0
   221
	bi->init=0;
sl@0
   222
	bi->ptr=(char *)ctx;
sl@0
   223
	bi->flags=0;
sl@0
   224
	return(1);
sl@0
   225
	}
sl@0
   226
sl@0
   227
static int ok_free(BIO *a)
sl@0
   228
	{
sl@0
   229
	if (a == NULL) return(0);
sl@0
   230
	EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md);
sl@0
   231
	OPENSSL_cleanse(a->ptr,sizeof(BIO_OK_CTX));
sl@0
   232
	OPENSSL_free(a->ptr);
sl@0
   233
	a->ptr=NULL;
sl@0
   234
	a->init=0;
sl@0
   235
	a->flags=0;
sl@0
   236
	return(1);
sl@0
   237
	}
sl@0
   238
	
sl@0
   239
static int ok_read(BIO *b, char *out, int outl)
sl@0
   240
	{
sl@0
   241
	int ret=0,i,n;
sl@0
   242
	BIO_OK_CTX *ctx;
sl@0
   243
sl@0
   244
	if (out == NULL) return(0);
sl@0
   245
	ctx=(BIO_OK_CTX *)b->ptr;
sl@0
   246
sl@0
   247
	if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
sl@0
   248
sl@0
   249
	while(outl > 0)
sl@0
   250
		{
sl@0
   251
sl@0
   252
		/* copy clean bytes to output buffer */
sl@0
   253
		if (ctx->blockout)
sl@0
   254
			{
sl@0
   255
			i=ctx->buf_len-ctx->buf_off;
sl@0
   256
			if (i > outl) i=outl;
sl@0
   257
			memcpy(out,&(ctx->buf[ctx->buf_off]),i);
sl@0
   258
			ret+=i;
sl@0
   259
			out+=i;
sl@0
   260
			outl-=i;
sl@0
   261
			ctx->buf_off+=i;
sl@0
   262
sl@0
   263
			/* all clean bytes are out */
sl@0
   264
			if (ctx->buf_len == ctx->buf_off)
sl@0
   265
				{
sl@0
   266
				ctx->buf_off=0;
sl@0
   267
sl@0
   268
				/* copy start of the next block into proper place */
sl@0
   269
				if(ctx->buf_len_save- ctx->buf_off_save > 0)
sl@0
   270
					{
sl@0
   271
					ctx->buf_len= ctx->buf_len_save- ctx->buf_off_save;
sl@0
   272
					memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]),
sl@0
   273
							ctx->buf_len);
sl@0
   274
					}
sl@0
   275
				else
sl@0
   276
					{
sl@0
   277
					ctx->buf_len=0;
sl@0
   278
					}
sl@0
   279
				ctx->blockout= 0;
sl@0
   280
				}
sl@0
   281
			}
sl@0
   282
	
sl@0
   283
		/* output buffer full -- cancel */
sl@0
   284
		if (outl == 0) break;
sl@0
   285
sl@0
   286
		/* no clean bytes in buffer -- fill it */
sl@0
   287
		n=IOBS- ctx->buf_len;
sl@0
   288
		i=BIO_read(b->next_bio,&(ctx->buf[ctx->buf_len]),n);
sl@0
   289
sl@0
   290
		if (i <= 0) break;	/* nothing new */
sl@0
   291
sl@0
   292
		ctx->buf_len+= i;
sl@0
   293
sl@0
   294
		/* no signature yet -- check if we got one */
sl@0
   295
		if (ctx->sigio == 1) sig_in(b);
sl@0
   296
sl@0
   297
		/* signature ok -- check if we got block */
sl@0
   298
		if (ctx->sigio == 0) block_in(b);
sl@0
   299
sl@0
   300
		/* invalid block -- cancel */
sl@0
   301
		if (ctx->cont <= 0) break;
sl@0
   302
sl@0
   303
		}
sl@0
   304
sl@0
   305
	BIO_clear_retry_flags(b);
sl@0
   306
	BIO_copy_next_retry(b);
sl@0
   307
	return(ret);
sl@0
   308
	}
sl@0
   309
sl@0
   310
static int ok_write(BIO *b, const char *in, int inl)
sl@0
   311
	{
sl@0
   312
	int ret=0,n,i;
sl@0
   313
	BIO_OK_CTX *ctx;
sl@0
   314
sl@0
   315
	if (inl <= 0) return inl;
sl@0
   316
sl@0
   317
	ctx=(BIO_OK_CTX *)b->ptr;
sl@0
   318
	ret=inl;
sl@0
   319
sl@0
   320
	if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0);
sl@0
   321
sl@0
   322
	if(ctx->sigio) sig_out(b);
sl@0
   323
sl@0
   324
	do{
sl@0
   325
		BIO_clear_retry_flags(b);
sl@0
   326
		n=ctx->buf_len-ctx->buf_off;
sl@0
   327
		while (ctx->blockout && n > 0)
sl@0
   328
			{
sl@0
   329
			i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
sl@0
   330
			if (i <= 0)
sl@0
   331
				{
sl@0
   332
				BIO_copy_next_retry(b);
sl@0
   333
				if(!BIO_should_retry(b))
sl@0
   334
					ctx->cont= 0;
sl@0
   335
				return(i);
sl@0
   336
				}
sl@0
   337
			ctx->buf_off+=i;
sl@0
   338
			n-=i;
sl@0
   339
			}
sl@0
   340
sl@0
   341
		/* at this point all pending data has been written */
sl@0
   342
		ctx->blockout= 0;
sl@0
   343
		if (ctx->buf_len == ctx->buf_off)
sl@0
   344
			{
sl@0
   345
			ctx->buf_len=OK_BLOCK_BLOCK;
sl@0
   346
			ctx->buf_off=0;
sl@0
   347
			}
sl@0
   348
	
sl@0
   349
		if ((in == NULL) || (inl <= 0)) return(0);
sl@0
   350
sl@0
   351
		n= (inl+ ctx->buf_len > OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) ? 
sl@0
   352
			(int)(OK_BLOCK_SIZE+OK_BLOCK_BLOCK-ctx->buf_len) : inl;
sl@0
   353
sl@0
   354
		memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),(unsigned char *)in,n);
sl@0
   355
		ctx->buf_len+= n;
sl@0
   356
		inl-=n;
sl@0
   357
		in+=n;
sl@0
   358
sl@0
   359
		if(ctx->buf_len >= OK_BLOCK_SIZE+ OK_BLOCK_BLOCK)
sl@0
   360
			{
sl@0
   361
			block_out(b);
sl@0
   362
			}
sl@0
   363
	}while(inl > 0);
sl@0
   364
sl@0
   365
	BIO_clear_retry_flags(b);
sl@0
   366
	BIO_copy_next_retry(b);
sl@0
   367
	return(ret);
sl@0
   368
	}
sl@0
   369
sl@0
   370
static long ok_ctrl(BIO *b, int cmd, long num, void *ptr)
sl@0
   371
	{
sl@0
   372
	BIO_OK_CTX *ctx;
sl@0
   373
	EVP_MD *md;
sl@0
   374
	const EVP_MD **ppmd;
sl@0
   375
	long ret=1;
sl@0
   376
	int i;
sl@0
   377
sl@0
   378
	ctx=b->ptr;
sl@0
   379
sl@0
   380
	switch (cmd)
sl@0
   381
		{
sl@0
   382
	case BIO_CTRL_RESET:
sl@0
   383
		ctx->buf_len=0;
sl@0
   384
		ctx->buf_off=0;
sl@0
   385
		ctx->buf_len_save=0;
sl@0
   386
		ctx->buf_off_save=0;
sl@0
   387
		ctx->cont=1;
sl@0
   388
		ctx->finished=0;
sl@0
   389
		ctx->blockout= 0;
sl@0
   390
		ctx->sigio=1;
sl@0
   391
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   392
		break;
sl@0
   393
	case BIO_CTRL_EOF:	/* More to read */
sl@0
   394
		if (ctx->cont <= 0)
sl@0
   395
			ret=1;
sl@0
   396
		else
sl@0
   397
			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   398
		break;
sl@0
   399
	case BIO_CTRL_PENDING: /* More to read in buffer */
sl@0
   400
	case BIO_CTRL_WPENDING: /* More to read in buffer */
sl@0
   401
		ret=ctx->blockout ? ctx->buf_len-ctx->buf_off : 0;
sl@0
   402
		if (ret <= 0)
sl@0
   403
			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   404
		break;
sl@0
   405
	case BIO_CTRL_FLUSH:
sl@0
   406
		/* do a final write */
sl@0
   407
		if(ctx->blockout == 0)
sl@0
   408
			block_out(b);
sl@0
   409
sl@0
   410
		while (ctx->blockout)
sl@0
   411
			{
sl@0
   412
			i=ok_write(b,NULL,0);
sl@0
   413
			if (i < 0)
sl@0
   414
				{
sl@0
   415
				ret=i;
sl@0
   416
				break;
sl@0
   417
				}
sl@0
   418
			}
sl@0
   419
sl@0
   420
		ctx->finished=1;
sl@0
   421
		ctx->buf_off=ctx->buf_len=0;
sl@0
   422
		ctx->cont=(int)ret;
sl@0
   423
		
sl@0
   424
		/* Finally flush the underlying BIO */
sl@0
   425
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   426
		break;
sl@0
   427
	case BIO_C_DO_STATE_MACHINE:
sl@0
   428
		BIO_clear_retry_flags(b);
sl@0
   429
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   430
		BIO_copy_next_retry(b);
sl@0
   431
		break;
sl@0
   432
	case BIO_CTRL_INFO:
sl@0
   433
		ret=(long)ctx->cont;
sl@0
   434
		break;
sl@0
   435
	case BIO_C_SET_MD:
sl@0
   436
		md=ptr;
sl@0
   437
		EVP_DigestInit_ex(&ctx->md, md, NULL);
sl@0
   438
		b->init=1;
sl@0
   439
		break;
sl@0
   440
	case BIO_C_GET_MD:
sl@0
   441
		if (b->init)
sl@0
   442
			{
sl@0
   443
			ppmd=ptr;
sl@0
   444
			*ppmd=ctx->md.digest;
sl@0
   445
			}
sl@0
   446
		else
sl@0
   447
			ret=0;
sl@0
   448
		break;
sl@0
   449
	default:
sl@0
   450
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
sl@0
   451
		break;
sl@0
   452
		}
sl@0
   453
	return(ret);
sl@0
   454
	}
sl@0
   455
sl@0
   456
static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
sl@0
   457
	{
sl@0
   458
	long ret=1;
sl@0
   459
sl@0
   460
	if (b->next_bio == NULL) return(0);
sl@0
   461
	switch (cmd)
sl@0
   462
		{
sl@0
   463
	default:
sl@0
   464
		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
sl@0
   465
		break;
sl@0
   466
		}
sl@0
   467
	return(ret);
sl@0
   468
	}
sl@0
   469
sl@0
   470
static void longswap(void *_ptr, size_t len)
sl@0
   471
{	const union { long one; char little; } is_endian = {1};
sl@0
   472
sl@0
   473
	if (is_endian.little) {
sl@0
   474
		size_t i;
sl@0
   475
		unsigned char *p=_ptr,c;
sl@0
   476
sl@0
   477
		for(i= 0;i < len;i+= 4) {
sl@0
   478
			c=p[0],p[0]=p[3],p[3]=c;
sl@0
   479
			c=p[1],p[1]=p[2],p[2]=c;
sl@0
   480
		}
sl@0
   481
	}
sl@0
   482
}
sl@0
   483
sl@0
   484
static void sig_out(BIO* b)
sl@0
   485
	{
sl@0
   486
	BIO_OK_CTX *ctx;
sl@0
   487
	EVP_MD_CTX *md;
sl@0
   488
sl@0
   489
	ctx=b->ptr;
sl@0
   490
	md=&ctx->md;
sl@0
   491
sl@0
   492
	if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return;
sl@0
   493
sl@0
   494
	EVP_DigestInit_ex(md, md->digest, NULL);
sl@0
   495
	/* FIXME: there's absolutely no guarantee this makes any sense at all,
sl@0
   496
	 * particularly now EVP_MD_CTX has been restructured.
sl@0
   497
	 */
sl@0
   498
	RAND_pseudo_bytes(md->md_data, md->digest->md_size);
sl@0
   499
	memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size);
sl@0
   500
	longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size);
sl@0
   501
	ctx->buf_len+= md->digest->md_size;
sl@0
   502
sl@0
   503
	EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
sl@0
   504
	EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
sl@0
   505
	ctx->buf_len+= md->digest->md_size;
sl@0
   506
	ctx->blockout= 1;
sl@0
   507
	ctx->sigio= 0;
sl@0
   508
	}
sl@0
   509
sl@0
   510
static void sig_in(BIO* b)
sl@0
   511
	{
sl@0
   512
	BIO_OK_CTX *ctx;
sl@0
   513
	EVP_MD_CTX *md;
sl@0
   514
	unsigned char tmp[EVP_MAX_MD_SIZE];
sl@0
   515
	int ret= 0;
sl@0
   516
sl@0
   517
	ctx=b->ptr;
sl@0
   518
	md=&ctx->md;
sl@0
   519
sl@0
   520
	if((int)(ctx->buf_len-ctx->buf_off) < 2*md->digest->md_size) return;
sl@0
   521
sl@0
   522
	EVP_DigestInit_ex(md, md->digest, NULL);
sl@0
   523
	memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size);
sl@0
   524
	longswap(md->md_data, md->digest->md_size);
sl@0
   525
	ctx->buf_off+= md->digest->md_size;
sl@0
   526
sl@0
   527
	EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN));
sl@0
   528
	EVP_DigestFinal_ex(md, tmp, NULL);
sl@0
   529
	ret= memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0;
sl@0
   530
	ctx->buf_off+= md->digest->md_size;
sl@0
   531
	if(ret == 1)
sl@0
   532
		{
sl@0
   533
		ctx->sigio= 0;
sl@0
   534
		if(ctx->buf_len != ctx->buf_off)
sl@0
   535
			{
sl@0
   536
			memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), ctx->buf_len- ctx->buf_off);
sl@0
   537
			}
sl@0
   538
		ctx->buf_len-= ctx->buf_off;
sl@0
   539
		ctx->buf_off= 0;
sl@0
   540
		}
sl@0
   541
	else
sl@0
   542
		{
sl@0
   543
		ctx->cont= 0;
sl@0
   544
		}
sl@0
   545
	}
sl@0
   546
sl@0
   547
static void block_out(BIO* b)
sl@0
   548
	{
sl@0
   549
	BIO_OK_CTX *ctx;
sl@0
   550
	EVP_MD_CTX *md;
sl@0
   551
	unsigned long tl;
sl@0
   552
sl@0
   553
	ctx=b->ptr;
sl@0
   554
	md=&ctx->md;
sl@0
   555
sl@0
   556
	tl= ctx->buf_len- OK_BLOCK_BLOCK;
sl@0
   557
	ctx->buf[0]=(unsigned char)(tl>>24);
sl@0
   558
	ctx->buf[1]=(unsigned char)(tl>>16);
sl@0
   559
	ctx->buf[2]=(unsigned char)(tl>>8);
sl@0
   560
	ctx->buf[3]=(unsigned char)(tl);
sl@0
   561
	EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
sl@0
   562
	EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL);
sl@0
   563
	ctx->buf_len+= md->digest->md_size;
sl@0
   564
	ctx->blockout= 1;
sl@0
   565
	}
sl@0
   566
sl@0
   567
static void block_in(BIO* b)
sl@0
   568
	{
sl@0
   569
	BIO_OK_CTX *ctx;
sl@0
   570
	EVP_MD_CTX *md;
sl@0
   571
	unsigned long tl= 0;
sl@0
   572
	unsigned char tmp[EVP_MAX_MD_SIZE];
sl@0
   573
sl@0
   574
	ctx=b->ptr;
sl@0
   575
	md=&ctx->md;
sl@0
   576
sl@0
   577
	assert(sizeof(tl)>=OK_BLOCK_BLOCK);	/* always true */
sl@0
   578
	tl =ctx->buf[0]; tl<<=8;
sl@0
   579
	tl|=ctx->buf[1]; tl<<=8;
sl@0
   580
	tl|=ctx->buf[2]; tl<<=8;
sl@0
   581
	tl|=ctx->buf[3];
sl@0
   582
sl@0
   583
	if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return;
sl@0
   584
 
sl@0
   585
	EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
sl@0
   586
	EVP_DigestFinal_ex(md, tmp, NULL);
sl@0
   587
	if(memcmp(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 0)
sl@0
   588
		{
sl@0
   589
		/* there might be parts from next block lurking around ! */
sl@0
   590
		ctx->buf_off_save= tl+ OK_BLOCK_BLOCK+ md->digest->md_size;
sl@0
   591
		ctx->buf_len_save= ctx->buf_len;
sl@0
   592
		ctx->buf_off= OK_BLOCK_BLOCK;
sl@0
   593
		ctx->buf_len= tl+ OK_BLOCK_BLOCK;
sl@0
   594
		ctx->blockout= 1;
sl@0
   595
		}
sl@0
   596
	else
sl@0
   597
		{
sl@0
   598
		ctx->cont= 0;
sl@0
   599
		}
sl@0
   600
	}
sl@0
   601