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