Improve length checks for oiv and iv
authortb <tb@openbsd.org>
Thu, 4 Jan 2024 09:47:54 +0000 (09:47 +0000)
committertb <tb@openbsd.org>
Thu, 4 Jan 2024 09:47:54 +0000 (09:47 +0000)
There are two unsigned char arrays of size EVP_MAX_IV_LENGTH to store the
IVs of block ciphers. In most modes, only iv is used, but in some modes iv
is modified and oiv is used to store the original IV. At the moment nothing
enforces that they are of the same length. Therefore make sure the correct
one or both are checked before writing to or reading from them.

ok miod

lib/libcrypto/evp/evp_cipher.c

index c3e2cd4..81e3f63 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: evp_cipher.c,v 1.14 2024/01/03 09:13:32 tb Exp $ */
+/* $OpenBSD: evp_cipher.c,v 1.15 2024/01/04 09:47:54 tb Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -204,7 +204,8 @@ EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
 
                case EVP_CIPH_CBC_MODE:
                        iv_len = EVP_CIPHER_CTX_iv_length(ctx);
-                       if (iv_len < 0 || iv_len > sizeof(ctx->oiv)) {
+                       if (iv_len < 0 || iv_len > sizeof(ctx->oiv) ||
+                           iv_len > sizeof(ctx->iv)) {
                                EVPerror(EVP_R_IV_TOO_LARGE);
                                return 0;
                        }
@@ -906,7 +907,7 @@ EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
 
        if (type != NULL) {
                l = EVP_CIPHER_CTX_iv_length(ctx);
-               if (l < 0 || l > sizeof(ctx->iv)) {
+               if (l < 0 || l > sizeof(ctx->oiv) || l > sizeof(ctx->iv)) {
                        EVPerror(EVP_R_IV_TOO_LARGE);
                        return 0;
                }
@@ -939,7 +940,7 @@ EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
 
        if (type != NULL) {
                j = EVP_CIPHER_CTX_iv_length(ctx);
-               if (j < 0 || j > sizeof(ctx->iv)) {
+               if (j < 0 || j > sizeof(ctx->oiv)) {
                        EVPerror(EVP_R_IV_TOO_LARGE);
                        return 0;
                }