tdf#166241: add AES_192_CBC/AES_192_EBC
+ improve SALT management by taking the max between encryptedHashInput.size() and comphelper::roundUp(mInfo.saltSize, mInfo.blockSize) + add QA tests Change-Id: I90dce73928e0b204500ac659eb80cd1499a4f065 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184407 Tested-by: Jenkins Reviewed-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
@@ -185,4 +185,102 @@ CPPUNIT_TEST_FIXTURE(CryptoTest, testEncrypt_AES256_ECB)
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(CryptoTest, testEncrypt_AES192_CBC)
|
||||
{
|
||||
std::vector<sal_uInt8> key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22,
|
||||
0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32 };
|
||||
|
||||
std::vector<sal_uInt8> iv = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
|
||||
|
||||
std::vector<sal_uInt8> original = { 's', 'e', 'c', 'r', 'e', 't', '\0' };
|
||||
|
||||
std::vector<sal_uInt8> encrypted(original.size());
|
||||
|
||||
{
|
||||
sal_uInt32 nWrittenSize = 0;
|
||||
comphelper::Encrypt aEncryptor(key, iv, comphelper::CryptoType::AES_192_CBC);
|
||||
nWrittenSize = aEncryptor.update(encrypted, original);
|
||||
|
||||
// nothing should be written as the size of the input is not a multiple of block size
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), nWrittenSize);
|
||||
}
|
||||
|
||||
{
|
||||
sal_uInt32 nWrittenSize = 0;
|
||||
comphelper::Encrypt aEncryptor(key, iv, comphelper::CryptoType::AES_192_CBC);
|
||||
|
||||
original.resize(16, 0); // apply padding to make it multiple of block size
|
||||
encrypted.resize(16, 0);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("73656372657400000000000000000000"),
|
||||
comphelper::hashToString(original));
|
||||
|
||||
nWrittenSize = aEncryptor.update(encrypted, original);
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(16), nWrittenSize);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("e75cb91a34377c09c354c24fcef345a6"),
|
||||
comphelper::hashToString(encrypted));
|
||||
|
||||
std::vector<sal_uInt8> decrypted(encrypted.size(), 0);
|
||||
|
||||
comphelper::Decrypt aDecryptor(key, iv, comphelper::CryptoType::AES_192_CBC);
|
||||
nWrittenSize = aDecryptor.update(decrypted, encrypted);
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(16), nWrittenSize);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("73656372657400000000000000000000"),
|
||||
comphelper::hashToString(decrypted));
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(CryptoTest, testEncrypt_AES192_ECB)
|
||||
{
|
||||
std::vector<sal_uInt8> key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22,
|
||||
0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32 };
|
||||
|
||||
std::vector<sal_uInt8> iv = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
|
||||
|
||||
std::vector<sal_uInt8> original = { 's', 'e', 'c', 'r', 'e', 't', '\0' };
|
||||
|
||||
std::vector<sal_uInt8> encrypted(original.size());
|
||||
|
||||
{
|
||||
sal_uInt32 nWrittenSize = 0;
|
||||
comphelper::Encrypt aEncryptor(key, iv, comphelper::CryptoType::AES_192_ECB);
|
||||
nWrittenSize = aEncryptor.update(encrypted, original);
|
||||
|
||||
// nothing should be written as the size of the input is not a multiple of block size
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), nWrittenSize);
|
||||
}
|
||||
|
||||
{
|
||||
sal_uInt32 nWrittenSize = 0;
|
||||
comphelper::Encrypt aEncryptor(key, iv, comphelper::CryptoType::AES_192_ECB);
|
||||
|
||||
original.resize(16, 0); // apply padding to make it multiple of block size
|
||||
encrypted.resize(16, 0);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("73656372657400000000000000000000"),
|
||||
comphelper::hashToString(original));
|
||||
|
||||
nWrittenSize = aEncryptor.update(encrypted, original);
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(16), nWrittenSize);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("abf7abec9a6b58c089e902397c47ac49"),
|
||||
comphelper::hashToString(encrypted));
|
||||
|
||||
std::vector<sal_uInt8> decrypted(encrypted.size(), 0);
|
||||
|
||||
comphelper::Decrypt aDecryptor(key, iv, comphelper::CryptoType::AES_192_ECB);
|
||||
nWrittenSize = aDecryptor.update(decrypted, encrypted);
|
||||
CPPUNIT_ASSERT_EQUAL(sal_uInt32(16), nWrittenSize);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("73656372657400000000000000000000"),
|
||||
comphelper::hashToString(decrypted));
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@@ -169,13 +169,12 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
case CryptoType::AES_192_ECB:
|
||||
case CryptoType::AES_256_ECB:
|
||||
mechanism = CKM_AES_ECB;
|
||||
break;
|
||||
case CryptoType::AES_128_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
break;
|
||||
case CryptoType::AES_192_CBC:
|
||||
case CryptoType::AES_256_CBC:
|
||||
mechanism = CKM_AES_CBC;
|
||||
pIvItem = &ivItem;
|
||||
|
@@ -144,10 +144,14 @@ public:
|
||||
{
|
||||
case CryptoType::AES_128_ECB:
|
||||
return EVP_aes_128_ecb();
|
||||
case CryptoType::AES_192_ECB:
|
||||
return EVP_aes_192_ecb();
|
||||
case CryptoType::AES_256_ECB:
|
||||
return EVP_aes_256_ecb();
|
||||
case CryptoType::AES_128_CBC:
|
||||
return EVP_aes_128_cbc();
|
||||
case CryptoType::AES_192_CBC:
|
||||
return EVP_aes_192_cbc();
|
||||
case CryptoType::AES_256_CBC:
|
||||
return EVP_aes_256_cbc();
|
||||
default:
|
||||
|
@@ -46,6 +46,8 @@ enum class CryptoType
|
||||
UNKNOWN,
|
||||
AES_128_ECB,
|
||||
AES_128_CBC,
|
||||
AES_192_ECB,
|
||||
AES_192_CBC,
|
||||
AES_256_ECB,
|
||||
AES_256_CBC,
|
||||
};
|
||||
|
@@ -65,6 +65,7 @@ enum class AgileEncryptionPreset
|
||||
{
|
||||
AES_128_SHA1,
|
||||
AES_128_SHA384,
|
||||
AES_192_SHA384,
|
||||
AES_256_SHA512,
|
||||
};
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <oox/crypto/AgileEngine.hxx>
|
||||
|
||||
#include <oox/helper/binaryinputstream.hxx>
|
||||
@@ -238,6 +239,8 @@ comphelper::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo)
|
||||
{
|
||||
if (rInfo.keyBits == 128 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
|
||||
return comphelper::CryptoType::AES_128_CBC;
|
||||
else if (rInfo.keyBits == 192 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
|
||||
return comphelper::CryptoType::AES_192_CBC;
|
||||
else if (rInfo.keyBits == 256 && rInfo.cipherAlgorithm == "AES" && rInfo.cipherChaining == "ChainingModeCBC")
|
||||
return comphelper::CryptoType::AES_256_CBC;
|
||||
return comphelper::CryptoType::UNKNOWN;
|
||||
@@ -337,10 +340,7 @@ bool AgileEngine::decryptAndCheckVerifierHash(OUString const & rPassword)
|
||||
calculateHashFinal(rPassword, hashFinal);
|
||||
|
||||
std::vector<sal_uInt8>& encryptedHashInput = mInfo.encryptedVerifierHashInput;
|
||||
// SALT - needs to be a multiple of block size (?)
|
||||
sal_uInt32 nSaltSize = comphelper::roundUp(mInfo.saltSize, mInfo.blockSize);
|
||||
if (nSaltSize < encryptedHashInput.size())
|
||||
return false;
|
||||
sal_uInt32 nSaltSize = std::max<sal_uInt32>(comphelper::roundUp(mInfo.saltSize, mInfo.blockSize), encryptedHashInput.size());
|
||||
std::vector<sal_uInt8> hashInput(nSaltSize, 0);
|
||||
calculateBlock(constBlock1, hashFinal, encryptedHashInput, hashInput);
|
||||
|
||||
@@ -358,6 +358,10 @@ void AgileEngine::decryptEncryptionKey(OUString const & rPassword)
|
||||
sal_Int32 nKeySize = mInfo.keyBits / 8;
|
||||
|
||||
mKey.clear();
|
||||
// tdf#166241: for AES 192
|
||||
// mKey is the outbuf and in that moment, mInfo.encryptedKeyValue length is 32, while mKey size is 24.
|
||||
// so the end result is: we simply need to reserve mKey for mInfo.encryptedKeyValue.size() before resizing.
|
||||
mKey.reserve(mInfo.encryptedKeyValue.size());
|
||||
mKey.resize(nKeySize, 0);
|
||||
|
||||
std::vector<sal_uInt8> aPasswordHash(mInfo.hashSize, 0);
|
||||
@@ -570,6 +574,16 @@ bool AgileEngine::readEncryptionInfo(uno::Reference<io::XInputStream> & rxInputS
|
||||
return true;
|
||||
}
|
||||
|
||||
// AES 192 CBC with SHA384
|
||||
if (mInfo.keyBits == 192 &&
|
||||
mInfo.cipherAlgorithm == "AES" &&
|
||||
mInfo.cipherChaining == "ChainingModeCBC" &&
|
||||
mInfo.hashAlgorithm == "SHA384" &&
|
||||
mInfo.hashSize == comphelper::SHA384_HASH_LENGTH)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// AES 256 CBC with SHA512
|
||||
if (mInfo.keyBits == 256 &&
|
||||
mInfo.cipherAlgorithm == "AES" &&
|
||||
@@ -705,6 +719,8 @@ bool AgileEngine::setupEncryption(OUString const & rPassword)
|
||||
setupEncryptionParameters({ 100000, 16, 128, 20, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA1"_ustr });
|
||||
else if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA384)
|
||||
setupEncryptionParameters({ 100000, 16, 128, 48, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA384"_ustr });
|
||||
else if (meEncryptionPreset == AgileEncryptionPreset::AES_192_SHA384)
|
||||
setupEncryptionParameters({ 100000, 16, 192, 48, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA384"_ustr });
|
||||
else
|
||||
setupEncryptionParameters({ 100000, 16, 256, 64, 16, u"AES"_ustr, u"ChainingModeCBC"_ustr, u"SHA512"_ustr });
|
||||
|
||||
|
Reference in New Issue
Block a user