From 22e8e99d4c0d7224b310ad978455c468f060f907 Mon Sep 17 00:00:00 2001 From: Praise-Garfield <260351813+Praise-Garfield@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:30:46 +0000 Subject: [PATCH] LibCrypto: Use EVP_EncryptInit instead of EVP_DecryptInit in GCM encrypt The first EVP initialization call in AESGCMCipher::encrypt() used EVP_DecryptInit. Every other cipher mode in the file correctly matches its init calls to the operation direction (CBC, CTR, OCB, KW). The second EVP_EncryptInit call overrides the context direction before any ciphertext is produced, but the EVP_CTRL_GCM_SET_IVLEN control call on the next line executes while the context is in decrypt mode. --- Libraries/LibCrypto/Cipher/AES.cpp | 2 +- Tests/LibCrypto/TestAES.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Libraries/LibCrypto/Cipher/AES.cpp b/Libraries/LibCrypto/Cipher/AES.cpp index ab28dd8ce2..bdb8545c3a 100644 --- a/Libraries/LibCrypto/Cipher/AES.cpp +++ b/Libraries/LibCrypto/Cipher/AES.cpp @@ -119,7 +119,7 @@ ErrorOr AESGCMCipher::encrypt(ReadonlyBytes plainte { auto ctx = TRY(OpenSSL_CIPHER_CTX::create()); - OPENSSL_TRY(EVP_DecryptInit(ctx.ptr(), m_cipher, nullptr, nullptr)); + OPENSSL_TRY(EVP_EncryptInit(ctx.ptr(), m_cipher, nullptr, nullptr)); OPENSSL_TRY(EVP_CIPHER_CTX_ctrl(ctx.ptr(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), nullptr)); OPENSSL_TRY(EVP_EncryptInit(ctx.ptr(), nullptr, m_key.data(), iv.data())); diff --git a/Tests/LibCrypto/TestAES.cpp b/Tests/LibCrypto/TestAES.cpp index 158d7a537c..5998986054 100644 --- a/Tests/LibCrypto/TestAES.cpp +++ b/Tests/LibCrypto/TestAES.cpp @@ -444,6 +444,22 @@ TEST_CASE(test_AES_GCM_128bit_encrypt_with_aad) EXPECT(memcmp(result_tag, tag.data(), tag.size()) == 0); } +TEST_CASE(test_AES_GCM_128bit_encrypt_decrypt_round_trip_with_non_standard_iv) +{ + Crypto::Cipher::AESGCMCipher cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b); + auto plaintext = "The quick brown fox jumps over the lazy dog!"_b; + // 16-byte IV (non-standard; default is 12) to exercise EVP_CTRL_GCM_SET_IVLEN. + auto iv = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"_b; + auto aad = "\xde\xad\xbe\xef"_b; + + auto [ciphertext, tag] = TRY_OR_FAIL(cipher.encrypt(plaintext, iv, aad, 16)); + EXPECT_NE(ciphertext.size(), 0u); + + auto decrypted = TRY_OR_FAIL(cipher.decrypt(ciphertext, iv, aad, tag)); + EXPECT_EQ(decrypted.size(), plaintext.size()); + EXPECT(memcmp(plaintext.data(), decrypted.data(), plaintext.size()) == 0); +} + TEST_CASE(test_AES_GCM_128bit_decrypt_empty) { Crypto::Cipher::AESGCMCipher cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b);