From 5b5cb4188e706c8e29735469b18116f6692924cc Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Tue, 30 May 2017 19:49:54 +0300 Subject: [PATCH] OfficeCryptReader - check data integrity --- OfficeCryptReader/Test/Test.cpp | 6 ++- OfficeCryptReader/source/CryptTransform.cpp | 37 +++++++------- OfficeCryptReader/source/CryptTransform.h | 5 +- OfficeCryptReader/source/ECMACryptFile.cpp | 55 ++++++--------------- OfficeCryptReader/source/ECMACryptFile.h | 2 +- X2tConverter/src/ASCConverters.cpp | 20 ++++++-- 6 files changed, 59 insertions(+), 66 deletions(-) diff --git a/OfficeCryptReader/Test/Test.cpp b/OfficeCryptReader/Test/Test.cpp index b87d797938..ca27330329 100644 --- a/OfficeCryptReader/Test/Test.cpp +++ b/OfficeCryptReader/Test/Test.cpp @@ -12,9 +12,11 @@ int _tmain(int argc, _TCHAR* argv[]) std::wstring password = L"password"; ECMACryptFile crypt_file; - crypt_file.DecryptOfficeFile(srcFileName, dstFileName, password); + bool result, bDataIntegrity; + + result = crypt_file.DecryptOfficeFile(srcFileName, dstFileName, password, bDataIntegrity); - crypt_file.EncryptOfficeFile(dstFileName, dstFileName2, password); + result = crypt_file.EncryptOfficeFile(dstFileName, dstFileName2, password); return 0; } diff --git a/OfficeCryptReader/source/CryptTransform.cpp b/OfficeCryptReader/source/CryptTransform.cpp index 6f4973b4d7..6c7c690134 100644 --- a/OfficeCryptReader/source/CryptTransform.cpp +++ b/OfficeCryptReader/source/CryptTransform.cpp @@ -488,8 +488,10 @@ void ECMADecryptor::Decrypt(char* data , const size_t size, const unsigned long } } } -bool ECMADecryptor::IsDataIntegrity(unsigned char* data, int size) +bool ECMADecryptor::CheckDataIntegrity(unsigned char* data, int size) { + if (cryptData.bAgile == false) return true; + _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); _buf pBlockHmacKey ((unsigned char*)encrDataIntegritySaltBlockKey, 8); _buf pBlockHmacValue((unsigned char*)encrDataIntegrityHmacValueBlockKey, 8); @@ -522,7 +524,7 @@ bool ECMADecryptor::IsDataIntegrity(unsigned char* data, int size) std::string sData((char*)data, size); _buf hmac = Hmac(salt, cryptData.hashAlgorithm, sData); - + return (hmac == expected); } void ECMADecryptor::Decrypt(unsigned char* data_ptr, int data_size, unsigned char*& data_out) @@ -540,8 +542,6 @@ void ECMADecryptor::Decrypt(unsigned char* data_ptr, int data_size, unsigned ch if (cryptData.bAgile) { - bool isDataIntegrity = IsDataIntegrity(data_ptr, data_size); - _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); _buf pDataSalt (cryptData.dataSaltValue); _buf pKeyValue (cryptData.encryptedKeyValue); @@ -603,6 +603,7 @@ void ECMADecryptor::Decrypt(unsigned char* data_ptr, int data_size, unsigned ch DecryptCipher(hashKey, empty, pInp, pOut, cryptData.cipherAlgorithm); } } + //----------------------------------------------------------------------------------------------------------- ECMAEncryptor::ECMAEncryptor() { @@ -622,6 +623,7 @@ void ECMAEncryptor::GetCryptData(_ecmaCryptData &data) { data = cryptData; } + void ECMAEncryptor::UpdateDataIntegrity(unsigned char* data, int size) { if (cryptData.bAgile == false) return; @@ -636,31 +638,32 @@ void ECMAEncryptor::UpdateDataIntegrity(unsigned char* data, int size) _buf pDataSalt (cryptData.dataSaltValue); _buf pKeyValue (cryptData.encryptedKeyValue); - _buf pEncHmacKey (cryptData.encryptedHmacKey); - _buf pEncHmacValue (cryptData.encryptedHmacValue); - + _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); _buf secretKey; DecryptCipher( agileKey, pSalt, pKeyValue, secretKey, cryptData.cipherAlgorithm); -//---- + _buf iv1 = HashAppend(pDataSalt, pBlockHmacKey, cryptData.hashAlgorithm); CorrectHashSize(iv1, cryptData.blockSize, 0x36); _buf iv2 = HashAppend(pDataSalt, pBlockHmacValue, cryptData.hashAlgorithm); CorrectHashSize(iv2, cryptData.blockSize, 0x36); - _buf salt; - DecryptCipher(secretKey, iv1, pEncHmacKey, salt, cryptData.cipherAlgorithm); - - _buf expected; - DecryptCipher(secretKey, iv2, pEncHmacValue, expected, cryptData.cipherAlgorithm); - +//---- std::string sData((char*)data, size); - _buf hmac = Hmac(salt, cryptData.hashAlgorithm, sData); - - //return (hmac == expected); + _buf hmac = Hmac(pSalt, cryptData.hashAlgorithm, sData); + + _buf pEncHmacKey; + EncryptCipher(secretKey, iv1, pSalt, pEncHmacKey, cryptData.cipherAlgorithm); + + _buf pEncHmacValue; + EncryptCipher(secretKey, iv2, hmac, pEncHmacValue, cryptData.cipherAlgorithm); + + cryptData.encryptedHmacKey = std::string((char*)pEncHmacKey.ptr, pEncHmacKey.size); + cryptData.encryptedHmacValue = std::string((char*)pEncHmacValue.ptr, pEncHmacValue.size); } + int ECMAEncryptor::Encrypt(unsigned char* data_inp_ptr, int size, unsigned char*& data_out_ptr) { data_out_ptr = NULL; diff --git a/OfficeCryptReader/source/CryptTransform.h b/OfficeCryptReader/source/CryptTransform.h index 71a1465baa..7ebcd92992 100644 --- a/OfficeCryptReader/source/CryptTransform.h +++ b/OfficeCryptReader/source/CryptTransform.h @@ -133,11 +133,12 @@ public: virtual bool SetPassword (std::wstring password); virtual bool IsVerify(); + bool CheckDataIntegrity(unsigned char* data, int size); + void SetCryptData(_ecmaCryptData &data); private: - bool IsDataIntegrity(unsigned char* data, int size); - + std::wstring password; _ecmaCryptData cryptData; bool bVerify; diff --git a/OfficeCryptReader/source/ECMACryptFile.cpp b/OfficeCryptReader/source/ECMACryptFile.cpp index a53083c7f5..6aa96d186d 100644 --- a/OfficeCryptReader/source/ECMACryptFile.cpp +++ b/OfficeCryptReader/source/ECMACryptFile.cpp @@ -575,6 +575,9 @@ bool ECMACryptFile::EncryptOfficeFile(std::wstring file_name_inp, std::wstring f { unsigned char* data_out2 = NULL; decryptor.Decrypt(data_out, lengthData, data_out2); + + bool bDataIntegrity = decryptor.CheckDataIntegrity(data_out, lengthData); + NSFile::CFileBinary test; test.CreateFileW(file_name_out + L"-back.oox"); @@ -586,8 +589,10 @@ bool ECMACryptFile::EncryptOfficeFile(std::wstring file_name_inp, std::wstring f return true; } -bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password) +bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password, bool & bDataIntegrity) { + bDataIntegrity = false; + POLE::Storage *pStorage = new POLE::Storage(file_name_inp.c_str()); if (!pStorage)return false; @@ -597,45 +602,10 @@ bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring f delete pStorage; return false; } - _ecmaCryptData cryptData; +//------------------------------------------------------------------------------------------- + _ecmaCryptData cryptData; bool result = false; -//------------------------------------------------------------------------ - //{ - // std::wstring f = file_name_out + L"-1.docx"; - // POLE::Storage *pStorage1 = new POLE::Storage(f.c_str()); - // pStorage1->open(true, true); - - // POLE::Stream *pStrIn = new POLE::Stream(pStorage, "EncryptionInfo"); - // POLE::uint64 sz = pStrIn->size(); - // POLE::Stream *pStrOut = new POLE::Stream(pStorage1, "EncryptionInfo", true, sz); - - // BYTE *d = new BYTE [sz]; - // pStrIn->read(d, sz); - // pStrOut->write(d, sz); - // delete d; - - // pStrOut->flush(); - // delete pStrOut; - // delete pStrIn; - - // pStrIn = new POLE::Stream(pStorage, "EncryptedPackage"); - // sz = pStrIn->size(); - // pStrOut = new POLE::Stream(pStorage1, "EncryptedPackage", true, sz); - - // d = new BYTE [sz]; - // pStrIn->read(d, sz); - // pStrOut->write(d, sz); - // delete d; - - // pStrOut->flush(); - // delete pStrOut; - // delete pStrIn; - - // pStorage1->close(); - // delete pStorage1; - //} -//---------------------------------------------------------------------------- POLE::Stream *pStream = new POLE::Stream(pStorage, "EncryptionInfo"); if (pStream) @@ -747,8 +717,6 @@ bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring f lengthData = *((_UINT64*)data); decryptor.Decrypt(data, readTrue, data_out);//todoo сделать покусочное чтение декриптование - delete pStream; - delete []data; if (data_out) { @@ -760,11 +728,16 @@ bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring f delete []data_out; result = true; } + + bDataIntegrity = decryptor.CheckDataIntegrity(data, readTrue); + + delete pStream; + delete []data; } //------------------------------------------------------------------- delete pStorage; - cryptDataGlobal = cryptData; + cryptDataGlobal = cryptData; // for encrypt like sample return result; } diff --git a/OfficeCryptReader/source/ECMACryptFile.h b/OfficeCryptReader/source/ECMACryptFile.h index 45b789f91d..40f5f90d3f 100644 --- a/OfficeCryptReader/source/ECMACryptFile.h +++ b/OfficeCryptReader/source/ECMACryptFile.h @@ -37,7 +37,7 @@ class ECMACryptFile { public: - bool DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password); + bool DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password, bool & bDataIntegrity); bool EncryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password); struct _refComponent diff --git a/X2tConverter/src/ASCConverters.cpp b/X2tConverter/src/ASCConverters.cpp index e9a82d3811..d04b2b6c73 100644 --- a/X2tConverter/src/ASCConverters.cpp +++ b/X2tConverter/src/ASCConverters.cpp @@ -1457,14 +1457,21 @@ namespace NExtractTools int mscrypt2oox (const std::wstring &sFrom, const std::wstring &sTo, const std::wstring & sTemp, InputParams& params) { std::wstring password = params.getPassword(); - //decrypt to sTo + ECMACryptFile cryptReader; - if (cryptReader.DecryptOfficeFile(sFrom, sTo, password) == false) + bool bDataIntegrity = false; + + if (cryptReader.DecryptOfficeFile(sFrom, sTo, password, bDataIntegrity) == false) { if (password.empty()) return AVS_FILEUTILS_ERROR_CONVERT_DRM; else return AVS_FILEUTILS_ERROR_CONVERT_PASSWORD; } + if (bDataIntegrity == false) + { + //было несанкционированое вешательство в файл + } + return S_OK; } int mscrypt2oot_bin (const std::wstring &sFrom, const std::wstring &sTo, const std::wstring & sTemp, InputParams& params) @@ -1473,9 +1480,16 @@ namespace NExtractTools std::wstring sResultDecryptFile = sTemp + FILE_SEPARATOR_STR + L"uncrypt_file.oox"; ECMACryptFile cryptReader; - if (cryptReader.DecryptOfficeFile(sFrom, sResultDecryptFile, params.getPassword()) == false) + bool bDataIntegrity = false; + + if (cryptReader.DecryptOfficeFile(sFrom, sResultDecryptFile, params.getPassword(), bDataIntegrity) == false) return AVS_FILEUTILS_ERROR_CONVERT_PASSWORD; + if (bDataIntegrity == false) + { + //было несанкционированое вешательство в файл + } + COfficeFileFormatChecker OfficeFileFormatChecker; if (OfficeFileFormatChecker.isOfficeFile(sResultDecryptFile))