diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2018-07-04 17:45:00 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2018-07-06 18:26:47 +0200 |
commit | 96fb57611f8c9fa19a12c0fd9ed6e0c383962ac7 (patch) | |
tree | 04612c2b2f6e32fbb692b3744682f3a54bc9bab4 /oox | |
parent | 72aa159a6fce92f47a56a8de8c7f8260577dd936 (diff) |
oox: move reading of the encryption info into the crypt engine
Change-Id: I92345cd8a0f9fc9172ae087e1bc1a16afdd67d8a
Reviewed-on: https://gerrit.libreoffice.org/56972
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/source/crypto/AgileEngine.cxx | 200 | ||||
-rw-r--r-- | oox/source/crypto/DocumentDecryption.cxx | 306 | ||||
-rw-r--r-- | oox/source/crypto/Standard2007Engine.cxx | 56 |
3 files changed, 273 insertions, 289 deletions
diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx index 49b428053061..72cd51e16986 100644 --- a/oox/source/crypto/AgileEngine.cxx +++ b/oox/source/crypto/AgileEngine.cxx @@ -13,14 +13,161 @@ #include <oox/helper/binaryinputstream.hxx> #include <oox/helper/binaryoutputstream.hxx> +#include <sax/tools/converter.hxx> + #include <comphelper/hash.hxx> #include <comphelper/docpasswordhelper.hxx> +#include <comphelper/random.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/base64.hxx> +#include <comphelper/sequence.hxx> + +#include <filter/msfilter/mscodec.hxx> + +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/sax/XFastParser.hpp> +#include <com/sun/star/xml/sax/XFastTokenHandler.hpp> +#include <com/sun/star/xml/sax/FastParser.hpp> +#include <com/sun/star/xml/sax/FastToken.hpp> + +using namespace css; +using namespace css::beans; +using namespace css::io; +using namespace css::lang; +using namespace css::uno; +using namespace css::xml::sax; +using namespace css::xml; namespace oox { namespace core { namespace { +OUString stripNamespacePrefix(OUString const & rsInputName) +{ + return rsInputName.copy(rsInputName.indexOf(":") + 1); +} + +class AgileTokenHandler : public cppu::WeakImplHelper<XFastTokenHandler> +{ +public: + virtual sal_Int32 SAL_CALL getTokenFromUTF8(const Sequence< sal_Int8 >& /*nIdentifier*/) override + { + return FastToken::DONTKNOW; + } + + virtual Sequence<sal_Int8> SAL_CALL getUTF8Identifier(sal_Int32 /*nToken*/) override + { + return Sequence<sal_Int8>(); + } +}; + +class AgileDocumentHandler : public ::cppu::WeakImplHelper<XFastDocumentHandler> +{ + AgileEncryptionInfo& mInfo; + +public: + explicit AgileDocumentHandler(AgileEncryptionInfo& rInfo) : + mInfo(rInfo) + {} + + void SAL_CALL startDocument() override {} + void SAL_CALL endDocument() override {} + void SAL_CALL processingInstruction( const OUString& /*rTarget*/, const OUString& /*rData*/ ) override {} + void SAL_CALL setDocumentLocator( const Reference< XLocator >& /*xLocator*/ ) override {} + void SAL_CALL startFastElement( sal_Int32 /*Element*/, const Reference< XFastAttributeList >& /*Attribs*/ ) override {} + + void SAL_CALL startUnknownElement( const OUString& /*aNamespace*/, const OUString& rName, const Reference< XFastAttributeList >& aAttributeList ) override + { + const OUString& rLocalName = stripNamespacePrefix(rName); + + for (const Attribute& rAttribute : aAttributeList->getUnknownAttributes()) + { + const OUString& rAttrLocalName = stripNamespacePrefix(rAttribute.Name); + + if (rAttrLocalName == "spinCount") + { + ::sax::Converter::convertNumber(mInfo.spinCount, rAttribute.Value); + } + else if (rAttrLocalName == "saltSize") + { + ::sax::Converter::convertNumber(mInfo.saltSize, rAttribute.Value); + } + else if (rAttrLocalName == "blockSize") + { + ::sax::Converter::convertNumber(mInfo.blockSize, rAttribute.Value); + } + else if (rAttrLocalName == "keyBits") + { + ::sax::Converter::convertNumber(mInfo.keyBits, rAttribute.Value); + } + else if (rAttrLocalName == "hashSize") + { + ::sax::Converter::convertNumber(mInfo.hashSize, rAttribute.Value); + } + else if (rAttrLocalName == "cipherAlgorithm") + { + mInfo.cipherAlgorithm = rAttribute.Value; + } + else if (rAttrLocalName == "cipherChaining") + { + mInfo.cipherChaining = rAttribute.Value; + } + else if (rAttrLocalName == "hashAlgorithm") + { + mInfo.hashAlgorithm = rAttribute.Value; + } + else if (rAttrLocalName == "saltValue") + { + Sequence<sal_Int8> saltValue; + comphelper::Base64::decode(saltValue, rAttribute.Value); + if (rLocalName == "encryptedKey") + mInfo.saltValue = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(saltValue); + else if (rLocalName == "keyData") + mInfo.keyDataSalt = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(saltValue); + } + else if (rAttrLocalName == "encryptedVerifierHashInput") + { + Sequence<sal_Int8> encryptedVerifierHashInput; + comphelper::Base64::decode(encryptedVerifierHashInput, rAttribute.Value); + mInfo.encryptedVerifierHashInput = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(encryptedVerifierHashInput); + } + else if (rAttrLocalName == "encryptedVerifierHashValue") + { + Sequence<sal_Int8> encryptedVerifierHashValue; + comphelper::Base64::decode(encryptedVerifierHashValue, rAttribute.Value); + mInfo.encryptedVerifierHashValue = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(encryptedVerifierHashValue); + } + else if (rAttrLocalName == "encryptedKeyValue") + { + Sequence<sal_Int8> encryptedKeyValue; + comphelper::Base64::decode(encryptedKeyValue, rAttribute.Value); + mInfo.encryptedKeyValue = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(encryptedKeyValue); + } + } + } + + void SAL_CALL endFastElement( sal_Int32 /*aElement*/ ) override + {} + void SAL_CALL endUnknownElement( const OUString& /*aNamespace*/, const OUString& /*aName*/ ) override + {} + + Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 /*aElement*/, const Reference< XFastAttributeList >& /*aAttribs*/ ) override + { + return nullptr; + } + + Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& /*aNamespace*/, const OUString& /*aName*/, const Reference< XFastAttributeList >& /*aAttribs*/ ) override + { + return this; + } + + void SAL_CALL characters( const OUString& /*aChars*/ ) override + {} +}; + const sal_uInt32 constSegmentLength = 4096; bool hashCalc(std::vector<sal_uInt8>& output, @@ -163,6 +310,59 @@ bool AgileEngine::decrypt(BinaryXInputStream& aInputStream, return true; } +bool AgileEngine::readEncryptionInfo(uno::Reference<io::XInputStream> & rxInputStream) +{ + mInfo.spinCount = 0; + mInfo.saltSize = 0; + mInfo.keyBits = 0; + mInfo.hashSize = 0; + mInfo.blockSize = 0; + + Reference<XFastDocumentHandler> xFastDocumentHandler(new AgileDocumentHandler(mInfo)); + Reference<XFastTokenHandler> xFastTokenHandler(new AgileTokenHandler); + + Reference<XFastParser> xParser(css::xml::sax::FastParser::create(comphelper::getProcessComponentContext())); + + xParser->setFastDocumentHandler(xFastDocumentHandler); + xParser->setTokenHandler(xFastTokenHandler); + + InputSource aInputSource; + aInputSource.aInputStream = rxInputStream; + xParser->parseStream(aInputSource); + + // CHECK info data + if (2 > mInfo.blockSize || mInfo.blockSize > 4096) + return false; + + if (0 > mInfo.spinCount || mInfo.spinCount > 10000000) + return false; + + if (1 > mInfo.saltSize|| mInfo.saltSize > 65536) // Check + return false; + + // AES 128 CBC with SHA1 + if (mInfo.keyBits == 128 && + mInfo.cipherAlgorithm == "AES" && + mInfo.cipherChaining == "ChainingModeCBC" && + mInfo.hashAlgorithm == "SHA1" && + mInfo.hashSize == msfilter::SHA1_HASH_LENGTH) + { + return true; + } + + // AES 256 CBC with SHA512 + if (mInfo.keyBits == 256 && + mInfo.cipherAlgorithm == "AES" && + mInfo.cipherChaining == "ChainingModeCBC" && + mInfo.hashAlgorithm == "SHA512" && + mInfo.hashSize == msfilter::SHA512_HASH_LENGTH) + { + return true; + } + + return false; +} + void AgileEngine::writeEncryptionInfo( const OUString& /*aPassword*/, BinaryXOutputStream& /*rStream*/) diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx index bd8dff7e022a..40d854123568 100644 --- a/oox/source/crypto/DocumentDecryption.cxx +++ b/oox/source/crypto/DocumentDecryption.cxx @@ -10,18 +10,11 @@ #include <oox/crypto/DocumentDecryption.hxx> -#include <comphelper/base64.hxx> #include <comphelper/sequenceashashmap.hxx> -#include <sax/tools/converter.hxx> #include <cppuhelper/implbase.hxx> -#include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/uno/XComponentContext.hpp> -#include <com/sun/star/xml/sax/XFastParser.hpp> -#include <com/sun/star/xml/sax/XFastTokenHandler.hpp> -#include <com/sun/star/xml/sax/FastParser.hpp> -#include <com/sun/star/xml/sax/FastToken.hpp> #include <oox/crypto/AgileEngine.hxx> #include <oox/crypto/Standard2007Engine.hxx> #include <oox/helper/binaryinputstream.hxx> @@ -31,158 +24,9 @@ namespace oox { namespace core { -using namespace css::beans; -using namespace css::io; -using namespace css::lang; -using namespace css::uno; -using namespace css::xml::sax; -using namespace css::xml; +using namespace css; -namespace { - -std::vector<sal_uInt8> convertToVector(Sequence<sal_Int8> const & input) -{ - const sal_uInt8* inputArray = reinterpret_cast<const sal_uInt8*>(input.getConstArray()); - return std::vector<sal_uInt8>(inputArray, inputArray + input.getLength()); -} - -class AgileTokenHandler : public cppu::WeakImplHelper<XFastTokenHandler> -{ -public: - virtual sal_Int32 SAL_CALL getTokenFromUTF8( const Sequence< sal_Int8 >& /*nIdentifier*/ ) override - { - return FastToken::DONTKNOW; - } - - virtual Sequence<sal_Int8> SAL_CALL getUTF8Identifier(sal_Int32 /*nToken*/) override - { - return Sequence<sal_Int8>(); - } -}; - -class AgileDocumentHandler : public ::cppu::WeakImplHelper<XFastDocumentHandler> -{ - AgileEncryptionInfo& mInfo; - -public: - explicit AgileDocumentHandler(AgileEncryptionInfo& rInfo) : - mInfo(rInfo) - {} - - void SAL_CALL startDocument() override - {} - void SAL_CALL endDocument() override - {} - void SAL_CALL processingInstruction( const OUString& /*rTarget*/, const OUString& /*rData*/ ) override - {} - void SAL_CALL setDocumentLocator( const Reference< XLocator >& /*xLocator*/ ) override - {} - void SAL_CALL startFastElement( sal_Int32 /*Element*/, const Reference< XFastAttributeList >& /*Attribs*/ ) override - {} - - void SAL_CALL startUnknownElement( const OUString& /*aNamespace*/, const OUString& rName, const Reference< XFastAttributeList >& aAttributeList ) override - { - const auto& localname = [](const OUString &a) { return a.copy(a.indexOf(":") + 1); }; - const OUString& rLocalName = localname(rName); - if (rLocalName == "keyData") - { - for (const Attribute& rAttribute : aAttributeList->getUnknownAttributes()) - { - if (localname(rAttribute.Name) == "saltValue") - { - Sequence<sal_Int8> keyDataSalt; - ::comphelper::Base64::decode(keyDataSalt, rAttribute.Value); - mInfo.keyDataSalt = convertToVector(keyDataSalt); - } - } - } - else if (rLocalName == "encryptedKey") - { - for (const Attribute& rAttribute : aAttributeList->getUnknownAttributes()) - { - const OUString& rAttrLocalName = localname(rAttribute.Name); - if (rAttrLocalName == "spinCount") - { - ::sax::Converter::convertNumber(mInfo.spinCount, rAttribute.Value); - } - else if (rAttrLocalName == "saltSize") - { - ::sax::Converter::convertNumber(mInfo.saltSize, rAttribute.Value); - } - else if (rAttrLocalName == "blockSize") - { - ::sax::Converter::convertNumber(mInfo.blockSize, rAttribute.Value); - } - else if (rAttrLocalName == "keyBits") - { - ::sax::Converter::convertNumber(mInfo.keyBits, rAttribute.Value); - } - else if (rAttrLocalName == "hashSize") - { - ::sax::Converter::convertNumber(mInfo.hashSize, rAttribute.Value); - } - else if (rAttrLocalName == "cipherAlgorithm") - { - mInfo.cipherAlgorithm = rAttribute.Value; - } - else if (rAttrLocalName == "cipherChaining") - { - mInfo.cipherChaining = rAttribute.Value; - } - else if (rAttrLocalName == "hashAlgorithm") - { - mInfo.hashAlgorithm = rAttribute.Value; - } - else if (rAttrLocalName == "saltValue") - { - Sequence<sal_Int8> saltValue; - ::comphelper::Base64::decode(saltValue, rAttribute.Value); - mInfo.saltValue = convertToVector(saltValue); - } - else if (rAttrLocalName == "encryptedVerifierHashInput") - { - Sequence<sal_Int8> encryptedVerifierHashInput; - ::comphelper::Base64::decode(encryptedVerifierHashInput, rAttribute.Value); - mInfo.encryptedVerifierHashInput = convertToVector(encryptedVerifierHashInput); - } - else if (rAttrLocalName == "encryptedVerifierHashValue") - { - Sequence<sal_Int8> encryptedVerifierHashValue; - ::comphelper::Base64::decode(encryptedVerifierHashValue, rAttribute.Value); - mInfo.encryptedVerifierHashValue = convertToVector(encryptedVerifierHashValue); - } - else if (rAttrLocalName == "encryptedKeyValue") - { - Sequence<sal_Int8> encryptedKeyValue; - ::comphelper::Base64::decode(encryptedKeyValue, rAttribute.Value); - mInfo.encryptedKeyValue = convertToVector(encryptedKeyValue); - } - } - } - } - - void SAL_CALL endFastElement( sal_Int32 /*aElement*/ ) override - {} - void SAL_CALL endUnknownElement( const OUString& /*aNamespace*/, const OUString& /*aName*/ ) override - {} - - Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 /*aElement*/, const Reference< XFastAttributeList >& /*aAttribs*/ ) override - { - return nullptr; - } - - Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& /*aNamespace*/, const OUString& /*aName*/, const Reference< XFastAttributeList >& /*aAttribs*/ ) override - { - return this; - } - - void SAL_CALL characters( const OUString& /*aChars*/ ) override - {} -}; - -} // namespace - -DocumentDecryption::DocumentDecryption(oox::ole::OleStorage& rOleStorage, Reference<XComponentContext> const & xContext) : +DocumentDecryption::DocumentDecryption(oox::ole::OleStorage& rOleStorage, uno::Reference<uno::XComponentContext> const & xContext) : mxContext(xContext), mrOleStorage(rOleStorage), mCryptoType(UNKNOWN) @@ -190,136 +34,19 @@ DocumentDecryption::DocumentDecryption(oox::ole::OleStorage& rOleStorage, Refere bool DocumentDecryption::generateEncryptionKey(const OUString& rPassword) { - if (mEngine.get()) + if (mEngine) return mEngine->generateEncryptionKey(rPassword); return false; } -bool DocumentDecryption::readAgileEncryptionInfo(Reference< XInputStream > const & xInputStream) -{ - AgileEngine* engine = new AgileEngine; - mEngine.reset(engine); - AgileEncryptionInfo& info = engine->getInfo(); - info.spinCount = 0; - info.saltSize = 0; - info.keyBits = 0; - info.hashSize = 0; - info.blockSize = 0; - - Reference<XFastDocumentHandler> xFastDocumentHandler( new AgileDocumentHandler(info) ); - Reference<XFastTokenHandler> xFastTokenHandler ( new AgileTokenHandler ); - - Reference<XFastParser> xParser(css::xml::sax::FastParser::create(mxContext)); - - xParser->setFastDocumentHandler(xFastDocumentHandler); - xParser->setTokenHandler(xFastTokenHandler); - - InputSource aInputSource; - aInputSource.aInputStream = xInputStream; - xParser->parseStream(aInputSource); - - // CHECK info data - if (2 > info.blockSize || info.blockSize > 4096) - return false; - - if (0 > info.spinCount || info.spinCount > 10000000) - return false; - - if (1 > info.saltSize|| info.saltSize > 65536) // Check - return false; - - // AES 128 CBC with SHA1 - if (info.keyBits == 128 && - info.cipherAlgorithm == "AES" && - info.cipherChaining == "ChainingModeCBC" && - info.hashAlgorithm == "SHA1" && - info.hashSize == msfilter::SHA1_HASH_LENGTH) - { - return true; - } - - // AES 256 CBC with SHA512 - if (info.keyBits == 256 && - info.cipherAlgorithm == "AES" && - info.cipherChaining == "ChainingModeCBC" && - info.hashAlgorithm == "SHA512" && - info.hashSize == msfilter::SHA512_HASH_LENGTH) - { - return true; - } - - return false; -} - -bool DocumentDecryption::readStandard2007EncryptionInfo(BinaryInputStream& rStream) -{ - Standard2007Engine* engine = new Standard2007Engine; - mEngine.reset(engine); - msfilter::StandardEncryptionInfo& info = engine->getInfo(); - - info.header.flags = rStream.readuInt32(); - if (getFlag(info.header.flags, msfilter::ENCRYPTINFO_EXTERNAL)) - return false; - - sal_uInt32 nHeaderSize = rStream.readuInt32(); - - sal_uInt32 actualHeaderSize = sizeof(info.header); - - if (nHeaderSize < actualHeaderSize) - return false; - - info.header.flags = rStream.readuInt32(); - info.header.sizeExtra = rStream.readuInt32(); - info.header.algId = rStream.readuInt32(); - info.header.algIdHash = rStream.readuInt32(); - info.header.keyBits = rStream.readuInt32(); - info.header.providedType = rStream.readuInt32(); - info.header.reserved1 = rStream.readuInt32(); - info.header.reserved2 = rStream.readuInt32(); - - rStream.skip(nHeaderSize - actualHeaderSize); - - info.verifier.saltSize = rStream.readuInt32(); - rStream.readArray(info.verifier.salt, SAL_N_ELEMENTS(info.verifier.salt)); - rStream.readArray(info.verifier.encryptedVerifier, SAL_N_ELEMENTS(info.verifier.encryptedVerifier)); - info.verifier.encryptedVerifierHashSize = rStream.readuInt32(); - rStream.readArray(info.verifier.encryptedVerifierHash, SAL_N_ELEMENTS(info.verifier.encryptedVerifierHash)); - - if (info.verifier.saltSize != 16) - return false; - - // check flags and algorithm IDs, required are AES128 and SHA-1 - if (!getFlag(info.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI)) - return false; - - if (!getFlag(info.header.flags, msfilter::ENCRYPTINFO_AES)) - return false; - - // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set - if (info.header.algId != 0 && info.header.algId != msfilter::ENCRYPT_ALGO_AES128) - return false; - - // hash algorithm ID 0 defaults to SHA-1 too - if (info.header.algIdHash != 0 && info.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1) - return false; - - if (info.verifier.encryptedVerifierHashSize != 20) - return false; - - return !rStream.isEof(); -} - bool DocumentDecryption::readEncryptionInfo() { if (!mrOleStorage.isStorage()) return false; - Reference<XInputStream> xEncryptionInfo(mrOleStorage.openInputStream("EncryptionInfo"), UNO_SET_THROW); - - bool bResult = false; + uno::Reference<io::XInputStream> xEncryptionInfo(mrOleStorage.openInputStream("EncryptionInfo"), uno::UNO_QUERY); BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true); - sal_uInt32 aVersion = aBinaryInputStream.readuInt32(); switch (aVersion) @@ -327,21 +54,22 @@ bool DocumentDecryption::readEncryptionInfo() case msfilter::VERSION_INFO_2007_FORMAT: case msfilter::VERSION_INFO_2007_FORMAT_SP2: mCryptoType = STANDARD_2007; // Set encryption info format - bResult = readStandard2007EncryptionInfo( aBinaryInputStream ); + mEngine.reset(new Standard2007Engine); break; case msfilter::VERSION_INFO_AGILE: mCryptoType = AGILE; // Set encryption info format - aBinaryInputStream.skip(4); - bResult = readAgileEncryptionInfo( xEncryptionInfo ); + xEncryptionInfo->skipBytes(4); + mEngine.reset(new AgileEngine); break; default: break; } - - return bResult; + if (mEngine) + return mEngine->readEncryptionInfo(xEncryptionInfo); + return false; } -Sequence<NamedValue> DocumentDecryption::createEncryptionData(const OUString& rPassword) +uno::Sequence<beans::NamedValue> DocumentDecryption::createEncryptionData(const OUString& rPassword) { comphelper::SequenceAsHashMap aEncryptionData; @@ -358,27 +86,27 @@ Sequence<NamedValue> DocumentDecryption::createEncryptionData(const OUString& rP return aEncryptionData.getAsConstNamedValueList(); } -bool DocumentDecryption::decrypt(const Reference<XStream>& xDocumentStream) +bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStream) { - bool aResult = false; + bool bResult = false; if (!mrOleStorage.isStorage()) return false; // open the required input streams in the encrypted package - Reference<XInputStream> xEncryptedPackage(mrOleStorage.openInputStream("EncryptedPackage"), UNO_SET_THROW); + uno::Reference<io::XInputStream> xEncryptedPackage(mrOleStorage.openInputStream("EncryptedPackage"), uno::UNO_QUERY); // create temporary file for unencrypted package - Reference<XOutputStream> xDecryptedPackage(xDocumentStream->getOutputStream(), UNO_SET_THROW); + uno::Reference<io::XOutputStream> xDecryptedPackage(xDocumentStream->getOutputStream(), uno::UNO_QUERY); BinaryXOutputStream aDecryptedPackage(xDecryptedPackage, true); BinaryXInputStream aEncryptedPackage(xEncryptedPackage, true); - aResult = mEngine->decrypt(aEncryptedPackage, aDecryptedPackage); + bResult = mEngine->decrypt(aEncryptedPackage, aDecryptedPackage); xDecryptedPackage->flush(); aDecryptedPackage.seekToStart(); - return aResult; + return bResult; } } // namespace core diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx index 8955101f6842..6da188f514c5 100644 --- a/oox/source/crypto/Standard2007Engine.cxx +++ b/oox/source/crypto/Standard2007Engine.cxx @@ -226,6 +226,62 @@ void Standard2007Engine::encrypt(BinaryXInputStream& aInputStream, } } +bool Standard2007Engine::readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) +{ + BinaryXInputStream aBinaryStream(rxInputStream, false); + + mInfo.header.flags = aBinaryStream.readuInt32(); + if (getFlag(mInfo.header.flags, msfilter::ENCRYPTINFO_EXTERNAL)) + return false; + + sal_uInt32 nHeaderSize = aBinaryStream.readuInt32(); + + sal_uInt32 actualHeaderSize = sizeof(mInfo.header); + + if (nHeaderSize < actualHeaderSize) + return false; + + mInfo.header.flags = aBinaryStream.readuInt32(); + mInfo.header.sizeExtra = aBinaryStream.readuInt32(); + mInfo.header.algId = aBinaryStream.readuInt32(); + mInfo.header.algIdHash = aBinaryStream.readuInt32(); + mInfo.header.keyBits = aBinaryStream.readuInt32(); + mInfo.header.providedType = aBinaryStream.readuInt32(); + mInfo.header.reserved1 = aBinaryStream.readuInt32(); + mInfo.header.reserved2 = aBinaryStream.readuInt32(); + + aBinaryStream.skip(nHeaderSize - actualHeaderSize); + + mInfo.verifier.saltSize = aBinaryStream.readuInt32(); + aBinaryStream.readArray(mInfo.verifier.salt, SAL_N_ELEMENTS(mInfo.verifier.salt)); + aBinaryStream.readArray(mInfo.verifier.encryptedVerifier, SAL_N_ELEMENTS(mInfo.verifier.encryptedVerifier)); + mInfo.verifier.encryptedVerifierHashSize = aBinaryStream.readuInt32(); + aBinaryStream.readArray(mInfo.verifier.encryptedVerifierHash, SAL_N_ELEMENTS(mInfo.verifier.encryptedVerifierHash)); + + if (mInfo.verifier.saltSize != 16) + return false; + + // check flags and algorithm IDs, required are AES128 and SHA-1 + if (!getFlag(mInfo.header.flags, msfilter::ENCRYPTINFO_CRYPTOAPI)) + return false; + + if (!getFlag(mInfo.header.flags, msfilter::ENCRYPTINFO_AES)) + return false; + + // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set + if (mInfo.header.algId != 0 && mInfo.header.algId != msfilter::ENCRYPT_ALGO_AES128) + return false; + + // hash algorithm ID 0 defaults to SHA-1 too + if (mInfo.header.algIdHash != 0 && mInfo.header.algIdHash != msfilter::ENCRYPT_HASH_SHA1) + return false; + + if (mInfo.verifier.encryptedVerifierHashSize != 20) + return false; + + return !aBinaryStream.isEof(); +} + } // namespace core } // namespace oox |