[Libreoffice-commits] core.git: Branch 'feature/cib_contract3756b' - 84 commits - basctl/source comphelper/qa comphelper/source configure.ac dictionaries framework/inc framework/Library_fwk.mk framework/source .gitreview helpcontent2 include/oox include/sfx2 include/unotools include/vcl odk/examples odk/settings offapi/com offapi/UnoApi_offapi.mk officecfg/registry oox/Library_oox.mk oox/source oox/util package/source readlicense_oo/license scripting/java scripting/Library_protocolhandler.mk scripting/source sc/source sd/qa sd/sdi sd/source sfx2/sdi sfx2/source svx/source sw/qa sw/sdi sw/source translations unotools/source vcl/inc vcl/source

Thorsten Behrens (via logerrit) logerrit at kemper.freedesktop.org
Wed Dec 4 05:26:00 UTC 2019


Rebased ref, commits from common ancestor:
commit 11efda4c4fcb2b38a77fc18a9239d42757514770
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Wed Dec 4 06:24:26 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:24:26 2019 +0100

    Update default branch
    
    Change-Id: I5bed5207db18747539ce8398ed85619385d51249

diff --git a/.gitreview b/.gitreview
index 042036087fed..fd925839a944 100644
--- a/.gitreview
+++ b/.gitreview
@@ -3,5 +3,5 @@ host=gerrit.libreoffice.org
 port=29418
 project=core
 defaultremote=logerrit
-defaultbranch=libreoffice-6-3-0
+defaultbranch=feature/cib_contract3756b
 
commit a2a5030705fee6f66c25c4fc9c2d51257248e606
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Fri Nov 29 13:07:57 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:23:14 2019 +0100

    tdf#118639: store ODF encryption data for autorecovery
    
    When saving autorecovery information, ODF is used. If the original
    document is password-protected, its autorecovery is also generated
    password-protected (since ef87ff6680f79362a431db6e7ef2f40cfc576219).
    But when the stored encryption data for non-ODF document does not
    contain "PackageSHA256UTF8EncryptionKey" value, following
    ZipPackage::GetEncryptionKey fails, so the whole save fails.
    
    So just generate and append ODF encryption keys where we still have
    user password.
    
    Change-Id: I776e28de784489521e4941d1075690f90c056014
    Reviewed-on: https://gerrit.libreoffice.org/84052
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    
    Conflicts:
            sfx2/source/dialog/filedlghelper.cxx

diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index 9134e7d050a2..af3741347344 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -422,6 +422,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
         bool* pbIsDefaultPassword )
 {
     css::uno::Sequence< css::beans::NamedValue > aEncData;
+    OUString aPassword;
     DocPasswordVerifierResult eResult = DocPasswordVerifierResult::WrongPassword;
 
     // first, try provided default passwords
@@ -435,8 +436,12 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
             if( !rPassword.isEmpty() )
             {
                 eResult = rVerifier.verifyPassword( rPassword, aEncData );
-                if( pbIsDefaultPassword )
-                    *pbIsDefaultPassword = eResult == DocPasswordVerifierResult::OK;
+                if (eResult == DocPasswordVerifierResult::OK)
+                {
+                    aPassword = rPassword;
+                    if (pbIsDefaultPassword)
+                        *pbIsDefaultPassword = true;
+                }
                 if( eResult != DocPasswordVerifierResult::WrongPassword )
                     break;
             }
@@ -458,7 +463,11 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
     if( eResult == DocPasswordVerifierResult::WrongPassword )
     {
         if( !rMediaPassword.isEmpty() )
+        {
             eResult = rVerifier.verifyPassword( rMediaPassword, aEncData );
+            if (eResult == DocPasswordVerifierResult::OK)
+                aPassword = rMediaPassword;
+        }
     }
 
     // request a password (skip, if result is OK or ABORT)
@@ -474,6 +483,8 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
             {
                 if( !pRequest->getPassword().isEmpty() )
                     eResult = rVerifier.verifyPassword( pRequest->getPassword(), aEncData );
+                if (eResult == DocPasswordVerifierResult::OK)
+                    aPassword = pRequest->getPassword();
             }
             else
             {
@@ -486,6 +497,21 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
     {
     }
 
+    if (eResult == DocPasswordVerifierResult::OK && !aPassword.isEmpty())
+    {
+        if (std::find_if(std::cbegin(aEncData), std::cend(aEncData),
+                         [](const css::beans::NamedValue& val) {
+                             return val.Name == PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
+                         })
+            == std::cend(aEncData))
+        {
+            // tdf#118639: We need ODF encryption data for autorecovery, where password
+            // will already be unavailable, so generate and append it here
+            aEncData = comphelper::concatSequences(
+                aEncData, OStorageHelper::CreatePackageEncryptionData(aPassword));
+        }
+    }
+
     return (eResult == DocPasswordVerifierResult::OK) ? aEncData : uno::Sequence< beans::NamedValue >();
 }
 
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index 28f7d1179824..a2167c3a255b 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -2727,6 +2727,8 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter,
     {
         if ( pPasswordRequest->getPassword().getLength() )
         {
+            css::uno::Sequence< css::beans::NamedValue > aEncryptionData;
+
             // TODO/LATER: The filters should show the password dialog themself in future
             if ( bMSType )
             {
@@ -2736,7 +2738,7 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter,
                     ::comphelper::SequenceAsHashMap aHashData;
                     aHashData[ OUString( "OOXPassword"  ) ] <<= pPasswordRequest->getPassword();
                     aHashData[ OUString( "CryptoType" ) ] <<= OUString( "Standard" );
-                    pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) );
+                    aEncryptionData = aHashData.getAsConstNamedValueList();
                 }
                 else
                 {
@@ -2749,7 +2751,7 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter,
                         aHashData[ OUString( "STD97EncryptionKey"  ) ] <<= aEncryptionKey;
                         aHashData[ OUString( "STD97UniqueID"  ) ] <<= aUniqueID;
 
-                        pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) );
+                        aEncryptionData = aHashData.getAsConstNamedValueList();
                     }
                     else
                     {
@@ -2757,10 +2759,14 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter,
                     }
                 }
             }
-            else
-            {
-                pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest->getPassword() ) ) ) );
-            }
+
+            // tdf#118639: We need ODF encryption data for autorecovery where password will already
+            // be unavailable, even for non-ODF documents, so append it here unconditionally
+            pSet->Put(SfxUnoAnyItem(
+                SID_ENCRYPTIONDATA,
+                uno::makeAny(comphelper::concatSequences(
+                    aEncryptionData, comphelper::OStorageHelper::CreatePackageEncryptionData(
+                                         pPasswordRequest->getPassword())))));
         }
 
         if ( pPasswordRequest->getRecommendReadOnly() )
commit ecd76fe0201975e809dc5772b4caba0acc336b49
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 29 11:57:51 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:20:14 2019 +0100

    oox: fixes for cang errors after refactoring:
    
    Change-Id: I6c0ff55e3a6d3edbac78aa6e806da4a290af142d

