Clean up EVP_DecryptFinal_ex()
authortb <tb@openbsd.org>
Wed, 20 Dec 2023 11:01:34 +0000 (11:01 +0000)
committertb <tb@openbsd.org>
Wed, 20 Dec 2023 11:01:34 +0000 (11:01 +0000)
Rework the code to use the usual variable names, return early if we
have block size 1 and unindent the remainder of the code for block
sizes 8 and 16. Rework the padding check to be less acrobatic and
copy the remainder of the plain text into out using memcpy() rather
than a for loop.

input/ok jsing

lib/libcrypto/evp/evp_enc.c

index b001505..2bcef15 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: evp_enc.c,v 1.65 2023/12/20 10:42:43 tb Exp $ */
+/* $OpenBSD: evp_enc.c,v 1.66 2023/12/20 11:01:34 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -487,50 +487,53 @@ EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 int
 EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 {
-       int i, n;
-       unsigned int b;
+       const int block_size = ctx->cipher->block_size;
+       int buf_offset = ctx->buf_len;
+       int i, pad, plain_len;
 
        *outl = 0;
 
        if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
                return evp_cipher(ctx, out, outl, NULL, 0);
 
-       b = ctx->cipher->block_size;
-       if (ctx->flags & EVP_CIPH_NO_PADDING) {
-               if (ctx->buf_len) {
+       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
+               if (buf_offset != 0) {
                        EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
                        return 0;
                }
-               *outl = 0;
                return 1;
        }
-       if (b > 1) {
-               if (ctx->buf_len || !ctx->final_used) {
-                       EVPerror(EVP_R_WRONG_FINAL_BLOCK_LENGTH);
-                       return (0);
-               }
-               if (b > sizeof ctx->final) {
-                       EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-                       return 0;
-               }
-               n = ctx->final[b - 1];
-               if (n == 0 || n > (int)b) {
+
+       if (block_size == 1)
+               return 1;
+
+       if (buf_offset != 0 || !ctx->final_used) {
+               EVPerror(EVP_R_WRONG_FINAL_BLOCK_LENGTH);
+               return 0;
+       }
+
+       if (block_size > sizeof(ctx->final)) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+
+       pad = ctx->final[block_size - 1];
+       if (pad <= 0 || pad > block_size) {
+               EVPerror(EVP_R_BAD_DECRYPT);
+               return 0;
+       }
+       plain_len = block_size - pad;
+       for (i = plain_len; i < block_size; i++) {
+               if (ctx->final[i] != pad) {
                        EVPerror(EVP_R_BAD_DECRYPT);
-                       return (0);
-               }
-               for (i = 0; i < n; i++) {
-                       if (ctx->final[--b] != n) {
-                               EVPerror(EVP_R_BAD_DECRYPT);
-                               return (0);
-                       }
+                       return 0;
                }
-               n = ctx->cipher->block_size - n;
-               for (i = 0; i < n; i++)
-                       out[i] = ctx->final[i];
-               *outl = n;
-       } else
-               *outl = 0;
-       return (1);
+       }
+
+       memcpy(out, ctx->final, plain_len);
+       *outl = plain_len;
+
+       return 1;
 }
 
 EVP_CIPHER_CTX *