| OLD | NEW |
| (Empty) |
| 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 From: Arne Ansper <arne@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 int sig_out(BIO* b); | |
| 137 static int sig_in(BIO* b); | |
| 138 static int block_out(BIO* b); | |
| 139 static int 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 plac
e */ | |
| 243 if(ctx->buf_len_save- ctx->buf_off_save > 0) | |
| 244 { | |
| 245 ctx->buf_len= ctx->buf_len_save- ctx->bu
f_off_save; | |
| 246 memmove(ctx->buf, &(ctx->buf[ctx->buf_of
f_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) | |
| 270 { | |
| 271 if (!sig_in(b)) | |
| 272 { | |
| 273 BIO_clear_retry_flags(b); | |
| 274 return 0; | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 /* signature ok -- check if we got block */ | |
| 279 if (ctx->sigio == 0) | |
| 280 { | |
| 281 if (!block_in(b)) | |
| 282 { | |
| 283 BIO_clear_retry_flags(b); | |
| 284 return 0; | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 /* invalid block -- cancel */ | |
| 289 if (ctx->cont <= 0) break; | |
| 290 | |
| 291 } | |
| 292 | |
| 293 BIO_clear_retry_flags(b); | |
| 294 BIO_copy_next_retry(b); | |
| 295 return(ret); | |
| 296 } | |
| 297 | |
| 298 static int ok_write(BIO *b, const char *in, int inl) | |
| 299 { | |
| 300 int ret=0,n,i; | |
| 301 BIO_OK_CTX *ctx; | |
| 302 | |
| 303 if (inl <= 0) return inl; | |
| 304 | |
| 305 ctx=(BIO_OK_CTX *)b->ptr; | |
| 306 ret=inl; | |
| 307 | |
| 308 if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return(0); | |
| 309 | |
| 310 if(ctx->sigio && !sig_out(b)) | |
| 311 return 0; | |
| 312 | |
| 313 do{ | |
| 314 BIO_clear_retry_flags(b); | |
| 315 n=ctx->buf_len-ctx->buf_off; | |
| 316 while (ctx->blockout && n > 0) | |
| 317 { | |
| 318 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); | |
| 319 if (i <= 0) | |
| 320 { | |
| 321 BIO_copy_next_retry(b); | |
| 322 if(!BIO_should_retry(b)) | |
| 323 ctx->cont= 0; | |
| 324 return(i); | |
| 325 } | |
| 326 ctx->buf_off+=i; | |
| 327 n-=i; | |
| 328 } | |
| 329 | |
| 330 /* at this point all pending data has been written */ | |
| 331 ctx->blockout= 0; | |
| 332 if (ctx->buf_len == ctx->buf_off) | |
| 333 { | |
| 334 ctx->buf_len=OK_BLOCK_BLOCK; | |
| 335 ctx->buf_off=0; | |
| 336 } | |
| 337 | |
| 338 if ((in == NULL) || (inl <= 0)) return(0); | |
| 339 | |
| 340 n= (inl+ ctx->buf_len > OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) ? | |
| 341 (int)(OK_BLOCK_SIZE+OK_BLOCK_BLOCK-ctx->buf_len) : inl; | |
| 342 | |
| 343 memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])),(unsigned ch
ar *)in,n); | |
| 344 ctx->buf_len+= n; | |
| 345 inl-=n; | |
| 346 in+=n; | |
| 347 | |
| 348 if(ctx->buf_len >= OK_BLOCK_SIZE+ OK_BLOCK_BLOCK) | |
| 349 { | |
| 350 if (!block_out(b)) | |
| 351 { | |
| 352 BIO_clear_retry_flags(b); | |
| 353 return 0; | |
| 354 } | |
| 355 } | |
| 356 }while(inl > 0); | |
| 357 | |
| 358 BIO_clear_retry_flags(b); | |
| 359 BIO_copy_next_retry(b); | |
| 360 return(ret); | |
| 361 } | |
| 362 | |
| 363 static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) | |
| 364 { | |
| 365 BIO_OK_CTX *ctx; | |
| 366 EVP_MD *md; | |
| 367 const EVP_MD **ppmd; | |
| 368 long ret=1; | |
| 369 int i; | |
| 370 | |
| 371 ctx=b->ptr; | |
| 372 | |
| 373 switch (cmd) | |
| 374 { | |
| 375 case BIO_CTRL_RESET: | |
| 376 ctx->buf_len=0; | |
| 377 ctx->buf_off=0; | |
| 378 ctx->buf_len_save=0; | |
| 379 ctx->buf_off_save=0; | |
| 380 ctx->cont=1; | |
| 381 ctx->finished=0; | |
| 382 ctx->blockout= 0; | |
| 383 ctx->sigio=1; | |
| 384 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 385 break; | |
| 386 case BIO_CTRL_EOF: /* More to read */ | |
| 387 if (ctx->cont <= 0) | |
| 388 ret=1; | |
| 389 else | |
| 390 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 391 break; | |
| 392 case BIO_CTRL_PENDING: /* More to read in buffer */ | |
| 393 case BIO_CTRL_WPENDING: /* More to read in buffer */ | |
| 394 ret=ctx->blockout ? ctx->buf_len-ctx->buf_off : 0; | |
| 395 if (ret <= 0) | |
| 396 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 397 break; | |
| 398 case BIO_CTRL_FLUSH: | |
| 399 /* do a final write */ | |
| 400 if(ctx->blockout == 0) | |
| 401 if (!block_out(b)) | |
| 402 return 0; | |
| 403 | |
| 404 while (ctx->blockout) | |
| 405 { | |
| 406 i=ok_write(b,NULL,0); | |
| 407 if (i < 0) | |
| 408 { | |
| 409 ret=i; | |
| 410 break; | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 ctx->finished=1; | |
| 415 ctx->buf_off=ctx->buf_len=0; | |
| 416 ctx->cont=(int)ret; | |
| 417 | |
| 418 /* Finally flush the underlying BIO */ | |
| 419 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 420 break; | |
| 421 case BIO_C_DO_STATE_MACHINE: | |
| 422 BIO_clear_retry_flags(b); | |
| 423 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 424 BIO_copy_next_retry(b); | |
| 425 break; | |
| 426 case BIO_CTRL_INFO: | |
| 427 ret=(long)ctx->cont; | |
| 428 break; | |
| 429 case BIO_C_SET_MD: | |
| 430 md=ptr; | |
| 431 if (!EVP_DigestInit_ex(&ctx->md, md, NULL)) | |
| 432 return 0; | |
| 433 b->init=1; | |
| 434 break; | |
| 435 case BIO_C_GET_MD: | |
| 436 if (b->init) | |
| 437 { | |
| 438 ppmd=ptr; | |
| 439 *ppmd=ctx->md.digest; | |
| 440 } | |
| 441 else | |
| 442 ret=0; | |
| 443 break; | |
| 444 default: | |
| 445 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); | |
| 446 break; | |
| 447 } | |
| 448 return(ret); | |
| 449 } | |
| 450 | |
| 451 static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) | |
| 452 { | |
| 453 long ret=1; | |
| 454 | |
| 455 if (b->next_bio == NULL) return(0); | |
| 456 switch (cmd) | |
| 457 { | |
| 458 default: | |
| 459 ret=BIO_callback_ctrl(b->next_bio,cmd,fp); | |
| 460 break; | |
| 461 } | |
| 462 return(ret); | |
| 463 } | |
| 464 | |
| 465 static void longswap(void *_ptr, size_t len) | |
| 466 { const union { long one; char little; } is_endian = {1}; | |
| 467 | |
| 468 if (is_endian.little) { | |
| 469 size_t i; | |
| 470 unsigned char *p=_ptr,c; | |
| 471 | |
| 472 for(i= 0;i < len;i+= 4) { | |
| 473 c=p[0],p[0]=p[3],p[3]=c; | |
| 474 c=p[1],p[1]=p[2],p[2]=c; | |
| 475 } | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 static int sig_out(BIO* b) | |
| 480 { | |
| 481 BIO_OK_CTX *ctx; | |
| 482 EVP_MD_CTX *md; | |
| 483 | |
| 484 ctx=b->ptr; | |
| 485 md=&ctx->md; | |
| 486 | |
| 487 if(ctx->buf_len+ 2* md->digest->md_size > OK_BLOCK_SIZE) return 1; | |
| 488 | |
| 489 if (!EVP_DigestInit_ex(md, md->digest, NULL)) | |
| 490 goto berr; | |
| 491 /* FIXME: there's absolutely no guarantee this makes any sense at all, | |
| 492 * particularly now EVP_MD_CTX has been restructured. | |
| 493 */ | |
| 494 RAND_pseudo_bytes(md->md_data, md->digest->md_size); | |
| 495 memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size); | |
| 496 longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size); | |
| 497 ctx->buf_len+= md->digest->md_size; | |
| 498 | |
| 499 if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) | |
| 500 goto berr; | |
| 501 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) | |
| 502 goto berr; | |
| 503 ctx->buf_len+= md->digest->md_size; | |
| 504 ctx->blockout= 1; | |
| 505 ctx->sigio= 0; | |
| 506 return 1; | |
| 507 berr: | |
| 508 BIO_clear_retry_flags(b); | |
| 509 return 0; | |
| 510 } | |
| 511 | |
| 512 static int sig_in(BIO* b) | |
| 513 { | |
| 514 BIO_OK_CTX *ctx; | |
| 515 EVP_MD_CTX *md; | |
| 516 unsigned char tmp[EVP_MAX_MD_SIZE]; | |
| 517 int ret= 0; | |
| 518 | |
| 519 ctx=b->ptr; | |
| 520 md=&ctx->md; | |
| 521 | |
| 522 if((int)(ctx->buf_len-ctx->buf_off) < 2*md->digest->md_size) return 1; | |
| 523 | |
| 524 if (!EVP_DigestInit_ex(md, md->digest, NULL)) | |
| 525 goto berr; | |
| 526 memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size); | |
| 527 longswap(md->md_data, md->digest->md_size); | |
| 528 ctx->buf_off+= md->digest->md_size; | |
| 529 | |
| 530 if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) | |
| 531 goto berr; | |
| 532 if (!EVP_DigestFinal_ex(md, tmp, NULL)) | |
| 533 goto berr; | |
| 534 ret= memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0; | |
| 535 ctx->buf_off+= md->digest->md_size; | |
| 536 if(ret == 1) | |
| 537 { | |
| 538 ctx->sigio= 0; | |
| 539 if(ctx->buf_len != ctx->buf_off) | |
| 540 { | |
| 541 memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), ctx->buf_le
n- ctx->buf_off); | |
| 542 } | |
| 543 ctx->buf_len-= ctx->buf_off; | |
| 544 ctx->buf_off= 0; | |
| 545 } | |
| 546 else | |
| 547 { | |
| 548 ctx->cont= 0; | |
| 549 } | |
| 550 return 1; | |
| 551 berr: | |
| 552 BIO_clear_retry_flags(b); | |
| 553 return 0; | |
| 554 } | |
| 555 | |
| 556 static int block_out(BIO* b) | |
| 557 { | |
| 558 BIO_OK_CTX *ctx; | |
| 559 EVP_MD_CTX *md; | |
| 560 unsigned long tl; | |
| 561 | |
| 562 ctx=b->ptr; | |
| 563 md=&ctx->md; | |
| 564 | |
| 565 tl= ctx->buf_len- OK_BLOCK_BLOCK; | |
| 566 ctx->buf[0]=(unsigned char)(tl>>24); | |
| 567 ctx->buf[1]=(unsigned char)(tl>>16); | |
| 568 ctx->buf[2]=(unsigned char)(tl>>8); | |
| 569 ctx->buf[3]=(unsigned char)(tl); | |
| 570 if (!EVP_DigestUpdate(md, | |
| 571 (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl)) | |
| 572 goto berr; | |
| 573 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) | |
| 574 goto berr; | |
| 575 ctx->buf_len+= md->digest->md_size; | |
| 576 ctx->blockout= 1; | |
| 577 return 1; | |
| 578 berr: | |
| 579 BIO_clear_retry_flags(b); | |
| 580 return 0; | |
| 581 } | |
| 582 | |
| 583 static int block_in(BIO* b) | |
| 584 { | |
| 585 BIO_OK_CTX *ctx; | |
| 586 EVP_MD_CTX *md; | |
| 587 unsigned long tl= 0; | |
| 588 unsigned char tmp[EVP_MAX_MD_SIZE]; | |
| 589 | |
| 590 ctx=b->ptr; | |
| 591 md=&ctx->md; | |
| 592 | |
| 593 assert(sizeof(tl)>=OK_BLOCK_BLOCK); /* always true */ | |
| 594 tl =ctx->buf[0]; tl<<=8; | |
| 595 tl|=ctx->buf[1]; tl<<=8; | |
| 596 tl|=ctx->buf[2]; tl<<=8; | |
| 597 tl|=ctx->buf[3]; | |
| 598 | |
| 599 if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return 1; | |
| 600 | |
| 601 if (!EVP_DigestUpdate(md, | |
| 602 (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl)) | |
| 603 goto berr; | |
| 604 if (!EVP_DigestFinal_ex(md, tmp, NULL)) | |
| 605 goto berr; | |
| 606 if(memcmp(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) ==
0) | |
| 607 { | |
| 608 /* there might be parts from next block lurking around ! */ | |
| 609 ctx->buf_off_save= tl+ OK_BLOCK_BLOCK+ md->digest->md_size; | |
| 610 ctx->buf_len_save= ctx->buf_len; | |
| 611 ctx->buf_off= OK_BLOCK_BLOCK; | |
| 612 ctx->buf_len= tl+ OK_BLOCK_BLOCK; | |
| 613 ctx->blockout= 1; | |
| 614 } | |
| 615 else | |
| 616 { | |
| 617 ctx->cont= 0; | |
| 618 } | |
| 619 return 1; | |
| 620 berr: | |
| 621 BIO_clear_retry_flags(b); | |
| 622 return 0; | |
| 623 } | |
| 624 | |
| OLD | NEW |