apache / apache/arrow

[C++][Gandiva] Heap buffer overflow in aes_encrypt output buffer sizing

Open
#50,522 0 comments 0 reactions 1 assignee Claimed by @Arawoof06 View on GitHub
Dominant language
C++
Stars
17.1k
Forks
4.3k
Avg merge
3d 13h
Merged PRs (30d)
88

Description

### Describe the bug, including details regarding any error messages, version, and platform.

`gdv_fn_aes_encrypt` sizes its output buffer with `RoundUpToPowerOf2(data_len, key_data_len)`, using the key length as the AES block size. Two things are wrong with that.

AES always operates on 16 byte blocks, whatever the key length is, so the rounding factor should be 16. A 24 byte key also makes `RoundUpToPowerOf2` round to a factor that is not a power of two, which its contract requires, so the result can come out below `data_len`.

Separately, PKCS#7 padding always appends a whole block, so a block aligned input produces a ciphertext one block longer than the input. When `data_len` is already a multiple of 16 the buffer is 16 bytes short and `EVP_EncryptFinal_ex` writes past the end of it.

Measured against the current sizing:

| key | data_len | allocated | actual ciphertext |
|-----|----------|-----------|-------------------|
| 16 | 16 | 16 | 32 |
| 16 | 8192 | 8192 | 8208 |
| 24 | 8 | 8 | 16 |
| 32 | 32 | 32 | 48 |

So `aes_encrypt(col, key)` over any 16/32/48/... byte value overruns the arena buffer by 16 bytes, and a 24 byte key with an 8 byte value overruns by 8. The write lands on whatever the arena hands out next, so the previous row's output gets corrupted; with a value larger than the arena chunk size it runs off the end of the chunk itself.

`gdv_fn_aes_decrypt` computes its size with the same expression.

### Component(s)

C++ - Gandiva

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.