summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/crypto/AgileEngine.hxx6
-rw-r--r--include/oox/crypto/CryptTools.hxx4
-rw-r--r--include/oox/crypto/CryptoEngine.hxx6
-rw-r--r--include/oox/crypto/DocumentDecryption.hxx22
-rw-r--r--include/oox/crypto/DocumentEncryption.hxx17
-rw-r--r--include/oox/crypto/Standard2007Engine.hxx6
-rw-r--r--include/oox/crypto/StrongEncryptionDataSpace.hxx76
-rw-r--r--offapi/UnoApi_offapi.mk2
-rw-r--r--offapi/com/sun/star/packages/PackageEncryption.idl25
-rw-r--r--offapi/com/sun/star/packages/XPackageEncryption.idl134
-rw-r--r--oox/Library_oox.mk1
-rw-r--r--oox/qa/unit/CryptoTest.cxx46
-rw-r--r--oox/source/core/filterdetect.cxx20
-rw-r--r--oox/source/core/xmlfilterbase.cxx19
-rw-r--r--oox/source/crypto/AgileEngine.cxx10
-rw-r--r--oox/source/crypto/CryptTools.cxx4
-rw-r--r--oox/source/crypto/DocumentDecryption.cxx185
-rw-r--r--oox/source/crypto/DocumentEncryption.cxx72
-rw-r--r--oox/source/crypto/Standard2007Engine.cxx6
-rw-r--r--oox/source/crypto/StrongEncryptionDataSpace.cxx206
-rw-r--r--oox/util/oox.component4
-rw-r--r--sfx2/source/dialog/filedlghelper.cxx3
-rwxr-xr-xsolenv/bin/native-code.py1
-rw-r--r--sw/qa/inc/swmodeltestbase.hxx1
-rw-r--r--unotools/source/misc/mediadescriptor.cxx5
25 files changed, 724 insertions, 157 deletions
diff --git a/include/oox/crypto/AgileEngine.hxx b/include/oox/crypto/AgileEngine.hxx
index b4aeec6de5be..ac028533d71c 100644
--- a/include/oox/crypto/AgileEngine.hxx
+++ b/include/oox/crypto/AgileEngine.hxx
@@ -25,7 +25,7 @@ namespace oox {
}
namespace oox {
-namespace core {
+namespace crypto {
struct OOX_DLLPUBLIC AgileEncryptionInfo
{
@@ -125,7 +125,7 @@ public:
void writeEncryptionInfo(BinaryXOutputStream& rStream) override;
- void encrypt(css::uno::Reference<css::io::XInputStream>& rxInputStream,
+ void encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
css::uno::Reference<css::io::XOutputStream>& rxOutputStream,
sal_uInt32 nSize) override;
@@ -141,7 +141,7 @@ public:
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 4e8d8e586922..31d90efcbc49 100644
--- a/include/oox/crypto/CryptTools.hxx
+++ b/include/oox/crypto/CryptTools.hxx
@@ -27,7 +27,7 @@
#include <memory>
namespace oox {
-namespace core {
+namespace crypto {
/** Rounds up the input to the nearest multiple
*
@@ -114,7 +114,7 @@ public:
};
-} // namespace core
+} // namespace crypto
} // namespace oox
#endif
diff --git a/include/oox/crypto/CryptoEngine.hxx b/include/oox/crypto/CryptoEngine.hxx
index 8a947f10d106..72bde8920dfc 100644
--- a/include/oox/crypto/CryptoEngine.hxx
+++ b/include/oox/crypto/CryptoEngine.hxx
@@ -25,7 +25,7 @@ namespace oox {
}
namespace oox {
-namespace core {
+namespace crypto {
class CryptoEngine
{
@@ -53,14 +53,14 @@ public:
virtual bool setupEncryption(const OUString& rPassword) = 0;
- virtual void encrypt(css::uno::Reference<css::io::XInputStream> & rxInputStream,
+ 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 core
+} // namespace crypto
} // namespace oox
#endif
diff --git a/include/oox/crypto/DocumentDecryption.hxx b/include/oox/crypto/DocumentDecryption.hxx
index 7919fa7a40f3..2c058121c1b7 100644
--- a/include/oox/crypto/DocumentDecryption.hxx
+++ b/include/oox/crypto/DocumentDecryption.hxx
@@ -17,7 +17,6 @@
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/Sequence.hxx>
-#include <oox/crypto/CryptoEngine.hxx>
#include <rtl/ustring.hxx>
namespace com::sun::star {
@@ -25,29 +24,24 @@ namespace com::sun::star {
namespace io { class XInputStream; }
namespace io { class XStream; }
namespace uno { class XComponentContext; }
+ namespace packages { class XPackageEncryption; }
}
namespace oox::ole { class OleStorage; }
namespace oox {
-namespace core {
+namespace crypto {
class DocumentDecryption
{
private:
- enum CryptoType
- {
- UNKNOWN,
- STANDARD_2007,
- AGILE
- };
-
- oox::ole::OleStorage& mrOleStorage;
- std::unique_ptr<CryptoEngine> mEngine;
- CryptoType mCryptoType;
+ 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;
public:
- DocumentDecryption(oox::ole::OleStorage& rOleStorage);
+ DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, oox::ole::OleStorage& rOleStorage);
bool decrypt(const css::uno::Reference< css::io::XStream >& xDocumentStream);
bool readEncryptionInfo();
@@ -57,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 9be7c99bb41c..17480652aa8d 100644
--- a/include/oox/crypto/DocumentEncryption.hxx
+++ b/include/oox/crypto/DocumentEncryption.hxx
@@ -14,38 +14,43 @@
#include <oox/dllapi.h>
#include <com/sun/star/uno/Reference.hxx>
-#include <oox/crypto/Standard2007Engine.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
#include <rtl/ustring.hxx>
namespace com::sun::star {
namespace io { class XStream; }
+ namespace packages { class XPackageEncryption; }
+ namespace beans { struct NamedValue; }
+ namespace uno { class XComponentContext; }
}
namespace oox::ole { class OleStorage; }
namespace oox {
-namespace core {
+namespace crypto {
class DocumentEncryption
{
private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
css::uno::Reference< css::io::XStream > mxDocumentStream;
oox::ole::OleStorage& mrOleStorage;
OUString maPassword;
- Standard2007Engine mEngine;
+ css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption;
+ const css::uno::Sequence< css::beans::NamedValue >& mMediaEncData;
public:
- DocumentEncryption(
+ DocumentEncryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
css::uno::Reference< css::io::XStream > const & xDocumentStream,
oox::ole::OleStorage& rOleStorage,
- const OUString& aPassword);
+ const css::uno::Sequence< css::beans::NamedValue >& rMediaEncData);
bool encrypt();
};
-} // namespace core
+} // namespace crypto
} // namespace oox
#endif
diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx
index 7583447319c6..4a6eaae9e43c 100644
--- a/include/oox/crypto/Standard2007Engine.hxx
+++ b/include/oox/crypto/Standard2007Engine.hxx
@@ -23,7 +23,7 @@ namespace oox {
}
namespace oox {
-namespace core {
+namespace crypto {
class OOX_DLLPUBLIC Standard2007Engine final : public CryptoEngine
{
@@ -45,7 +45,7 @@ public:
bool checkDataIntegrity() override;
- void encrypt(css::uno::Reference<css::io::XInputStream>& rxInputStream,
+ void encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream,
css::uno::Reference<css::io::XOutputStream>& rxOutputStream,
sal_uInt32 nSize) override;
@@ -55,7 +55,7 @@ public:
};
-} // 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..d287970e6519
--- /dev/null
+++ b/include/oox/crypto/StrongEncryptionDataSpace.hxx
@@ -0,0 +1,76 @@
+/* -*- 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 <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#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::lang::XServiceInfo, 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;
+
+ // com.sun.star.lang.XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+} // namespace crypto
+} // namespace oox
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 61262689343b..aacbe14805d3 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2934,6 +2934,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/packages,\
NoRawFormatException \
WrongPasswordException \
XDataSinkEncrSupport \
+ XPackageEncryption \
+ PackageEncryption \
))
$(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/packages/manifest,\
XManifestReader \
diff --git a/offapi/com/sun/star/packages/PackageEncryption.idl b/offapi/com/sun/star/packages/PackageEncryption.idl
new file mode 100644
index 000000000000..a2ab55ed3be8
--- /dev/null
+++ b/offapi/com/sun/star/packages/PackageEncryption.idl
@@ -0,0 +1,25 @@
+/* -*- 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 __com_sun_star_packages_PackageEncryption_idl__
+#define __com_sun_star_packages_PackageEncryption_idl__
+
+#include <com/sun/star/packages/XPackageEncryption.idl>
+
+
+module com { module sun { module star { module packages {
+
+
+service PackageEncryption : XPackageEncryption;
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/packages/XPackageEncryption.idl b/offapi/com/sun/star/packages/XPackageEncryption.idl
new file mode 100644
index 000000000000..402c3e2f25d4
--- /dev/null
+++ b/offapi/com/sun/star/packages/XPackageEncryption.idl
@@ -0,0 +1,134 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef __com_sun_star_packages_XPackageEncryption_idl__
+#define __com_sun_star_packages_XPackageEncryption_idl__
+
+#include <com/sun/star/uno/XInterface.idl>
+
+#include <com/sun/star/io/XInputStream.idl>
+#include <com/sun/star/io/XOutputStream.idl>
+
+
+module com { module sun { module star { module packages {
+
+
+/** Allows to transparently plug-in crypto for PackageStreams.
+
+ @since LibreOffice 6.5
+ */
+interface XPackageEncryption: com::sun::star::uno::XInterface
+{
+ /** Read package crypto information
+
+ @param rStreams
+ Substreams of the package (in the case of MS encryption, those
+ are OLE substorage streams).
+
+ @returns
+ True if crypto info could be retrieved, and engine initialised. False otherwise.
+ */
+ boolean readEncryptionInfo([in] sequence < com::sun::star::beans::NamedValue > rStreams);
+
+ /** Set or refresh encrytion key
+
+ @param rPassword
+ Optional password to use for generating encryption key.
+
+ @returns
+ True if key setup was successful. False otherwise.
+ */
+ boolean generateEncryptionKey([in] string rPassword);
+
+ /** Decrypt document content
+
+ After crypto setup via readEncryptionInfo(), pipe package bits through
+ encryption engine.
+
+ @param rxInputStream
+ Input data (encrypted)
+
+ @param rxOutputStream
+ Output data (decrypted)
+
+ @returns
+ True if decryption finished without error. False otherwise.
+ */
+ boolean decrypt([in] com::sun::star::io::XInputStream rxInputStream,
+ [out] com::sun::star::io::XOutputStream rxOutputStream);
+
+ /** Create key-value list of encryption meta data
+
+ After generateEncryptionKey() succeeded in setting up crypto,
+ use this method to create requisite meta data. Depending on
+ underlying crypto, this can be a salt, init vector, or other
+ algorithm-specific information that needs to be stored
+ alongside an encrypted document
+
+ @param rPassword
+ Same password as provided to generateEncryptionKey
+
+ @returns
+ Sequence of opaque key-value pairs needed for decrypting this
+ setup. Can be passed back into other instances of this service
+ via setupEncryption()
+ */
+ sequence<com::sun::star::beans::NamedValue> createEncryptionData([in] string rPassword);
+
+ /** Set key-value list of encryption meta data
+
+ Use this method to setup requisite encryption meta
+ data. Depending on the underlying crypto, this can be a salt, init
+ vector, or other algorithm-specific information that needs to
+ be stored alongside an encrypted document
+
+ @returns
+ True if encryption algo setup finished without error. False otherwise.
+ */
+ boolean setupEncryption([in] sequence<com::sun::star::beans::NamedValue> rMediaEncData);
+
+ /** Encrypt given stream
+
+ After setting up crypto via setupEncryption(), use this method to encrypt content.
+
+ @returns
+ Sequence of named output streams, specific to the crypto
+ provider. The names of sequence entry denote the substream
+ identifiers, if any. In the case of MS OLE storage, it's the
+ substorage names.
+ */
+ sequence<com::sun::star::beans::NamedValue> encrypt([in] com::sun::star::io::XInputStream rxInputStream);
+
+ /** Check if decryption meta data is valid
+
+ Some implementations might for example check HMAC values
+ here. Call this before trusting encrypted data.
+
+ @returns
+ True if decryption algo setup finished without error and
+ consistency checks have passed. False otherwise.
+ */
+ boolean checkDataIntegrity();
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index cc235b87e360..3d8b46b2a24b 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/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx
index e1a4781d234c..c4058619e5c9 100644
--- a/oox/qa/unit/CryptoTest.cxx
+++ b/oox/qa/unit/CryptoTest.cxx
@@ -66,7 +66,7 @@ void CryptoTest::testCryptoHash()
aContentString.getStr() + aContentString.getLength());
std::vector<sal_uInt8> aKey = { 'k', 'e', 'y' };
{
- oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA1);
+ oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA1);
aCryptoHash.update(aContent);
std::vector<sal_uInt8> aHash = aCryptoHash.finalize();
CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"),
@@ -74,7 +74,7 @@ void CryptoTest::testCryptoHash()
}
{
- oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA256);
+ oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA256);
aCryptoHash.update(aContent);
std::vector<sal_uInt8> aHash = aCryptoHash.finalize();
CPPUNIT_ASSERT_EQUAL(
@@ -83,7 +83,7 @@ void CryptoTest::testCryptoHash()
}
{
- oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA512);
+ oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA512);
aCryptoHash.update(aContent);
std::vector<sal_uInt8> aHash = aCryptoHash.finalize();
CPPUNIT_ASSERT_EQUAL(
@@ -95,18 +95,18 @@ void CryptoTest::testCryptoHash()
void CryptoTest::testRoundUp()
{
- CPPUNIT_ASSERT_EQUAL(16, oox::core::roundUp(16, 16));
- CPPUNIT_ASSERT_EQUAL(32, oox::core::roundUp(32, 16));
- CPPUNIT_ASSERT_EQUAL(64, oox::core::roundUp(64, 16));
+ CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(16, 16));
+ CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(32, 16));
+ CPPUNIT_ASSERT_EQUAL(64, oox::crypto::roundUp(64, 16));
- CPPUNIT_ASSERT_EQUAL(16, oox::core::roundUp(01, 16));
- CPPUNIT_ASSERT_EQUAL(32, oox::core::roundUp(17, 16));
- CPPUNIT_ASSERT_EQUAL(32, oox::core::roundUp(31, 16));
+ CPPUNIT_ASSERT_EQUAL(16, oox::crypto::roundUp(01, 16));
+ CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(17, 16));
+ CPPUNIT_ASSERT_EQUAL(32, oox::crypto::roundUp(31, 16));
}
void CryptoTest::testStandard2007()
{
- oox::core::Standard2007Engine aEngine;
+ oox::crypto::Standard2007Engine aEngine;
{
aEngine.setupEncryption("Password");
@@ -173,7 +173,7 @@ void CryptoTest::testStandard2007()
void CryptoTest::testAgileEncryptionVerifier()
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
OUString aPassword("Password");
@@ -200,9 +200,9 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
{ // Preset AES128 - SHA1
SvMemoryStream aEncryptionInfo;
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
- aEngine.setPreset(oox::core::AgileEncryptionPreset::AES_128_SHA1);
+ aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_128_SHA1);
aEngine.setupEncryption(aPassword);
aKeyDataSalt = aEngine.getInfo().keyDataSalt;
@@ -218,7 +218,7 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN);
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
uno::Reference<io::XInputStream> xInputStream(
new utl::OSeekableInputStreamWrapper(aEncryptionInfo));
@@ -227,7 +227,7 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream));
- oox::core::AgileEncryptionInfo& rInfo = aEngine.getInfo();
+ oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount);
CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize);
CPPUNIT_ASSERT_EQUAL(sal_Int32(128), rInfo.keyBits);
@@ -246,9 +246,9 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
{ // Preset AES256 - SHA512
SvMemoryStream aEncryptionInfo;
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
- aEngine.setPreset(oox::core::AgileEncryptionPreset::AES_256_SHA512);
+ aEngine.setPreset(oox::crypto::AgileEncryptionPreset::AES_256_SHA512);
aEngine.setupEncryption(aPassword);
aKeyDataSalt = aEngine.getInfo().keyDataSalt;
@@ -264,7 +264,7 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN);
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
uno::Reference<io::XInputStream> xInputStream(
new utl::OSeekableInputStreamWrapper(aEncryptionInfo));
@@ -273,7 +273,7 @@ void CryptoTest::testAgileEncrpytionInfoWritingAndParsing()
CPPUNIT_ASSERT(aEngine.readEncryptionInfo(xInputStream));
- oox::core::AgileEncryptionInfo& rInfo = aEngine.getInfo();
+ oox::crypto::AgileEncryptionInfo& rInfo = aEngine.getInfo();
CPPUNIT_ASSERT_EQUAL(sal_Int32(100000), rInfo.spinCount);
CPPUNIT_ASSERT_EQUAL(sal_Int32(16), rInfo.saltSize);
CPPUNIT_ASSERT_EQUAL(sal_Int32(256), rInfo.keyBits);
@@ -301,7 +301,7 @@ void CryptoTest::testAgileDataIntegrityHmacKey()
SvMemoryStream aEncryptionInfo;
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
aEngine.setupEncryption(aPassword);
oox::BinaryXOutputStream aBinaryEncryptionInfoOutputStream(
new utl::OSeekableOutputStreamWrapper(aEncryptionInfo), true);
@@ -316,7 +316,7 @@ void CryptoTest::testAgileDataIntegrityHmacKey()
aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN);
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
uno::Reference<io::XInputStream> xInputStream(
new utl::OSeekableInputStreamWrapper(aEncryptionInfo));
@@ -346,7 +346,7 @@ void CryptoTest::testAgileEncryptingAndDecrypting()
OString aTestString = OUStringToOString("1234567890ABCDEFGH", RTL_TEXTENCODING_UTF8);
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
// Setup input
SvMemoryStream aUnencryptedInput;
@@ -381,7 +381,7 @@ void CryptoTest::testAgileEncryptingAndDecrypting()
aEncryptionInfo.Seek(STREAM_SEEK_TO_BEGIN);
{
- oox::core::AgileEngine aEngine;
+ oox::crypto::AgileEngine aEngine;
// Read encryption info
uno::Reference<io::XInputStream> xEncryptionInfo(
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index 4a6edbdd7658..0ab68688c9be 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -276,23 +276,31 @@ 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)
{}
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;
}
@@ -326,7 +334,7 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
{
try
{
- DocumentDecryption aDecryptor(aOleStorage);
+ crypto::DocumentDecryption aDecryptor(mxContext, aOleStorage);
if( aDecryptor.readEncryptionInfo() )
{
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index 03d68fc232c4..5c5d5e5076e5 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -881,13 +881,7 @@ Reference<XStream> XmlFilterBase::implGetOutputStream( MediaDescriptor& rMediaDe
MediaDescriptor::PROP_ENCRYPTIONDATA(),
Sequence< NamedValue >() );
- OUString aPassword;
- auto pProp = std::find_if(aMediaEncData.begin(), aMediaEncData.end(),
- [](const NamedValue& rProp) { return rProp.Name == "OOXPassword"; });
- if (pProp != aMediaEncData.end())
- pProp->Value >>= aPassword;
-
- if (aPassword.isEmpty())
+ if (aMediaEncData.getLength() == 0)
{
return FilterBase::implGetOutputStream( rMediaDescriptor );
}
@@ -908,20 +902,13 @@ bool XmlFilterBase::implFinalizeExport( MediaDescriptor& rMediaDescriptor )
MediaDescriptor::PROP_ENCRYPTIONDATA(),
Sequence< NamedValue >() );
- OUString aPassword;
-
- auto pProp = std::find_if(aMediaEncData.begin(), aMediaEncData.end(),
- [](const NamedValue& rProp) { return rProp.Name == "OOXPassword"; });
- if (pProp != aMediaEncData.end())
- pProp->Value >>= aPassword;
-
- if (!aPassword.isEmpty())
+ if (aMediaEncData.getLength())
{
commitStorage();
Reference< XStream> xDocumentStream (FilterBase::implGetOutputStream(rMediaDescriptor));
oox::ole::OleStorage aOleStorage( getComponentContext(), xDocumentStream, true );
- DocumentEncryption encryptor(getMainDocumentStream(), aOleStorage, aPassword);
+ 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 d8c184caa46c..f4eb9d21ea6f 100644
--- a/oox/source/crypto/AgileEngine.cxx
+++ b/oox/source/crypto/AgileEngine.cxx
@@ -40,7 +40,7 @@ using namespace css::uno;
using namespace css::xml::sax;
using namespace css::xml;
-namespace oox::core {
+namespace oox::crypto {
namespace {
@@ -585,7 +585,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);
@@ -759,7 +759,7 @@ void AgileEngine::writeEncryptionInfo(BinaryXOutputStream & rStream)
rStream.writeMemory(aMemStream.GetData(), aMemStream.GetSize());
}
-void AgileEngine::encrypt(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)
{
@@ -799,7 +799,7 @@ void AgileEngine::encrypt(css::uno::Reference<css::io::XInputStream> & rxInputS
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);
@@ -822,6 +822,6 @@ void AgileEngine::encrypt(css::uno::Reference<css::io::XInputStream> & rxInputS
encryptHmacValue();
}
-} // namespace oox::core
+} // namespace oox::crypto
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx
index cc8c5a925b43..ff11ebbc0436 100644
--- a/oox/source/crypto/CryptTools.cxx
+++ b/oox/source/crypto/CryptTools.cxx
@@ -24,7 +24,7 @@
#include <pk11pub.h>
#endif // USE_TLS_NSS
-namespace oox::core {
+namespace oox::crypto {
#if USE_TLS_OPENSSL
struct CryptoImpl
@@ -478,6 +478,6 @@ std::vector<sal_uInt8> CryptoHash::finalize()
return aHash;
}
-} // namespace oox::core
+} // namespace oox::crypto
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx
index 1ed26f4d341c..45b820a89302 100644
--- a/oox/source/crypto/DocumentDecryption.cxx
+++ b/oox/source/crypto/DocumentDecryption.cxx
@@ -13,26 +13,89 @@
#include <comphelper/sequenceashashmap.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/io/XStream.hpp>
-#include <oox/crypto/AgileEngine.hxx>
-#include <oox/crypto/Standard2007Engine.hxx>
-#include <oox/helper/binaryinputstream.hxx>
-#include <oox/helper/binaryoutputstream.hxx>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
#include <oox/ole/olestorage.hxx>
+#include <oox/helper/binaryinputstream.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>
+
+#include <sal/log.hxx>
+
+namespace {
+
+void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rElementNames)
+{
+ std::vector< OUString > oElementNames;
+ pStorage->getElementNames(oElementNames);
+ for (const auto & sName : oElementNames)
+ {
+ oox::StorageRef rSubStorage = pStorage->openSubStorage(sName, false);
+ if (rSubStorage && rSubStorage->isStorage())
+ {
+ lcl_getListOfStreams(rSubStorage.get(), rElementNames);
+ }
+ else
+ {
+ if (pStorage->isRootStorage())
+ rElementNames.push_back(sName);
+ else
+ rElementNames.push_back(pStorage->getPath() + "/" + sName);
+ }
+ }
+}
+
+}
-namespace oox::core {
+namespace oox::crypto {
using namespace css;
-DocumentDecryption::DocumentDecryption(oox::ole::OleStorage& rOleStorage) :
- mrOleStorage(rOleStorage),
- mCryptoType(UNKNOWN)
-{}
+DocumentDecryption::DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
+ oox::ole::OleStorage& rOleStorage) :
+ mxContext(rxContext),
+ mrOleStorage(rOleStorage)
+{
+ // Get OLE streams into sequences for later use in CryptoEngine
+ std::vector< OUString > aStreamNames;
+ lcl_getListOfStreams(&mrOleStorage, aStreamNames);
+
+ comphelper::SequenceAsHashMap aStreamsData;
+ for (const auto & sStreamName : aStreamNames)
+ {
+ uno::Reference<io::XInputStream> xStream = mrOleStorage.openInputStream(sStreamName);
+ if (!xStream.is())
+ throw io::IOException( "Cannot open OLE input stream for " + sStreamName + "!" );
+
+ BinaryXInputStream aBinaryInputStream(xStream, true);
+
+ css::uno::Sequence< sal_Int8 > oData;
+ sal_Int32 nStreamSize = aBinaryInputStream.size();
+ sal_Int32 nReadBytes = aBinaryInputStream.readData(oData, nStreamSize);
+
+ if (nStreamSize != nReadBytes)
+ {
+ SAL_WARN("oox", "OLE stream invalid content");
+ throw io::IOException( "OLE stream invalid content for " + sStreamName + "!" );
+ }
+
+ aStreamsData[sStreamName] <<= oData;
+ }
+ maStreamsSequence = aStreamsData.getAsConstNamedValueList();
+}
bool DocumentDecryption::generateEncryptionKey(const OUString& rPassword)
{
- if (mEngine)
- return mEngine->generateEncryptionKey(rPassword);
+ if (mxPackageEncryption.is())
+ return mxPackageEncryption->generateEncryptionKey(rPassword);
return false;
}
@@ -41,45 +104,70 @@ bool DocumentDecryption::readEncryptionInfo()
if (!mrOleStorage.isStorage())
return false;
- uno::Reference<io::XInputStream> xEncryptionInfo = mrOleStorage.openInputStream("EncryptionInfo");
+ // Read 0x6DataSpaces/DataSpaceMap
+ uno::Reference<io::XInputStream> xDataSpaceMap = mrOleStorage.openInputStream("\006DataSpaces/DataSpaceMap");
+ OUString sDataSpaceName;
- BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true);
- sal_uInt32 aVersion = aBinaryInputStream.readuInt32();
+ if (xDataSpaceMap.is())
+ {
+ BinaryXInputStream aDataSpaceStream(xDataSpaceMap, true);
+ sal_uInt32 aHeaderLength = aDataSpaceStream.readuInt32();
+ SAL_WARN_IF(aHeaderLength != 8, "oox", "DataSpaceMap length != 8 is not supported. Some content may be skipped");
+ sal_uInt32 aEntryCount = aDataSpaceStream.readuInt32();
+ SAL_WARN_IF(aEntryCount != 1, "oox", "DataSpaceMap contains more than one entry. Some content may be skipped");
+
+ // Read each DataSpaceMapEntry (MS-OFFCRYPTO 2.1.6.1)
+ for (sal_uInt32 i = 0; i < aEntryCount; i++)
+ {
+ // entryLen unused for the moment
+ aDataSpaceStream.skip(sizeof(sal_uInt32));
+
+ // Read each DataSpaceReferenceComponent (MS-OFFCRYPTO 2.1.6.2)
+ sal_uInt32 aReferenceComponentCount = aDataSpaceStream.readuInt32();
+ for (sal_uInt32 j = 0; j < aReferenceComponentCount; j++)
+ {
+ // Read next reference component
+ // refComponentType unused for the moment
+ aDataSpaceStream.skip(sizeof(sal_uInt32));
+ sal_uInt32 aReferenceComponentNameLength = aDataSpaceStream.readuInt32();
+ // sReferenceComponentName unused for the moment
+ aDataSpaceStream.readUnicodeArray(aReferenceComponentNameLength / 2);
+ aDataSpaceStream.skip((4 - (aReferenceComponentNameLength & 3)) & 3); // Skip padding
+ }
+
+ sal_uInt32 aDataSpaceNameLength = aDataSpaceStream.readuInt32();
+ sDataSpaceName = aDataSpaceStream.readUnicodeArray(aDataSpaceNameLength / 2);
+ aDataSpaceStream.skip((4 - (aDataSpaceNameLength & 3)) & 3); // Skip padding
+ }
+ }
+ 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");
+ sDataSpaceName = "StrongEncryptionDataSpace";
+ }
- switch (aVersion)
+ 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())
{
- case msfilter::VERSION_INFO_2007_FORMAT:
- case msfilter::VERSION_INFO_2007_FORMAT_SP2:
- mCryptoType = STANDARD_2007; // Set encryption info format
- mEngine.reset(new Standard2007Engine);
- break;
- case msfilter::VERSION_INFO_AGILE:
- mCryptoType = AGILE; // Set encryption info format
- mEngine.reset(new AgileEngine);
- break;
- default:
- break;
+ // we do not know how to decrypt this document
+ return false;
}
- if (mEngine)
- return mEngine->readEncryptionInfo(xEncryptionInfo);
- return false;
+
+ return mxPackageEncryption->readEncryptionInfo(maStreamsSequence);
}
uno::Sequence<beans::NamedValue> DocumentDecryption::createEncryptionData(const OUString& rPassword)
{
- comphelper::SequenceAsHashMap aEncryptionData;
+ if (!mxPackageEncryption.is())
+ return uno::Sequence<beans::NamedValue>();
- if (mCryptoType == AGILE)
- {
- aEncryptionData["CryptoType"] <<= OUString("Agile");
- }
- else if (mCryptoType == STANDARD_2007)
- {
- aEncryptionData["CryptoType"] <<= OUString("Standard");
- }
-
- aEncryptionData["OOXPassword"] <<= rPassword;
- return aEncryptionData.getAsConstNamedValueList();
+ return mxPackageEncryption->createEncryptionData(rPassword);
}
bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStream)
@@ -89,25 +177,26 @@ bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStr
if (!mrOleStorage.isStorage())
return false;
+ if (!mxPackageEncryption.is())
+ return false;
+
// open the required input streams in the encrypted package
uno::Reference<io::XInputStream> xEncryptedPackage = mrOleStorage.openInputStream("EncryptedPackage");
// create temporary file for unencrypted package
uno::Reference<io::XOutputStream> xDecryptedPackage = xDocumentStream->getOutputStream();
- BinaryXOutputStream aDecryptedPackage(xDecryptedPackage, true);
- BinaryXInputStream aEncryptedPackage(xEncryptedPackage, true);
- bResult = mEngine->decrypt(aEncryptedPackage, aDecryptedPackage);
+ bResult = mxPackageEncryption->decrypt(xEncryptedPackage, xDecryptedPackage);
- xDecryptedPackage->flush();
- aDecryptedPackage.seekToStart();
+ css::uno::Reference<io::XSeekable> xSeekable(xDecryptedPackage, css::uno::UNO_QUERY);
+ xSeekable->seek(0);
if (bResult)
- return mEngine->checkDataIntegrity();
+ return mxPackageEncryption->checkDataIntegrity();
return bResult;
}
-} // namespace oox::core
+} // namespace oox::crypto
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/DocumentEncryption.cxx b/oox/source/crypto/DocumentEncryption.cxx
index 1ea421c8392f..6b88549299a1 100644
--- a/oox/source/crypto/DocumentEncryption.cxx
+++ b/oox/source/crypto/DocumentEncryption.cxx
@@ -14,58 +14,90 @@
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
#include <oox/helper/binaryoutputstream.hxx>
#include <oox/ole/olestorage.hxx>
+#include <sal/log.hxx>
-namespace oox::core {
+namespace oox::crypto {
using namespace css::io;
using namespace css::uno;
+using namespace css::beans;
-DocumentEncryption::DocumentEncryption(Reference<XStream> const & xDocumentStream,
+DocumentEncryption::DocumentEncryption(const Reference< XComponentContext >& rxContext,
+ Reference<XStream> const & xDocumentStream,
oox::ole::OleStorage& rOleStorage,
- const OUString& rPassword)
- : mxDocumentStream(xDocumentStream)
+ const Sequence<NamedValue>& rMediaEncData)
+ : mxContext(rxContext)
+ , mxDocumentStream(xDocumentStream)
, mrOleStorage(rOleStorage)
- , maPassword(rPassword)
-{}
+ , mMediaEncData(rMediaEncData)
+{
+ // Select engine
+ for (int i = 0; i < rMediaEncData.getLength(); i++)
+ {
+ if (rMediaEncData[i].Name == "CryptoType")
+ {
+ OUString sCryptoType;
+ rMediaEncData[i].Value >>= sCryptoType;
+
+ if (sCryptoType == "Standard")
+ sCryptoType = "StrongEncryptionDataSpace";
+
+ Sequence<Any> aArguments;
+ mxPackageEncryption.set(
+ mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, mxContext), css::uno::UNO_QUERY);
+
+ if (!mxPackageEncryption.is())
+ {
+ SAL_WARN("oox", "Requested encryption method \"" << sCryptoType << "\" is not supported");
+ }
+
+ break;
+ }
+ }
+}
bool DocumentEncryption::encrypt()
{
+ if (!mxPackageEncryption.is())
+ return false;
+
Reference<XInputStream> xInputStream (mxDocumentStream->getInputStream(), UNO_SET_THROW);
Reference<XSeekable> xSeekable(xInputStream, UNO_QUERY);
if (!xSeekable.is())
return false;
- sal_uInt32 aLength = xSeekable->getLength(); // check length of the stream
xSeekable->seek(0); // seek to begin of the document stream
if (!mrOleStorage.isStorage())
return false;
- mEngine.setupEncryption(maPassword);
-
- Reference<XOutputStream> xOutputStream(mrOleStorage.openOutputStream("EncryptedPackage"), UNO_SET_THROW);
+ mxPackageEncryption->setupEncryption(mMediaEncData);
- mEngine.encrypt(xInputStream, xOutputStream, aLength);
+ Sequence<NamedValue> aStreams = mxPackageEncryption->encrypt(xInputStream);
- xOutputStream->flush();
- xOutputStream->closeOutput();
+ for (const NamedValue & aStream : std::as_const(aStreams))
+ {
+ Reference<XOutputStream> xOutputStream(mrOleStorage.openOutputStream(aStream.Name), UNO_SET_THROW);
+ BinaryXOutputStream aBinaryOutputStream(xOutputStream, true);
- Reference<XOutputStream> xEncryptionInfo(mrOleStorage.openOutputStream("EncryptionInfo"), UNO_SET_THROW);
- BinaryXOutputStream aEncryptionInfoBinaryOutputStream(xEncryptionInfo, false);
+ css::uno::Sequence<sal_Int8> aStreamSequence;
+ aStream.Value >>= aStreamSequence;
- mEngine.writeEncryptionInfo(aEncryptionInfoBinaryOutputStream);
+ aBinaryOutputStream.writeData(aStreamSequence);
- aEncryptionInfoBinaryOutputStream.close();
- xEncryptionInfo->flush();
- xEncryptionInfo->closeOutput();
+ aBinaryOutputStream.close();
+ }
return true;
}
-} // namespace oox::core
+} // namespace oox::crypto
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx
index 0ad782522450..2aaf6f4ec3f3 100644
--- a/oox/source/crypto/Standard2007Engine.cxx
+++ b/oox/source/crypto/Standard2007Engine.cxx
@@ -17,7 +17,7 @@
#include <comphelper/hash.hxx>
-namespace oox::core {
+namespace oox::crypto {
/* =========================================================================== */
/* Kudos to Caolan McNamara who provided the core decryption implementations. */
@@ -228,7 +228,7 @@ void Standard2007Engine::writeEncryptionInfo(BinaryXOutputStream& rStream)
rStream.writeMemory(&mInfo.verifier, sizeof(msfilter::EncryptionVerifierAES));
}
-void Standard2007Engine::encrypt(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)
{
@@ -316,6 +316,6 @@ bool Standard2007Engine::readEncryptionInfo(css::uno::Reference<css::io::XInputS
return !aBinaryStream.isEof();
}
-} // namespace oox::core
+} // namespace oox::crypto
/* 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..2e21a89158f6
--- /dev/null
+++ b/oox/source/crypto/StrongEncryptionDataSpace.cxx
@@ -0,0 +1,206 @@
+/* -*- 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 <oox/helper/binaryoutputstream.hxx>
+#include <oox/helper/binaryinputstream.hxx>
+#include <com/sun/star/io/SequenceInputStream.hpp>
+#include <com/sun/star/io/XSequenceOutputStream.hpp>
+
+#include <comphelper/sequenceashashmap.hxx>
+#include <cppuhelper/supportsservice.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> aStream2(
+ io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq),
+ UNO_QUERY_THROW);
+ return aStream2;
+ }
+ }
+ 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();
+
+ 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();
+}
+
+OUString SAL_CALL StrongEncryptionDataSpace::getImplementationName()
+{
+ return "com.sun.star.comp.oox.crypto.StrongEncryptionDataSpace";
+}
+
+sal_Bool SAL_CALL StrongEncryptionDataSpace::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL StrongEncryptionDataSpace::getSupportedServiceNames()
+{
+ Sequence<OUString> aServices{ "com.sun.star.packages.PackageEncryption" };
+ return aServices;
+}
+
+} // 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 32a8100b8fb8..ef54da9a11e2 100644
--- a/oox/util/oox.component
+++ b/oox/util/oox.component
@@ -40,4 +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.StrongEncryptionDataSpace"
+ constructor="com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation">
+ <service name="com.sun.star.packages.PackageEncryption"/>
+ </implementation>
</component>
diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx
index e39033880c0e..1400bf71e17b 100644
--- a/sfx2/source/dialog/filedlghelper.cxx
+++ b/sfx2/source/dialog/filedlghelper.cxx
@@ -2697,7 +2697,8 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter,
if (bOOXML)
{
::comphelper::SequenceAsHashMap aHashData;
- aHashData[ OUString( "OOXPassword" ) ] <<= pPasswordRequest->getPassword();
+ aHashData[ OUString( "OOXPassword" ) ] <<= pPasswordRequest->getPassword();
+ aHashData[ OUString( "CryptoType" ) ] <<= OUString( "Standard" );
aEncryptionData = aHashData.getAsConstNamedValueList();
}
else
diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py
index f5012b2ff18f..d2165c197ac9 100755
--- a/solenv/bin/native-code.py
+++ b/solenv/bin/native-code.py
@@ -358,6 +358,7 @@ core_constructor_list = [
"com_sun_star_comp_oox_docprop_DocumentPropertiesImporter_get_implementation",
"com_sun_star_comp_oox_ppt_PowerPointImport_get_implementation",
"com_sun_star_comp_oox_ShapeContextHandler_get_implementation",
+ "com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation",
]
# edit group for apps, where you can edit documents
diff --git a/sw/qa/inc/swmodeltestbase.hxx b/sw/qa/inc/swmodeltestbase.hxx
index c6cbf9f83afe..32db863d5d3d 100644
--- a/sw/qa/inc/swmodeltestbase.hxx
+++ b/sw/qa/inc/swmodeltestbase.hxx
@@ -808,6 +808,7 @@ protected:
{
OUString sPassword = OUString::createFromAscii(pPassword);
css::uno::Sequence<css::beans::NamedValue> aEncryptionData {
+ { "CryptoType", css::uno::makeAny(OUString("Standard")) },
{ "OOXPassword", css::uno::makeAny(sPassword) }
};
aMediaDescriptor[utl::MediaDescriptor::PROP_ENCRYPTIONDATA()] <<= aEncryptionData;
diff --git a/unotools/source/misc/mediadescriptor.cxx b/unotools/source/misc/mediadescriptor.cxx
index 1b830fb4e7d9..7f8f4e3c3785 100644
--- a/unotools/source/misc/mediadescriptor.cxx
+++ b/unotools/source/misc/mediadescriptor.cxx
@@ -473,8 +473,9 @@ css::uno::Sequence< css::beans::NamedValue > MediaDescriptor::requestAndVerifyDo
erase( PROP_PASSWORD() );
erase( PROP_ENCRYPTIONDATA() );
- // insert valid password into media descriptor (but not a default password)
- if( aEncryptionData.hasElements() && !bIsDefaultPassword )
+ // insert encryption info into media descriptor
+ // TODO
+ if( aEncryptionData.hasElements() )
(*this)[ PROP_ENCRYPTIONDATA() ] <<= aEncryptionData;
return aEncryptionData;