]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix stack buffer over-read in DES OFB/CFB64 via unchecked num parameter
authorOwenSanzas <zesheng@tamu.edu>
Tue, 10 Mar 2026 00:05:35 +0000 (00:05 +0000)
committerTomas Mraz <tomas@openssl.foundation>
Thu, 12 Mar 2026 14:24:31 +0000 (15:24 +0100)
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)

(cherry picked from commit 134342e194a23b1d3cc0687b05d97cfdd0f31c4a)

crypto/des/cfb64ede.c
crypto/des/cfb64enc.c
crypto/des/ofb64ede.c
crypto/des/ofb64enc.c
providers/implementations/ciphers/ciphercommon.c

index 26613a05fe8a46a707f96cd9175c9e2d3a27d057..56aab27f0dbbf8de71442be9fa8c27a867ed452e 100644 (file)
@@ -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;
 
index 3ddd6819e2ed8aeb0e0ada9ff4835220fb76f0ca..b3abc12a2539a971a97401f52cdcbaa9de9740c6 100644 (file)
@@ -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;
 
index b0f9f0441cfb799a221c08d6cc1e72819441c7b8..17236d219585a10d5f86445811c8b1eba3c1a2fb 100644 (file)
@@ -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;
index df4e2077e96cdc7e92dc67089f467a14f86b397f..1426407423f9a061e0c75ef1de233b7e7c80f4d0 100644 (file)
@@ -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;
index 9e6f386e02cf37bff8008bd886d31450505bfe86..36c3864c9afd2d40432e270be35e4212c9e12dd4 100644 (file)
@@ -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;