diff --git a/include/oox/crypto/DocumentDecryption.hxx b/include/oox/crypto/DocumentDecryption.hxx
index d1754c791a4a..d188336a07d6 100644
--- a/include/oox/crypto/DocumentDecryption.hxx
+++ b/include/oox/crypto/DocumentDecryption.hxx
@@ -35,10 +35,10 @@ namespace crypto {
 class OOX_DLLPUBLIC DocumentDecryption
 {
 private:
+    css::uno::Reference< css::uno::XComponentContext > mxContext;
     oox::ole::OleStorage&                      mrOleStorage;
     css::uno::Sequence<css::beans::NamedValue> maStreamsSequence;
     css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption;
-    css::uno::Reference< css::uno::XComponentContext > mxContext;
 
 public:
     DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, oox::ole::OleStorage& rOleStorage);
diff --git a/include/oox/crypto/DocumentEncryption.hxx b/include/oox/crypto/DocumentEncryption.hxx
index f87eaac8342c..2172c842deb6 100644
--- a/include/oox/crypto/DocumentEncryption.hxx
+++ b/include/oox/crypto/DocumentEncryption.hxx
@@ -20,6 +20,7 @@
 namespace com { namespace sun { namespace star {
     namespace io { class XStream; }
     namespace packages { class XPackageEncryption; }
+    namespace beans { struct NamedValue; }
 } } }
 
 namespace oox { namespace ole { class OleStorage; } }
@@ -30,11 +31,11 @@ namespace crypto {
 class OOX_DLLPUBLIC DocumentEncryption
 {
 private:
+    css::uno::Reference< css::uno::XComponentContext > mxContext;
     css::uno::Reference< css::io::XStream > mxDocumentStream;
     oox::ole::OleStorage& mrOleStorage;
     css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption;
     const css::uno::Sequence< css::beans::NamedValue >& mMediaEncData;
-    css::uno::Reference< css::uno::XComponentContext > mxContext;
 
 public:
     DocumentEncryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
diff --git a/include/oox/crypto/StrongEncryptionDataSpace.hxx b/include/oox/crypto/StrongEncryptionDataSpace.hxx
index d3eb76a2c1a8..966185c94612 100644
--- a/include/oox/crypto/StrongEncryptionDataSpace.hxx
+++ b/include/oox/crypto/StrongEncryptionDataSpace.hxx
@@ -12,6 +12,7 @@
 #define INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX
 
 #include <oox/dllapi.h>
+#include <cppuhelper/implbase.hxx>
 #include <com/sun/star/packages/XPackageEncryption.hpp>
 #include <com/sun/star/io/XInputStream.hpp>
 #include <oox/crypto/CryptoEngine.hxx>
commit 5e12769a3f03314b1b7e8f3b1a96c831cda39ab5
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Tue Nov 26 11:08:14 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:19:58 2019 +0100

    oox: encryption engines refactoring
    
    Restore original state of Agile and Standard 2007 engines.
    Instead of standalone services for each of them
    use newly introduced wrapper service.
    
    Change-Id: Icc32a4e0ce215090c3b739f1dcaa0654b36b7f08
    
    Conflicts:
            include/oox/crypto/AgileEngine.hxx
            include/oox/crypto/Standard2007Engine.hxx

diff --git a/include/oox/crypto/AgileEngine.hxx b/include/oox/crypto/AgileEngine.hxx
index de3836ffdb19..7c923c0f2cd6 100644
--- a/include/oox/crypto/AgileEngine.hxx
+++ b/include/oox/crypto/AgileEngine.hxx
@@ -15,19 +15,17 @@
 
 #include <oox/dllapi.h>
 #include <oox/crypto/CryptTools.hxx>
+#include <oox/crypto/CryptoEngine.hxx>
 #include <rtl/ustring.hxx>
 #include <sal/types.h>
-#include <com/sun/star/packages/XPackageEncryption.hpp>
 
 namespace oox {
     class BinaryXInputStream;
     class BinaryXOutputStream;
 }
 
-namespace com::sun::star::uno { class XComponentContext; }
-
 namespace oox {
-namespace core {
+namespace crypto {
 
 struct OOX_DLLPUBLIC AgileEncryptionInfo
 {
@@ -76,15 +74,11 @@ enum class AgileEncryptionPreset
     AES_256_SHA512,
 };
 
-class OOX_DLLPUBLIC AgileEngine : public cppu::WeakImplHelper<css::packages::XPackageEncryption>
+class OOX_DLLPUBLIC AgileEngine : public CryptoEngine
 {
 private:
-    std::vector<sal_uInt8> mKey;
     AgileEncryptionInfo mInfo;
     AgileEncryptionPreset meEncryptionPreset;
-    css::uno::Reference< css::uno::XComponentContext > mxContext;
-
-    css::uno::Reference<css::io::XInputStream> getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName);
 
     void calculateHashFinal(const OUString& rPassword, std::vector<sal_uInt8>& aHashFinal);
 
@@ -102,58 +96,52 @@ private:
 
     static Crypto::CryptoType cryptoType(const AgileEncryptionInfo& rInfo);
 
-    // Decryption
-
-    bool decryptHmacKey();
-    bool decryptHmacValue();
+public:
+    AgileEngine();
 
-    AgileEncryptionInfo& getInfo() { return mInfo; }
+    AgileEncryptionInfo& getInfo() { return mInfo;}
 
     void setPreset(AgileEncryptionPreset ePreset)
     {
         meEncryptionPreset = ePreset;
     }
 
+    // Decryption
+
     void decryptEncryptionKey(OUString const & rPassword);
     bool decryptAndCheckVerifierHash(OUString const & rPassword);
 
-    // Encryption
-
-    bool encryptHmacKey();
-    bool encryptHmacValue();
-
-    bool generateAndEncryptVerifierHash(OUString const & rPassword);
-
-    bool encryptEncryptionKey(OUString const & rPassword);
-    void setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters);
-    bool setupEncryptionKey(OUString const & rPassword);
-
-    css::uno::Sequence<sal_Int8> writeEncryptionInfo();
-    css::uno::Sequence<sal_Int8> writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream);
+    bool generateEncryptionKey(OUString const & rPassword) override;
+    bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) override;
+    bool decrypt(BinaryXInputStream& aInputStream,
+                 BinaryXOutputStream& aOutputStream) override;
 
-public:
-    AgileEngine(const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+    bool checkDataIntegrity() override;
 
-    // Decryption
+    bool decryptHmacKey();
+    bool decryptHmacValue();
 
-    virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString & rPassword) override;
-    virtual sal_Bool SAL_CALL readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override;
-    virtual sal_Bool SAL_CALL decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
-                 css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override;
+    // Encryption
 
+    void writeEncryptionInfo(BinaryXOutputStream& rStream) override;
 
-    virtual sal_Bool SAL_CALL checkDataIntegrity() override;
+    void encrypt(const css::uno::Reference<css::io::XInputStream>&  rxInputStream,
+                 css::uno::Reference<css::io::XOutputStream>& rxOutputStream,
+                 sal_uInt32 nSize) override;
 
-    // Encryption
+    bool setupEncryption(OUString const & rPassword) override;
 
-    virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override;
+    bool generateAndEncryptVerifierHash(OUString const & rPassword);
 
-    virtual sal_Bool SAL_CALL setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override;
+    bool encryptHmacKey();
+    bool encryptHmacValue();
 
-    virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL createEncryptionData(const OUString& rPassword) override;
+    bool encryptEncryptionKey(OUString const & rPassword);
+    void setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters);
+    bool setupEncryptionKey(OUString const & rPassword);
 };
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 #endif
diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx
index 80d52cbeed74..2489cafe3c9c 100644
--- a/include/oox/crypto/CryptTools.hxx
+++ b/include/oox/crypto/CryptTools.hxx
@@ -28,7 +28,7 @@
 #include <memory>
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 /** Rounds up the input to the nearest multiple
  *
@@ -115,7 +115,7 @@ public:
 };
 
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 #endif
diff --git a/include/oox/crypto/CryptoEngine.hxx b/include/oox/crypto/CryptoEngine.hxx
new file mode 100644
index 000000000000..72bde8920dfc
--- /dev/null
+++ b/include/oox/crypto/CryptoEngine.hxx
@@ -0,0 +1,68 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_OOX_CRYPTO_CRYPTOENGINE_HXX
+#define INCLUDED_OOX_CRYPTO_CRYPTOENGINE_HXX
+
+#include <vector>
+
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+namespace oox {
+    class BinaryXInputStream;
+    class BinaryXOutputStream;
+}
+
+namespace oox {
+namespace crypto {
+
+class CryptoEngine
+{
+protected:
+    std::vector<sal_uInt8> mKey;
+
+public:
+    CryptoEngine()
+    {}
+
+    virtual ~CryptoEngine()
+    {}
+
+    // Decryption
+    virtual bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) = 0;
+
+    virtual bool generateEncryptionKey(const OUString& rPassword) = 0;
+
+    virtual bool decrypt(
+                    BinaryXInputStream& aInputStream,
+                    BinaryXOutputStream& aOutputStream) = 0;
+
+    // Encryption
+    virtual void writeEncryptionInfo(BinaryXOutputStream & rStream) = 0;
+
+    virtual bool setupEncryption(const OUString& rPassword) = 0;
+
+    virtual void encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream,
+                         css::uno::Reference<css::io::XOutputStream> & rxOutputStream,
+                         sal_uInt32 nSize) = 0;
+
+    virtual bool checkDataIntegrity() = 0;
+};
+
+} // namespace crypto
+} // namespace oox
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/oox/crypto/DocumentDecryption.hxx b/include/oox/crypto/DocumentDecryption.hxx
index fdea2c25f9f7..d1754c791a4a 100644
--- a/include/oox/crypto/DocumentDecryption.hxx
+++ b/include/oox/crypto/DocumentDecryption.hxx
@@ -30,7 +30,7 @@ namespace com { namespace sun { namespace star {
 namespace oox { namespace ole { class OleStorage; } }
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 class OOX_DLLPUBLIC DocumentDecryption
 {
@@ -40,8 +40,6 @@ private:
     css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption;
     css::uno::Reference< css::uno::XComponentContext > mxContext;
 
-    void readStrongEncryptionInfo();
-
 public:
     DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, oox::ole::OleStorage& rOleStorage);
 
@@ -53,7 +51,7 @@ public:
 
 };
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 #endif
diff --git a/include/oox/crypto/DocumentEncryption.hxx b/include/oox/crypto/DocumentEncryption.hxx
index c99cadc972f4..f87eaac8342c 100644
--- a/include/oox/crypto/DocumentEncryption.hxx
+++ b/include/oox/crypto/DocumentEncryption.hxx
@@ -25,7 +25,7 @@ namespace com { namespace sun { namespace star {
 namespace oox { namespace ole { class OleStorage; } }
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 class OOX_DLLPUBLIC DocumentEncryption
 {
@@ -46,7 +46,7 @@ public:
 
 };
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 #endif
diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx
index d1ab8039d772..fef8fc55bab0 100644
--- a/include/oox/crypto/Standard2007Engine.hxx
+++ b/include/oox/crypto/Standard2007Engine.hxx
@@ -12,7 +12,7 @@
 #define INCLUDED_OOX_CRYPTO_STANDARD2007ENGINE_HXX
 
 #include <oox/dllapi.h>
-#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <oox/crypto/CryptoEngine.hxx>
 #include <filter/msfilter/mscodec.hxx>
 #include <rtl/digest.h>
 #include <rtl/ustring.hxx>
@@ -23,47 +23,40 @@ namespace oox {
     class BinaryXOutputStream;
 }
 
-namespace com::sun::star::uno { class XComponentContext; }
-
 namespace oox {
-namespace core {
+namespace crypto {
 
-class OOX_DLLPUBLIC Standard2007Engine : public cppu::WeakImplHelper<css::packages::XPackageEncryption>
+class OOX_DLLPUBLIC Standard2007Engine : public CryptoEngine
 {
     msfilter::StandardEncryptionInfo mInfo;
-    std::vector<sal_uInt8> mKey;
-    css::uno::Reference< css::uno::XComponentContext > mxContext;
 
     bool generateVerifier();
     bool calculateEncryptionKey(const OUString& rPassword);
 
-    css::uno::Reference<css::io::XInputStream> getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName);
-    css::uno::Sequence<sal_Int8> writeEncryptionInfo();
-    css::uno::Sequence<sal_Int8> writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream);
-
 public:
-    Standard2007Engine(const css::uno::Reference<css::uno::XComponentContext>& rxContext);
+    Standard2007Engine() = default;
 
-    // Decryption
+    bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) override;
 
-    virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString & rPassword) override;
-    virtual sal_Bool SAL_CALL readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override;
-    virtual sal_Bool SAL_CALL decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
-                 css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override;
+    virtual bool generateEncryptionKey(OUString const & rPassword) override;
 
+    virtual bool decrypt(
+                    BinaryXInputStream& aInputStream,
+                    BinaryXOutputStream& aOutputStream) override;
 
-    virtual sal_Bool SAL_CALL checkDataIntegrity() override;
+    bool checkDataIntegrity() override;
 
-    // Encryption
+    void encrypt(const css::uno::Reference<css::io::XInputStream>&  rxInputStream,
+                 css::uno::Reference<css::io::XOutputStream>& rxOutputStream,
+                 sal_uInt32 nSize) override;
 
-    virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override;
+    virtual void writeEncryptionInfo(BinaryXOutputStream& rStream) override;
 
-    virtual sal_Bool SAL_CALL setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override;
+    virtual bool setupEncryption(OUString const & rPassword) override;
 
-    virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL createEncryptionData(const OUString& rPassword) override;
 };
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 #endif
diff --git a/include/oox/crypto/StrongEncryptionDataSpace.hxx b/include/oox/crypto/StrongEncryptionDataSpace.hxx
new file mode 100644
index 000000000000..d3eb76a2c1a8
--- /dev/null
+++ b/include/oox/crypto/StrongEncryptionDataSpace.hxx
@@ -0,0 +1,69 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX
+#define INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX
+
+#include <oox/dllapi.h>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <oox/crypto/CryptoEngine.hxx>
+
+namespace com::sun::star::uno
+{
+class XComponentContext;
+}
+
+namespace oox
+{
+namespace crypto
+{
+class OOX_DLLPUBLIC StrongEncryptionDataSpace final
+    : public cppu::WeakImplHelper<css::packages::XPackageEncryption>
+{
+    css::uno::Reference<css::uno::XComponentContext> mxContext;
+    std::unique_ptr<CryptoEngine> mCryptoEngine;
+
+    css::uno::Reference<css::io::XInputStream>
+    getStream(const css::uno::Sequence<css::beans::NamedValue>& rStreams,
+              const rtl::OUString sStreamName);
+
+public:
+    StrongEncryptionDataSpace(const css::uno::Reference<css::uno::XComponentContext>& rxContext);
+
+    // Decryption
+
+    virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString& rPassword) override;
+    virtual sal_Bool SAL_CALL
+    readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override;
+    virtual sal_Bool SAL_CALL
+    decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
+            css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override;
+
+    virtual sal_Bool SAL_CALL checkDataIntegrity() override;
+
+    // Encryption
+
+    virtual css::uno::Sequence<css::beans::NamedValue>
+        SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override;
+
+    virtual sal_Bool SAL_CALL
+    setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override;
+
+    virtual css::uno::Sequence<css::beans::NamedValue>
+        SAL_CALL createEncryptionData(const OUString& rPassword) override;
+};
+
+} // namespace crypto
+} // namespace oox
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index 2d4718a320cb..51b61a931cd1 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -102,6 +102,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
     oox/source/crypto/DocumentEncryption \
     oox/source/crypto/DocumentDecryption \
     oox/source/crypto/Standard2007Engine \
+    oox/source/crypto/StrongEncryptionDataSpace \
     oox/source/docprop/docprophandler \
     oox/source/docprop/ooxmldocpropimport \
     oox/source/drawingml/chart/axiscontext \
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index f59b15c56df9..565ac9c8d9a6 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -250,16 +250,16 @@ bool lclIsZipPackage( const Reference< XComponentContext >& rxContext, const Ref
 class PasswordVerifier : public IDocPasswordVerifier
 {
 public:
-    explicit PasswordVerifier( DocumentDecryption& aDecryptor );
+    explicit PasswordVerifier( crypto::DocumentDecryption& aDecryptor );
 
     virtual DocPasswordVerifierResult verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData ) override;
 
     virtual DocPasswordVerifierResult verifyEncryptionData( const Sequence<NamedValue>& rEncryptionData ) override;
 private:
-    DocumentDecryption& mDecryptor;
+    crypto::DocumentDecryption& mDecryptor;
 };
 
-PasswordVerifier::PasswordVerifier( DocumentDecryption& aDecryptor ) :
+PasswordVerifier::PasswordVerifier( crypto::DocumentDecryption& aDecryptor ) :
     mDecryptor(aDecryptor)
 {}
 
@@ -308,7 +308,7 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
     {
         try
         {
-            DocumentDecryption aDecryptor(mxContext, aOleStorage);
+            crypto::DocumentDecryption aDecryptor(mxContext, aOleStorage);
 
             if( aDecryptor.readEncryptionInfo() )
             {
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index fe7e541de4b3..91be91736911 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -908,7 +908,7 @@ bool XmlFilterBase::implFinalizeExport( MediaDescriptor& rMediaDescriptor )
 
         Reference< XStream> xDocumentStream (FilterBase::implGetOutputStream(rMediaDescriptor));
         oox::ole::OleStorage aOleStorage( getComponentContext(), xDocumentStream, true );
-        DocumentEncryption encryptor( getComponentContext(), getMainDocumentStream(), aOleStorage, aMediaEncData );
+        crypto::DocumentEncryption encryptor( getComponentContext(), getMainDocumentStream(), aOleStorage, aMediaEncData );
         bRet = encryptor.encrypt();
         if (bRet)
             aOleStorage.commit();
diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx
index fea1498cc8b9..e232a7ef94c3 100644
--- a/oox/source/crypto/AgileEngine.cxx
+++ b/oox/source/crypto/AgileEngine.cxx
@@ -21,7 +21,6 @@
 #include <comphelper/processfactory.hxx>
 #include <comphelper/base64.hxx>
 #include <comphelper/sequence.hxx>
-#include <comphelper/sequenceashashmap.hxx>
 
 #include <filter/msfilter/mscodec.hxx>
 #include <tools/stream.hxx>
@@ -29,8 +28,6 @@
 
 #include <com/sun/star/io/XSeekable.hpp>
 #include <com/sun/star/io/XStream.hpp>
-#include <com/sun/star/io/SequenceInputStream.hpp>
-#include <com/sun/star/io/XSequenceOutputStream.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/xml/sax/XFastParser.hpp>
 #include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
@@ -46,15 +43,7 @@ using namespace css::xml::sax;
 using namespace css::xml;
 
 namespace oox {
-namespace core {
-
-extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
-    com_sun_star_comp_oox_crypto_Agile_get_implementation(
-        XComponentContext* pCtx, Sequence<Any> const& /*arguments*/)
-{
-    return cppu::acquire(new AgileEngine(pCtx/*, arguments*/));
-}
-
+namespace crypto {
 
 namespace {
 
@@ -159,13 +148,13 @@ public:
                 comphelper::Base64::decode(encryptedKeyValue, rAttribute.Value);
                 mInfo.encryptedKeyValue = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(encryptedKeyValue);
             }
-            else if (rAttrLocalName == "encryptedHmacKey")
+            if (rAttrLocalName == "encryptedHmacKey")
             {
                 Sequence<sal_Int8> aValue;
                 comphelper::Base64::decode(aValue, rAttribute.Value);
                 mInfo.hmacEncryptedKey = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(aValue);
             }
-            else if (rAttrLocalName == "encryptedHmacValue")
+            if (rAttrLocalName == "encryptedHmacValue")
             {
                 Sequence<sal_Int8> aValue;
                 comphelper::Base64::decode(aValue, rAttribute.Value);
@@ -229,9 +218,8 @@ CryptoHashType cryptoHashTypeFromString(OUString const & sAlgorithm)
 
 } // namespace
 
-AgileEngine::AgileEngine(const Reference< XComponentContext >& rxContext) :
-    meEncryptionPreset(AgileEncryptionPreset::AES_256_SHA512),
-    mxContext(rxContext)
+AgileEngine::AgileEngine()
+    : meEncryptionPreset(AgileEncryptionPreset::AES_256_SHA512)
 {}
 
 Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo)
@@ -358,7 +346,7 @@ void AgileEngine::decryptEncryptionKey(OUString const & rPassword)
 }
 
 // TODO: Rename
-sal_Bool AgileEngine::generateEncryptionKey(OUString const & rPassword)
+bool AgileEngine::generateEncryptionKey(OUString const & rPassword)
 {
     bool bResult = decryptAndCheckVerifierHash(rPassword);
 
@@ -422,7 +410,7 @@ bool AgileEngine::decryptHmacValue()
     return true;
 }
 
-sal_Bool AgileEngine::checkDataIntegrity()
+bool AgileEngine::checkDataIntegrity()
 {
     bool bResult = (mInfo.hmacHash.size() == mInfo.hmacCalculatedHash.size() &&
                std::equal(mInfo.hmacHash.begin(), mInfo.hmacHash.end(), mInfo.hmacCalculatedHash.begin()));
@@ -430,14 +418,11 @@ sal_Bool AgileEngine::checkDataIntegrity()
     return bResult;
 }
 
-sal_Bool AgileEngine::decrypt(const css::uno::Reference<css::io::XInputStream>&  rxInputStream,
-    css::uno::Reference<css::io::XOutputStream>& rxOutputStream)
+bool AgileEngine::decrypt(BinaryXInputStream& aInputStream,
+                          BinaryXOutputStream& aOutputStream)
 {
     CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm));
 
-    BinaryXInputStream aInputStream(rxInputStream, true);
-    BinaryXOutputStream aOutputStream(rxOutputStream, true);
-
     sal_uInt32 totalSize = aInputStream.readuInt32(); // Document unencrypted size - 4 bytes
     // account for size in HMAC
     std::vector<sal_uInt8> aSizeBytes(sizeof(sal_uInt32));
@@ -495,39 +480,17 @@ sal_Bool AgileEngine::decrypt(const css::uno::Reference<css::io::XInputStream>&
 
     mInfo.hmacCalculatedHash = aCryptoHash.finalize();
 
-    rxOutputStream->flush();
-
     return true;
 }
 
-uno::Reference<io::XInputStream> AgileEngine::getStream(const Sequence<NamedValue> & rStreams, const OUString sStreamName)
+bool AgileEngine::readEncryptionInfo(uno::Reference<io::XInputStream> & rxInputStream)
 {
-    for (const auto & aStream : rStreams)
-    {
-        if (aStream.Name == sStreamName)
-        {
-            css::uno::Sequence<sal_Int8> aSeq;
-            aStream.Value >>= aSeq;
-            Reference<XInputStream> aStream(io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq), UNO_QUERY_THROW);
-            return aStream;
-        }
-    }
-    return nullptr;
-}
-
-sal_Bool AgileEngine::readEncryptionInfo(const Sequence<NamedValue>& aStreams)
-{
-    uno::Reference<io::XInputStream> xEncryptionInfo = getStream(aStreams, "EncryptionInfo");
-
-    BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true);
-    aBinaryInputStream.readuInt32();    // Version
-
     // Check reserved value
     std::vector<sal_uInt8> aExpectedReservedBytes(sizeof(sal_uInt32));
     ByteOrderConverter::writeLittleEndian(aExpectedReservedBytes.data(), msfilter::AGILE_ENCRYPTION_RESERVED);
 
     uno::Sequence<sal_Int8> aReadReservedBytes(sizeof(sal_uInt32));
-    xEncryptionInfo->readBytes(aReadReservedBytes, aReadReservedBytes.getLength());
+    rxInputStream->readBytes(aReadReservedBytes, aReadReservedBytes.getLength());
 
     if (!std::equal(aReadReservedBytes.begin(), aReadReservedBytes.end(), aExpectedReservedBytes.begin()))
         return false;
@@ -547,7 +510,7 @@ sal_Bool AgileEngine::readEncryptionInfo(const Sequence<NamedValue>& aStreams)
     xParser->setTokenHandler(xFastTokenHandler);
 
     InputSource aInputSource;
-    aInputSource.aInputStream = xEncryptionInfo;
+    aInputSource.aInputStream = rxInputStream;
     xParser->parseStream(aInputSource);
 
     // CHECK info data
@@ -619,7 +582,7 @@ bool AgileEngine::encryptHmacKey()
         return false;
 
     // Encrypted salt must be multiple of block size
-    sal_Int32 nEncryptedSaltSize = oox::core::roundUp(mInfo.hashSize, mInfo.blockSize);
+    sal_Int32 nEncryptedSaltSize = oox::crypto::roundUp(mInfo.hashSize, mInfo.blockSize);
 
     // We need to extend hmacSalt to multiple of block size, padding with 0x36
     std::vector<sal_uInt8> extendedSalt(mInfo.hmacKey);
@@ -695,33 +658,14 @@ bool AgileEngine::encryptEncryptionKey(OUString const & rPassword)
     return true;
 }
 
-sal_Bool AgileEngine::setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData)
+bool AgileEngine::setupEncryption(OUString const & rPassword)
 {
     if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA1)
         setupEncryptionParameters({ 100000, 16, 128, 20, 16, OUString("AES"), OUString("ChainingModeCBC"), OUString("SHA1") });
     else
         setupEncryptionParameters({ 100000, 16, 256, 64, 16, OUString("AES"), OUString("ChainingModeCBC"), OUString("SHA512") });
 
