Skip to content

Commit 4befacf

Browse files
committed
use the aes block size to size the aes_encrypt output buffer
1 parent 1f3f40f commit 4befacf

2 files changed

Lines changed: 42 additions & 12 deletions

File tree

cpp/src/gandiva/gdv_function_stubs.cc

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ extern "C" {
4444

4545
ARROW_SUPPRESS_MISSING_DECLARATIONS_WARNING
4646

47+
// AES operates on 16 byte blocks for every supported key length.
48+
static constexpr int64_t kAesBlockSize = 16;
49+
4750
static char mask_array[256] = {
4851
(char)0, (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7,
4952
(char)8, (char)9, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15,
@@ -361,19 +364,16 @@ const char* gdv_fn_aes_encrypt(int64_t context, const char* data, int32_t data_l
361364
return "";
362365
}
363366

364-
int64_t kAesBlockSize = 0;
365-
if (key_data_len == 16 || key_data_len == 24 || key_data_len == 32) {
366-
kAesBlockSize = static_cast<int64_t>(key_data_len);
367-
} else {
367+
if (key_data_len != 16 && key_data_len != 24 && key_data_len != 32) {
368368
std::ostringstream oss;
369369
oss << "invalid key length: " << key_data_len;
370370
gdv_fn_context_set_error_msg(context, oss.str().c_str());
371371
*out_len = 0;
372372
return nullptr;
373373
}
374374

375-
*out_len =
376-
static_cast<int32_t>(arrow::bit_util::RoundUpToPowerOf2(data_len, kAesBlockSize));
375+
*out_len = static_cast<int32_t>(
376+
arrow::bit_util::RoundUpToPowerOf2(data_len, kAesBlockSize) + kAesBlockSize);
377377
char* ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, *out_len));
378378
if (ret == nullptr) {
379379
std::string err_msg = "AES_ENCRYPT: could not allocate memory for ciphertext output";
@@ -407,19 +407,16 @@ const char* gdv_fn_aes_decrypt(int64_t context, const char* data, int32_t data_l
407407
return "";
408408
}
409409

410-
int64_t kAesBlockSize = 0;
411-
if (key_data_len == 16 || key_data_len == 24 || key_data_len == 32) {
412-
kAesBlockSize = static_cast<int64_t>(key_data_len);
413-
} else {
410+
if (key_data_len != 16 && key_data_len != 24 && key_data_len != 32) {
414411
std::ostringstream oss;
415412
oss << "invalid key length: " << key_data_len;
416413
gdv_fn_context_set_error_msg(context, oss.str().c_str());
417414
*out_len = 0;
418415
return nullptr;
419416
}
420417

421-
*out_len =
422-
static_cast<int32_t>(arrow::bit_util::RoundUpToPowerOf2(data_len, kAesBlockSize));
418+
*out_len = static_cast<int32_t>(
419+
arrow::bit_util::RoundUpToPowerOf2(data_len, kAesBlockSize) + kAesBlockSize);
423420
char* ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, *out_len));
424421
if (ret == nullptr) {
425422
std::string err_msg = "Could not allocate memory for returning aes decrypt plaintext";

cpp/src/gandiva/gdv_function_stubs_test.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,4 +1584,37 @@ TEST(TestGdvFnStubs, TestAesEncryptDecryptValidation) {
15841584
EXPECT_THAT(ctx.get_error(), ::testing::HasSubstr("invalid key length"));
15851585
ctx.Reset();
15861586
}
1587+
1588+
TEST(TestGdvFnStubs, TestAesEncryptBlockAlignedInput) {
1589+
gandiva::ExecutionContext ctx;
1590+
std::string key16 = "12345678abcdefgh";
1591+
auto key16_len = static_cast<int32_t>(key16.length());
1592+
int64_t ctx_ptr = reinterpret_cast<int64_t>(&ctx);
1593+
1594+
// A block-aligned input still gets a whole block of padding appended, so the
1595+
// ciphertext is one block longer than the input. Encrypting twice from the same
1596+
// context makes an undersized output buffer observable, because the second
1597+
// ciphertext lands on top of the first one.
1598+
std::string first = "aaaaaaaaaaaaaaaa";
1599+
std::string second = "bbbbbbbbbbbbbbbb";
1600+
auto first_len = static_cast<int32_t>(first.length());
1601+
auto second_len = static_cast<int32_t>(second.length());
1602+
1603+
int32_t first_cipher_len = 0;
1604+
const char* first_cipher = gdv_fn_aes_encrypt(
1605+
ctx_ptr, first.c_str(), first_len, key16.c_str(), key16_len, &first_cipher_len);
1606+
ASSERT_FALSE(ctx.has_error());
1607+
EXPECT_EQ(first_cipher_len, first_len + 16);
1608+
1609+
int32_t second_cipher_len = 0;
1610+
gdv_fn_aes_encrypt(ctx_ptr, second.c_str(), second_len, key16.c_str(), key16_len,
1611+
&second_cipher_len);
1612+
ASSERT_FALSE(ctx.has_error());
1613+
1614+
int32_t decrypted_len = 0;
1615+
const char* decrypted = gdv_fn_aes_decrypt(ctx_ptr, first_cipher, first_cipher_len,
1616+
key16.c_str(), key16_len, &decrypted_len);
1617+
ASSERT_FALSE(ctx.has_error());
1618+
EXPECT_EQ(first, std::string(decrypted, decrypted_len));
1619+
}
15871620
} // namespace gandiva

0 commit comments

Comments
 (0)