Commit 134342e194 for openssl.org

commit 134342e194a23b1d3cc0687b05d97cfdd0f31c4a
Author: OwenSanzas <zesheng@tamu.edu>
Date:   Tue Mar 10 00:05:35 2026 +0000

    Fix stack buffer over-read in DES OFB/CFB64 via unchecked num parameter

    The `num` parameter in DES OFB64/CFB64 functions tracks the byte offset
    within an 8-byte DES block, so valid values are 0-7. However, neither
    the EVP set_params path nor the low-level DES functions validated this
    bound, allowing an out-of-range `num` to cause a stack buffer over-read
    when used as an array index into the 8-byte keystream buffer.

    Fix at two levels:
    1. Provider layer: reject num >= blocksize in
       ossl_cipher_common_set_ctx_params() before it reaches the cipher.
    2. Low-level DES: mask `*num` with `& 0x07` on entry to
       DES_ofb64_encrypt, DES_ede3_ofb64_encrypt, DES_cfb64_encrypt,
       and DES_ede3_cfb64_encrypt, consistent with how `n` is already
       masked at the end of these functions before being written back.

    Fixes #30284

    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    MergeDate: Thu Mar 12 14:24:12 2026
    (Merged from https://github.com/openssl/openssl/pull/30332)

diff --git a/crypto/des/cfb64ede.c b/crypto/des/cfb64ede.c
index 26613a05fe..56aab27f0d 100644
--- a/crypto/des/cfb64ede.c
+++ b/crypto/des/cfb64ede.c
@@ -28,7 +28,7 @@ void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out,
 {
     register DES_LONG v0, v1;
     register long l = length;
-    register int n = *num;
+    register int n = *num & 0x07;
     DES_LONG ti[2];
     unsigned char *iv, c, cc;

diff --git a/crypto/des/cfb64enc.c b/crypto/des/cfb64enc.c
index 3ddd6819e2..b3abc12a25 100644
--- a/crypto/des/cfb64enc.c
+++ b/crypto/des/cfb64enc.c
@@ -27,7 +27,7 @@ void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out,
 {
     register DES_LONG v0, v1;
     register long l = length;
-    register int n = *num;
+    register int n = *num & 0x07;
     DES_LONG ti[2];
     unsigned char *iv, c, cc;

diff --git a/crypto/des/ofb64ede.c b/crypto/des/ofb64ede.c
index b0f9f0441c..17236d2195 100644
--- a/crypto/des/ofb64ede.c
+++ b/crypto/des/ofb64ede.c
@@ -26,7 +26,7 @@ void DES_ede3_ofb64_encrypt(register const unsigned char *in,
     DES_key_schedule *k3, DES_cblock *ivec, int *num)
 {
     register DES_LONG v0, v1;
-    register int n = *num;
+    register int n = *num & 0x07;
     register long l = length;
     DES_cblock d;
     register char *dp;
diff --git a/crypto/des/ofb64enc.c b/crypto/des/ofb64enc.c
index df4e2077e9..1426407423 100644
--- a/crypto/des/ofb64enc.c
+++ b/crypto/des/ofb64enc.c
@@ -25,7 +25,7 @@ void DES_ofb64_encrypt(register const unsigned char *in,
     DES_key_schedule *schedule, DES_cblock *ivec, int *num)
 {
     register DES_LONG v0, v1, t;
-    register int n = *num;
+    register int n = *num & 0x07;
     register long l = length;
     DES_cblock d;
     register unsigned char *dp;
diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c
index 9e6f386e02..36c3864c9a 100644
--- a/providers/implementations/ciphers/ciphercommon.c
+++ b/providers/implementations/ciphers/ciphercommon.c
@@ -650,6 +650,10 @@ int ossl_cipher_common_set_ctx_params(PROV_CIPHER_CTX *ctx, const struct ossl_ci
             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
             return 0;
         }
+        if (ctx->blocksize > 0 && num >= (unsigned int)ctx->blocksize) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
         ctx->num = num;
     }
     return 1;