diff options
author | tb <> | 2023-12-20 10:35:25 +0000 |
---|---|---|
committer | tb <> | 2023-12-20 10:35:25 +0000 |
commit | a9a5598c7249fefcb98e69b5a75ee16d3c01d5ee (patch) | |
tree | 4b8deba64a935d81b714b45fdd6ed99942ce2021 /src | |
parent | c0cd30c4ff668c8c13b4ff65ea9d6c956cb08b27 (diff) | |
download | openbsd-a9a5598c7249fefcb98e69b5a75ee16d3c01d5ee.tar.gz openbsd-a9a5598c7249fefcb98e69b5a75ee16d3c01d5ee.tar.bz2 openbsd-a9a5598c7249fefcb98e69b5a75ee16d3c01d5ee.zip |
Simplify EVP_DecryptUpdate() a bit
This time the block size is called b and there's some awful length
fiddling with fix_len, which until recently also served as store
for the return value for do_cipher()...
If we land on a block boundary, we keep the last block decrypted and
don't count it as part of the output. So in the next call we need to
feed it back in. Feeding it back in counts as output written this time
around, so instead of remembering that we need to adjust outl, keep a
tally of the bytes written. This way we can also do some overflow and
underflow checking.
ok jsing
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/evp/evp_enc.c | 54 |
1 files changed, 28 insertions, 26 deletions
diff --git a/src/lib/libcrypto/evp/evp_enc.c b/src/lib/libcrypto/evp/evp_enc.c index 0b58a6d9ee..16a993eb0d 100644 --- a/src/lib/libcrypto/evp/evp_enc.c +++ b/src/lib/libcrypto/evp/evp_enc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: evp_enc.c,v 1.63 2023/12/16 17:40:22 tb Exp $ */ | 1 | /* $OpenBSD: evp_enc.c,v 1.64 2023/12/20 10:35:25 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -420,8 +420,8 @@ int | |||
420 | EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | 420 | EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, |
421 | const unsigned char *in, int inl) | 421 | const unsigned char *in, int inl) |
422 | { | 422 | { |
423 | int fix_len; | 423 | const int block_size = ctx->cipher->block_size; |
424 | unsigned int b; | 424 | int len = 0, total_len = 0; |
425 | 425 | ||
426 | *outl = 0; | 426 | *outl = 0; |
427 | 427 | ||
@@ -434,47 +434,49 @@ EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | |||
434 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) | 434 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) |
435 | return evp_cipher(ctx, out, outl, in, inl); | 435 | return evp_cipher(ctx, out, outl, in, inl); |
436 | 436 | ||
437 | if (ctx->flags & EVP_CIPH_NO_PADDING) | 437 | if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) |
438 | return EVP_EncryptUpdate(ctx, out, outl, in, inl); | 438 | return EVP_EncryptUpdate(ctx, out, outl, in, inl); |
439 | 439 | ||
440 | b = ctx->cipher->block_size; | 440 | if (block_size > sizeof(ctx->final)) { |
441 | if (b > sizeof ctx->final) { | ||
442 | EVPerror(EVP_R_BAD_BLOCK_LENGTH); | 441 | EVPerror(EVP_R_BAD_BLOCK_LENGTH); |
443 | return 0; | 442 | return 0; |
444 | } | 443 | } |
445 | 444 | ||
446 | if (ctx->final_used) { | 445 | if (ctx->final_used) { |
447 | /* | 446 | /* |
448 | * final_used is only ever set if buf_len is 0. Therefore the | 447 | * final_used is only set if buf_len is 0. Therefore the maximum |
449 | * maximum length output we will ever see from EVP_EncryptUpdate | 448 | * length output from EVP_EncryptUpdate() is inl & ~block_mask. |
450 | * is inl & ~(b - 1). Since final_used is set, the final output | 449 | * Ensure (inl & ~block_mask) + block_size doesn't overflow. |
451 | * length is (inl & ~(b - 1)) + b. Ensure it doesn't overflow. | ||
452 | */ | 450 | */ |
453 | if ((inl & ~(b - 1)) > INT_MAX - b) { | 451 | if ((inl & ~ctx->block_mask) > INT_MAX - block_size) { |
454 | EVPerror(EVP_R_TOO_LARGE); | 452 | EVPerror(EVP_R_TOO_LARGE); |
455 | return 0; | 453 | return 0; |
456 | } | 454 | } |
457 | memcpy(out, ctx->final, b); | 455 | memcpy(out, ctx->final, block_size); |
458 | out += b; | 456 | out += block_size; |
459 | fix_len = 1; | 457 | total_len = block_size; |
460 | } else | 458 | } |
461 | fix_len = 0; | ||
462 | 459 | ||
460 | ctx->final_used = 0; | ||
463 | 461 | ||
464 | if (!EVP_EncryptUpdate(ctx, out, outl, in, inl)) | 462 | len = 0; |
463 | if (!EVP_EncryptUpdate(ctx, out, &len, in, inl)) | ||
465 | return 0; | 464 | return 0; |
466 | 465 | ||
467 | /* if we have 'decrypted' a multiple of block size, make sure | 466 | /* Keep copy of last block if a multiple of block_size was decrypted. */ |
468 | * we have a copy of this last block */ | 467 | if (block_size > 1 && ctx->buf_len == 0) { |
469 | if (b > 1 && !ctx->buf_len) { | 468 | if (len < block_size) |
470 | *outl -= b; | 469 | return 0; |
470 | len -= block_size; | ||
471 | memcpy(ctx->final, &out[len], block_size); | ||
471 | ctx->final_used = 1; | 472 | ctx->final_used = 1; |
472 | memcpy(ctx->final, &out[*outl], b); | 473 | } |
473 | } else | ||
474 | ctx->final_used = 0; | ||
475 | 474 | ||
476 | if (fix_len) | 475 | if (len > INT_MAX - total_len) |
477 | *outl += b; | 476 | return 0; |
477 | total_len += len; | ||
478 | |||
479 | *outl = total_len; | ||
478 | 480 | ||
479 | return 1; | 481 | return 1; |
480 | } | 482 | } |