]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: ssl/sample: check output buffer size in aes_cbc_enc converter
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 4 May 2026 15:34:13 +0000 (17:34 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Mon, 4 May 2026 15:38:15 +0000 (17:38 +0200)
AES-CBC uses a 16-byte block size, and PKCS padding always adds at least
one byte (up to a full 16 bytes when input is already block-aligned), so
the encrypted output is always larger than the input. Without checking
that the output buffer can hold the padded result, encryption could
overflow it. Add a pre-encryption guard for block cipher (blksize > 1)
that rejects the operation when the output buffer is too small.

No backport needed.

Reported-by: Omkhar Arasaratnam <omkhar@linkedin.com>
src/ssl_sample.c

index 7c10e43bed0278f5582f737a3c8cc58e8b369de2..f35dc9e18fa370552eccb8e9fce0e066ff02d964 100644 (file)
@@ -328,6 +328,7 @@ int aes_process(struct buffer *data, struct buffer *nonce, struct buffer *key, i
        EVP_CIPHER_CTX *ctx = NULL;
        int size;
        int ret;
+       size_t blksize;
 
        ctx = EVP_CIPHER_CTX_new();
 
@@ -376,6 +377,16 @@ int aes_process(struct buffer *data, struct buffer *nonce, struct buffer *key, i
                                 (unsigned char*)b_orig(nonce)))
                goto err;
 
+       blksize = EVP_CIPHER_CTX_block_size(ctx);
+       /* https://docs.openssl.org/3.0/man3/EVP_EncryptInit/#notes
+        * PKCS padding works by adding n padding bytes of value n to make the
+        * total length of the encrypted data a multiple of the block size.
+        * Padding is always added so if the data is already a multiple of the
+        * block size n will equal the block size.
+        */
+       if (!decrypt && blksize > 1 && (b_size(out) < (b_data(data) / blksize + 1) * blksize))
+               goto err;
+
        if (aad && b_data(aad)) {
                if (!sample_conv_aes_update(decrypt, ctx, NULL, (int*)&out->data,
                                            (unsigned char*)b_orig(aad), (int)b_data(aad)))