Skip to content

Commit

Permalink
HPCC-31123 Fix regression in roxie AES encryption using openSSL
Browse files Browse the repository at this point in the history
Signed-off-by: Gavin Halliday <[email protected]>
  • Loading branch information
ghalliday committed Jan 15, 2024
1 parent 1d8e100 commit 0926a64
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
8 changes: 5 additions & 3 deletions system/jlib/jencrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1870,7 +1870,8 @@ MemoryBuffer &aesEncrypt(const void *key, size_t keylen, const void *plaintext,
encryptError("Unsupported key length");
break;
}
byte *ciphertext = (byte *) output.reserve(plaintext_len + 100);
unsigned originalLen = output.length();
byte *ciphertext = (byte *) output.reserve(plaintext_len + 16);
int ciphertext_len = 0;
int thislen = 0;
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &thislen, (const unsigned char *) plaintext, plaintext_len))
Expand All @@ -1880,7 +1881,7 @@ MemoryBuffer &aesEncrypt(const void *key, size_t keylen, const void *plaintext,
encryptError("Error in EVP_EncryptFinal_ex");
ciphertext_len += thislen;
EVP_CIPHER_CTX_free(ctx);
output.setLength(ciphertext_len);
output.setLength(originalLen + ciphertext_len);
return output;
}
catch (...)
Expand Down Expand Up @@ -1928,6 +1929,7 @@ MemoryBuffer &aesDecrypt(const void *key, size_t keylen, const void *ciphertext,
decryptError("Unsupported key length");
break;
}
unsigned originalLen = output.length();
byte *plaintext = (byte *) output.reserve(ciphertext_len);
if(1 != EVP_DecryptUpdate(ctx, plaintext, &thislen, (const unsigned char *) ciphertext, ciphertext_len))
decryptError("Error in EVP_DecryptUpdate");
Expand All @@ -1936,7 +1938,7 @@ MemoryBuffer &aesDecrypt(const void *key, size_t keylen, const void *ciphertext,
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + plaintext_len, &thislen))
decryptError("Error in EVP_DecryptFinal_ex");
plaintext_len += thislen;
output.setLength(plaintext_len);
output.setLength(originalLen + plaintext_len);
EVP_CIPHER_CTX_free(ctx);
return output;
}
Expand Down
60 changes: 41 additions & 19 deletions testing/unittests/jlibtests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3778,49 +3778,71 @@ class JLibOpensslAESTest : public CppUnit::TestFixture
0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31
};
constexpr const char * prefix = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
constexpr unsigned lenPrefix = strlen(prefix);

MemoryBuffer ciphertext1, ciphertext2, decrypted1, decrypted2;

ciphertext1.append(lenPrefix, prefix);
ciphertext2.append(lenPrefix, prefix);
openssl::aesEncrypt(key, 32, intext, len, ciphertext1);
jlib::aesEncrypt(key, 32, intext, len, ciphertext2);

CPPUNIT_ASSERT(memcmp(ciphertext1.bytes(), prefix, lenPrefix) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext2.bytes(), prefix, lenPrefix) == 0);
if (len)
CPPUNIT_ASSERT(ciphertext1.length() > len + lenPrefix);
else
CPPUNIT_ASSERT(ciphertext1.length() == len + lenPrefix);
CPPUNIT_ASSERT(ciphertext1.length() <= len + lenPrefix + 16);
CPPUNIT_ASSERT(ciphertext1.length()==ciphertext2.length());
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes(), ciphertext2.bytes(), ciphertext1.length()) == 0);

unsigned cipherlen = ciphertext1.length() - lenPrefix;

/* Decrypt the ciphertext */
openssl::aesDecrypt(key, 32, ciphertext1.bytes(), ciphertext1.length(), decrypted1);
assert(decrypted1.length() == len);
CPPUNIT_ASSERT(decrypted1.length() == len);
CPPUNIT_ASSERT(memcmp(decrypted1.bytes(), intext, len) == 0);
decrypted1.append(lenPrefix, prefix);
openssl::aesDecrypt(key, 32, ciphertext1.bytes()+lenPrefix, cipherlen, decrypted1);
CPPUNIT_ASSERT(decrypted1.length() == len+lenPrefix);
CPPUNIT_ASSERT(memcmp(decrypted1.bytes(), prefix, lenPrefix) == 0);
CPPUNIT_ASSERT(memcmp(decrypted1.bytes()+lenPrefix, intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes(), ciphertext2.bytes(), ciphertext1.length()) == 0); // check input unchanged

jlib::aesDecrypt(key, 32, ciphertext2.bytes(), ciphertext2.length(), decrypted2);
CPPUNIT_ASSERT(decrypted2.length() == len);
CPPUNIT_ASSERT(memcmp(decrypted2.bytes(), intext, len) == 0);
decrypted2.append(lenPrefix, prefix);
jlib::aesDecrypt(key, 32, ciphertext2.bytes()+lenPrefix, cipherlen, decrypted2);
CPPUNIT_ASSERT(memcmp(decrypted2.bytes(), prefix, lenPrefix) == 0);
CPPUNIT_ASSERT(decrypted2.length() == len + lenPrefix);
CPPUNIT_ASSERT(memcmp(decrypted2.bytes() + lenPrefix, intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes(), ciphertext2.bytes(), ciphertext1.length()) == 0); // check input unchanged

// Now test in-place decrypt
unsigned cipherlen = ciphertext1.length();
ciphertext1.append(4, "XXXX"); // Marker
unsigned decryptedlen = openssl::aesDecryptInPlace(key, 32, (void *) ciphertext1.bytes(), cipherlen);
unsigned decryptedlen = openssl::aesDecryptInPlace(key, 32, (void *)(ciphertext1.bytes() + lenPrefix), cipherlen);
CPPUNIT_ASSERT(decryptedlen == len);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes(), intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes()+cipherlen, "XXXX", 4) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes()+lenPrefix, intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext1.bytes()+lenPrefix+cipherlen, "XXXX", 4) == 0);

cipherlen = ciphertext2.length();
ciphertext2.append(4, "XXXX"); // Marker
decryptedlen = jlib::aesDecryptInPlace(key, 32, (void *) ciphertext2.bytes(), cipherlen);
decryptedlen = jlib::aesDecryptInPlace(key, 32, (void *)(ciphertext2.bytes() + lenPrefix), cipherlen);
CPPUNIT_ASSERT(decryptedlen == len);
CPPUNIT_ASSERT(memcmp(ciphertext2.bytes(), intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext2.bytes()+cipherlen, "XXXX", 4) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext2.bytes()+lenPrefix, intext, len) == 0);
CPPUNIT_ASSERT(memcmp(ciphertext2.bytes()+lenPrefix+cipherlen, "XXXX", 4) == 0);
}

void test()
{
/* Message to be encrypted */
const char *plaintext = "The quick brown fox jumps over the lazy dog";
for (unsigned l = 0; l < strlen(plaintext); l++)
testOne(l, plaintext);
try
{
/* Message to be encrypted */
const char *plaintext = "The quick brown fox jumps over the lazy dog";
for (unsigned l = 0; l < strlen(plaintext); l++)
testOne(l, plaintext);
}
catch (IException * e)
{
EXCLOG(e, "Exception in AES unit test");
throw;
}
}

};
Expand Down

0 comments on commit 0926a64

Please sign in to comment.