diff --git a/cpp/src/gandiva/encrypt_mode_dispatcher.cc b/cpp/src/gandiva/encrypt_mode_dispatcher.cc index 1f63a96be68..fad1c54ba9f 100644 --- a/cpp/src/gandiva/encrypt_mode_dispatcher.cc +++ b/cpp/src/gandiva/encrypt_mode_dispatcher.cc @@ -67,12 +67,11 @@ int32_t EncryptModeDispatcher::encrypt( switch (ParseEncryptionMode(mode_str)) { case EncryptionMode::ECB: case EncryptionMode::ECB_PKCS7: - // Shorthand AES-ECB and explicit AES-ECB-PKCS7 both use ECB with PKCS7 - return aes_encrypt_ecb(plaintext, plaintext_len, key, key_len, cipher); + // Shorthand AES-ECB and explicit AES-ECB-PKCS7 both use ECB with PKCS7 padding + return aes_encrypt_ecb(plaintext, plaintext_len, key, key_len, true, cipher); case EncryptionMode::ECB_NONE: - // ECB mode doesn't use padding, but we still call the same function - // since ECB doesn't have padding options - return aes_encrypt_ecb(plaintext, plaintext_len, key, key_len, cipher); + // ECB without padding + return aes_encrypt_ecb(plaintext, plaintext_len, key, key_len, false, cipher); case EncryptionMode::CBC: case EncryptionMode::CBC_PKCS7: // Shorthand AES-CBC and explicit AES-CBC-PKCS7 both use CBC with PKCS7 @@ -107,12 +106,11 @@ int32_t EncryptModeDispatcher::decrypt( switch (ParseEncryptionMode(mode_str)) { case EncryptionMode::ECB: case EncryptionMode::ECB_PKCS7: - // Shorthand AES-ECB and explicit AES-ECB-PKCS7 both use ECB with PKCS7 - return aes_decrypt_ecb(ciphertext, ciphertext_len, key, key_len, plaintext); + // Shorthand AES-ECB and explicit AES-ECB-PKCS7 both use ECB with PKCS7 padding + return aes_decrypt_ecb(ciphertext, ciphertext_len, key, key_len, true, plaintext); case EncryptionMode::ECB_NONE: - // ECB mode doesn't use padding, but we still call the same function - // since ECB doesn't have padding options - return aes_decrypt_ecb(ciphertext, ciphertext_len, key, key_len, plaintext); + // ECB without padding + return aes_decrypt_ecb(ciphertext, ciphertext_len, key, key_len, false, plaintext); case EncryptionMode::CBC: case EncryptionMode::CBC_PKCS7: // Shorthand AES-CBC and explicit AES-CBC-PKCS7 both use CBC with PKCS7 diff --git a/cpp/src/gandiva/encrypt_utils_ecb.cc b/cpp/src/gandiva/encrypt_utils_ecb.cc index 5cc13f335a7..b4913e1c880 100644 --- a/cpp/src/gandiva/encrypt_utils_ecb.cc +++ b/cpp/src/gandiva/encrypt_utils_ecb.cc @@ -48,7 +48,7 @@ const EVP_CIPHER* get_ecb_cipher_algo(int32_t key_length) { GANDIVA_EXPORT int32_t aes_encrypt_ecb(const char* plaintext, int32_t plaintext_len, const char* key, - int32_t key_len, unsigned char* cipher) { + int32_t key_len, bool use_padding, unsigned char* cipher) { int32_t cipher_len = 0; int32_t len = 0; EVP_CIPHER_CTX* en_ctx = EVP_CIPHER_CTX_new(); @@ -66,6 +66,13 @@ int32_t aes_encrypt_ecb(const char* plaintext, int32_t plaintext_len, const char get_openssl_error_string()); } + int padding_flag = use_padding ? 1 : 0; + if (!EVP_CIPHER_CTX_set_padding(en_ctx, padding_flag)) { + EVP_CIPHER_CTX_free(en_ctx); + throw std::runtime_error("Could not set padding mode for encryption: " + + get_openssl_error_string()); + } + if (!EVP_EncryptUpdate(en_ctx, cipher, &len, reinterpret_cast(plaintext), plaintext_len)) { @@ -90,7 +97,7 @@ int32_t aes_encrypt_ecb(const char* plaintext, int32_t plaintext_len, const char GANDIVA_EXPORT int32_t aes_decrypt_ecb(const char* ciphertext, int32_t ciphertext_len, const char* key, - int32_t key_len, unsigned char* plaintext) { + int32_t key_len, bool use_padding, unsigned char* plaintext) { int32_t plaintext_len = 0; int32_t len = 0; EVP_CIPHER_CTX* de_ctx = EVP_CIPHER_CTX_new(); @@ -108,6 +115,13 @@ int32_t aes_decrypt_ecb(const char* ciphertext, int32_t ciphertext_len, const ch get_openssl_error_string()); } + int padding_flag = use_padding ? 1 : 0; + if (!EVP_CIPHER_CTX_set_padding(de_ctx, padding_flag)) { + EVP_CIPHER_CTX_free(de_ctx); + throw std::runtime_error("Could not set padding mode for decryption: " + + get_openssl_error_string()); + } + if (!EVP_DecryptUpdate(de_ctx, plaintext, &len, reinterpret_cast(ciphertext), ciphertext_len)) { diff --git a/cpp/src/gandiva/encrypt_utils_ecb.h b/cpp/src/gandiva/encrypt_utils_ecb.h index f8a44632e80..ba62bf3bea9 100644 --- a/cpp/src/gandiva/encrypt_utils_ecb.h +++ b/cpp/src/gandiva/encrypt_utils_ecb.h @@ -38,13 +38,14 @@ constexpr const char* AES_ECB_NONE_MODE = "AES-ECB-NONE"; * @param plaintext_len Length of plaintext in bytes * @param key The encryption key (16, 24, or 32 bytes for 128, 192, 256-bit keys) * @param key_len Length of key in bytes + * @param use_padding Whether to use PKCS7 padding (true) or no padding (false) * @param cipher Output buffer for encrypted data * @return Length of encrypted data in bytes * @throws std::runtime_error on encryption failure */ GANDIVA_EXPORT int32_t aes_encrypt_ecb(const char* plaintext, int32_t plaintext_len, const char* key, - int32_t key_len, unsigned char* cipher); + int32_t key_len, bool use_padding, unsigned char* cipher); /** * Decrypt data using AES-ECB algorithm (legacy, insecure) @@ -56,13 +57,14 @@ int32_t aes_encrypt_ecb(const char* plaintext, int32_t plaintext_len, const char * @param ciphertext_len Length of ciphertext in bytes * @param key The decryption key (16, 24, or 32 bytes for 128, 192, 256-bit keys) * @param key_len Length of key in bytes + * @param use_padding Whether to use PKCS7 padding (true) or no padding (false) * @param plaintext Output buffer for decrypted data * @return Length of decrypted data in bytes * @throws std::runtime_error on decryption failure */ GANDIVA_EXPORT int32_t aes_decrypt_ecb(const char* ciphertext, int32_t ciphertext_len, const char* key, - int32_t key_len, unsigned char* plaintext); + int32_t key_len, bool use_padding, unsigned char* plaintext); } // namespace gandiva diff --git a/cpp/src/gandiva/encrypt_utils_ecb_test.cc b/cpp/src/gandiva/encrypt_utils_ecb_test.cc index d8983e947c1..52687a8a4a9 100644 --- a/cpp/src/gandiva/encrypt_utils_ecb_test.cc +++ b/cpp/src/gandiva/encrypt_utils_ecb_test.cc @@ -30,11 +30,11 @@ TEST(TestAesEcbEncryptUtils, TestAesEncryptDecrypt) { static_cast(strlen(reinterpret_cast(to_encrypt))); unsigned char cipher_1[64]; - int32_t cipher_1_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, cipher_1); + int32_t cipher_1_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, true, cipher_1); unsigned char decrypted_1[64]; int32_t decrypted_1_len = gandiva::aes_decrypt_ecb(reinterpret_cast(cipher_1), - cipher_1_len, key, key_len, decrypted_1); + cipher_1_len, key, key_len, true, decrypted_1); EXPECT_EQ(std::string(reinterpret_cast(to_encrypt), to_encrypt_len), std::string(reinterpret_cast(decrypted_1), decrypted_1_len)); @@ -48,11 +48,11 @@ TEST(TestAesEcbEncryptUtils, TestAesEncryptDecrypt) { static_cast(strlen(reinterpret_cast(to_encrypt))); unsigned char cipher_2[64]; - int32_t cipher_2_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, cipher_2); + int32_t cipher_2_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, true, cipher_2); unsigned char decrypted_2[64]; int32_t decrypted_2_len = gandiva::aes_decrypt_ecb(reinterpret_cast(cipher_2), - cipher_2_len, key, key_len, decrypted_2); + cipher_2_len, key, key_len, true, decrypted_2); EXPECT_EQ(std::string(reinterpret_cast(to_encrypt), to_encrypt_len), std::string(reinterpret_cast(decrypted_2), decrypted_2_len)); @@ -66,11 +66,11 @@ TEST(TestAesEcbEncryptUtils, TestAesEncryptDecrypt) { static_cast(strlen(reinterpret_cast(to_encrypt))); unsigned char cipher_3[64]; - int32_t cipher_3_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, cipher_3); + int32_t cipher_3_len = gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, true, cipher_3); unsigned char decrypted_3[64]; int32_t decrypted_3_len = gandiva::aes_decrypt_ecb(reinterpret_cast(cipher_3), - cipher_3_len, key, key_len, decrypted_3); + cipher_3_len, key, key_len, true, decrypted_3); EXPECT_EQ(std::string(reinterpret_cast(to_encrypt), to_encrypt_len), std::string(reinterpret_cast(decrypted_3), decrypted_3_len)); @@ -88,11 +88,11 @@ TEST(TestAesEcbEncryptUtils, TestAesEncryptDecrypt) { static_cast(strlen(reinterpret_cast(to_encrypt))); unsigned char cipher_4[64]; ASSERT_THROW({ - gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, cipher_4); + gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, true, cipher_4); }, std::runtime_error); ASSERT_THROW({ - gandiva::aes_decrypt_ecb(cipher, cipher_len, key, key_len, plain_text); + gandiva::aes_decrypt_ecb(cipher, cipher_len, key, key_len, true, plain_text); }, std::runtime_error); key = "12345678"; @@ -103,10 +103,10 @@ TEST(TestAesEcbEncryptUtils, TestAesEncryptDecrypt) { static_cast(strlen(reinterpret_cast(to_encrypt))); unsigned char cipher_5[64]; ASSERT_THROW({ - gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, cipher_5); + gandiva::aes_encrypt_ecb(to_encrypt, to_encrypt_len, key, key_len, true, cipher_5); }, std::runtime_error); ASSERT_THROW({ - gandiva::aes_decrypt_ecb(cipher, cipher_len, key, key_len, plain_text); + gandiva::aes_decrypt_ecb(cipher, cipher_len, key, key_len, true, plain_text); }, std::runtime_error); }