Commit 6c01725f authored by ElenaSubbotina's avatar ElenaSubbotina

DocFormat - fix bugs, add new chipher crypt

parent 11792a59
......@@ -200,6 +200,7 @@ namespace DocFileFormat
}
//-----------------------------------------------------------
_isSectionPageBreak = 0;
if (sectionEnd)
{
// this is the last paragraph of this section
......
......@@ -49,46 +49,120 @@ namespace DocFileFormat
if(0x0001 == vMajor) // RC4 encryption header structure
{// fib->m_FibBase.lKey == 52
crypt_data.Salt.b1 = tStream.ReadUInt32();
crypt_data.Salt.b2 = tStream.ReadUInt32();
crypt_data.Salt.b3 = tStream.ReadUInt32();
crypt_data.Salt.b4 = tStream.ReadUInt32();
bStandard = true;
crypt_data_rc4.Salt.b1 = tStream.ReadUInt32();
crypt_data_rc4.Salt.b2 = tStream.ReadUInt32();
crypt_data_rc4.Salt.b3 = tStream.ReadUInt32();
crypt_data_rc4.Salt.b4 = tStream.ReadUInt32();
crypt_data.EncryptedVerifier.b1 = tStream.ReadUInt32();
crypt_data.EncryptedVerifier.b2 = tStream.ReadUInt32();
crypt_data.EncryptedVerifier.b3 = tStream.ReadUInt32();
crypt_data.EncryptedVerifier.b4 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifier.b1 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifier.b2 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifier.b3 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifier.b4 = tStream.ReadUInt32();
crypt_data.EncryptedVerifierHash.b1 = tStream.ReadUInt32();
crypt_data.EncryptedVerifierHash.b2 = tStream.ReadUInt32();
crypt_data.EncryptedVerifierHash.b3 = tStream.ReadUInt32();
crypt_data.EncryptedVerifierHash.b4 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifierHash.b1 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifierHash.b2 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifierHash.b3 = tStream.ReadUInt32();
crypt_data_rc4.EncryptedVerifierHash.b4 = tStream.ReadUInt32();
}
else
{
// unsigned short flags = tStream.ReadUInt16();
// bool fCryptoAPI = GETBIT(flags, 2);
// bool fDocProps = GETBIT(flags, 3);
// bool fExternal = GETBIT(flags, 4);
// bool fAES = GETBIT(flags, 5);
// _UINT32 EncryptionHeaderSize = tStream.ReadUInt32();
////header
//
// tStream.ReadUInt32(); // reserved (SizeExtra)
// _INT32 AlgID = tStream.ReadInt32();
// _INT32 AlgIDHash = tStream.ReadInt32();
// _UINT32 KeySize = tStream.ReadUInt32();
// _UINT32 ProviderType = tStream.ReadUInt32();
// tStream.ReadUInt32();
// tStream.ReadUInt32(); // reserved
//
// //std::wstring CSPName;
// //record >> CSPName;
//// + crypt_data
bStandard = false;
crypt_data_aes.bAgile = false;
unsigned short flags = tStream.ReadUInt32();
unsigned char *pDataRead = NULL;
bool fCryptoAPI = GETBIT(flags, 1);
bool fDocProps = GETBIT(flags, 2);
bool fExternal = GETBIT(flags, 3);
bool fAES = GETBIT(flags, 4);
//EncryptionHeader
int HeaderSize = tStream.ReadUInt32();
int Flags = tStream.ReadUInt32();
int SizeExtra = tStream.ReadUInt32();
int AlgID = tStream.ReadUInt32();
int AlgIDHash = tStream.ReadUInt32();
int KeySize = tStream.ReadUInt32();
int ProviderType= tStream.ReadUInt32();
int Reserved1 = tStream.ReadUInt32();
int Reserved2 = tStream.ReadUInt32();
int pos = tStream.GetPosition();
int size = tStream.GetSize();
std::vector<char> dataCSPName;
while(pos < size - 1)
{
dataCSPName.push_back(tStream.ReadByte());
dataCSPName.push_back(tStream.ReadByte());
if (dataCSPName[dataCSPName.size() - 1] == 0 && dataCSPName[dataCSPName.size() - 2] == 0)
{
break;
}
pos+=2;//unicode null-terminate string
}
//EncryptionVerifier
crypt_data_aes.saltSize = tStream.ReadUInt32();
pDataRead = tStream.ReadBytes(crypt_data_aes.saltSize, true);
if (pDataRead)
{
crypt_data_aes.saltValue = std::string((char*)pDataRead, crypt_data_aes.saltSize);
delete pDataRead;
}
pDataRead = tStream.ReadBytes(0x10, true);
if (pDataRead)
{
crypt_data_aes.encryptedVerifierInput = std::string((char*)pDataRead, 0x10);
delete pDataRead;
}
crypt_data_aes.hashSize = tStream.ReadUInt32();
int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20;
pDataRead = tStream.ReadBytes(szEncryptedVerifierHash, true);
if (pDataRead)
{
crypt_data_aes.encryptedVerifierValue = std::string((char*)pDataRead, szEncryptedVerifierHash);
delete pDataRead;
}
pos = tStream.GetPosition();
//------------------------------------------------------------------------------------------
crypt_data_aes.hashAlgorithm = CRYPT_METHOD::SHA1; //by AlgIDHash -> 0x0000 || 0x8004
crypt_data_aes.spinCount = 50000;
switch(AlgID)
{
case 0x6801:
crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4;
crypt_data_aes.keySize = KeySize / 8;
break;
case 0x660E:
crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB;
crypt_data_aes.keySize = 128 /8;
break;
case 0x660F:
crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB;
crypt_data_aes.keySize = 192 /8;
break;
case 0x6610:
crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB;
crypt_data_aes.keySize = 256 /8;
break;
}
switch(ProviderType)
{
case 0x0001: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; break;
case 0x0018: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; break;
}
}
//RELEASEARRAYOBJECTS( bytes );
......
......@@ -32,6 +32,7 @@
#pragma once
#include "FileInformationBlock.h"
#include "../../OfficeCryptReader/source/CryptTransform.h"
#include "IVisitable.h"
......@@ -49,6 +50,8 @@ namespace DocFileFormat
EncryptionHeader( FileInformationBlock* fib, POLE::Stream* tableStream );
private:
CRYPT::CryptRC4Data crypt_data;
CRYPT::CryptRC4Data crypt_data_rc4;
CRYPT::ECMADecryptor::_cryptData crypt_data_aes;
bool bStandard;
};
}
......@@ -509,7 +509,6 @@ namespace DocFileFormat
public:
bool m_bOlderVersion;
int m_CodePage;
CRYPT::DecryptorPtr m_Decryptor;
FibBase m_FibBase;
RgW97 m_RgW97;
......
......@@ -134,8 +134,10 @@ namespace DocFileFormat
unsigned short flag = reader->ReadUInt16();
pSpa->fHdr = FormatUtils::BitmaskToBool(flag, 0x0001);
pSpa->bx = (AnchorType)FormatUtils::BitmaskToInt(flag, 0x0006);
pSpa->by = (AnchorType)FormatUtils::BitmaskToInt(flag, 0x0018);
int bx = FormatUtils::BitmaskToInt(flag, 0x0006);
int by = FormatUtils::BitmaskToInt(flag, 0x0018);
pSpa->bx = (AnchorType)bx;
pSpa->by = (AnchorType)by;
pSpa->wr = (unsigned short)FormatUtils::BitmaskToInt(flag, 0x01E0);
pSpa->wrk = (unsigned short)FormatUtils::BitmaskToInt(flag, 0x1E00);
pSpa->fRcaSimple = FormatUtils::BitmaskToBool(flag, 0x2000);
......
......@@ -1545,6 +1545,9 @@ namespace DocFileFormat
bool bRelH = false;
bool bRelV = false;
bool bPosH = false;
bool bPosV = false;
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
{
......@@ -1554,6 +1557,7 @@ namespace DocFileFormat
case posh:
{
appendStyleProperty(oStyle, _T("mso-position-horizontal"), mapHorizontalPosition((PositionHorizontal)iter->op));
bPosH = true;
}
break;
......@@ -1567,6 +1571,7 @@ namespace DocFileFormat
case posv:
{
appendStyleProperty(oStyle, _T("mso-position-vertical"), mapVerticalPosition((PositionVertical)iter->op));
bPosV = true;
}
break;
......@@ -1655,6 +1660,15 @@ namespace DocFileFormat
{
appendStyleProperty(oStyle, _T("mso-position-vertical-relative"), mapVerticalPositionRelative(m_pSpa->bx));
}
if (!bPosH)
{
appendStyleProperty(oStyle, _T("mso-position-horizontal"), _T( "absolute" ));
}
if (!bPosV)
{
appendStyleProperty(oStyle, _T("mso-position-vertical"), _T( "absolute" ));
}
}
//
......@@ -1878,34 +1892,29 @@ namespace DocFileFormat
case 1:
{
return _T( "tile" );
return _T( "pattern" );
}
break;
case 2:
{
return _T( "pattern" );
return _T( "tile" );
}
break;
case 3:
{
return _T( "frame" );
}
break;
case 4:
{
return _T( "gradient" );
}
break;
case 5:
{
return _T( "gradientRadial" );
}
break;
case 6:
{
return _T( "gradientRadial" );
......@@ -1917,13 +1926,11 @@ namespace DocFileFormat
return _T( "gradient" );
}
break;
case 9:
{
return _T( "solid" );
}
break;
default:
{
return _T( "solid" );
......
......@@ -39,7 +39,6 @@
#include "../../Common/DocxFormat/Source/SystemUtility/FileSystem/Directory.h"
#include "../../DesktopEditor/common/File.h"
namespace DocFileFormat
{
WordDocument::WordDocument (const ProgressCallback* pCallFunc, const std::wstring & sTempFolder ) :
......@@ -137,18 +136,36 @@ namespace DocFileFormat
{
encryptionHeader = new EncryptionHeader (FIB, TableStream);
FIB->m_Decryptor = CRYPT::DecryptorPtr(new CRYPT::Decryptor(encryptionHeader->crypt_data, m_sPassword, 1));
if (encryptionHeader->bStandard)
{
CRYPT::RC4Decryptor Decryptor(encryptionHeader->crypt_data_rc4, m_sPassword, 1);
if (Decryptor.IsVerify() == false)
{
Clear();
if (FIB->m_Decryptor->IsVerify() == false)
if (m_sPassword.empty() ) return AVS_ERROR_DRM;
else return AVS_ERROR_PASSWORD;
}
if (DecryptOfficeFile(&Decryptor) == false) return AVS_ERROR_DRM;
}
else
{
Clear();
CRYPT::ECMADecryptor Decryptor;
if (m_sPassword.empty() ) return AVS_ERROR_DRM;
else return AVS_ERROR_PASSWORD;
Decryptor.SetCryptData(encryptionHeader->crypt_data_aes);
if (Decryptor.SetPassword(m_sPassword) == false)
{
Clear();
if (m_sPassword.empty() ) return AVS_ERROR_DRM;
else return AVS_ERROR_PASSWORD;
}
if (DecryptOfficeFile(&Decryptor) == false) return AVS_ERROR_DRM;
}
if (DecryptFile() == false) return AVS_ERROR_DRM;
FIB->reset(VirtualStreamReader(WordDocumentStream, 68, false));
}
else if (FIB->m_FibBase.fEncrypted) return AVS_ERROR_DRM;
......@@ -429,8 +446,7 @@ namespace DocFileFormat
return 0;
}
bool WordDocument::DecryptFile()
bool WordDocument::DecryptOfficeFile(CRYPT::Decryptor* Decryptor)
{
if (m_sTempFolder.empty())
{
......@@ -458,11 +474,11 @@ namespace DocFileFormat
for (std::list<std::string>::iterator it2 = list_entry.begin(); it2 != list_entry.end(); it2++)
{
DecryptStream(*it2, storageIn, storageOut);
DecryptStream(Decryptor, *it2, storageIn, storageOut);
}
}
else
DecryptStream(*it, storageIn, storageOut);
DecryptStream(Decryptor, *it, storageIn, storageOut);
}
storageOut->close();
......@@ -487,7 +503,8 @@ namespace DocFileFormat
return true;
}
bool WordDocument::DecryptStream(std::string streamName, POLE::Storage * storageIn, POLE::Storage * storageOut)
bool WordDocument::DecryptStream(CRYPT::Decryptor* Decryptor, std::string streamName, POLE::Storage * storageIn, POLE::Storage * storageOut)
{
POLE::Stream *stream = new POLE::Stream(storageIn, streamName);
if (!stream) return false;
......@@ -513,7 +530,7 @@ namespace DocFileFormat
if (data_store)
memcpy(data_store, data_stream, sz_data_store);
FIB->m_Decryptor->Decrypt((char*)data_stream, sz_stream, 0);
Decryptor->Decrypt((char*)data_stream, sz_stream, 0);
if (data_store)
memcpy(data_stream, data_store, sz_data_store);
......
......@@ -60,6 +60,11 @@
#include "IVisitable.h"
#include "../Common/Callback.h"
namespace CRYPT
{
class Decryptor;
}
namespace DocFileFormat
{
class WordDocument: public IVisitable
......@@ -95,8 +100,8 @@ namespace DocFileFormat
int document_code_page;
private:
bool DecryptFile();
bool DecryptStream(std::string streamName, POLE::Storage * storageIn, POLE::Storage * storageOut);
bool DecryptOfficeFile (CRYPT::Decryptor* Decryptor);
bool DecryptStream (CRYPT::Decryptor* Decryptor, std::string streamName, POLE::Storage * storageIn, POLE::Storage * storageOut);
inline StructuredStorageReader* GetStorage() const
{
......
......@@ -31,7 +31,7 @@
*/
#pragma once
#include "Crypt.h"
#include "Decryptor.h"
#include "rtl/cipher.h"
#include "rtl/digest.h"
......
......@@ -64,24 +64,24 @@ namespace CRYPT
} EncryptedVerifierHash;
};
class Crypt
{
public:
class Crypt
{
public:
virtual void Encrypt(char* data, const size_t size) = 0;
virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos) = 0;
virtual void Encrypt(char* data, const size_t size) = 0;
virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos) = 0;
typedef enum
{
RC4,
RC4CryptoAPI,
XOR
} crypt_type;
typedef enum
{
RC4,
RC4CryptoAPI,
XOR
} crypt_type;
virtual bool IsVerify() = 0;
virtual bool IsVerify() = 0;
};
};
typedef boost::shared_ptr<Crypt> CryptPtr;
typedef boost::shared_ptr<Crypt> CryptPtr;
} // namespace CRYPT
......@@ -37,25 +37,24 @@
namespace CRYPT
{
Decryptor::Decryptor(CryptRC4Data & header, std::wstring password, int type) :
RC4Decryptor::RC4Decryptor(CryptRC4Data & header, std::wstring password, int type) :
crypt (new RC4Crypt(header, password, type)),
type (Crypt::RC4)
{
crypt_data = header;
}
void Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos)
void RC4Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos)
{
crypt->Decrypt(data, size, stream_pos);
}
bool Decryptor::IsVerify()
bool RC4Decryptor::IsVerify()
{
return crypt->IsVerify();
}
bool Decryptor::SetPassword(std::wstring password)
bool RC4Decryptor::SetPassword(std::wstring password)
{
crypt.reset();
crypt = CryptPtr(new RC4Crypt(crypt_data, password, 1));
......
......@@ -31,28 +31,30 @@
*/
#pragma once
#include "Crypt.h"
#include "../../../../OfficeCryptReader/source/CryptTransform.h"
namespace CRYPT
{
class Decryptor
{
public:
Decryptor(CryptRC4Data & header, std::wstring password, int type);
class RC4Decryptor : public Decryptor
{
public:
RC4Decryptor(CryptRC4Data & header, std::wstring password, int type);
void Decrypt(char* data, const size_t size, const unsigned long stream_pos);
virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos);
bool IsVerify();
bool IsVerify();
bool SetPassword(std::wstring password);
bool SetPassword(std::wstring password);
private:
CryptPtr crypt;
Crypt::crypt_type type;
CryptRC4Data crypt_data;
};
private:
CryptPtr crypt;
Crypt::crypt_type type;
CryptRC4Data crypt_data;
};
typedef boost::shared_ptr<Decryptor> DecryptorPtr;
typedef boost::shared_ptr<RC4Decryptor> RC4DecryptorPtr;
} // namespace CRYPT
......@@ -86,7 +86,7 @@ void FilePass::readFields(CFRecord& record)
rc4HeaderPtr->load (record);
record.getGlobalWorkbookInfo()->decryptor =
CRYPT::DecryptorPtr(new CRYPT::Decryptor(rc4HeaderPtr->RC4Data, record.getGlobalWorkbookInfo()->password, 2));
CRYPT::RC4DecryptorPtr(new CRYPT::RC4Decryptor(rc4HeaderPtr->RC4Data, record.getGlobalWorkbookInfo()->password, 2));
Log::info("Encryption type: RC4 Standard");
}
......
......@@ -77,7 +77,7 @@ public:
unsigned short CodePage;
CRYPT::DecryptorPtr decryptor;
CRYPT::RC4DecryptorPtr decryptor;
std::wstring password;
std::vector<std::wstring> sheets_state;
......
......@@ -37,6 +37,7 @@
#include "../../Common/3dParty/cryptopp/modes.h"
#include "../../Common/3dParty/cryptopp/aes.h"
#include "../../Common/3dParty/cryptopp/sha.h"
#include "../../Common/3dParty/cryptopp/md5.h"
#include "../../Common/3dParty/cryptopp/pwdbased.h"
#include "../../Common/3dParty/cryptopp/filters.h"
......@@ -49,9 +50,6 @@ static const unsigned char encrKeyValueBlockKey[8] = { 0x14, 0x6e, 0x0b, 0xe
static const unsigned char encrDataIntegritySaltBlockKey[8] = { 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6 };
static const unsigned char encrDataIntegrityHmacValueBlockKey[8] = { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 };
ECMADecryptor::ECMADecryptor()
{
}
class _buf
{
......@@ -174,7 +172,7 @@ _buf HashAppend(_buf & hashBuf, _buf & block, CRYPT_METHOD::_hashAlgorithm algo
{//todooo переделать
if (algorithm == CRYPT_METHOD::SHA1)
{
CryptoPP::SHA1 hash;
CryptoPP::MD5 hash;
if (hashBuf.ptr && hashBuf.size > 0) hash.Update( hashBuf.ptr, hashBuf.size);
if (block.ptr && block.size > 0) hash.Update( block.ptr , block.size);
......@@ -183,6 +181,15 @@ _buf HashAppend(_buf & hashBuf, _buf & block, CRYPT_METHOD::_hashAlgorithm algo
hash.Final(buffer);
return _buf(buffer.BytePtr(), buffer.SizeInBytes());
//CryptoPP::SHA1 hash;
//if (hashBuf.ptr && hashBuf.size > 0) hash.Update( hashBuf.ptr, hashBuf.size);
//if (block.ptr && block.size > 0) hash.Update( block.ptr , block.size);
//CryptoPP::SecByteBlock buffer(hash.DigestSize());
//hash.Final(buffer);
//return _buf(buffer.BytePtr(), buffer.SizeInBytes());
}
else if (algorithm == CRYPT_METHOD::SHA256)
{
......@@ -290,6 +297,13 @@ bool DecryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYP
return true;
}
//------------------------------------------------------------------------------------------------------------------------------------
namespace CRYPT
{
ECMADecryptor::ECMADecryptor()
{
}
bool ECMADecryptor::SetPassword(std::wstring password_)
{
......@@ -353,7 +367,17 @@ void ECMADecryptor::SetCryptData(_cryptData &data)
{
cryptData = data;
}
void ECMADecryptor::Decrypt(char* data , const size_t size, const unsigned long stream_pos)
{
unsigned char* data_out = NULL;
Decrypt((unsigned char*)data, size, data_out);
if (data_out)
{
delete []data;
data = (char*)data_out;
}
}
void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& data_out)
{
data_out = NULL;
......@@ -408,3 +432,4 @@ void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*&
DecryptCipher(hashKey, empty, pInp, pOut, cryptData.cipherAlgorithm);
}
}
}
\ No newline at end of file
......@@ -54,8 +54,15 @@ namespace CRYPT_METHOD
AES_ECB
};
}
namespace CRYPT
{
class Decryptor
{
public:
virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos) = 0;
};
class ECMADecryptor
class ECMADecryptor : public Decryptor
{
public:
......@@ -96,6 +103,7 @@ public:
virtual ~ECMADecryptor(){}
void Decrypt(unsigned char* data, int size, unsigned char*& data_out);
virtual void Decrypt(char* data , const size_t size, const unsigned long stream_pos);
bool SetPassword(std::wstring password);
......@@ -105,14 +113,5 @@ private:
_cryptData cryptData;
std::wstring password;
};
//
//class ECMAEncryptor
//{
//public:
// ECMAEncryptor(int type);
// virtual ~ECMAEncryptor();
//
// void Encrypt(char* data, int size);
//
// bool SetPassword(std::wstring password);
//};
\ No newline at end of file
}
\ No newline at end of file
......@@ -41,6 +41,8 @@
#include "../../ASCOfficeDocFile/DocDocxConverter/MemoryStream.h"
using namespace CRYPT;
#define GETBIT(from, num) ((from & (1 << num)) != 0)
#define WritingElement_ReadAttributes_Start(Reader) \
......@@ -340,6 +342,7 @@ bool ReadExtensibleEncryptionInfo(unsigned char* data, int size, ECMADecryptor::
//--------------------------------------------------------------
bool ECMACryptReader::DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password)
{
POLE::Storage *pStorage = new POLE::Storage(file_name_inp.c_str());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment