Don't overflow the output length in EVP_CipherUpdate calls.

CVE-2021-23840

(Imported from upstream's 6a51b9e1d0cf0bf8515f7201b68fb0a3482b3dc1.)

This differs slightly from upstream's version:

- EVP_R_OUTPUT_WOULD_OVERFLOW didn't seem necessary when ERR_R_OVERFLOW
  already exists. (Also since we use CIPHER_R_*, it wouldn't have helped
  with compatibility anyway. Though there's probably something to be
  said for us folding CIPHER_R_* back into EVP_R_*.)

- For simplicity, just check in_len + bl at the top, rather than trying
  to predict the exact number of bytes written.

Update-Note: Passing extremely large input lengths into EVP_CipherUpdate
will now fail. Use EVP_AEAD instead, which is size_t-based and has more
explicit output bounds.

Change-Id: I31835c89dcdecb6b112828f57deb798dc7187db5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/45685
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/cipher/cipher.c b/crypto/fipsmodule/cipher/cipher.c
index c50c6c5..1522379 100644
--- a/crypto/fipsmodule/cipher/cipher.c
+++ b/crypto/fipsmodule/cipher/cipher.c
@@ -57,6 +57,7 @@
 #include <openssl/cipher.h>
 
 #include <assert.h>
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/err.h>
@@ -240,14 +241,20 @@
 
 int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
                       const uint8_t *in, int in_len) {
-  int i, j, bl;
+  // Ciphers that use blocks may write up to |bl| extra bytes. Ensure the output
+  // does not overflow |*out_len|.
+  int bl = ctx->cipher->block_size;
+  if (bl > 1 && in_len > INT_MAX - bl) {
+    OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW);
+    return 0;
+  }
 
   if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
-    i = ctx->cipher->cipher(ctx, out, in, in_len);
-    if (i < 0) {
+    int ret = ctx->cipher->cipher(ctx, out, in, in_len);
+    if (ret < 0) {
       return 0;
     } else {
-      *out_len = i;
+      *out_len = ret;
     }
     return 1;
   }
@@ -267,8 +274,7 @@
     }
   }
 
-  i = ctx->buf_len;
-  bl = ctx->cipher->block_size;
+  int i = ctx->buf_len;
   assert(bl <= (int)sizeof(ctx->buf));
   if (i != 0) {
     if (bl - i > in_len) {
@@ -277,7 +283,7 @@
       *out_len = 0;
       return 1;
     } else {
-      j = bl - i;
+      int j = bl - i;
       OPENSSL_memcpy(&ctx->buf[i], in, j);
       if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) {
         return 0;
@@ -353,8 +359,13 @@
 
 int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
                       const uint8_t *in, int in_len) {
-  int fix_len;
-  unsigned int b;
+  // Ciphers that use blocks may write up to |bl| extra bytes. Ensure the output
+  // does not overflow |*out_len|.
+  unsigned int b = ctx->cipher->block_size;
+  if (b > 1 && in_len > INT_MAX - (int)b) {
+    OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW);
+    return 0;
+  }
 
   if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
     int r = ctx->cipher->cipher(ctx, out, in, in_len);
@@ -376,15 +387,12 @@
     return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
   }
 
-  b = ctx->cipher->block_size;
   assert(b <= sizeof(ctx->final));
-
+  int fix_len = 0;
   if (ctx->final_used) {
     OPENSSL_memcpy(out, ctx->final, b);
     out += b;
     fix_len = 1;
-  } else {
-    fix_len = 0;
   }
 
   if (!EVP_EncryptUpdate(ctx, out, out_len, in, in_len)) {
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
index c6bec48..3feadea 100644
--- a/include/openssl/cipher.h
+++ b/include/openssl/cipher.h
@@ -558,6 +558,10 @@
 
   // block_mask contains |cipher->block_size| minus one. (The block size
   // assumed to be a power of two.)
+  //
+  // TODO(davidben): This is redundant with |cipher->block_size| and constant
+  // for the whole |EVP_CIPHER|. Move it there, or possibly even remove it and
+  // do the subtraction on demand.
   int block_mask;
 
   uint8_t final[EVP_MAX_BLOCK_LENGTH];  // possible final block