include/oox/ole/vbaexport.hxx | 35 +++++++ oox/CppunitTest_oox_vba_encryption.mk | 50 ++++++++++ oox/Module_oox.mk | 1 oox/qa/unit/vba_encryption.cxx | 97 ++++++++++++++++++++ oox/source/ole/vbaexport.cxx | 158 +++++++++++++++++++++++++++++++++- 5 files changed, 340 insertions(+), 1 deletion(-)
New commits: commit 7168f6b20ba620e20233bc9e89e1c97b6b353b97 Author: Rosemary <rosemarys...@gmail.com> Date: Thu Oct 8 10:15:03 2015 +0530 The correct size of length is 4 Change-Id: I8735e68e1094e40f989ebc0a8a3926c9e2f06fd4 diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx index 20b9741..717f6eb 100644 --- a/oox/source/ole/vbaexport.cxx +++ b/oox/source/ole/vbaexport.cxx @@ -424,7 +424,7 @@ void VBAEncryption::writeIgnoredEnc() void VBAEncryption::writeDataLengthEnc() { sal_uInt16 temp = mnLength; - for(sal_Int8 i = 0; i < 2; ++i) + for(sal_Int8 i = 0; i < 4; ++i) { sal_uInt8 nByte = temp & 0xFF; sal_uInt8 nByteEnc = nByte ^ (mnEncryptedByte2 + mnUnencryptedByte1); commit e5f1bba213b8ca9c3b8138ba053da453852ffb87 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Wed Oct 7 21:01:42 2015 +0200 add test for projkey generation Change-Id: I42957abbdcf396830713d7ca4eb7539e6c110e11 diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx index 2275c13..db63ce3 100644 --- a/include/oox/ole/vbaexport.hxx +++ b/include/oox/ole/vbaexport.hxx @@ -122,6 +122,8 @@ public: void write(); + static sal_uInt8 calculateProjKey(const OUString& rString); + private: const sal_uInt8* mpData; // an array of bytes to be obfuscated const sal_uInt16 mnLength; // the length of Data diff --git a/oox/qa/unit/vba_encryption.cxx b/oox/qa/unit/vba_encryption.cxx index 1c7fc02..785c480 100644 --- a/oox/qa/unit/vba_encryption.cxx +++ b/oox/qa/unit/vba_encryption.cxx @@ -25,6 +25,8 @@ public: void testSimple2(); + void testProjKey1(); + // avoid the BootstrapFixtureBase::setUp and tearDown virtual void setUp() SAL_OVERRIDE; virtual void tearDown() SAL_OVERRIDE; @@ -32,6 +34,7 @@ public: CPPUNIT_TEST_SUITE(TestVbaEncryption); // CPPUNIT_TEST(testSimple1); // CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST(testProjKey1); CPPUNIT_TEST_SUITE_END(); private: @@ -48,7 +51,6 @@ void TestVbaEncryption::testSimple1() VBAEncryption aEncryption(pData, nLength, aEncryptedStream, &nSeed, nProjKey); aEncryption.write(); - } void TestVbaEncryption::testSimple2() @@ -73,6 +75,13 @@ void TestVbaEncryption::testSimple2() } } +void TestVbaEncryption::testProjKey1() +{ + OUString aProjectID("{917DED54-440B-4FD1-A5C1-74ACF261E600}"); + sal_uInt8 nProjKey = VBAEncryption::calculateProjKey(aProjectID); + CPPUNIT_ASSERT_EQUAL((int)0xdf, (int)nProjKey); +} + void TestVbaEncryption::setUp() { } diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx index e5352ca..20b9741 100644 --- a/oox/source/ole/vbaexport.cxx +++ b/oox/source/ole/vbaexport.cxx @@ -384,19 +384,22 @@ void VBAEncryption::writeVersionEnc() exportHexString(mrEncryptedData, mnVersionEnc); } -void VBAEncryption::writeProjKeyEnc() +sal_uInt8 VBAEncryption::calculateProjKey(const OUString& rProjectKey) { - if(!mnProjKey) + sal_uInt8 nProjKey = 0; + sal_Int32 n = rProjectKey.getLength(); + const sal_Unicode* pString = rProjectKey.getStr(); + for (sal_Int32 i = 0; i < n; ++i) { - OUString sProjectCLSID = "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"; //TODO:Find the real ProjectId.ProjectClSID - sal_Int32 n = sProjectCLSID.getLength(); - const sal_Unicode* pString = sProjectCLSID.getStr(); - for (sal_Int32 i = 0; i < n; ++i) - { - sal_Unicode character = pString[i]; - mnProjKey += character; - } + sal_Unicode character = pString[i]; + nProjKey += character; } + + return nProjKey; +} + +void VBAEncryption::writeProjKeyEnc() +{ sal_uInt8 nProjKeyEnc = mnSeed ^ mnProjKey; exportHexString(mrEncryptedData, nProjKeyEnc); mnUnencryptedByte1 = mnProjKey; @@ -861,7 +864,8 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN // section 2.3.1.2 ProjectId exportString(rStrm, "ID=\""); - exportString(rStrm, "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"); + OUString aProjectID("{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"); + exportString(rStrm, aProjectID); exportString(rStrm, "\"\r\n"); // section 2.3.1.3 ProjectModule @@ -894,7 +898,8 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN SvMemoryStream aProtectedStream(4096, 4096); aProtectedStream.WriteUInt32(0x00000000); const sal_uInt8* pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aProtectionState(pData, 4, rStrm, NULL, 0); + sal_uInt8 nProjKey = VBAEncryption::calculateProjKey(aProjectID); + VBAEncryption aProtectionState(pData, 4, rStrm, NULL, nProjKey); aProtectionState.write(); exportString(rStrm, "\"\r\n"); #else @@ -907,7 +912,7 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN aProtectedStream.Seek(0); aProtectedStream.WriteUInt8(0x00); pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aProjectPassword(pData, 1, rStrm, NULL, 0); + VBAEncryption aProjectPassword(pData, 1, rStrm, NULL, nProjKey); aProjectPassword.write(); exportString(rStrm, "\"\r\n"); #else @@ -920,7 +925,7 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN aProtectedStream.Seek(0); aProtectedStream.WriteUInt8(0xFF); pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aVisibilityState(pData, 1, rStrm, NULL, 0); + VBAEncryption aVisibilityState(pData, 1, rStrm, NULL, nProjKey); aVisibilityState.write(); exportString(rStrm, "\"\r\n\r\n"); #else commit 6970e2bac2b64c50ce04565ef1daea12d8a1df9a Author: Rosemary <rosemarys...@gmail.com> Date: Wed Oct 7 15:47:55 2015 +0530 Correct export for strings of hexadecimal digits Change-Id: Ie71cca63cc4ac277c57516348f4c15f5bb2395c3 diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx index 5be8730..e5352ca 100644 --- a/oox/source/ole/vbaexport.cxx +++ b/oox/source/ole/vbaexport.cxx @@ -71,6 +71,19 @@ void exportUTF16String(SvStream& rStrm, const OUString& rString) } } +void exportHexString(SvStream& rStrm, const sal_uInt8 nByte) +{ + sal_uInt8 nNibble = (nByte & 0xF0) >> 4; + for(sal_uInt8 i = 0; i < 2; i++) + { + if(nNibble > 9) + rStrm.WriteUInt8(nNibble + 55); + else + rStrm.WriteUInt8(nNibble + 48); + nNibble = nByte & 0xF; + } +} + bool isWorkbook(css::uno::Reference<css::uno::XInterface> xInterface) { css::uno::Reference<ooo::vba::excel::XWorkbook> xWorkbook(xInterface, css::uno::UNO_QUERY); @@ -362,29 +375,30 @@ VBAEncryption::VBAEncryption(const sal_uInt8* pData, const sal_uInt16 length, Sv void VBAEncryption::writeSeed() { - mrEncryptedData.WriteUInt8(mnSeed); + exportHexString(mrEncryptedData, mnSeed); } void VBAEncryption::writeVersionEnc() { mnVersionEnc = mnSeed ^ mnVersion; - mrEncryptedData.WriteUInt8(mnVersionEnc); + exportHexString(mrEncryptedData, mnVersionEnc); } void VBAEncryption::writeProjKeyEnc() { - /* - OUString mrProjectCLSID = "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"; //TODO:Find the real ProjectId.ProjectClSID - sal_Int32 n = mrProjectCLSID.getLength(); - const sal_Unicode* pString = mrProjectCLSID.getStr(); - for (sal_Int32 i = 0; i < n; ++i) + if(!mnProjKey) { - sal_Unicode character = pString[i]; - mnProjKey += character; + OUString sProjectCLSID = "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"; //TODO:Find the real ProjectId.ProjectClSID + sal_Int32 n = sProjectCLSID.getLength(); + const sal_Unicode* pString = sProjectCLSID.getStr(); + for (sal_Int32 i = 0; i < n; ++i) + { + sal_Unicode character = pString[i]; + mnProjKey += character; + } } - */ sal_uInt8 nProjKeyEnc = mnSeed ^ mnProjKey; - mrEncryptedData.WriteUInt8(nProjKeyEnc); + exportHexString(mrEncryptedData, nProjKeyEnc); mnUnencryptedByte1 = mnProjKey; mnEncryptedByte1 = nProjKeyEnc; // ProjKeyEnc mnEncryptedByte2 = mnVersionEnc; // VersionEnc @@ -397,7 +411,7 @@ void VBAEncryption::writeIgnoredEnc() { sal_uInt8 nTempValue = 0xBE; // TODO:Generate a random value sal_uInt8 nByteEnc = nTempValue ^ (mnEncryptedByte2 + mnUnencryptedByte1); - mrEncryptedData.WriteUInt8(nByteEnc); + exportHexString(mrEncryptedData, nByteEnc); mnEncryptedByte2 = mnEncryptedByte1; mnEncryptedByte1 = nByteEnc; mnUnencryptedByte1 = nTempValue; @@ -411,7 +425,7 @@ void VBAEncryption::writeDataLengthEnc() { sal_uInt8 nByte = temp & 0xFF; sal_uInt8 nByteEnc = nByte ^ (mnEncryptedByte2 + mnUnencryptedByte1); - mrEncryptedData.WriteUInt8(nByteEnc); + exportHexString(mrEncryptedData, nByteEnc); mnEncryptedByte2 = mnEncryptedByte1; mnEncryptedByte1 = nByteEnc; mnUnencryptedByte1 = nByte; @@ -424,7 +438,7 @@ void VBAEncryption::writeDataEnc() for(sal_Int8 i = 0; i < mnLength; i++) { sal_uInt8 nByteEnc = mpData[i] ^ (mnEncryptedByte2 + mnUnencryptedByte1); - mrEncryptedData.WriteUInt8(nByteEnc); + exportHexString(mrEncryptedData, nByteEnc); mnEncryptedByte2 = mnEncryptedByte1; mnEncryptedByte1 = nByteEnc; mnUnencryptedByte1 = mpData[i]; commit 3ba169bd68d81980a112998a57ff5d2b638252fa Author: Markus Mohrhard <markus.mohrh...@googlemail.com> Date: Tue Oct 6 17:06:16 2015 +0200 add initial tests for vba encryption Change-Id: Ic6128ecade39e8947863c9162523e0d9690f0026 diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx index 2c03cc27..2275c13 100644 --- a/include/oox/ole/vbaexport.hxx +++ b/include/oox/ole/vbaexport.hxx @@ -111,13 +111,14 @@ private: SvMemoryStream& mrUncompressedStream; }; -class VBAEncryption +class OOX_DLLPUBLIC VBAEncryption { public: VBAEncryption(const sal_uInt8* pData, const sal_uInt16 nLength, - SvStream& rEncryptedData - ); + SvStream& rEncryptedData, + sal_uInt8* pSeed, + sal_uInt8 nProjKey); void write(); diff --git a/oox/CppunitTest_oox_vba_encryption.mk b/oox/CppunitTest_oox_vba_encryption.mk new file mode 100644 index 0000000..1f8bb5c --- /dev/null +++ b/oox/CppunitTest_oox_vba_encryption.mk @@ -0,0 +1,50 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,oox_vba_encryption)) + +$(eval $(call gb_CppunitTest_add_exception_objects,oox_vba_encryption,\ + oox/qa/unit/vba_encryption \ +)) + +$(eval $(call gb_CppunitTest_use_api,oox_vba_encryption,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,oox_vba_encryption,\ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + editeng \ + expwrap \ + drawinglayer \ + msfilter \ + sal \ + i18nlangtag \ + oox \ + sax \ + sfx \ + svl \ + svt \ + svx \ + svxcore \ + sot \ + tl \ + unotest \ + utl \ + vcl \ + xo \ + xmlscript \ + $(gb_UWINAPI) \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/oox/Module_oox.mk b/oox/Module_oox.mk index 1c8edf0..4d7a79e 100644 --- a/oox/Module_oox.mk +++ b/oox/Module_oox.mk @@ -19,6 +19,7 @@ $(eval $(call gb_Module_add_targets,oox,\ $(eval $(call gb_Module_add_check_targets,oox,\ CppunitTest_oox_tokenmap \ CppunitTest_oox_vba_compression \ + CppunitTest_oox_vba_encryption \ )) # vim: set noet sw=4 ts=4: diff --git a/oox/qa/unit/vba_encryption.cxx b/oox/qa/unit/vba_encryption.cxx new file mode 100644 index 0000000..1c7fc02 --- /dev/null +++ b/oox/qa/unit/vba_encryption.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <unotest/bootstrapfixturebase.hxx> + +#include <cppunit/plugin/TestPlugIn.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestFixture.h> + +#include <oox/ole/vbaexport.hxx> +#include <algorithm> + +class TestVbaEncryption : public test::BootstrapFixtureBase +{ +public: + + // an initial test for the encryption taken from the spec + void testSimple1(); + + void testSimple2(); + + // avoid the BootstrapFixtureBase::setUp and tearDown + virtual void setUp() SAL_OVERRIDE; + virtual void tearDown() SAL_OVERRIDE; + + CPPUNIT_TEST_SUITE(TestVbaEncryption); + // CPPUNIT_TEST(testSimple1); + // CPPUNIT_TEST(testSimple2); + CPPUNIT_TEST_SUITE_END(); + +private: +}; + +void TestVbaEncryption::testSimple1() +{ + sal_uInt8 nSeed = 0x07; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x04; + sal_uInt8 pData[] = { 0x00, 0x00, 0x00, 0x00 }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); + +} + +void TestVbaEncryption::testSimple2() +{ + sal_uInt8 nSeed = 0x15; + sal_uInt8 nProjKey = 0xDF; + sal_uInt16 nLength = 0x01; + sal_uInt8 pData[] = { 0xFF }; + + SvMemoryStream aEncryptedStream(4096, 4096); + VBAEncryption aEncryption(pData, nLength, aEncryptedStream, + &nSeed, nProjKey); + aEncryption.write(); + sal_uInt8 pExpectedData[] = "1517CAF1D6F9D7F9D706"; + size_t length = sizeof(pExpectedData); + aEncryptedStream.Seek(0); + for (size_t i = 0; i < length; ++i) + { + unsigned char val = 0; + aEncryptedStream.ReadUChar(val); + CPPUNIT_ASSERT_EQUAL((int)pExpectedData[i], (int)sal_uInt8(val)); + } +} + +void TestVbaEncryption::setUp() +{ +} + +void TestVbaEncryption::tearDown() +{ +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaEncryption); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx index 0339203..5be8730 100644 --- a/oox/source/ole/vbaexport.cxx +++ b/oox/source/ole/vbaexport.cxx @@ -47,10 +47,10 @@ #define VBA_USE_ORIGINAL_PROJECT_STREAM 0 #define VBA_USE_ORIGINAL_VBA_PROJECT 0 -#define VBA_ENCRYPTION 0 /* Enable to see VBA Encryption work. For now the input data and length values * for encryption correspond to the case when the VBA macro is not protected. */ +#define VBA_ENCRYPTION 1 namespace { @@ -344,23 +344,24 @@ void VBACompression::write() // section 2.4.3 #if VBA_ENCRYPTION -VBAEncryption::VBAEncryption(const sal_uInt8* pData, const sal_uInt16 length, SvStream& rEncryptedData) +VBAEncryption::VBAEncryption(const sal_uInt8* pData, const sal_uInt16 length, SvStream& rEncryptedData, sal_uInt8* pSeed, sal_uInt8 nProjKey) :mpData(pData) ,mnLength(length) ,mrEncryptedData(rEncryptedData) ,mnEncryptedByte1(0) ,mnEncryptedByte2(0) ,mnVersion(2) - ,mnProjKey(0) + ,mnProjKey(nProjKey) ,mnIgnoredLength(0) - ,mnSeed(0) + ,mnSeed(pSeed ? *pSeed : 0x00) ,mnVersionEnc(0) { + if (!pSeed) + mnSeed = 0xBE; // sample seed value TODO:Generate random seed values } void VBAEncryption::writeSeed() { - mnSeed = 0xBE; // sample seed value TODO:Generate random seed values mrEncryptedData.WriteUInt8(mnSeed); } @@ -372,6 +373,7 @@ void VBAEncryption::writeVersionEnc() void VBAEncryption::writeProjKeyEnc() { + /* OUString mrProjectCLSID = "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"; //TODO:Find the real ProjectId.ProjectClSID sal_Int32 n = mrProjectCLSID.getLength(); const sal_Unicode* pString = mrProjectCLSID.getStr(); @@ -380,6 +382,7 @@ void VBAEncryption::writeProjKeyEnc() sal_Unicode character = pString[i]; mnProjKey += character; } + */ sal_uInt8 nProjKeyEnc = mnSeed ^ mnProjKey; mrEncryptedData.WriteUInt8(nProjKeyEnc); mnUnencryptedByte1 = mnProjKey; @@ -877,7 +880,7 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN SvMemoryStream aProtectedStream(4096, 4096); aProtectedStream.WriteUInt32(0x00000000); const sal_uInt8* pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aProtectionState(pData, 4, rStrm); + VBAEncryption aProtectionState(pData, 4, rStrm, NULL, 0); aProtectionState.write(); exportString(rStrm, "\"\r\n"); #else @@ -890,7 +893,7 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN aProtectedStream.Seek(0); aProtectedStream.WriteUInt8(0x00); pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aProjectPassword(pData, 1, rStrm); + VBAEncryption aProjectPassword(pData, 1, rStrm, NULL, 0); aProjectPassword.write(); exportString(rStrm, "\"\r\n"); #else @@ -903,7 +906,7 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN aProtectedStream.Seek(0); aProtectedStream.WriteUInt8(0xFF); pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); - VBAEncryption aVisibilityState(pData, 1, rStrm); + VBAEncryption aVisibilityState(pData, 1, rStrm, NULL, 0); aVisibilityState.write(); exportString(rStrm, "\"\r\n\r\n"); #else commit c597581852cf1d3550359dc639f1bb7f6476f419 Author: Rosemary <rosemarys...@gmail.com> Date: Sun Oct 4 07:58:21 2015 +0530 Implement encryption for the VBA export Change-Id: Id994095de9f43cf0c2857272b613abe7cbd9324e diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx index 7b5b916..2c03cc27 100644 --- a/include/oox/ole/vbaexport.hxx +++ b/include/oox/ole/vbaexport.hxx @@ -111,6 +111,38 @@ private: SvMemoryStream& mrUncompressedStream; }; +class VBAEncryption +{ +public: + VBAEncryption(const sal_uInt8* pData, + const sal_uInt16 nLength, + SvStream& rEncryptedData + ); + + void write(); + +private: + const sal_uInt8* mpData; // an array of bytes to be obfuscated + const sal_uInt16 mnLength; // the length of Data + SvStream& mrEncryptedData; // Encrypted Data Structure + sal_uInt8 mnUnencryptedByte1; // the last unencrypted byte read or written + sal_uInt8 mnEncryptedByte1; // the last encrypted byte read or written + sal_uInt8 mnEncryptedByte2; // the next-to-last encrypted byte read or written + sal_uInt8 mnVersion; // the encrypted version + sal_Unicode mnProjKey; // a project-specific encryption key + sal_uInt8 mnIgnoredLength; // the length in bytes of IgnoredEnc + + sal_uInt8 mnSeed; // the seed value + sal_uInt8 mnVersionEnc; // the version encoding + + void writeSeed(); + void writeVersionEnc(); + void writeProjKeyEnc(); + void writeIgnoredEnc(); + void writeDataLengthEnc(); + void writeDataEnc(); +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx index eaa8078..0339203 100644 --- a/oox/source/ole/vbaexport.cxx +++ b/oox/source/ole/vbaexport.cxx @@ -47,6 +47,11 @@ #define VBA_USE_ORIGINAL_PROJECT_STREAM 0 #define VBA_USE_ORIGINAL_VBA_PROJECT 0 +#define VBA_ENCRYPTION 0 +/* Enable to see VBA Encryption work. For now the input data and length values + * for encryption correspond to the case when the VBA macro is not protected. + */ + namespace { void exportString(SvStream& rStrm, const OUString& rString) @@ -336,6 +341,105 @@ void VBACompression::write() } } +// section 2.4.3 +#if VBA_ENCRYPTION + +VBAEncryption::VBAEncryption(const sal_uInt8* pData, const sal_uInt16 length, SvStream& rEncryptedData) + :mpData(pData) + ,mnLength(length) + ,mrEncryptedData(rEncryptedData) + ,mnEncryptedByte1(0) + ,mnEncryptedByte2(0) + ,mnVersion(2) + ,mnProjKey(0) + ,mnIgnoredLength(0) + ,mnSeed(0) + ,mnVersionEnc(0) +{ +} + +void VBAEncryption::writeSeed() +{ + mnSeed = 0xBE; // sample seed value TODO:Generate random seed values + mrEncryptedData.WriteUInt8(mnSeed); +} + +void VBAEncryption::writeVersionEnc() +{ + mnVersionEnc = mnSeed ^ mnVersion; + mrEncryptedData.WriteUInt8(mnVersionEnc); +} + +void VBAEncryption::writeProjKeyEnc() +{ + OUString mrProjectCLSID = "{9F10AB9C-89AC-4C0F-8AFB-8E9B96D5F170}"; //TODO:Find the real ProjectId.ProjectClSID + sal_Int32 n = mrProjectCLSID.getLength(); + const sal_Unicode* pString = mrProjectCLSID.getStr(); + for (sal_Int32 i = 0; i < n; ++i) + { + sal_Unicode character = pString[i]; + mnProjKey += character; + } + sal_uInt8 nProjKeyEnc = mnSeed ^ mnProjKey; + mrEncryptedData.WriteUInt8(nProjKeyEnc); + mnUnencryptedByte1 = mnProjKey; + mnEncryptedByte1 = nProjKeyEnc; // ProjKeyEnc + mnEncryptedByte2 = mnVersionEnc; // VersionEnc +} + +void VBAEncryption::writeIgnoredEnc() +{ + mnIgnoredLength = (mnSeed & 6) / 2; + for(sal_Int32 i = 1; i <= mnIgnoredLength; ++i) + { + sal_uInt8 nTempValue = 0xBE; // TODO:Generate a random value + sal_uInt8 nByteEnc = nTempValue ^ (mnEncryptedByte2 + mnUnencryptedByte1); + mrEncryptedData.WriteUInt8(nByteEnc); + mnEncryptedByte2 = mnEncryptedByte1; + mnEncryptedByte1 = nByteEnc; + mnUnencryptedByte1 = nTempValue; + } +} + +void VBAEncryption::writeDataLengthEnc() +{ + sal_uInt16 temp = mnLength; + for(sal_Int8 i = 0; i < 2; ++i) + { + sal_uInt8 nByte = temp & 0xFF; + sal_uInt8 nByteEnc = nByte ^ (mnEncryptedByte2 + mnUnencryptedByte1); + mrEncryptedData.WriteUInt8(nByteEnc); + mnEncryptedByte2 = mnEncryptedByte1; + mnEncryptedByte1 = nByteEnc; + mnUnencryptedByte1 = nByte; + temp >>= 8; + } +} + +void VBAEncryption::writeDataEnc() +{ + for(sal_Int8 i = 0; i < mnLength; i++) + { + sal_uInt8 nByteEnc = mpData[i] ^ (mnEncryptedByte2 + mnUnencryptedByte1); + mrEncryptedData.WriteUInt8(nByteEnc); + mnEncryptedByte2 = mnEncryptedByte1; + mnEncryptedByte1 = nByteEnc; + mnUnencryptedByte1 = mpData[i]; + } +} + +void VBAEncryption::write() +{ + writeSeed(); + writeVersionEnc(); + writeProjKeyEnc(); + writeIgnoredEnc(); + writeDataLengthEnc(); + writeDataEnc(); +} + +#endif + VbaExport::VbaExport(css::uno::Reference<css::frame::XModel> xModel): mxModel(xModel) { @@ -768,13 +872,43 @@ void exportPROJECTStream(SvStream& rStrm, css::uno::Reference<css::container::XN exportString(rStrm, "VersionCompatible32=\"393222000\"\r\n"); // section 2.3.1.15 ProjectProtectionState +#if VBA_ENCRYPTION + exportString(rStrm, "CMG=\""); + SvMemoryStream aProtectedStream(4096, 4096); + aProtectedStream.WriteUInt32(0x00000000); + const sal_uInt8* pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); + VBAEncryption aProtectionState(pData, 4, rStrm); + aProtectionState.write(); + exportString(rStrm, "\"\r\n"); +#else exportString(rStrm, "CMG=\"BEBC9256EEAAA8AEA8AEA8AEA8AE\"\r\n"); +#endif // section 2.3.1.16 ProjectPassword +#if VBA_ENCRYPTION + exportString(rStrm, "DPB=\""); + aProtectedStream.Seek(0); + aProtectedStream.WriteUInt8(0x00); + pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); + VBAEncryption aProjectPassword(pData, 1, rStrm); + aProjectPassword.write(); + exportString(rStrm, "\"\r\n"); +#else exportString(rStrm, "DPB=\"7C7E5014B0D3B1D3B1D3\"\r\n"); +#endif // section 2.3.1.17 ProjectVisibilityState +#if VBA_ENCRYPTION + exportString(rStrm, "GC=\""); + aProtectedStream.Seek(0); + aProtectedStream.WriteUInt8(0xFF); + pData = static_cast<const sal_uInt8*>(aProtectedStream.GetData()); + VBAEncryption aVisibilityState(pData, 1, rStrm); + aVisibilityState.write(); + exportString(rStrm, "\"\r\n\r\n"); +#else exportString(rStrm, "GC=\"3A3816DAD5DBD5DB2A\"\r\n\r\n"); +#endif // section 2.3.1.18 HostExtenders exportString(rStrm, "[Host Extender Info]\r\n" _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits