diff options
Diffstat (limited to 'package/source')
-rw-r--r-- | package/source/zipapi/ZipFile.cxx | 11 | ||||
-rw-r--r-- | package/source/zipapi/sha1context.cxx | 52 | ||||
-rw-r--r-- | package/source/zipapi/sha1context.hxx | 26 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackageStream.cxx | 32 |
4 files changed, 104 insertions, 17 deletions
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index de4c1a364acd..3d4abb65a8f9 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -144,7 +144,16 @@ uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextFor xDigestContext.set( xDigestContextSupplier->getDigestContext( xEncryptionData->m_nCheckAlg, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); } else if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA1_1K ) - xDigestContext.set( SHA1DigestContext::Create(), uno::UNO_SET_THROW ); + { + if (xEncryptionData->m_bTryWrongSHA1) + { + xDigestContext.set(StarOfficeSHA1DigestContext::Create(), uno::UNO_SET_THROW); + } + else + { + xDigestContext.set(CorrectSHA1DigestContext::Create(), uno::UNO_SET_THROW); + } + } return xDigestContext; } diff --git a/package/source/zipapi/sha1context.cxx b/package/source/zipapi/sha1context.cxx index f24064616edb..af3123e2dbd0 100644 --- a/package/source/zipapi/sha1context.cxx +++ b/package/source/zipapi/sha1context.cxx @@ -19,6 +19,7 @@ #include <sal/config.h> +#include <comphelper/hash.hxx> #include <com/sun/star/lang/DisposedException.hpp> #include <rtl/digest.h> #include <rtl/ref.hxx> @@ -28,9 +29,9 @@ using namespace ::com::sun::star; // static -uno::Reference< xml::crypto::XDigestContext > SHA1DigestContext::Create() +uno::Reference<xml::crypto::XDigestContext> StarOfficeSHA1DigestContext::Create() { - ::rtl::Reference< SHA1DigestContext > xResult = new SHA1DigestContext(); + ::rtl::Reference<StarOfficeSHA1DigestContext> xResult = new StarOfficeSHA1DigestContext(); xResult->m_pDigest = rtl_digest_createSHA1(); if ( !xResult->m_pDigest ) throw uno::RuntimeException("Can not create cipher!" ); @@ -38,7 +39,7 @@ uno::Reference< xml::crypto::XDigestContext > SHA1DigestContext::Create() return uno::Reference< xml::crypto::XDigestContext >( xResult.get() ); } -SHA1DigestContext::~SHA1DigestContext() +StarOfficeSHA1DigestContext::~StarOfficeSHA1DigestContext() { if ( m_pDigest ) { @@ -47,7 +48,7 @@ SHA1DigestContext::~SHA1DigestContext() } } -void SAL_CALL SHA1DigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData ) +void SAL_CALL StarOfficeSHA1DigestContext::updateDigest(const uno::Sequence<::sal_Int8>& aData) { ::osl::MutexGuard aGuard( m_aMutex ); if ( !m_pDigest ) @@ -62,7 +63,7 @@ void SAL_CALL SHA1DigestContext::updateDigest( const uno::Sequence< ::sal_Int8 > } } -uno::Sequence< ::sal_Int8 > SAL_CALL SHA1DigestContext::finalizeDigestAndDispose() +uno::Sequence<::sal_Int8> SAL_CALL StarOfficeSHA1DigestContext::finalizeDigestAndDispose() { ::osl::MutexGuard aGuard( m_aMutex ); if ( !m_pDigest ) @@ -83,4 +84,45 @@ uno::Sequence< ::sal_Int8 > SAL_CALL SHA1DigestContext::finalizeDigestAndDispose return aResult; } +uno::Reference<xml::crypto::XDigestContext> CorrectSHA1DigestContext::Create() +{ + return new CorrectSHA1DigestContext(); +} + +struct CorrectSHA1DigestContext::Impl +{ + ::osl::Mutex m_Mutex; + ::comphelper::Hash m_Hash{::comphelper::HashType::SHA1}; + bool m_bDisposed{false}; +}; + +CorrectSHA1DigestContext::CorrectSHA1DigestContext() + : m_pImpl(new Impl) +{ +} + +CorrectSHA1DigestContext::~CorrectSHA1DigestContext() +{ +} + +void SAL_CALL CorrectSHA1DigestContext::updateDigest(const uno::Sequence<::sal_Int8>& rData) +{ + ::osl::MutexGuard aGuard(m_pImpl->m_Mutex); + if (m_pImpl->m_bDisposed) + throw lang::DisposedException(); + + m_pImpl->m_Hash.update(reinterpret_cast<unsigned char const*>(rData.getConstArray()), rData.getLength()); +} + +uno::Sequence<::sal_Int8> SAL_CALL CorrectSHA1DigestContext::finalizeDigestAndDispose() +{ + ::osl::MutexGuard aGuard(m_pImpl->m_Mutex); + if (m_pImpl->m_bDisposed) + throw lang::DisposedException(); + + m_pImpl->m_bDisposed = true; + std::vector<unsigned char> const sha1(m_pImpl->m_Hash.finalize()); + return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(sha1.data()), sha1.size()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/sha1context.hxx b/package/source/zipapi/sha1context.hxx index ef9c433082d3..436dfcccbf7c 100644 --- a/package/source/zipapi/sha1context.hxx +++ b/package/source/zipapi/sha1context.hxx @@ -24,18 +24,19 @@ #include <cppuhelper/implbase.hxx> #include <osl/mutex.hxx> -class SHA1DigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext > +class StarOfficeSHA1DigestContext + : public cppu::WeakImplHelper<css::xml::crypto::XDigestContext> { ::osl::Mutex m_aMutex; void* m_pDigest; - SHA1DigestContext() + StarOfficeSHA1DigestContext() : m_pDigest( nullptr ) {} public: - virtual ~SHA1DigestContext() override; + virtual ~StarOfficeSHA1DigestContext() override; static css::uno::Reference< css::xml::crypto::XDigestContext > Create(); @@ -44,6 +45,25 @@ public: }; +class CorrectSHA1DigestContext + : public cppu::WeakImplHelper<css::xml::crypto::XDigestContext> +{ + struct Impl; + std::unique_ptr<Impl> m_pImpl; + + CorrectSHA1DigestContext(); + +public: + + virtual ~CorrectSHA1DigestContext() override; + + static css::uno::Reference<css::xml::crypto::XDigestContext> Create(); + + virtual void SAL_CALL updateDigest(const css::uno::Sequence<::sal_Int8>& rData) override; + virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeDigestAndDispose() override; + +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx index bd914b663406..c9e987aec1bd 100644 --- a/package/source/zippackage/ZipPackageStream.cxx +++ b/package/source/zippackage/ZipPackageStream.cxx @@ -198,26 +198,27 @@ sal_Int32 ZipPackageStream::GetBlockSize() const return GetEncryptionAlgorithm() == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8; } -::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding ) +::rtl::Reference<EncryptionData> ZipPackageStream::GetEncryptionData(Bugs const bugs) { ::rtl::Reference< EncryptionData > xResult; if ( m_xBaseEncryptionData.is() ) xResult = new EncryptionData( *m_xBaseEncryptionData, - GetEncryptionKey( bUseWinEncoding ), + GetEncryptionKey(bugs), GetEncryptionAlgorithm(), m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : m_rZipPackage.GetChecksumAlgID(), m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : m_rZipPackage.GetDefaultDerivedKeySize(), - GetStartKeyGenID() ); + GetStartKeyGenID(), + bugs != Bugs::None); return xResult; } -uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding ) +uno::Sequence<sal_Int8> ZipPackageStream::GetEncryptionKey(Bugs const bugs) { uno::Sequence< sal_Int8 > aResult; sal_Int32 nKeyGenID = GetStartKeyGenID(); - bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding ); + bool const bUseWinEncoding = (bugs == Bugs::WinEncodingWrongSHA1 || m_bUseWinEncoding); if ( m_bHaveOwnKey && m_aStorageEncryptionKeys.getLength() ) { @@ -226,7 +227,11 @@ uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncodi aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; else if ( nKeyGenID == xml::crypto::DigestID::SHA1 ) { - aNameToFind = bUseWinEncoding ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252) : OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8); + aNameToFind = bUseWinEncoding + ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252) + : (bugs == Bugs::WrongSHA1) + ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8) + : OUString(PACKAGE_ENCRYPTIONDATA_SHA1CORRECT); } else throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" ); @@ -1007,12 +1012,23 @@ uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream() uno::Reference< io::XInputStream > xResult; try { - xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() ); + xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(Bugs::WrongSHA1), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() ); } catch( const packages::WrongPasswordException& ) { if ( m_rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 ) { + SAL_WARN("package", "ZipPackageStream::getDataStream(): SHA1 mismatch, trying fallbacks..."); + try + { // tdf#114939 try without legacy StarOffice SHA1 bug + xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(Bugs::None), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() ); + return xResult; + } + catch (const packages::WrongPasswordException&) + { + /* ignore and try next... */ + } + try { // rhbz#1013844 / fdo#47482 workaround for the encrypted @@ -1035,7 +1051,7 @@ uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream() // workaround for the encrypted documents generated with the old OOo1.x bug. if ( !m_bUseWinEncoding ) { - xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() ); + xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(Bugs::WinEncodingWrongSHA1), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() ); m_bUseWinEncoding = true; } else |