diff options
-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 | } |