bio_ok.c revision 296341
1145519Sdarrenr/* crypto/evp/bio_ok.c */ 2145510Sdarrenr/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 322514Sdarrenr * All rights reserved. 453024Sguido * 522514Sdarrenr * This package is an SSL implementation written 680486Sdarrenr * by Eric Young (eay@cryptsoft.com). 7145510Sdarrenr * The implementation was written so as to conform with Netscapes SSL. 822514Sdarrenr * 931183Speter * This library is free for commercial and non-commercial use as long as 1031183Speter * the following conditions are aheared to. The following conditions 11255332Scy * apply to all code found in this distribution, be it the RC4, RSA, 1222514Sdarrenr * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1322514Sdarrenr * included with this distribution is covered by the same copyright terms 1422514Sdarrenr * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1522514Sdarrenr * 1622514Sdarrenr * Copyright remains Eric Young's, and as such any Copyright notices in 1722514Sdarrenr * the code are not to be removed. 1822514Sdarrenr * If this package is used in a product, Eric Young should be given attribution 1922514Sdarrenr * as the author of the parts of the library used. 2022514Sdarrenr * This can be in the form of a textual message at program startup or 2122514Sdarrenr * in documentation (online or textual) provided with the package. 2222514Sdarrenr * 2322514Sdarrenr * Redistribution and use in source and binary forms, with or without 2422514Sdarrenr * modification, are permitted provided that the following conditions 2522514Sdarrenr * are met: 2622514Sdarrenr * 1. Redistributions of source code must retain the copyright 2722514Sdarrenr * notice, this list of conditions and the following disclaimer. 2822514Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright 2922514Sdarrenr * notice, this list of conditions and the following disclaimer in the 3022514Sdarrenr * documentation and/or other materials provided with the distribution. 3122514Sdarrenr * 3. All advertising materials mentioning features or use of this software 3222514Sdarrenr * must display the following acknowledgement: 3322514Sdarrenr * "This product includes cryptographic software written by 3422514Sdarrenr * Eric Young (eay@cryptsoft.com)" 3522514Sdarrenr * The word 'cryptographic' can be left out if the rouines from the library 3622514Sdarrenr * being used are not cryptographic related :-). 3722514Sdarrenr * 4. If you include any Windows specific code (or a derivative thereof) from 3822514Sdarrenr * the apps directory (application code) you must include an acknowledgement: 3922514Sdarrenr * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4022514Sdarrenr * 4122514Sdarrenr * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4222514Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4322514Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4422514Sdarrenr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4522514Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4622514Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4722514Sdarrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4831183Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4922514Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5022514Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5124583Sdarrenr * SUCH DAMAGE. 5222514Sdarrenr * 5322514Sdarrenr * The licence and distribution terms for any publically available version or 5422514Sdarrenr * derivative of this code cannot be changed. i.e. this code cannot simply be 5522514Sdarrenr * copied and put under another distribution licence 5622514Sdarrenr * [including the GNU Public Licence.] 5722514Sdarrenr */ 5822514Sdarrenr 5922514Sdarrenr/*- 6022514Sdarrenr From: Arne Ansper <arne@cyber.ee> 6122514Sdarrenr 6222514Sdarrenr Why BIO_f_reliable? 6322514Sdarrenr 6422514Sdarrenr I wrote function which took BIO* as argument, read data from it 6522514Sdarrenr and processed it. Then I wanted to store the input file in 6622514Sdarrenr encrypted form. OK I pushed BIO_f_cipher to the BIO stack 6722514Sdarrenr and everything was OK. BUT if user types wrong password 6822514Sdarrenr BIO_f_cipher outputs only garbage and my function crashes. Yes 69255332Scy I can and I should fix my function, but BIO_f_cipher is 70255332Scy easy way to add encryption support to many existing applications 71255332Scy and it's hard to debug and fix them all. 7222514Sdarrenr 7322514Sdarrenr So I wanted another BIO which would catch the incorrect passwords and 7422514Sdarrenr file damages which cause garbage on BIO_f_cipher's output. 7522514Sdarrenr 7622514Sdarrenr The easy way is to push the BIO_f_md and save the checksum at 7722514Sdarrenr the end of the file. However there are several problems with this 7822514Sdarrenr approach: 7922514Sdarrenr 8022514Sdarrenr 1) you must somehow separate checksum from actual data. 8122514Sdarrenr 2) you need lot's of memory when reading the file, because you 8222514Sdarrenr must read to the end of the file and verify the checksum before 8322514Sdarrenr letting the application to read the data. 8422514Sdarrenr 8522514Sdarrenr BIO_f_reliable tries to solve both problems, so that you can 8622514Sdarrenr read and write arbitrary long streams using only fixed amount 8722514Sdarrenr of memory. 8822514Sdarrenr 8922514Sdarrenr BIO_f_reliable splits data stream into blocks. Each block is prefixed 9022514Sdarrenr with it's length and suffixed with it's digest. So you need only 9122514Sdarrenr several Kbytes of memory to buffer single block before verifying 9222514Sdarrenr it's digest. 9322514Sdarrenr 9422514Sdarrenr BIO_f_reliable goes further and adds several important capabilities: 9522514Sdarrenr 9622514Sdarrenr 1) the digest of the block is computed over the whole stream 9722514Sdarrenr -- so nobody can rearrange the blocks or remove or replace them. 9822514Sdarrenr 9922514Sdarrenr 2) to detect invalid passwords right at the start BIO_f_reliable 10022514Sdarrenr adds special prefix to the stream. In order to avoid known plain-text 10122514Sdarrenr attacks this prefix is generated as follows: 10222514Sdarrenr 10322514Sdarrenr *) digest is initialized with random seed instead of 10422514Sdarrenr standardized one. 10522514Sdarrenr *) same seed is written to output 10622514Sdarrenr *) well-known text is then hashed and the output 10722514Sdarrenr of the digest is also written to output. 10822514Sdarrenr 10922514Sdarrenr reader can now read the seed from stream, hash the same string 11024583Sdarrenr and then compare the digest output. 11122514Sdarrenr 11222514Sdarrenr Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I 11322514Sdarrenr initially wrote and tested this code on x86 machine and wrote the 11422514Sdarrenr digests out in machine-dependent order :( There are people using 11522514Sdarrenr this code and I cannot change this easily without making existing 11624583Sdarrenr data files unreadable. 11722514Sdarrenr 11822514Sdarrenr*/ 11922514Sdarrenr 12022514Sdarrenr#include <stdio.h> 12122514Sdarrenr#include <errno.h> 12222514Sdarrenr#include <assert.h> 12324583Sdarrenr#include "cryptlib.h" 12422514Sdarrenr#include <openssl/buffer.h> 12522514Sdarrenr#include <openssl/bio.h> 12622514Sdarrenr#include <openssl/evp.h> 12722514Sdarrenr#include <openssl/rand.h> 12822514Sdarrenr 12922514Sdarrenrstatic int ok_write(BIO *h, const char *buf, int num); 13022514Sdarrenrstatic int ok_read(BIO *h, char *buf, int size); 13122514Sdarrenrstatic long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2); 13224583Sdarrenrstatic int ok_new(BIO *h); 13322514Sdarrenrstatic int ok_free(BIO *data); 13422514Sdarrenrstatic long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 13522514Sdarrenr 13622514Sdarrenrstatic int sig_out(BIO *b); 13722514Sdarrenrstatic int sig_in(BIO *b); 13822514Sdarrenrstatic int block_out(BIO *b); 13922514Sdarrenrstatic int block_in(BIO *b); 14022514Sdarrenr#define OK_BLOCK_SIZE (1024*4) 14122514Sdarrenr#define OK_BLOCK_BLOCK 4 14222514Sdarrenr#define IOBS (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE) 14322514Sdarrenr#define WELLKNOWN "The quick brown fox jumped over the lazy dog's back." 14422514Sdarrenr 14522514Sdarrenrtypedef struct ok_struct { 14622514Sdarrenr size_t buf_len; 14722514Sdarrenr size_t buf_off; 14822514Sdarrenr size_t buf_len_save; 14922514Sdarrenr size_t buf_off_save; 15022514Sdarrenr int cont; /* <= 0 when finished */ 15122514Sdarrenr int finished; 15222514Sdarrenr EVP_MD_CTX md; 153255332Scy int blockout; /* output block is ready */ 154255332Scy int sigio; /* must process signature */ 15522514Sdarrenr unsigned char buf[IOBS]; 15622514Sdarrenr} BIO_OK_CTX; 15722514Sdarrenr 15822514Sdarrenrstatic BIO_METHOD methods_ok = { 15922514Sdarrenr BIO_TYPE_CIPHER, "reliable", 16022514Sdarrenr ok_write, 16122514Sdarrenr ok_read, 16222514Sdarrenr NULL, /* ok_puts, */ 16322514Sdarrenr NULL, /* ok_gets, */ 16422514Sdarrenr ok_ctrl, 16522514Sdarrenr ok_new, 16622514Sdarrenr ok_free, 16724583Sdarrenr ok_callback_ctrl, 16822514Sdarrenr}; 16922514Sdarrenr 17022514SdarrenrBIO_METHOD *BIO_f_reliable(void) 17122514Sdarrenr{ 17222514Sdarrenr return (&methods_ok); 17322514Sdarrenr} 17424583Sdarrenr 17522514Sdarrenrstatic int ok_new(BIO *bi) 17622514Sdarrenr{ 17722514Sdarrenr BIO_OK_CTX *ctx; 17822514Sdarrenr 17922514Sdarrenr ctx = (BIO_OK_CTX *)OPENSSL_malloc(sizeof(BIO_OK_CTX)); 18022514Sdarrenr if (ctx == NULL) 18122514Sdarrenr return (0); 18224583Sdarrenr 18322514Sdarrenr ctx->buf_len = 0; 18422514Sdarrenr ctx->buf_off = 0; 18522514Sdarrenr ctx->buf_len_save = 0; 18622514Sdarrenr ctx->buf_off_save = 0; 18722514Sdarrenr ctx->cont = 1; 18822514Sdarrenr ctx->finished = 0; 18922514Sdarrenr ctx->blockout = 0; 19022514Sdarrenr ctx->sigio = 1; 19131183Speter 192255332Scy EVP_MD_CTX_init(&ctx->md); 193255332Scy 194255332Scy bi->init = 0; 195255332Scy bi->ptr = (char *)ctx; 19622514Sdarrenr bi->flags = 0; 19722514Sdarrenr return (1); 19822514Sdarrenr} 19922514Sdarrenr 20022514Sdarrenrstatic int ok_free(BIO *a) 20122514Sdarrenr{ 20222514Sdarrenr if (a == NULL) 20322514Sdarrenr return (0); 20422514Sdarrenr EVP_MD_CTX_cleanup(&((BIO_OK_CTX *)a->ptr)->md); 20522514Sdarrenr OPENSSL_cleanse(a->ptr, sizeof(BIO_OK_CTX)); 20622514Sdarrenr OPENSSL_free(a->ptr); 20722514Sdarrenr a->ptr = NULL; 20822514Sdarrenr a->init = 0; 20922514Sdarrenr a->flags = 0; 21022514Sdarrenr return (1); 21122514Sdarrenr} 21222514Sdarrenr 21322514Sdarrenrstatic int ok_read(BIO *b, char *out, int outl) 21422514Sdarrenr{ 21522514Sdarrenr int ret = 0, i, n; 21622514Sdarrenr BIO_OK_CTX *ctx; 21722514Sdarrenr 21822514Sdarrenr if (out == NULL) 21922514Sdarrenr return (0); 22022514Sdarrenr ctx = (BIO_OK_CTX *)b->ptr; 22122514Sdarrenr 22222514Sdarrenr if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) 22322514Sdarrenr return (0); 22422514Sdarrenr 22522514Sdarrenr while (outl > 0) { 22622514Sdarrenr 22722514Sdarrenr /* copy clean bytes to output buffer */ 22822514Sdarrenr if (ctx->blockout) { 229145510Sdarrenr i = ctx->buf_len - ctx->buf_off; 230161357Sguido if (i > outl) 231161357Sguido i = outl; 23222514Sdarrenr memcpy(out, &(ctx->buf[ctx->buf_off]), i); 23322514Sdarrenr ret += i; 23422514Sdarrenr out += i; 23522514Sdarrenr outl -= i; 23622514Sdarrenr ctx->buf_off += i; 23722514Sdarrenr 23822514Sdarrenr /* all clean bytes are out */ 23922514Sdarrenr if (ctx->buf_len == ctx->buf_off) { 24022514Sdarrenr ctx->buf_off = 0; 24122514Sdarrenr 24222514Sdarrenr /* 24322514Sdarrenr * copy start of the next block into proper place 24422514Sdarrenr */ 24522514Sdarrenr if (ctx->buf_len_save - ctx->buf_off_save > 0) { 24622514Sdarrenr ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save; 24724583Sdarrenr memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]), 24822514Sdarrenr ctx->buf_len); 24922514Sdarrenr } else { 25022514Sdarrenr ctx->buf_len = 0; 25131183Speter } 25222514Sdarrenr ctx->blockout = 0; 25331183Speter } 25422514Sdarrenr } 25522514Sdarrenr 25622514Sdarrenr /* output buffer full -- cancel */ 25722514Sdarrenr if (outl == 0) 25822514Sdarrenr break; 25922514Sdarrenr 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) 265 break; /* nothing new */ 266 267 ctx->buf_len += i; 268 269 /* no signature yet -- check if we got one */ 270 if (ctx->sigio == 1) { 271 if (!sig_in(b)) { 272 BIO_clear_retry_flags(b); 273 return 0; 274 } 275 } 276 277 /* signature ok -- check if we got block */ 278 if (ctx->sigio == 0) { 279 if (!block_in(b)) { 280 BIO_clear_retry_flags(b); 281 return 0; 282 } 283 } 284 285 /* invalid block -- cancel */ 286 if (ctx->cont <= 0) 287 break; 288 289 } 290 291 BIO_clear_retry_flags(b); 292 BIO_copy_next_retry(b); 293 return (ret); 294} 295 296static int ok_write(BIO *b, const char *in, int inl) 297{ 298 int ret = 0, n, i; 299 BIO_OK_CTX *ctx; 300 301 if (inl <= 0) 302 return inl; 303 304 ctx = (BIO_OK_CTX *)b->ptr; 305 ret = inl; 306 307 if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) 308 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 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 318 if (i <= 0) { 319 BIO_copy_next_retry(b); 320 if (!BIO_should_retry(b)) 321 ctx->cont = 0; 322 return (i); 323 } 324 ctx->buf_off += i; 325 n -= i; 326 } 327 328 /* at this point all pending data has been written */ 329 ctx->blockout = 0; 330 if (ctx->buf_len == ctx->buf_off) { 331 ctx->buf_len = OK_BLOCK_BLOCK; 332 ctx->buf_off = 0; 333 } 334 335 if ((in == NULL) || (inl <= 0)) 336 return (0); 337 338 n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ? 339 (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl; 340 341 memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])), 342 (unsigned char *)in, n); 343 ctx->buf_len += n; 344 inl -= n; 345 in += n; 346 347 if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) { 348 if (!block_out(b)) { 349 BIO_clear_retry_flags(b); 350 return 0; 351 } 352 } 353 } while (inl > 0); 354 355 BIO_clear_retry_flags(b); 356 BIO_copy_next_retry(b); 357 return (ret); 358} 359 360static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) 361{ 362 BIO_OK_CTX *ctx; 363 EVP_MD *md; 364 const EVP_MD **ppmd; 365 long ret = 1; 366 int i; 367 368 ctx = b->ptr; 369 370 switch (cmd) { 371 case BIO_CTRL_RESET: 372 ctx->buf_len = 0; 373 ctx->buf_off = 0; 374 ctx->buf_len_save = 0; 375 ctx->buf_off_save = 0; 376 ctx->cont = 1; 377 ctx->finished = 0; 378 ctx->blockout = 0; 379 ctx->sigio = 1; 380 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 381 break; 382 case BIO_CTRL_EOF: /* More to read */ 383 if (ctx->cont <= 0) 384 ret = 1; 385 else 386 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 387 break; 388 case BIO_CTRL_PENDING: /* More to read in buffer */ 389 case BIO_CTRL_WPENDING: /* More to read in buffer */ 390 ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0; 391 if (ret <= 0) 392 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 393 break; 394 case BIO_CTRL_FLUSH: 395 /* do a final write */ 396 if (ctx->blockout == 0) 397 if (!block_out(b)) 398 return 0; 399 400 while (ctx->blockout) { 401 i = ok_write(b, NULL, 0); 402 if (i < 0) { 403 ret = i; 404 break; 405 } 406 } 407 408 ctx->finished = 1; 409 ctx->buf_off = ctx->buf_len = 0; 410 ctx->cont = (int)ret; 411 412 /* Finally flush the underlying BIO */ 413 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 414 break; 415 case BIO_C_DO_STATE_MACHINE: 416 BIO_clear_retry_flags(b); 417 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 418 BIO_copy_next_retry(b); 419 break; 420 case BIO_CTRL_INFO: 421 ret = (long)ctx->cont; 422 break; 423 case BIO_C_SET_MD: 424 md = ptr; 425 if (!EVP_DigestInit_ex(&ctx->md, md, NULL)) 426 return 0; 427 b->init = 1; 428 break; 429 case BIO_C_GET_MD: 430 if (b->init) { 431 ppmd = ptr; 432 *ppmd = ctx->md.digest; 433 } else 434 ret = 0; 435 break; 436 default: 437 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 438 break; 439 } 440 return (ret); 441} 442 443static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 444{ 445 long ret = 1; 446 447 if (b->next_bio == NULL) 448 return (0); 449 switch (cmd) { 450 default: 451 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 452 break; 453 } 454 return (ret); 455} 456 457static void longswap(void *_ptr, size_t len) 458{ 459 const union { 460 long one; 461 char little; 462 } is_endian = { 463 1 464 }; 465 466 if (is_endian.little) { 467 size_t i; 468 unsigned char *p = _ptr, c; 469 470 for (i = 0; i < len; i += 4) { 471 c = p[0], p[0] = p[3], p[3] = c; 472 c = p[1], p[1] = p[2], p[2] = c; 473 } 474 } 475} 476 477static int sig_out(BIO *b) 478{ 479 BIO_OK_CTX *ctx; 480 EVP_MD_CTX *md; 481 482 ctx = b->ptr; 483 md = &ctx->md; 484 485 if (ctx->buf_len + 2 * md->digest->md_size > OK_BLOCK_SIZE) 486 return 1; 487 488 if (!EVP_DigestInit_ex(md, md->digest, NULL)) 489 goto berr; 490 /* 491 * FIXME: there's absolutely no guarantee this makes any sense at all, 492 * particularly now EVP_MD_CTX has been restructured. 493 */ 494 if (RAND_pseudo_bytes(md->md_data, md->digest->md_size) < 0) 495 goto berr; 496 memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size); 497 longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size); 498 ctx->buf_len += md->digest->md_size; 499 500 if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) 501 goto berr; 502 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) 503 goto berr; 504 ctx->buf_len += md->digest->md_size; 505 ctx->blockout = 1; 506 ctx->sigio = 0; 507 return 1; 508 berr: 509 BIO_clear_retry_flags(b); 510 return 0; 511} 512 513static int sig_in(BIO *b) 514{ 515 BIO_OK_CTX *ctx; 516 EVP_MD_CTX *md; 517 unsigned char tmp[EVP_MAX_MD_SIZE]; 518 int ret = 0; 519 520 ctx = b->ptr; 521 md = &ctx->md; 522 523 if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md->digest->md_size) 524 return 1; 525 526 if (!EVP_DigestInit_ex(md, md->digest, NULL)) 527 goto berr; 528 memcpy(md->md_data, &(ctx->buf[ctx->buf_off]), md->digest->md_size); 529 longswap(md->md_data, md->digest->md_size); 530 ctx->buf_off += md->digest->md_size; 531 532 if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) 533 goto berr; 534 if (!EVP_DigestFinal_ex(md, tmp, NULL)) 535 goto berr; 536 ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md->digest->md_size) == 0; 537 ctx->buf_off += md->digest->md_size; 538 if (ret == 1) { 539 ctx->sigio = 0; 540 if (ctx->buf_len != ctx->buf_off) { 541 memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), 542 ctx->buf_len - ctx->buf_off); 543 } 544 ctx->buf_len -= ctx->buf_off; 545 ctx->buf_off = 0; 546 } else { 547 ctx->cont = 0; 548 } 549 return 1; 550 berr: 551 BIO_clear_retry_flags(b); 552 return 0; 553} 554 555static int block_out(BIO *b) 556{ 557 BIO_OK_CTX *ctx; 558 EVP_MD_CTX *md; 559 unsigned long tl; 560 561 ctx = b->ptr; 562 md = &ctx->md; 563 564 tl = ctx->buf_len - OK_BLOCK_BLOCK; 565 ctx->buf[0] = (unsigned char)(tl >> 24); 566 ctx->buf[1] = (unsigned char)(tl >> 16); 567 ctx->buf[2] = (unsigned char)(tl >> 8); 568 ctx->buf[3] = (unsigned char)(tl); 569 if (!EVP_DigestUpdate(md, 570 (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) 571 goto berr; 572 if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) 573 goto berr; 574 ctx->buf_len += md->digest->md_size; 575 ctx->blockout = 1; 576 return 1; 577 berr: 578 BIO_clear_retry_flags(b); 579 return 0; 580} 581 582static int block_in(BIO *b) 583{ 584 BIO_OK_CTX *ctx; 585 EVP_MD_CTX *md; 586 unsigned long tl = 0; 587 unsigned char tmp[EVP_MAX_MD_SIZE]; 588 589 ctx = b->ptr; 590 md = &ctx->md; 591 592 assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */ 593 tl = ctx->buf[0]; 594 tl <<= 8; 595 tl |= ctx->buf[1]; 596 tl <<= 8; 597 tl |= ctx->buf[2]; 598 tl <<= 8; 599 tl |= ctx->buf[3]; 600 601 if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md->digest->md_size) 602 return 1; 603 604 if (!EVP_DigestUpdate(md, 605 (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) 606 goto berr; 607 if (!EVP_DigestFinal_ex(md, tmp, NULL)) 608 goto berr; 609 if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 610 0) { 611 /* there might be parts from next block lurking around ! */ 612 ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md->digest->md_size; 613 ctx->buf_len_save = ctx->buf_len; 614 ctx->buf_off = OK_BLOCK_BLOCK; 615 ctx->buf_len = tl + OK_BLOCK_BLOCK; 616 ctx->blockout = 1; 617 } else { 618 ctx->cont = 0; 619 } 620 return 1; 621 berr: 622 BIO_clear_retry_flags(b); 623 return 0; 624} 625