[Libreoffice-commits] core.git: 5 commits - include/oox oox/CppunitTest_oox_vba_encryption.mk oox/Module_oox.mk oox/qa oox/source

Rosemary rosemaryseb8 at gmail.com
Thu Oct 8 08:46:42 PDT 2015


 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 <rosemaryseb8 at 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.mohrhard at 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 <rosemaryseb8 at 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.mohrhard at 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 <rosemaryseb8 at 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"


More information about the Libreoffice-commits mailing list