@@ -275,6 +275,17 @@ class FunctionEncrypt : public IFunction
275275 const auto block_size = static_cast <size_t >(EVP_CIPHER_block_size (evp_cipher));
276276 const auto key_size = static_cast <size_t >(EVP_CIPHER_key_length (evp_cipher));
277277 [[maybe_unused]] const auto iv_size = static_cast <size_t >(EVP_CIPHER_iv_length (evp_cipher));
278+ std::string zero_iv_buffer;
279+ auto getIVPtr = [&](const StringRef & iv_value) -> const unsigned char *
280+ {
281+ if (iv_size > 0 && iv_value.size == 0 )
282+ {
283+ if (zero_iv_buffer.size () != iv_size)
284+ zero_iv_buffer.assign (iv_size, ' \0 ' );
285+ return reinterpret_cast <const unsigned char *>(zero_iv_buffer.data ());
286+ }
287+ return reinterpret_cast <const unsigned char *>(iv_value.data );
288+ };
278289 const auto tag_size = 16 ; // https://tools.ietf.org/html/rfc5116#section-5.1
279290
280291 auto encrypted_result_column = ColumnString::create ();
@@ -341,7 +352,7 @@ class FunctionEncrypt : public IFunction
341352 {
342353 if (EVP_EncryptInit_ex (evp_ctx, evp_cipher, nullptr ,
343354 reinterpret_cast <const unsigned char *>(const_key_value.data ),
344- reinterpret_cast < const unsigned char *> (const_iv_value. data )) != 1 )
355+ getIVPtr (const_iv_value)) != 1 )
345356 onError (" EVP_EncryptInit_ex" );
346357 }
347358 }
@@ -358,7 +369,7 @@ class FunctionEncrypt : public IFunction
358369
359370 // / Reset context to the fresh state but keep the already prepared key schedule.
360371 if (row_idx != 0 && EVP_EncryptInit_ex (evp_ctx, nullptr , nullptr , nullptr ,
361- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
372+ getIVPtr (iv_value)) != 1 )
362373 onError (" EVP_EncryptInit_ex" );
363374 }
364375 else if (can_reuse_gcm_key)
@@ -395,7 +406,7 @@ class FunctionEncrypt : public IFunction
395406 validateIV<mode>(iv_value, iv_size);
396407
397408 if (EVP_EncryptInit_ex (evp_ctx, nullptr , nullptr , nullptr ,
398- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
409+ getIVPtr (iv_value)) != 1 )
399410 onError (" EVP_EncryptInit_ex" );
400411 }
401412 else
@@ -435,17 +446,17 @@ class FunctionEncrypt : public IFunction
435446 // 1: Init CTX
436447 if constexpr (mode == CipherMode::RFC5116_AEAD_AES_GCM)
437448 {
438- // 1.a.1: Init CTX with custom IV length
439- if (EVP_EncryptInit_ex (evp_ctx, evp_cipher, nullptr , nullptr , nullptr ) != 1 )
440- onError (" EVP_EncryptInit_ex" );
449+ // 1.a.1: Init CTX with custom IV length
450+ if (EVP_EncryptInit_ex (evp_ctx, evp_cipher, nullptr , nullptr , nullptr ) != 1 )
451+ onError (" EVP_EncryptInit_ex" );
441452
442- if (EVP_CIPHER_CTX_ctrl (evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, safe_cast<int >(iv_value.size ), nullptr ) != 1 )
443- onError (" EVP_CIPHER_CTX_ctrl" );
453+ if (EVP_CIPHER_CTX_ctrl (evp_ctx, EVP_CTRL_AEAD_SET_IVLEN, safe_cast<int >(iv_value.size ), nullptr ) != 1 )
454+ onError (" EVP_CIPHER_CTX_ctrl" );
444455
445- if (EVP_EncryptInit_ex (evp_ctx, nullptr , nullptr ,
446- reinterpret_cast <const unsigned char *>(key_value.data ),
447- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
448- onError (" EVP_EncryptInit_ex" );
456+ if (EVP_EncryptInit_ex (evp_ctx, nullptr , nullptr ,
457+ reinterpret_cast <const unsigned char *>(key_value.data ),
458+ getIVPtr (iv_value)) != 1 )
459+ onError (" EVP_EncryptInit_ex" );
449460 }
450461 else
451462 {
@@ -454,7 +465,7 @@ class FunctionEncrypt : public IFunction
454465
455466 if (EVP_EncryptInit_ex (evp_ctx, evp_cipher, nullptr ,
456467 reinterpret_cast <const unsigned char *>(key_value.data ),
457- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
468+ getIVPtr (iv_value)) != 1 )
458469 onError (" EVP_EncryptInit_ex" );
459470 }
460471 }
@@ -651,6 +662,17 @@ class FunctionDecrypt : public IFunction
651662
652663 [[maybe_unused]] const auto block_size = static_cast <size_t >(EVP_CIPHER_block_size (evp_cipher));
653664 [[maybe_unused]] const auto iv_size = static_cast <size_t >(EVP_CIPHER_iv_length (evp_cipher));
665+ std::string zero_iv_buffer;
666+ auto getIVPtr = [&](const StringRef & iv_value) -> const unsigned char *
667+ {
668+ if (iv_size > 0 && iv_value.size == 0 )
669+ {
670+ if (zero_iv_buffer.size () != iv_size)
671+ zero_iv_buffer.assign (iv_size, ' \0 ' );
672+ return reinterpret_cast <const unsigned char *>(zero_iv_buffer.data ());
673+ }
674+ return reinterpret_cast <const unsigned char *>(iv_value.data );
675+ };
654676
655677 const size_t key_size = static_cast <size_t >(EVP_CIPHER_key_length (evp_cipher));
656678 static constexpr size_t tag_size = 16 ; // https://tools.ietf.org/html/rfc5116#section-5.1
@@ -726,7 +748,7 @@ class FunctionDecrypt : public IFunction
726748 {
727749 if (EVP_DecryptInit_ex (evp_ctx, evp_cipher, nullptr ,
728750 reinterpret_cast <const unsigned char *>(const_key_value.data ),
729- reinterpret_cast < const unsigned char *> (const_iv_value. data )) != 1 )
751+ getIVPtr (const_iv_value)) != 1 )
730752 onError (" EVP_DecryptInit_ex" );
731753 }
732754 }
@@ -744,7 +766,7 @@ class FunctionDecrypt : public IFunction
744766
745767 // / Reset context but keep already computed key schedule.
746768 if (row_idx != 0 && EVP_DecryptInit_ex (evp_ctx, nullptr , nullptr , nullptr ,
747- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
769+ getIVPtr (iv_value)) != 1 )
748770 onError (" EVP_DecryptInit_ex" );
749771 }
750772 else if (can_reuse_gcm_key)
@@ -766,7 +788,7 @@ class FunctionDecrypt : public IFunction
766788 onError (" EVP_CIPHER_CTX_ctrl" );
767789
768790 if (EVP_DecryptInit_ex (evp_ctx, nullptr , nullptr , nullptr ,
769- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
791+ getIVPtr (iv_value)) != 1 )
770792 onError (" EVP_DecryptInit_ex" );
771793 }
772794 else if (can_reuse_key_schedule)
@@ -784,7 +806,7 @@ class FunctionDecrypt : public IFunction
784806 validateIV<mode>(iv_value, iv_size);
785807
786808 if (EVP_DecryptInit_ex (evp_ctx, nullptr , nullptr , nullptr ,
787- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
809+ getIVPtr (iv_value)) != 1 )
788810 onError (" EVP_DecryptInit_ex" );
789811 }
790812 else
@@ -850,7 +872,7 @@ class FunctionDecrypt : public IFunction
850872 // 1.a.1 : Init CTX with key and IV
851873 if (EVP_DecryptInit_ex (evp_ctx, nullptr , nullptr ,
852874 reinterpret_cast <const unsigned char *>(key_value.data ),
853- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
875+ getIVPtr (iv_value)) != 1 )
854876 onError (" EVP_DecryptInit_ex" );
855877 }
856878 else
@@ -860,7 +882,7 @@ class FunctionDecrypt : public IFunction
860882
861883 if (EVP_DecryptInit_ex (evp_ctx, evp_cipher, nullptr ,
862884 reinterpret_cast <const unsigned char *>(key_value.data ),
863- reinterpret_cast < const unsigned char *> (iv_value. data )) != 1 )
885+ getIVPtr (iv_value)) != 1 )
864886 onError (" EVP_DecryptInit_ex" );
865887 }
866888 }
0 commit comments