-    OUString sPassword;
-    for (int i = 0; i < rMediaEncData.getLength(); i++)
-    {
-        if (rMediaEncData[i].Name == "OOXPassword")
-        {
-            OUString sCryptoType;
-            rMediaEncData[i].Value >>= sPassword;
-        }
-    }
-
-    return setupEncryptionKey(sPassword);
-}
-
-uno::Sequence<beans::NamedValue> AgileEngine::createEncryptionData(const OUString & rPassword)
-{
-    comphelper::SequenceAsHashMap aEncryptionData;
-    aEncryptionData["OOXPassword"] <<= rPassword;
-    aEncryptionData["CryptoType"] <<= OUString("AgileEngine");
-
-    return aEncryptionData.getAsConstNamedValueList();
+    return setupEncryptionKey(rPassword);
 }
 
 void AgileEngine::setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters)
@@ -755,13 +699,8 @@ bool AgileEngine::setupEncryptionKey(OUString const & rPassword)
     return true;
 }
 
-css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptionInfo()
+void AgileEngine::writeEncryptionInfo(BinaryXOutputStream & rStream)
 {
-    Reference<XOutputStream> aEncryptionInfoStream(
-        mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext),
-        UNO_QUERY);
-    BinaryXOutputStream rStream(aEncryptionInfoStream, false);
-
     rStream.WriteUInt32(msfilter::VERSION_INFO_AGILE);
     rStream.WriteUInt32(msfilter::AGILE_ENCRYPTION_RESERVED);
 
@@ -815,29 +754,19 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptionInfo()
         aXmlWriter.endDocument();
     }
     rStream.writeMemory(aMemStream.GetData(), aMemStream.GetSize());
-
-    rStream.close();
-    aEncryptionInfoStream->flush();
-
-    Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream, UNO_QUERY);
-    return aEncryptionInfoSequenceStream->getWrittenBytes();
 }
 
-css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream)
+void AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> &  rxInputStream,
+                          css::uno::Reference<css::io::XOutputStream> & rxOutputStream,
+                          sal_uInt32 nSize)
 {
     CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm));
 
-    Reference<XOutputStream> aOutputStream(
-        mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext),
-        UNO_QUERY);
-    BinaryXOutputStream aBinaryOutputStream(aOutputStream, false);
-
+    BinaryXOutputStream aBinaryOutputStream(rxOutputStream, false);
     BinaryXInputStream aBinaryInputStream(rxInputStream, false);
-    Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY);
-    sal_uInt32 nLength = xSeekable->getLength();
 
     std::vector<sal_uInt8> aSizeBytes(sizeof(sal_uInt32));
-    ByteOrderConverter::writeLittleEndian(aSizeBytes.data(), nLength);
+    ByteOrderConverter::writeLittleEndian(aSizeBytes.data(), nSize);
     aBinaryOutputStream.writeMemory(aSizeBytes.data(), aSizeBytes.size()); // size
     aCryptoHash.update(aSizeBytes, aSizeBytes.size());
 
@@ -867,7 +796,7 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno:
     while ((inputLength = aBinaryInputStream.readMemory(inputBuffer.data(), inputBuffer.size())) > 0)
     {
         sal_uInt32 correctedInputLength = inputLength % mInfo.blockSize == 0 ?
-                        inputLength : oox::core::roundUp(inputLength, sal_uInt32(mInfo.blockSize));
+                        inputLength : oox::crypto::roundUp(inputLength, sal_uInt32(mInfo.blockSize));
 
         // Update Key
         sal_uInt8* segmentBegin = reinterpret_cast<sal_uInt8*>(&nSegment);
@@ -888,21 +817,9 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno:
     }
     mInfo.hmacHash = aCryptoHash.finalize();
     encryptHmacValue();
-
-    Reference<XSequenceOutputStream> aSequenceStream(aOutputStream, UNO_QUERY);
-    return aSequenceStream->getWrittenBytes();
-}
-
-
-css::uno::Sequence<css::beans::NamedValue> AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> &  rxInputStream)
-{
-    comphelper::SequenceAsHashMap aStreams;
-    aStreams["EncryptedPackage"] <<= writeEncryptedDocument(rxInputStream);
-    aStreams["EncryptionInfo"] <<= writeEncryptionInfo();
-    return aStreams.getAsConstNamedValueList();
 }
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx
index 96290e0dc5fc..f1c2b6bbb2ee 100644
--- a/oox/source/crypto/CryptTools.cxx
+++ b/oox/source/crypto/CryptTools.cxx
@@ -25,7 +25,7 @@
 #endif // USE_TLS_NSS
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 #if USE_TLS_OPENSSL
 struct CryptoImpl
@@ -481,7 +481,7 @@ std::vector<sal_uInt8> CryptoHash::finalize()
     return aHash;
 }
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx
index 8c8c52dd4a42..93398475d383 100644
--- a/oox/source/crypto/DocumentDecryption.cxx
+++ b/oox/source/crypto/DocumentDecryption.cxx
@@ -21,6 +21,14 @@
 #include <oox/ole/olestorage.hxx>
 #include <filter/msfilter/mscodec.hxx>
 
+#include <com/sun/star/task/PasswordRequestMode.hpp>
+#include <comphelper/docpasswordrequest.hxx>
+#include <comphelper/stillreadwriteinteraction.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/task/PasswordContainer.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+
+
 namespace {
 
 void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rElementNames)
@@ -47,7 +55,7 @@ void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rEl
 }
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 using namespace css;
 
@@ -84,33 +92,6 @@ bool DocumentDecryption::generateEncryptionKey(const OUString& rPassword)
     return false;
 }
 
-void DocumentDecryption::readStrongEncryptionInfo()
-{
-    uno::Reference<io::XInputStream> xEncryptionInfo = mrOleStorage.openInputStream("EncryptionInfo");
-
-    BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true);
-    sal_uInt32 aVersion = aBinaryInputStream.readuInt32();
-
-    uno::Sequence< uno::Any > aArguments;
-
-    switch (aVersion)
-    {
-    case msfilter::VERSION_INFO_2007_FORMAT:
-    case msfilter::VERSION_INFO_2007_FORMAT_SP2:
-        mxPackageEncryption.set(
-            mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
-                "com.sun.star.comp.oox.crypto.Standard2007Engine", aArguments, mxContext), css::uno::UNO_QUERY);
-        break;
-    case msfilter::VERSION_INFO_AGILE:
-        mxPackageEncryption.set(
-            mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
-                "com.sun.star.comp.oox.crypto.AgileEngine", aArguments, mxContext), css::uno::UNO_QUERY);
-        break;
-    default:
-        break;
-    }
-}
-
 bool DocumentDecryption::readEncryptionInfo()
 {
     if (!mrOleStorage.isStorage())
@@ -118,6 +99,8 @@ bool DocumentDecryption::readEncryptionInfo()
 
     // Read 0x6DataSpaces/DataSpaceMap
     uno::Reference<io::XInputStream> xDataSpaceMap = mrOleStorage.openInputStream("\006DataSpaces/DataSpaceMap");
+    OUString sDataSpaceName;
+
     if (xDataSpaceMap.is())
     {
         BinaryXInputStream aDataSpaceStream(xDataSpaceMap, true);
@@ -126,7 +109,6 @@ bool DocumentDecryption::readEncryptionInfo()
         sal_uInt32 aEntryCount = aDataSpaceStream.readuInt32();
         SAL_WARN_IF(aEntryCount != 1, "oox", "DataSpaceMap contains more than one entry. Some content may be skipped");
 
-        OUString sDataSpaceName;
         // Read each DataSpaceMapEntry (MS-OFFCRYPTO 2.1.6.1)
         for (sal_uInt32 i = 0; i < aEntryCount; i++)
         {
@@ -147,25 +129,20 @@ bool DocumentDecryption::readEncryptionInfo()
             sDataSpaceName = aDataSpaceStream.readUnicodeArray(aDataSpaceNameLength / 2);
             aDataSpaceStream.skip((4 - (aDataSpaceNameLength & 3)) & 3);  // Skip padding
         }
-
-        uno::Sequence< uno::Any > aArguments;
-        mxPackageEncryption.set(
-            mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
-                "com.sun.star.comp.oox.crypto." + sDataSpaceName, aArguments, mxContext), css::uno::UNO_QUERY);
-
-        if (!mxPackageEncryption.is() && sDataSpaceName == "StrongEncryptionDataSpace")
-        {
-            readStrongEncryptionInfo();
-        }
     }
     else
     {
         // Fallback for documents generated by LO: they sometimes do not have all
         // required by MS-OFFCRYPTO specification streams (0x6DataSpaces/DataSpaceMap and others)
         SAL_WARN("oox", "Encrypted package does not contain DataSpaceMap");
-        readStrongEncryptionInfo();
+        sDataSpaceName = "StrongEncryptionDataSpace";
     }
 
