diff options
Diffstat (limited to 'package/source/zipapi')
-rw-r--r-- | package/source/zipapi/MemoryByteGrabber.hxx | 2 | ||||
-rw-r--r-- | package/source/zipapi/XUnbufferedStream.cxx | 35 | ||||
-rw-r--r-- | package/source/zipapi/XUnbufferedStream.hxx | 1 | ||||
-rw-r--r-- | package/source/zipapi/ZipFile.cxx | 70 | ||||
-rw-r--r-- | package/source/zipapi/ZipOutputStream.cxx | 30 | ||||
-rw-r--r-- | package/source/zipapi/blowfishcontext.cxx | 27 | ||||
-rw-r--r-- | package/source/zipapi/blowfishcontext.hxx | 2 |
7 files changed, 105 insertions, 62 deletions
diff --git a/package/source/zipapi/MemoryByteGrabber.hxx b/package/source/zipapi/MemoryByteGrabber.hxx index 8a8d96556bae..f27eaf4826ad 100644 --- a/package/source/zipapi/MemoryByteGrabber.hxx +++ b/package/source/zipapi/MemoryByteGrabber.hxx @@ -62,7 +62,7 @@ public: nBytesToRead = mnEnd - mnCurrent; aData.realloc ( nBytesToRead ); - memcpy ( aData.getArray(), mpBuffer + mnCurrent, nBytesToRead ); + rtl_copyMemory( aData.getArray(), mpBuffer + mnCurrent, nBytesToRead ); mnCurrent += nBytesToRead; return nBytesToRead; } diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx index 67d27468e0c6..e8e16329eccc 100644 --- a/package/source/zipapi/XUnbufferedStream.cxx +++ b/package/source/zipapi/XUnbufferedStream.cxx @@ -27,10 +27,13 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_package.hxx" -#include <XUnbufferedStream.hxx> -#include <EncryptionData.hxx> + #include <com/sun/star/packages/zip/ZipConstants.hpp> #include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> + +#include <XUnbufferedStream.hxx> +#include <EncryptionData.hxx> #include <PackageConstants.hxx> #include <ZipFile.hxx> #include <EncryptedDataHeader.hxx> @@ -69,6 +72,7 @@ XUnbufferedStream::XUnbufferedStream( , mxZipSeek ( xNewZipStream, UNO_QUERY ) , maEntry ( rEntry ) , mxData ( rData ) +, mnBlockSize( 1 ) , maInflater ( sal_True ) , mbRawStream ( nStreamMode == UNBUFF_STREAM_RAW || nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) , mbWrappedRaw ( nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) @@ -95,7 +99,11 @@ XUnbufferedStream::XUnbufferedStream( sal_Bool bMustDecrypt = ( nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False; if ( bMustDecrypt ) + { m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false ); + mnBlockSize = ( rData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 1 ); + } + if ( bHaveEncryptData && mbWrappedRaw && bIsEncrypted ) { // if we have the data needed to decrypt it, but didn't want it decrypted (or @@ -116,13 +124,14 @@ XUnbufferedStream::XUnbufferedStream( // allows to read package raw stream XUnbufferedStream::XUnbufferedStream( - const uno::Reference< lang::XMultiServiceFactory >& xFactory, + const uno::Reference< lang::XMultiServiceFactory >& /*xFactory*/, const Reference < XInputStream >& xRawStream, const ::rtl::Reference< EncryptionData >& rData ) : maMutexHolder( new SotMutexHolder ) , mxZipStream ( xRawStream ) , mxZipSeek ( xRawStream, UNO_QUERY ) , mxData ( rData ) +, mnBlockSize( 1 ) , maInflater ( sal_True ) , mbRawStream ( sal_False ) , mbWrappedRaw ( sal_False ) @@ -151,7 +160,8 @@ XUnbufferedStream::XUnbufferedStream( mnZipEnd = mnZipCurrent + mnZipSize; - m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false ); + // the raw data will not be decrypted, no need for the cipher + // m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false ); } XUnbufferedStream::~XUnbufferedStream() @@ -180,7 +190,7 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa { sal_Int16 nHeadRead = static_cast< sal_Int16 >(( nRequestedBytes > mnHeaderToRead ? mnHeaderToRead : nRequestedBytes )); - memcpy ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nHeadRead ); + rtl_copyMemory ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nHeadRead ); mnHeaderToRead = mnHeaderToRead - nHeadRead; if ( nHeadRead < nRequestedBytes ) @@ -242,12 +252,17 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dictionaries are not supported!" ) ), Reference< XInterface >() ); - sal_Int32 nDiff = static_cast < sal_Int32 > ( mnZipEnd - mnZipCurrent ); + sal_Int32 nDiff = static_cast< sal_Int32 >( mnZipEnd - mnZipCurrent ); if ( nDiff > 0 ) { mxZipSeek->seek ( mnZipCurrent ); - sal_Int32 nToRead = std::min ( nDiff, std::max ( nRequestedBytes, static_cast< sal_Int32 >( 8192 ) ) ); - sal_Int32 nZipRead = mxZipStream->readBytes ( maCompBuffer, nToRead ); + + sal_Int32 nToRead = std::max( nRequestedBytes, static_cast< sal_Int32 >( 8192 ) ); + if ( mnBlockSize > 1 ) + nToRead = nToRead + mnBlockSize - nToRead % mnBlockSize; + nToRead = std::min( nDiff, nToRead ); + + sal_Int32 nZipRead = mxZipStream->readBytes( maCompBuffer, nToRead ); if ( nZipRead < nToRead ) throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "No expected data!" ) ), Reference< XInterface >() ); @@ -268,11 +283,9 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa { sal_Int32 nOldLen = maCompBuffer.getLength(); maCompBuffer.realloc( nOldLen + aSuffix.getLength() ); - memcpy( maCompBuffer.getArray() + nOldLen, aSuffix.getConstArray(), aSuffix.getLength() ); + rtl_copyMemory( maCompBuffer.getArray() + nOldLen, aSuffix.getConstArray(), aSuffix.getLength() ); } } - - ZipFile::StaticRemoveW3CPadding( mxData, maCompBuffer ); } maInflater.setInput ( maCompBuffer ); } diff --git a/package/source/zipapi/XUnbufferedStream.hxx b/package/source/zipapi/XUnbufferedStream.hxx index f4c6ba250631..f8878c25979a 100644 --- a/package/source/zipapi/XUnbufferedStream.hxx +++ b/package/source/zipapi/XUnbufferedStream.hxx @@ -59,6 +59,7 @@ protected: com::sun::star::uno::Sequence < sal_Int8 > maCompBuffer, maHeader; ZipEntry maEntry; ::rtl::Reference< EncryptionData > mxData; + sal_Int32 mnBlockSize; ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > m_xCipherContext; Inflater maInflater; sal_Bool mbRawStream, mbWrappedRaw, mbFinished; diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 5fbaf7cd025d..03ecc90c17c3 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -42,7 +42,6 @@ #include <comphelper/processfactory.hxx> #include <rtl/digest.h> -#include <string.h> // for memcpy #include <vector> #include "blowfishcontext.hxx" @@ -142,7 +141,7 @@ uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextFor xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); uno::Reference< xml::crypto::XDigestContextSupplier > xDigestContextSupplier( - xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.SEInitializer" ) ) ), + xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ), uno::UNO_QUERY_THROW ); xDigestContext.set( xDigestContextSupplier->getDigestContext( xEncryptionData->m_nCheckAlg, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); @@ -173,14 +172,14 @@ uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher( const un uno::Reference< XInterface >() ); } - if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC ) + if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING ) { uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory; if ( !xFactory.is() ) xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); uno::Reference< xml::crypto::XCipherContextSupplier > xCipherContextSupplier( - xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.SEInitializer" ) ) ), + xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ), uno::UNO_QUERY_THROW ); xResult = xCipherContextSupplier->getCipherContext( xEncryptionData->m_nEncAlg, aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt, uno::Sequence< beans::NamedValue >() ); @@ -275,19 +274,19 @@ void ZipFile::StaticFillHeader( const ::rtl::Reference< EncryptionData >& rData, *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF); // Then the salt content - memcpy ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength ); + rtl_copyMemory ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength ); pHeader += nSaltLength; // Then the IV content - memcpy ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength ); + rtl_copyMemory ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength ); pHeader += nIVLength; // Then the digest content - memcpy ( pHeader, rData->m_aDigest.getConstArray(), nDigestLength ); + rtl_copyMemory ( pHeader, rData->m_aDigest.getConstArray(), nDigestLength ); pHeader += nDigestLength; // Then the mediatype itself - memcpy ( pHeader, aMediaType.getStr(), nMediaTypeLength ); + rtl_copyMemory ( pHeader, aMediaType.getStr(), nMediaTypeLength ); pHeader += nMediaTypeLength; } @@ -349,15 +348,15 @@ sal_Bool ZipFile::StaticFillData ( ::rtl::Reference< BaseEncryptionData > & rDa if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) ) { rData->m_aSalt.realloc ( nSaltLength ); - memcpy ( rData->m_aSalt.getArray(), aBuffer.getConstArray(), nSaltLength ); + rtl_copyMemory ( rData->m_aSalt.getArray(), aBuffer.getConstArray(), nSaltLength ); if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) ) { rData->m_aInitVector.realloc ( nIVLength ); - memcpy ( rData->m_aInitVector.getArray(), aBuffer.getConstArray(), nIVLength ); + rtl_copyMemory ( rData->m_aInitVector.getArray(), aBuffer.getConstArray(), nIVLength ); if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) ) { rData->m_aDigest.realloc ( nDigestLength ); - memcpy ( rData->m_aDigest.getArray(), aBuffer.getConstArray(), nDigestLength ); + rtl_copyMemory ( rData->m_aDigest.getArray(), aBuffer.getConstArray(), nDigestLength ); if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) ) { @@ -396,8 +395,9 @@ uno::Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const uno::R OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" ); if ( rData->m_aDigest.getLength() ) { - sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() ); - nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize; + sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() ); + if ( nSize > n_ConstDigestLength + 32 ) + nSize = n_ConstDigestLength + 32; // skip header xSeek->seek( n_ConstHeaderSize + rData->m_aInitVector.getLength() + @@ -415,44 +415,38 @@ uno::Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const uno::R return new XUnbufferedStream( xFactory, xStream, rData ); } -void ZipFile::StaticRemoveW3CPadding( const ::rtl::Reference< EncryptionData >& rEncData, uno::Sequence< sal_Int8 >& o_rPaddedData ) -{ - sal_Int32 nPaddedDataLen = o_rPaddedData.getLength(); - if ( rEncData->m_nEncAlg == xml::crypto::CipherID::AES_CBC ) - { - if ( nPaddedDataLen > AES_CBC_BLOCK_SIZE - && nPaddedDataLen % AES_CBC_BLOCK_SIZE == 1 - && o_rPaddedData[ nPaddedDataLen - 1 ] <= AES_CBC_BLOCK_SIZE ) - { - o_rPaddedData.realloc( nPaddedDataLen - AES_CBC_BLOCK_SIZE + o_rPaddedData[nPaddedDataLen - 1] ); - } - else - { - OSL_ENSURE( sal_False, "No expected padding is found!" ); - } - } -} - sal_Bool ZipFile::StaticHasValidPassword( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const Sequence< sal_Int8 > &aReadBuffer, const ::rtl::Reference< EncryptionData > &rData ) { if ( !rData.is() || !rData->m_aKey.getLength() ) return sal_False; sal_Bool bRet = sal_False; - sal_Int32 nSize = aReadBuffer.getLength(); uno::Reference< xml::crypto::XCipherContext > xCipher( StaticGetCipher( xFactory, rData, false ), uno::UNO_SET_THROW ); - uno::Sequence< sal_Int8 > aDecryptBuffer = xCipher->convertWithCipherContext( aReadBuffer ); - uno::Sequence< sal_Int8 > aDecryptBuffer2 = xCipher->finalizeCipherContextAndDispose(); + uno::Sequence< sal_Int8 > aDecryptBuffer; + uno::Sequence< sal_Int8 > aDecryptBuffer2; + try + { + aDecryptBuffer = xCipher->convertWithCipherContext( aReadBuffer ); + aDecryptBuffer2 = xCipher->finalizeCipherContextAndDispose(); + } + catch( uno::Exception& ) + { + // decryption with padding will throw the exception in finalizing if the buffer represent only part of the stream + // it is no problem, actually this is why we read 32 additional bytes ( two of maximal possible encryption blocks ) + OSL_ENSURE( aReadBuffer.getLength() == n_ConstDigestDecrypt, "Unexpected exception by decryption!" ); + } + if ( aDecryptBuffer2.getLength() ) { sal_Int32 nOldLen = aDecryptBuffer.getLength(); aDecryptBuffer.realloc( nOldLen + aDecryptBuffer2.getLength() ); - memcpy( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getArray(), aDecryptBuffer2.getLength() ); + rtl_copyMemory( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getArray(), aDecryptBuffer2.getLength() ); } - StaticRemoveW3CPadding( rData, aDecryptBuffer ); + if ( aDecryptBuffer.getLength() > n_ConstDigestLength ) + aDecryptBuffer.realloc( n_ConstDigestLength ); uno::Sequence< sal_Int8 > aDigestSeq; uno::Reference< xml::crypto::XDigestContext > xDigestContext( StaticGetDigestContextForChecksum( xFactory, rData ), uno::UNO_SET_THROW ); @@ -486,7 +480,9 @@ sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize; // Only want to read enough to verify the digest - nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize; + if ( nSize > n_ConstDigestDecrypt ) + nSize = n_ConstDigestDecrypt; + Sequence < sal_Int8 > aReadBuffer ( nSize ); xStream->readBytes( aReadBuffer, nSize ); diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx index 8c70558e918d..172cfff463a2 100644 --- a/package/source/zipapi/ZipOutputStream.cxx +++ b/package/source/zipapi/ZipOutputStream.cxx @@ -55,7 +55,7 @@ ZipOutputStream::ZipOutputStream( const uno::Reference< lang::XMultiServiceFacto const uno::Reference < XOutputStream > &xOStream ) : m_xFactory( xFactory ) , xStream(xOStream) -, aBuffer(n_ConstBufferSize) +, m_aDeflateBuffer(n_ConstBufferSize) , aDeflater(DEFAULT_COMPRESSION, sal_True) , aChucker(xOStream) , pCurrentEntry(NULL) @@ -98,7 +98,10 @@ void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry, rEntry.nFlag = 1 << 11; if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 || rEntry.nCrc == -1) + { + rEntry.nSize = rEntry.nCompressedSize = 0; rEntry.nFlag |= 8; + } if (bEncrypt) { @@ -148,11 +151,12 @@ void SAL_CALL ZipOutputStream::closeEntry( ) } else { - pEntry->nSize = aDeflater.getTotalIn(); - pEntry->nCompressedSize = aDeflater.getTotalOut(); + if ( !bEncryptCurrentEntry ) + { + pEntry->nSize = aDeflater.getTotalIn(); + pEntry->nCompressedSize = aDeflater.getTotalOut(); + } pEntry->nCrc = aCRC.getValue(); - if ( bEncryptCurrentEntry ) - pEntry->nSize = pEntry->nCompressedSize; writeEXT(*pEntry); } aDeflater.reset(); @@ -249,12 +253,12 @@ void SAL_CALL ZipOutputStream::finish( ) void ZipOutputStream::doDeflate() { - sal_Int32 nLength = aDeflater.doDeflateSegment(aBuffer, 0, aBuffer.getLength()); - sal_Int32 nOldLength = aBuffer.getLength(); + sal_Int32 nLength = aDeflater.doDeflateSegment(m_aDeflateBuffer, 0, m_aDeflateBuffer.getLength()); + sal_Int32 nOldLength = m_aDeflateBuffer.getLength(); if ( nLength > 0 ) { - uno::Sequence< sal_Int8 > aTmpBuffer( aBuffer.getConstArray(), nLength ); + uno::Sequence< sal_Int8 > aTmpBuffer( m_aDeflateBuffer.getConstArray(), nLength ); if ( bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) { // Need to update our digest before encryption... @@ -270,10 +274,16 @@ void ZipOutputStream::doDeflate() uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer ); aChucker.WriteBytes( aEncryptionBuffer ); + + // the sizes as well as checksum for encrypted streams is calculated here + pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); + pCurrentEntry->nSize = pCurrentEntry->nCompressedSize; aCRC.update( aEncryptionBuffer ); } else + { aChucker.WriteBytes ( aTmpBuffer ); + } } if ( aDeflater.finished() && bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) @@ -282,6 +292,10 @@ void ZipOutputStream::doDeflate() if ( aEncryptionBuffer.getLength() ) { aChucker.WriteBytes( aEncryptionBuffer ); + + // the sizes as well as checksum for encrypted streams is calculated hier + pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); + pCurrentEntry->nSize = pCurrentEntry->nCompressedSize; aCRC.update( aEncryptionBuffer ); } } diff --git a/package/source/zipapi/blowfishcontext.cxx b/package/source/zipapi/blowfishcontext.cxx index 479497d25a7d..bd6605e2e6e5 100644 --- a/package/source/zipapi/blowfishcontext.cxx +++ b/package/source/zipapi/blowfishcontext.cxx @@ -53,6 +53,8 @@ uno::Reference< xml::crypto::XCipherContext > BlowfishCFB8CipherContext::Create( uno::Reference< XInterface >() ); } + xResult->m_bEncrypt = bEncrypt; + return uno::Reference< xml::crypto::XCipherContext >( xResult.get() ); } @@ -73,11 +75,26 @@ uno::Sequence< sal_Int8 > SAL_CALL BlowfishCFB8CipherContext::convertWithCipherC throw lang::DisposedException(); uno::Sequence< sal_Int8 > aResult( aData.getLength() ); - if ( rtl_Cipher_E_None != rtl_cipher_decode( m_pCipher, - aData.getConstArray(), - aData.getLength(), - reinterpret_cast< sal_uInt8* >( aResult.getArray() ), - aResult.getLength() ) ) + rtlCipherError nError = rtl_Cipher_E_None; + + if ( m_bEncrypt ) + { + rtl_cipher_encode( m_pCipher, + aData.getConstArray(), + aData.getLength(), + reinterpret_cast< sal_uInt8* >( aResult.getArray() ), + aResult.getLength() ); + } + else + { + rtl_cipher_decode( m_pCipher, + aData.getConstArray(), + aData.getLength(), + reinterpret_cast< sal_uInt8* >( aResult.getArray() ), + aResult.getLength() ); + } + + if ( rtl_Cipher_E_None != nError ) { throw uno::RuntimeException( ::rtl::OUString::createFromAscii( "Can not decrypt/encrypt with cipher!\n" ), uno::Reference< uno::XInterface >() ); diff --git a/package/source/zipapi/blowfishcontext.hxx b/package/source/zipapi/blowfishcontext.hxx index 4ac75fce2230..49cce2fc0e65 100644 --- a/package/source/zipapi/blowfishcontext.hxx +++ b/package/source/zipapi/blowfishcontext.hxx @@ -36,9 +36,11 @@ class BlowfishCFB8CipherContext : public cppu::WeakImplHelper1< ::com::sun::star { ::osl::Mutex m_aMutex; void* m_pCipher; + bool m_bEncrypt; BlowfishCFB8CipherContext() : m_pCipher( NULL ) + , m_bEncrypt( false ) {} public: |