+    uno::Sequence< uno::Any > aArguments;
+    mxPackageEncryption.set(
+        mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            "com.sun.star.comp.oox.crypto." + sDataSpaceName, aArguments, mxContext), css::uno::UNO_QUERY);
+
     if (!mxPackageEncryption.is())
     {
         // we do not know how to decrypt this document
@@ -210,7 +187,7 @@ bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStr
     return bResult;
 }
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/DocumentEncryption.cxx b/oox/source/crypto/DocumentEncryption.cxx
index 70b7f2a3a4e9..5776c8164917 100644
--- a/oox/source/crypto/DocumentEncryption.cxx
+++ b/oox/source/crypto/DocumentEncryption.cxx
@@ -19,7 +19,7 @@
 #include <oox/ole/olestorage.hxx>
 
 namespace oox {
-namespace core {
+namespace crypto {
 
 using namespace css::io;
 using namespace css::uno;
@@ -43,7 +43,7 @@ DocumentEncryption::DocumentEncryption(const Reference< XComponentContext >& rxC
             rMediaEncData[i].Value >>= sCryptoType;
 
             if (sCryptoType == "Standard")
-                sCryptoType = "Standard2007Engine";
+                sCryptoType = "StrongEncryptionDataSpace";
 
             Sequence<Any> aArguments;
             mxPackageEncryption.set(
@@ -96,7 +96,7 @@ bool DocumentEncryption::encrypt()
     return true;
 }
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx
index 9ddde339b1d5..f89b29f48ccb 100644
--- a/oox/source/crypto/Standard2007Engine.cxx
+++ b/oox/source/crypto/Standard2007Engine.cxx
@@ -10,10 +10,6 @@
 
 #include <oox/crypto/Standard2007Engine.hxx>
 
-#include <com/sun/star/io/XStream.hpp>
-#include <com/sun/star/io/XSeekable.hpp>
-#include <com/sun/star/io/SequenceInputStream.hpp>
-#include <com/sun/star/io/XSequenceOutputStream.hpp>
 #include <oox/crypto/CryptTools.hxx>
 #include <oox/helper/binaryinputstream.hxx>
 #include <oox/helper/binaryoutputstream.hxx>
@@ -21,20 +17,9 @@
 #include <rtl/random.h>
 
 #include <comphelper/hash.hxx>
-#include <comphelper/sequenceashashmap.hxx>
-
-using namespace css::io;
-using namespace css::uno;
 
 namespace oox {
-namespace core {
-
-extern "C" SAL_DLLPUBLIC_EXPORT XInterface*
-    com_sun_star_comp_oox_crypto_Standard2007_get_implementation(
-        XComponentContext* pCtx, Sequence<Any> const& /*arguments*/)
-{
-    return cppu::acquire(new Standard2007Engine(pCtx/*, arguments*/));
-}
+namespace crypto {
 
 /* =========================================================================== */
 /*  Kudos to Caolan McNamara who provided the core decryption implementations. */
@@ -54,12 +39,6 @@ constexpr const sal_uInt32 AES128Size = 16;
 
 } // end anonymous namespace
 
-Standard2007Engine::Standard2007Engine(const css::uno::Reference<css::uno::XComponentContext>& rxContext)
- : mxContext(rxContext)
-{
-
-}
-
 bool Standard2007Engine::generateVerifier()
 {
     // only support key of size 128 bit (16 byte)
@@ -138,7 +117,7 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword)
     return true;
 }
 
-sal_Bool Standard2007Engine::generateEncryptionKey(const OUString& password)
+bool Standard2007Engine::generateEncryptionKey(const OUString& password)
 {
     mKey.clear();
     /*
@@ -180,12 +159,9 @@ sal_Bool Standard2007Engine::generateEncryptionKey(const OUString& password)
     return std::equal(hash.begin(), hash.end(), verifierHash.begin());
 }
 
-sal_Bool Standard2007Engine::decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
-    css::uno::Reference<css::io::XOutputStream>& rxOutputStream)
+bool Standard2007Engine::decrypt(BinaryXInputStream& aInputStream,
+                                 BinaryXOutputStream& aOutputStream)
 {
-    BinaryXInputStream aInputStream(rxInputStream, true);
-    BinaryXOutputStream aOutputStream(rxOutputStream, true);
-
     sal_uInt32 totalSize = aInputStream.readuInt32(); // Document unencrypted size - 4 bytes
     aInputStream.skip(4); // Reserved 4 Bytes
 
@@ -204,27 +180,15 @@ sal_Bool Standard2007Engine::decrypt(const css::uno::Reference<css::io::XInputSt
         aOutputStream.writeMemory(outputBuffer.data(), writeLength);
         remaining -= outputLength;
     }
-
-    rxOutputStream->flush();
-
     return true;
 }
 
-sal_Bool Standard2007Engine::checkDataIntegrity()
+bool Standard2007Engine::checkDataIntegrity()
 {
     return true;
 }
 
-css::uno::Sequence<css::beans::NamedValue> Standard2007Engine::createEncryptionData(const OUString& rPassword)
-{
-    comphelper::SequenceAsHashMap aEncryptionData;
-    aEncryptionData["OOXPassword"] <<= rPassword;
-    aEncryptionData["CryptoType"] <<= OUString("Standard2007Engine");
-
-    return aEncryptionData.getAsConstNamedValueList();
-}
-
-sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData)
+bool Standard2007Engine::setupEncryption(OUString const & password)
 {
     mInfo.header.flags        = msfilter::ENCRYPTINFO_AES | msfilter::ENCRYPTINFO_CRYPTOAPI;
     mInfo.header.algId        = msfilter::ENCRYPT_ALGO_AES128;
@@ -238,17 +202,7 @@ sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans
     mKey.clear();
     mKey.resize(keyLength, 0);
 
-    OUString sPassword;
-    for (int i = 0; i < rMediaEncData.getLength(); i++)
-    {
-        if (rMediaEncData[i].Name == "OOXPassword")
-        {
-            OUString sCryptoType;
-            rMediaEncData[i].Value >>= sPassword;
-        }
-    }
-
-    if (!calculateEncryptionKey(sPassword))
+    if (!calculateEncryptionKey(password))
         return false;
 
     if (!generateVerifier())
@@ -257,13 +211,8 @@ sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans
     return true;
 }
 
-css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptionInfo()
+void Standard2007Engine::writeEncryptionInfo(BinaryXOutputStream& rStream)
 {
-    Reference<XOutputStream> aEncryptionInfoStream(
-        mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext),
-        UNO_QUERY);
-    BinaryXOutputStream rStream(aEncryptionInfoStream, false);
-
     rStream.WriteUInt32(msfilter::VERSION_INFO_2007_FORMAT);
 
     sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2;
@@ -279,25 +228,19 @@ css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptionInfo()
     rStream.WriteUInt16(0);
 
     rStream.writeMemory(&mInfo.verifier, sizeof(msfilter::EncryptionVerifierAES));
-
-    rStream.close();
-    aEncryptionInfoStream->flush();
-
-    Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream, UNO_QUERY);
-    return aEncryptionInfoSequenceStream->getWrittenBytes();
 }
 
-css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream> &  rxInputStream)
+void Standard2007Engine::encrypt(const css::uno::Reference<css::io::XInputStream> &  rxInputStream,
+                                 css::uno::Reference<css::io::XOutputStream> & rxOutputStream,
+                                 sal_uInt32 nSize)
 {
-    Reference<XOutputStream> aOutputStream(
-        mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext),
-        UNO_QUERY);
-    BinaryXOutputStream aBinaryOutputStream(aOutputStream, false);
+    if (mKey.empty())
+        return;
 
+    BinaryXOutputStream aBinaryOutputStream(rxOutputStream, false);
     BinaryXInputStream aBinaryInputStream(rxInputStream, false);
-    Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY);
 
-    aBinaryOutputStream.WriteUInt32(xSeekable->getLength()); // size
+    aBinaryOutputStream.WriteUInt32(nSize); // size
     aBinaryOutputStream.WriteUInt32(0U);    // reserved
 
     std::vector<sal_uInt8> inputBuffer(1024);
@@ -317,43 +260,11 @@ css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptedDocument(const cs
         outputLength = aEncryptor.update(outputBuffer, inputBuffer, inputLength);
         aBinaryOutputStream.writeMemory(outputBuffer.data(), outputLength);
     }
-
-    Reference<XSequenceOutputStream> aSequenceStream(aOutputStream, UNO_QUERY);
-    return aSequenceStream->getWrittenBytes();
-}
-
-css::uno::Sequence<css::beans::NamedValue> Standard2007Engine::encrypt(const css::uno::Reference<css::io::XInputStream> &  rxInputStream)
-{
-    if (mKey.empty())
-        return css::uno::Sequence<css::beans::NamedValue>();
-
-    comphelper::SequenceAsHashMap aStreams;
-
-    aStreams["EncryptedPackage"] <<= writeEncryptedDocument(rxInputStream);
-    aStreams["EncryptionInfo"] <<= writeEncryptionInfo();
-    return aStreams.getAsConstNamedValueList();
-}
-
-css::uno::Reference<css::io::XInputStream> Standard2007Engine::getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName)
-{
-    for (const auto & aStream : rStreams)
-    {
-        if (aStream.Name == sStreamName)
-        {
-            css::uno::Sequence<sal_Int8> aSeq;
-            aStream.Value >>= aSeq;
-            Reference<XInputStream> aStream(css::io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq), UNO_QUERY_THROW);
-            return aStream;
-        }
-    }
-    return nullptr;
 }
 
-sal_Bool Standard2007Engine::readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams)
+bool Standard2007Engine::readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream)
 {
-    Reference<css::io::XInputStream> rxInputStream = getStream(aStreams, "EncryptionInfo");
     BinaryXInputStream aBinaryStream(rxInputStream, false);
-    aBinaryStream.readuInt32();    // Version
 
     mInfo.header.flags = aBinaryStream.readuInt32();
     if (getFlag(mInfo.header.flags, msfilter::ENCRYPTINFO_EXTERNAL))
@@ -407,7 +318,7 @@ sal_Bool Standard2007Engine::readEncryptionInfo(const css::uno::Sequence<css::be
     return !aBinaryStream.isEof();
 }
 
-} // namespace core
+} // namespace crypto
 } // namespace oox
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/StrongEncryptionDataSpace.cxx b/oox/source/crypto/StrongEncryptionDataSpace.cxx
new file mode 100644
index 000000000000..c651d558794a
--- /dev/null
+++ b/oox/source/crypto/StrongEncryptionDataSpace.cxx
@@ -0,0 +1,189 @@
+/* -*- 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 <oox/crypto/StrongEncryptionDataSpace.hxx>
+#include <oox/crypto/AgileEngine.hxx>
+#include <oox/crypto/Standard2007Engine.hxx>
+#include <com/sun/star/io/SequenceInputStream.hpp>
+#include <com/sun/star/io/XSequenceOutputStream.hpp>
+
+#include <comphelper/sequenceashashmap.hxx>
+
+using namespace css;
+using namespace css::beans;
+using namespace css::io;
+using namespace css::lang;
+using namespace css::uno;
+
+namespace oox
+{
+namespace crypto
+{
+StrongEncryptionDataSpace::StrongEncryptionDataSpace(const Reference<XComponentContext>& rxContext)
+    : mxContext(rxContext)
+    , mCryptoEngine(new Standard2007Engine())
+{
+}
+
+sal_Bool StrongEncryptionDataSpace::generateEncryptionKey(const OUString& rPassword)
+{
+    if (!mCryptoEngine)
+        return false;
+
+    return mCryptoEngine->generateEncryptionKey(rPassword);
+}
+
+sal_Bool StrongEncryptionDataSpace::checkDataIntegrity()
+{
+    if (!mCryptoEngine)
+        return false;
+
+    return mCryptoEngine->checkDataIntegrity();
+}
+
+sal_Bool StrongEncryptionDataSpace::decrypt(const Reference<XInputStream>& rxInputStream,
+                                            Reference<XOutputStream>& rxOutputStream)
+{
+    if (!mCryptoEngine)
+        return false;
+
+    BinaryXInputStream aInputStream(rxInputStream, true);
+    BinaryXOutputStream aOutputStream(rxOutputStream, true);
+
+    mCryptoEngine->decrypt(aInputStream, aOutputStream);
+
+    rxOutputStream->flush();
+    return true;
+}
+
+Reference<XInputStream> StrongEncryptionDataSpace::getStream(const Sequence<NamedValue>& rStreams,
+                                                             const OUString sStreamName)
+{
+    for (const auto& aStream : rStreams)
+    {
+        if (aStream.Name == sStreamName)
+        {
+            Sequence<sal_Int8> aSeq;
+            aStream.Value >>= aSeq;
+            Reference<XInputStream> aStream(
+                io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq),
+                UNO_QUERY_THROW);
+            return aStream;
+        }
+    }
+    return nullptr;
+}
+
+sal_Bool StrongEncryptionDataSpace::readEncryptionInfo(const Sequence<NamedValue>& aStreams)
+{
+    Reference<XInputStream> xEncryptionInfo = getStream(aStreams, "EncryptionInfo");
+    if (!xEncryptionInfo.is())
+        return false;
+
+    BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true);
+    sal_uInt32 aVersion = aBinaryInputStream.readuInt32();
+
+    Sequence<Any> aArguments;
+
+    switch (aVersion)
+    {
+        case msfilter::VERSION_INFO_2007_FORMAT:
+        case msfilter::VERSION_INFO_2007_FORMAT_SP2:
+            mCryptoEngine.reset(new Standard2007Engine());
+            break;
+        case msfilter::VERSION_INFO_AGILE:
+            mCryptoEngine.reset(new AgileEngine());
+            break;
+        default:
+            break;
+    }
+
+    if (!mCryptoEngine)
+        return false;
+
+    return mCryptoEngine->readEncryptionInfo(xEncryptionInfo);
+}
+
+sal_Bool StrongEncryptionDataSpace::setupEncryption(const Sequence<NamedValue>& rMediaEncData)
+{
+    if (!mCryptoEngine)
+        return false;
+
+    OUString sPassword;
+    for (const auto& aParam : rMediaEncData)
+    {
+        if (aParam.Name == "OOXPassword")
+        {
+            aParam.Value >>= sPassword;
+        }
+    }
+
+    return mCryptoEngine->setupEncryption(sPassword);
+}
+
+Sequence<NamedValue> StrongEncryptionDataSpace::createEncryptionData(const OUString& rPassword)
+{
+    comphelper::SequenceAsHashMap aEncryptionData;
+    aEncryptionData["OOXPassword"] <<= rPassword;
+    aEncryptionData["CryptoType"] <<= OUString("StrongEncryptionDataSpace");
+
+    return aEncryptionData.getAsConstNamedValueList();
+}
+
+Sequence<NamedValue>
+StrongEncryptionDataSpace::encrypt(const Reference<XInputStream>& rxInputStream)
+{
+    if (!mCryptoEngine)
+        return Sequence<NamedValue>();
+
+    Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY);
+    if (!xSeekable.is())
+        return Sequence<NamedValue>();
+
+    sal_uInt32 aLength = xSeekable->getLength(); // check length of the stream
+
+    Reference<XOutputStream> xOutputStream(
+        mxContext->getServiceManager()->createInstanceWithContext(
+            "com.sun.star.io.SequenceOutputStream", mxContext),
+        UNO_QUERY);
+
+    mCryptoEngine->encrypt(rxInputStream, xOutputStream, aLength);
+
+    comphelper::SequenceAsHashMap aStreams;
+
+    Reference<XSequenceOutputStream> xEncodedFileSequenceStream(xOutputStream, UNO_QUERY);
+    aStreams["EncryptedPackage"] <<= xEncodedFileSequenceStream->getWrittenBytes();
+
+    Reference<XOutputStream> aEncryptionInfoStream(
+        mxContext->getServiceManager()->createInstanceWithContext(
+            "com.sun.star.io.SequenceOutputStream", mxContext),
+        UNO_QUERY);
+    BinaryXOutputStream rStream(aEncryptionInfoStream, false);
+    mCryptoEngine->writeEncryptionInfo(rStream);
+    aEncryptionInfoStream->flush();
+    Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream,
+                                                                   UNO_QUERY);
+
+    aStreams["EncryptionInfo"] <<= aEncryptionInfoSequenceStream->getWrittenBytes();
+
+    return aStreams.getAsConstNamedValueList();
+}
+
+} // namespace crypto
+} // namespace oox
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation(
+    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+    return cppu::acquire(new oox::crypto::StrongEncryptionDataSpace(pCtx));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/util/oox.component b/oox/util/oox.component
index d7167545b2be..cf3a2d4b16f1 100644
--- a/oox/util/oox.component
+++ b/oox/util/oox.component
@@ -40,12 +40,8 @@
     constructor="com_sun_star_comp_oox_ShapeContextHandler_get_implementation">
     <service name="com.sun.star.xml.sax.FastShapeContextHandler"/>
   </implementation>
-  <implementation name="com.sun.star.comp.oox.crypto.Standard2007Engine"
-    constructor="com_sun_star_comp_oox_crypto_Standard2007_get_implementation">
-    <service name="com.sun.star.packages.XPackageEncryption"/>
-  </implementation>
-  <implementation name="com.sun.star.comp.oox.crypto.AgileEngine"
-    constructor="com_sun_star_comp_oox_crypto_Agile_get_implementation">
+  <implementation name="com.sun.star.comp.oox.crypto.StrongEncryptionDataSpace"
+    constructor="com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation">
     <service name="com.sun.star.packages.XPackageEncryption"/>
   </implementation>
 </component>
commit 5b89840a1c88ed199c755b7fd64fad2cebfd8a4d
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Thu Nov 21 21:11:02 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:18:31 2019 +0100

    oox: exception on password veryfy attempt is ending loop
    
    If we receive an exception on createEncryptionData() there is
    no reason to ask user for another password.
    
    Change-Id: I7fa0949c737af20396ae7958e0e80d97af7cfe10

diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index 7e72d28482df..f59b15c56df9 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -265,8 +265,16 @@ PasswordVerifier::PasswordVerifier( DocumentDecryption& aDecryptor ) :
 
 comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData )
 {
-    if(mDecryptor.generateEncryptionKey(rPassword))
-        rEncryptionData = mDecryptor.createEncryptionData(rPassword);
+    try
+    {
+        if (mDecryptor.generateEncryptionKey(rPassword))
+            rEncryptionData = mDecryptor.createEncryptionData(rPassword);
+    }
+    catch (...)
+    {
+        // Any exception is a reason to abort
+        return comphelper::DocPasswordVerifierResult::Abort;
+    }
 
     return rEncryptionData.hasElements() ? comphelper::DocPasswordVerifierResult::OK : comphelper::DocPasswordVerifierResult::WrongPassword;
 }
commit acba7356b62c4c192430d6f6d73a484112bf4f3b
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Mon Nov 18 11:26:23 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:18:23 2019 +0100

    package: ignore unknown encryption parameters.
    
    Do not throw an exception if there are encryption parameters,
    but they are not supported in current output format.
    
    Change-Id: I21e4cf2f73d7c218ab5444b2016e838695163ca3
    
    Conflicts:
            package/source/zippackage/ZipPackage.cxx

diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 78627441b506..a66e3a63b22f 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -1646,11 +1646,6 @@ const uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey()
         for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
             if ( m_aStorageEncryptionKeys[nInd].Name == aNameToFind )
                 m_aStorageEncryptionKeys[nInd].Value >>= aResult;
-
-        // empty keys are not allowed here
-        // so it is not important whether there is no key, or the key is empty, it is an error
-        if ( !aResult.hasElements() )
-            throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
     }
     else
         aResult = m_aEncryptionKey;
commit d8cc493255b8c5101192620d5a828d3bae3d22d7
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Wed Nov 13 09:19:42 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:15 2019 +0100

    ms doc: pass additional arguments to encryption service
    
    XPackageEncryption mplementation should distingush types
    of files fo possibility to encrypt them in a different way.
    So additional parameter is provided to resolve this issue.
    
    Change-Id: I3cdff6c6b85f2483138ad5ddba7799fb7bf8be95

diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx
index 2e4015e34569..463afe74b90a 100644
--- a/sc/source/filter/excel/excel.cxx
+++ b/sc/source/filter/excel/excel.cxx
@@ -261,7 +261,8 @@ static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
         if (sCryptoType.getLength())
         {
             uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
-            uno::Sequence<uno::Any> aArguments;
+            uno::Sequence<uno::Any> aArguments(1);
+            aArguments[0] = uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true)));
             xPackageEncryption.set(
                 xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
                     "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY);
diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx
index cc418fd7fc5a..2a21dbcaa06b 100644
--- a/sd/source/filter/sdpptwrp.cxx
+++ b/sd/source/filter/sdpptwrp.cxx
@@ -264,7 +264,8 @@ bool SdPPTFilter::Export()
                 if (sCryptoType.getLength())
                 {
                     Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
-                    Sequence<Any> aArguments;
+                    Sequence<Any> aArguments(1);
+                    aArguments[0] = makeAny(NamedValue("Binary", makeAny(true)));
                     xPackageEncryption.set(
                         xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
                             "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY);
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 7d3ab12ae408..ad6a710b0ffc 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -3559,7 +3559,8 @@ ErrCode SwWW8Writer::WriteStorage()
             if (sCryptoType.getLength())
             {
                 uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
-                uno::Sequence<uno::Any> aArguments;
+                uno::Sequence<uno::Any> aArguments(1);
+                aArguments[0] = uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true)));
                 xPackageEncryption.set(
                     xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
                         "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY);
commit 4710ff6c70030d244a2c295c96a64a83abf7f7d0
Author:     Serge Krot <Serge.Krot at cib.de>
AuthorDate: Tue Nov 12 21:52:05 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:15 2019 +0100

    Add document level option to lock down edit doc command
    
    Change-Id: I431fa4cd0daa52c885030dbadcc4052b5a890d34
    Reviewed-on: https://gerrit.libreoffice.org/82553
    Reviewed-by: Serge Krot (CIB) <Serge.Krot at cib.de>
    Tested-by: Serge Krot (CIB) <Serge.Krot at cib.de>

diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index 218dc2eab259..df214e8b7309 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -1099,6 +1099,11 @@ void SAL_CALL SfxBaseModel::setArgs(const Sequence<beans::PropertyValue>& aArgs)
             rArg.Value >>= bValue;
             pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EDITDOC, bValue));
         }
+        else if (rArg.Name == "LockEditDoc")
+        {
+            rArg.Value >>= bValue;
+            pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EDITDOC, bValue));
+        }
         else if (rArg.Name == "EncryptionData")
         {
             rArg.Value >>= bValue;
commit d65fe2a545c2b6be08d1538a74f95f650bf61f56
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 21:17:10 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:14 2019 +0100

    sd: support for DRM encryption during saving to ppt
    
    Change-Id: Id82f8b3fa7ea045b00d7d81e2c9ce5e130c8060c

diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx
index bb42b9d4bc11..cc418fd7fc5a 100644
--- a/sd/source/filter/sdpptwrp.cxx
+++ b/sd/source/filter/sdpptwrp.cxx
@@ -219,8 +219,6 @@ bool SdPPTFilter::Export()
 
     if( mxModel.is() )
     {
-        tools::SvRef<SotStorage> xStorRef = new SotStorage( mrMedium.GetOutStream(), false );
-
 #ifdef DISABLE_DYNLOADING
         ExportPPTPointer PPTExport = ExportPPT;
 #else
@@ -228,7 +226,7 @@ bool SdPPTFilter::Export()
             SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "ExportPPT"));
 #endif
 
-        if( PPTExport && xStorRef.is() )
+        if( PPTExport)
         {
             sal_uInt32          nCnvrtFlags = 0;
             const SvtFilterOptions& rFilterOptions = SvtFilterOptions::Get();
@@ -252,8 +250,105 @@ bool SdPPTFilter::Export()
             aProperty.Value <<= mrMedium.GetBaseURL( true );
             aProperties.push_back( aProperty );
 
-            bRet = PPTExport( aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags );
-            xStorRef->Commit();
+            SvStream * pOutputStrm = mrMedium.GetOutStream();
+
+            Sequence< NamedValue > aEncryptionData;
+            Reference< css::packages::XPackageEncryption > xPackageEncryption;
+            const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mrMedium.GetItemSet(), SID_ENCRYPTIONDATA, false);
+            std::shared_ptr<SvStream> pMediaStrm;
+            if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData))
+            {
+                ::comphelper::SequenceAsHashMap aHashData(aEncryptionData);
+                OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString());
+
+                if (sCryptoType.getLength())
+                {
+                    Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+                    Sequence<Any> aArguments;
+                    xPackageEncryption.set(
+                        xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                            "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY);
+
+                    if (xPackageEncryption.is())
+                    {
+                        // We have an encryptor. Export document into memory stream and encrypt it later
+                        pMediaStrm.reset(new SvMemoryStream());
+                        pOutputStrm = pMediaStrm.get();
+
+                        // Temp removal of EncryptionData to avoid password protection triggering
+                        mrMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA);
+                    }
+                }
+            }
+
+            tools::SvRef<SotStorage> xStorRef = new SotStorage(pOutputStrm, false);
+
+            if (xStorRef.is())
+            {
+                bRet = PPTExport(aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags);
+                xStorRef->Commit();
+
+                if (xPackageEncryption.is())
+                {
+                    // Perform DRM encryption
+                    pOutputStrm->Seek(0);
+
+                    xPackageEncryption->setupEncryption(aEncryptionData);
+
+                    Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pOutputStrm, false));
+                    Sequence<NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream);
+
+                    tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(mrMedium.GetOutStream(), false);
+                    for (const NamedValue & aStreamData : aStreams)
+                    {
+                        // To avoid long paths split and open substorages recursively
+                        // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09
+                        SotStorage * pStorage = xEncryptedRootStrg.get();
+                        OUString sFileName;
+                        sal_Int32 idx = 0;
+                        do
+                        {
+                            OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx);
+                            if (!sPathElem.isEmpty())
+                            {
+                                if (idx < 0)
+                                {
+                                    sFileName = sPathElem;
+                                }
+                                else
+                                {
+                                    pStorage = pStorage->OpenSotStorage(sPathElem);
+                                }
+                            }
+                        } while (pStorage && idx >= 0);
+
+                        if (!pStorage)
+                        {
+                            bRet = false;
+                            break;
+                        }
+
+                        SotStorageStream* pStream = pStorage->OpenSotStream(sFileName);
+                        if (!pStream)
+                        {
+                            bRet = false;
+                            break;
+                        }
+                        Sequence<sal_Int8> aStreamContent;
+                        aStreamData.Value >>= aStreamContent;
+                        size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength());
+                        if (nBytesWritten != aStreamContent.getLength())
+                        {
+                            bRet = false;
+                            break;
+                        }
+                    }
+                    xEncryptedRootStrg->Commit();
+
+                    // Restore encryption data
+                    mrMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData)));
+                }
+            }
         }
     }
 
commit 2c7ea8fcad55ee988324aca8ad53b4a34e5b57e3
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 21:00:12 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:13 2019 +0100

    sd: support of DRM encrypted ppt files reading
    
    Change-Id: Ib91538d53ee1f53a3cd14a44d47fd6f6136c0472

diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx
index edc21c482d45..bb42b9d4bc11 100644
--- a/sd/source/filter/sdpptwrp.cxx
+++ b/sd/source/filter/sdpptwrp.cxx
@@ -23,6 +23,10 @@
 #include <svx/svxerr.hxx>
 #include <unotools/fltrcfg.hxx>
 #include <sot/storage.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
 
 #include <sdpptwrp.hxx>
 #include <DrawDocShell.hxx>
@@ -67,9 +71,101 @@ SdPPTFilter::~SdPPTFilter()
     delete pBas;    // deleting the compressed basic storage
 }
 
+static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix)
+{
+    SvStorageInfoList aElements;
+    pStorage->FillInfoList(&aElements);
+    for (const auto & aElement : aElements)
+    {
+        OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName();
+        if (aElement.IsStorage())
+        {
+            SotStorage * pSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL);
+            lcl_getListOfStreams(pSubStorage, aStreamsData, sStreamFullName);
+        }
+        else
+        {
+            // Read stream
+            tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL);
+            assert(rStream.is());
+
+            sal_Int32 nStreamSize = rStream->GetSize();
+            Sequence< sal_Int8 > oData;
+            oData.realloc(nStreamSize);
+            sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize);
+            assert(nStreamSize == nReadBytes);
+            aStreamsData[sStreamFullName] <<= oData;
+        }
+    }
+}
+
+static tools::SvRef<SotStorage> lcl_DRMDecrypt(SfxMedium& rMedium, tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm)
+{
+    tools::SvRef<SotStorage> aNewStorage;
+
+    // We have DRM encrypted storage. We should try to decrypt it first, if we can
+    Sequence< Any > aArguments;
+    Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    Reference< css::packages::XPackageEncryption > xPackageEncryption(
+        xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), UNO_QUERY);
+
+    if (!xPackageEncryption.is())
+    {
+        // We do not know how to decrypt this
+        return aNewStorage;
+    }
+
+    std::vector<OUString> aStreamsList;
+    comphelper::SequenceAsHashMap aStreamsData;
+    lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString(""));
+
+    try {
+        Sequence<NamedValue> aStreams = aStreamsData.getAsConstNamedValueList();
+        if (!xPackageEncryption->readEncryptionInfo(aStreams))
+        {
+            // We failed with decryption
+            return aNewStorage;
+        }
+
+        tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL);
+        if (!rContentStream.is())
+        {
+            return aNewStorage;
+        }
+
+        rNewStorageStrm.reset(new SvMemoryStream());
+
+        Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+        Reference<css::io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm.get()));
+
+        if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream))
+        {
+            // We failed with decryption
+            return aNewStorage;
+        }
+
+        rNewStorageStrm->Seek(0);
+
+        // Further reading is done from new document
+        aNewStorage = new SotStorage(*rNewStorageStrm);
+
+        // Set the media descriptor data
+        Sequence<NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData("");
+        rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData)));
+    }
+    catch (const std::exception&)
+    {
+        return aNewStorage;
+    }
+
+    return aNewStorage;
+}
+
 bool SdPPTFilter::Import()
 {
     bool bRet = false;
+    std::shared_ptr<SvStream> aDecryptedStorageStrm;
     tools::SvRef<SotStorage> pStorage = new SotStorage( mrMedium.GetInStream(), false );
     if( !pStorage->GetError() )
     {
@@ -82,6 +178,12 @@ bool SdPPTFilter::Import()
             xDualStorage = pStorage->OpenSotStorage( sDualStorage, StreamMode::STD_READ );
             pStorage = xDualStorage;
         }
+        OUString sDRMContent("\011DRMContent");
+        if (pStorage->IsContained(sDRMContent))
+        {
+            // Document is DRM encrypted
+            pStorage = lcl_DRMDecrypt(mrMedium, pStorage, aDecryptedStorageStrm);
+        }
         std::unique_ptr<SvStream> pDocStream(pStorage->OpenSotStream( "PowerPoint Document" , StreamMode::STD_READ ));
         if( pDocStream )
         {
commit dae91126c3ee4413f064c5329d56bef64c3c8474
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 18:28:41 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:13 2019 +0100

    calc: support for writing DRM encrypted xls files
    
    Change-Id: I5faf885cf494becca2838c6493413bcc56e91826

diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx
index 56adce29a061..2e4015e34569 100644
--- a/sc/source/filter/excel/excel.cxx
+++ b/sc/source/filter/excel/excel.cxx
@@ -24,7 +24,7 @@
 #include <sot/exchange.hxx>
 #include <filter/msfilter/classids.hxx>
 #include <tools/globname.hxx>
-#include <com/sun/star/packages/XPAckageEncryption.hpp>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
 #include <com/sun/star/ucb/ContentCreationException.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <unotools/streamwrap.hxx>
@@ -248,6 +248,36 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument*
 static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
         SvStream* pMedStrm, bool bBiff8, rtl_TextEncoding eNach )
 {
+    uno::Reference< packages::XPackageEncryption > xPackageEncryption;
+    uno::Sequence< beans::NamedValue > aEncryptionData;
+    const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(rMedium.GetItemSet(), SID_ENCRYPTIONDATA, false);
+    SvStream* pOriginalMediaStrm = pMedStrm;
+    std::shared_ptr<SvStream> pMediaStrm;
+    if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData))
+    {
+        ::comphelper::SequenceAsHashMap aHashData(aEncryptionData);
+        OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString());
+
+        if (sCryptoType.getLength())
+        {
+            uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+            uno::Sequence<uno::Any> aArguments;
+            xPackageEncryption.set(
+                xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                    "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY);
+
+            if (xPackageEncryption.is())
+            {
+                // We have an encryptor. Export document into memory stream and encrypt it later
+                pMediaStrm.reset(new SvMemoryStream());
+                pMedStrm = pMediaStrm.get();
+
+                // Temp removal of EncryptionData to avoid password protection triggering
+                rMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA);
+            }
+        }
+    }
+
     // try to open an OLE storage
     tools::SvRef<SotStorage> xRootStrg = new SotStorage( pMedStrm, false );
     if( xRootStrg->GetError() ) return SCERR_IMPORT_OPEN;
@@ -296,6 +326,67 @@ static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
     xStrgStrm->Commit();
     xRootStrg->Commit();
 
+    if (xPackageEncryption.is())
+    {
+        // Perform DRM encryption
+        pMedStrm->Seek(0);
+
+        xPackageEncryption->setupEncryption(aEncryptionData);
+
+        uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pMedStrm, false));
+        uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream);
+
+        tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(pOriginalMediaStrm, false);
+        for (const beans::NamedValue & aStreamData : aStreams)
+        {
+            // To avoid long paths split and open substorages recursively
+            // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09
+            SotStorage * pStorage = xEncryptedRootStrg.get();
+            OUString sFileName;
+            sal_Int32 idx = 0;
+            do
+            {
+                OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx);
+                if (!sPathElem.isEmpty())
+                {
+                    if (idx < 0)
+                    {
+                        sFileName = sPathElem;
+                    }
+                    else
+                    {
+                        pStorage = pStorage->OpenSotStorage(sPathElem);
+                    }
+                }
+            } while (pStorage && idx >= 0);
+
+            if (!pStorage)
+            {
+                eRet = ERRCODE_IO_GENERAL;
+                break;
+            }
+
+            SotStorageStream* pStream = pStorage->OpenSotStream(sFileName);
+            if (!pStream)
+            {
+                eRet = ERRCODE_IO_GENERAL;
+                break;
+            }
+            uno::Sequence<sal_Int8> aStreamContent;
+            aStreamData.Value >>= aStreamContent;
+            size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength());
+            if (nBytesWritten != aStreamContent.getLength())
+            {
+                eRet = ERRCODE_IO_CANTWRITE;
+                break;
+            }
+        }
+        xEncryptedRootStrg->Commit();
+
+        // Restore encryption data
+        rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData)));
+    }
+
     return eRet;
 }
 
commit 3c5c5a6c213d7594724338f28afc5ba813f5da9f
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 17:53:30 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:12 2019 +0100

    calc: support for reading DRM encrypted xls files
    
    DRM encryption is implemented as an optional service, so
    just use it when available.
    
    Change-Id: Ie580e5c12c48ccf99f9a932b1c66eb35866b7ef4

diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx
index ca87efc2988c..56adce29a061 100644
--- a/sc/source/filter/excel/excel.cxx
+++ b/sc/source/filter/excel/excel.cxx
@@ -24,7 +24,9 @@
 #include <sot/exchange.hxx>
 #include <filter/msfilter/classids.hxx>
 #include <tools/globname.hxx>
+#include <com/sun/star/packages/XPAckageEncryption.hpp>
 #include <com/sun/star/ucb/ContentCreationException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
 #include <unotools/streamwrap.hxx>
 #include <osl/diagnose.h>
 #include <filter.hxx>
@@ -32,6 +34,8 @@
 #include <xistream.hxx>
 #include <xltools.hxx>
 #include <docoptio.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/processfactory.hxx>
 
 #include <docsh.hxx>
 #include <scerrors.hxx>
@@ -42,6 +46,99 @@
 
 #include <memory>
 
+using namespace css;
+
+static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix)
+{
+    SvStorageInfoList aElements;
+    pStorage->FillInfoList(&aElements);
+    for (const auto & aElement : aElements)
+    {
+        OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName();
+        if (aElement.IsStorage())
+        {
+            SotStorage * pSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL);
+            lcl_getListOfStreams(pSubStorage, aStreamsData, sStreamFullName);
+        }
+        else
+        {
+            // Read stream
+            tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL);
+            assert(rStream.is());
+
+            sal_Int32 nStreamSize = rStream->GetSize();
+            uno::Sequence< sal_Int8 > oData;
+            oData.realloc(nStreamSize);
+            sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize);
+            assert(nStreamSize == nReadBytes);
+            aStreamsData[sStreamFullName] <<= oData;
+        }
+    }
+}
+
+static tools::SvRef<SotStorage> lcl_DRMDecrypt(SfxMedium& rMedium, tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm)
+{
+    tools::SvRef<SotStorage> aNewStorage;
+
+    // We have DRM encrypted storage. We should try to decrypt it first, if we can
+    uno::Sequence< uno::Any > aArguments;
+    uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    uno::Reference< packages::XPackageEncryption > xPackageEncryption(
+        xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), uno::UNO_QUERY);
+
+    if (!xPackageEncryption.is())
+    {
+        // We do not know how to decrypt this
+        return aNewStorage;
+    }
+
+    std::vector<OUString> aStreamsList;
+    comphelper::SequenceAsHashMap aStreamsData;
+    lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString(""));
+
+    try {
+        uno::Sequence<beans::NamedValue> aStreams = aStreamsData.getAsConstNamedValueList();
+        if (!xPackageEncryption->readEncryptionInfo(aStreams))
+        {
+            // We failed with decryption
+            return aNewStorage;
+        }
+
+        tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL);
+        if (!rContentStream.is())
+        {
+            return aNewStorage;
+        }
+
+        rNewStorageStrm.reset(new SvMemoryStream());
+
+        uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+        uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm.get()));
+
+        if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream))
+        {
+            // We failed with decryption
+            return aNewStorage;
+        }
+
+        rNewStorageStrm->Seek(0);
+
+        // Further reading is done from new document
+        aNewStorage = new SotStorage(*rNewStorageStrm);
+
+        // Set the media descriptor data
+        uno::Sequence<beans::NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData("");
+        rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData)));
+    }
+    catch (const std::exception&)
+    {
+        return aNewStorage;
+    }
+
+    return aNewStorage;
+}
+
 ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat )
 {
     // check the passed Calc document
@@ -67,6 +164,7 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument*
     // try to open an OLE storage
     tools::SvRef<SotStorage> xRootStrg;
     tools::SvRef<SotStorageStream> xStrgStrm;
+    std::shared_ptr<SvStream> aNewStorageStrm;
     if( SotStorage::IsStorageFile( pMedStrm ) )
     {
         xRootStrg = new SotStorage( pMedStrm, false );
@@ -77,6 +175,13 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument*
     // try to open "Book" or "Workbook" stream in OLE storage
     if( xRootStrg.is() )
     {
+        // Check if there is DRM encryption in storage
+        tools::SvRef<SotStorageStream> xDRMStrm = ScfTools::OpenStorageStreamRead(xRootStrg, "\011DRMContent");
+        if (xDRMStrm.is())
+        {
+            xRootStrg = lcl_DRMDecrypt(rMedium, xRootStrg, aNewStorageStrm);
+        }
+
         // try to open the "Book" stream
         tools::SvRef<SotStorageStream> xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK );
         XclBiff eBookBiff = xBookStrm.is() ?  XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN;
commit 42e9de130992c7caa8314d620882c00c2722cd97
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Thu Nov 7 11:13:49 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:11 2019 +0100

    ms doc: support for saving into binary doc with custom encryption
    
    if we have custome encryption data in media descriptor EncryptionData
    and corresponding service is available it will be used durng saving.
    
    Change-Id: I814e4a7f73979ff7a65831b99f77f1a9e85916de

diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index bf8fb4665528..7d3ab12ae408 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -22,6 +22,8 @@
 
 #include <com/sun/star/embed/ElementModes.hpp>
 #include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
 #include <unotools/ucbstreamhelper.hxx>
 #include <algorithm>
 #include <map>
@@ -93,6 +95,7 @@
 #include "sprmids.hxx"
 
 #include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/string.hxx>
 #include "writerhelper.hxx"
 #include "writerwordglue.hxx"
 #include "ww8attributeoutput.hxx"
@@ -3540,6 +3543,105 @@ void WW8Export::PrepareStorage()
 
 ErrCode SwWW8Writer::WriteStorage()
 {
+    tools::SvRef<SotStorage> pOrigStg;
+    uno::Reference< packages::XPackageEncryption > xPackageEncryption;
+    std::shared_ptr<SvStream> pSotStorageStream;
+    uno::Sequence< beans::NamedValue > aEncryptionData;
+    if (mpMedium)
+    {
+        // Check for specific encryption requests
+        const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mpMedium->GetItemSet(), SID_ENCRYPTIONDATA, false);
+        if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData))
+        {
+            ::comphelper::SequenceAsHashMap aHashData(aEncryptionData);
+            OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString());
+
+            if (sCryptoType.getLength())
+            {
+                uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+                uno::Sequence<uno::Any> aArguments;
+                xPackageEncryption.set(
+                    xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                        "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY);
+
+                if (xPackageEncryption.is())
+                {
+                    // We have an encryptor
+                    // Create new temporary storage for content
+                    pOrigStg = pStg;
+                    pSotStorageStream.reset(new SvMemoryStream());
+                    pStg = new SotStorage(*pSotStorageStream);
+                }
+            }
+        }
+    }
+
+    ErrCode nErrorCode = WriteStorageImpl();
+
+    if (xPackageEncryption.is())
+    {
+        pStg->Commit();
+        pSotStorageStream->Seek(0);
+
+        // Encrypt data written into temporary storage
+        xPackageEncryption->setupEncryption(aEncryptionData);
+
+        uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pSotStorageStream.get(), false));
+        uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream);
+
+        pStg = pOrigStg;
+        for (const beans::NamedValue & aStreamData : aStreams)
+        {
+            // To avoid long paths split and open substorages recursively
+            // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09
+            SotStorage * pStorage = pStg.get();
+            OUString sFileName;
+            sal_Int32 idx = 0;
+            do
+            {
+                OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx);
+                if (!sPathElem.isEmpty())
+                {
+                    if (idx < 0)
+                    {
+                        sFileName = sPathElem;
+                    }
+                    else
+                    {
+                        pStorage = pStorage->OpenSotStorage(sPathElem);
+                        if (!pStorage)
+                            break;
+                    }
+                }
+            } while (pStorage && idx >= 0);
+
+            if (!pStorage)
+            {
+                nErrorCode = ERRCODE_IO_GENERAL;
+                break;
+            }
+
+            SotStorageStream* pStream = pStorage->OpenSotStream(sFileName);
+            if (!pStream)
+            {
+                nErrorCode = ERRCODE_IO_GENERAL;
+                break;
+            }
+            uno::Sequence<sal_Int8> aStreamContent;
+            aStreamData.Value >>= aStreamContent;
+            size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength());
+            if (nBytesWritten != aStreamContent.getLength())
+            {
+                nErrorCode = ERRCODE_IO_CANTWRITE;
+                break;
+            }
+        }
+    }
+
+    return nErrorCode;
+}
+ErrCode SwWW8Writer::WriteStorageImpl()
+{
     // #i34818# - update layout (if present), for SwWriteTable
     SwViewShell* pViewShell = m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
     if( pViewShell != nullptr )
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index f72302f88538..04e485e39708 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -913,7 +913,6 @@ friend void WW8_WrtRedlineAuthor::Write(Writer &rWrt);
 
     WW8Export *m_pExport;
     SfxMedium *mpMedium;
-
 public:
     SwWW8Writer(const OUString& rFltName, const OUString& rBaseURL);
     virtual ~SwWW8Writer() override;
@@ -958,6 +957,7 @@ public:
 private:
     SwWW8Writer(const SwWW8Writer&) = delete;
     SwWW8Writer& operator=(const SwWW8Writer&) = delete;
+    ErrCode WriteStorageImpl();
 };
 
 /// Exporter of the binary Word file formats.
commit 4f939f0433313bdb072e3546524ad42f78fba468
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Mon Oct 28 14:23:36 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Dec 4 06:17:10 2019 +0100

    sw: support for DRM encryption for binary doc formats
    
    DRM encryption is implemented as a service and desrption
    will be called if we found corresponding streams inside
    binary OLE package.
    
    Change-Id: Ie1a5b0417e1e7851b24d410c8f41dc85dd9210f7
    Reviewed-on: https://gerrit.libreoffice.org/81600
    Reviewed-by: Vasily Melenchuk <vasily.melenchuk at cib.de>
    Tested-by: Vasily Melenchuk <vasily.melenchuk at cib.de>

diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index aa596ad3ee2d..b6e09ef63045 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list