diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2011-11-09 08:54:35 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2011-11-18 11:52:52 +0100 |
commit | c726de0c282cab62b9f1a3b51249e37224325fe9 (patch) | |
tree | 801a341269c597a84908da4a9b79070942afcefc | |
parent | 4fc80f9a1dcd3a1705a0e4c2b092a3804ca4b554 (diff) |
Backport reading AES-encrypted ODF 1.2 documents (as genereated by LibO 3.5).
This backports the reading half of CWS mav60 plus <http://cgit.freedesktop.org/
libreoffice/core/commit/?id=2d775f593abd9bc487ccc60f06aa5a3ca9632056> "Produce
correct sha256 uri, consume correct uri and original spec typo." It spans the
repos components, libs-core, libs-gui, and ure.
59 files changed, 2942 insertions, 1625 deletions
diff --git a/package/inc/EncryptedDataHeader.hxx b/package/inc/EncryptedDataHeader.hxx index 88cdaa57a..4e35664e4 100644 --- a/package/inc/EncryptedDataHeader.hxx +++ b/package/inc/EncryptedDataHeader.hxx @@ -36,6 +36,10 @@ Version number 2 bytes Iteraction count 4 bytes Size 4 bytes + EncAlgorithm 4 bytes + DigestAlgorithm 4 bytes + DerivedKeySize 4 bytes + StartKeyAlgorithm 4 bytes Salt length 2 bytes IV length 2 bytes Digest length 2 bytes @@ -46,8 +50,8 @@ MediaType X bytes */ -const sal_uInt32 n_ConstHeader = 0x0502474dL; // "MG\002\005" -const sal_Int32 n_ConstHeaderSize = 22; // + salt length + iv length + digest length + mediatype length +const sal_uInt32 n_ConstHeader = 0x05024d4dL; // "MM\002\005" +const sal_Int32 n_ConstHeaderSize = 38; // + salt length + iv length + digest length + mediatype length const sal_Int16 n_ConstCurrentVersion = 1; #endif diff --git a/package/inc/EncryptionData.hxx b/package/inc/EncryptionData.hxx index 4dba2e3f7..166251022 100644 --- a/package/inc/EncryptionData.hxx +++ b/package/inc/EncryptionData.hxx @@ -31,16 +31,54 @@ #include <com/sun/star/uno/Sequence.hxx> #include <cppuhelper/weak.hxx> -class EncryptionData : public cppu::OWeakObject +class BaseEncryptionData : public cppu::OWeakObject { public: - // On export aKey holds the derived key - // On import aKey holds the hash of the user enterred key - com::sun::star::uno::Sequence < sal_Int8 > aKey; - com::sun::star::uno::Sequence < sal_uInt8 > aSalt, aInitVector, aDigest; - sal_Int32 nIterationCount; - EncryptionData(): nIterationCount ( 0 ){} + ::com::sun::star::uno::Sequence< sal_Int8 > m_aSalt; + ::com::sun::star::uno::Sequence< sal_Int8 > m_aInitVector; + ::com::sun::star::uno::Sequence< sal_Int8 > m_aDigest; + sal_Int32 m_nIterationCount; + + BaseEncryptionData() + : m_nIterationCount ( 0 ){} + + BaseEncryptionData( const BaseEncryptionData& aData ) + : cppu::OWeakObject() + , m_aSalt( aData.m_aSalt ) + , m_aInitVector( aData.m_aInitVector ) + , m_aDigest( aData.m_aDigest ) + , m_nIterationCount( aData.m_nIterationCount ) + {} }; + +class EncryptionData : public BaseEncryptionData +{ +public: + ::com::sun::star::uno::Sequence < sal_Int8 > m_aKey; + sal_Int32 m_nEncAlg; + sal_Int32 m_nCheckAlg; + sal_Int32 m_nDerivedKeySize; + sal_Int32 m_nStartKeyGenID; + + EncryptionData( const BaseEncryptionData& aData, const ::com::sun::star::uno::Sequence< sal_Int8 >& aKey, sal_Int32 nEncAlg, sal_Int32 nCheckAlg, sal_Int32 nDerivedKeySize, sal_Int32 nStartKeyGenID ) + : BaseEncryptionData( aData ) + , m_aKey( aKey ) + , m_nEncAlg( nEncAlg ) + , m_nCheckAlg( nCheckAlg ) + , m_nDerivedKeySize( nDerivedKeySize ) + , m_nStartKeyGenID( nStartKeyGenID ) + {} + + EncryptionData( const EncryptionData& aData ) + : BaseEncryptionData( aData ) + , m_aKey( aData.m_aKey ) + , m_nEncAlg( aData.m_nEncAlg ) + , m_nCheckAlg( aData.m_nCheckAlg ) + , m_nDerivedKeySize( aData.m_nDerivedKeySize ) + , m_nStartKeyGenID( aData.m_nStartKeyGenID ) + {} +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/inc/PackageConstants.hxx b/package/inc/PackageConstants.hxx index 229f739f5..7507ada64 100644 --- a/package/inc/PackageConstants.hxx +++ b/package/inc/PackageConstants.hxx @@ -32,7 +32,12 @@ const sal_Int32 n_ConstBufferSize = 32768; const sal_Int32 n_ConstMaxMemoryStreamSize = 20480; + +// by calculation of the digest we read 32 bytes more ( if available ) +// it allows to ignore the padding if the stream is longer than n_ConstDigestDecrypt since we read at least two blocks more; +// if the stream is shorter or equal the padding will be done successfully const sal_Int32 n_ConstDigestLength = 1024; +const sal_Int32 n_ConstDigestDecrypt = 1056; // 1024 + 32 // the constants related to the manifest.xml entries #define PKG_MNFST_MEDIATYPE 0 @@ -44,9 +49,22 @@ const sal_Int32 n_ConstDigestLength = 1024; #define PKG_MNFST_ITERATION 5 #define PKG_MNFST_UCOMPSIZE 6 #define PKG_MNFST_DIGEST 7 +#define PKG_MNFST_ENCALG 8 +#define PKG_MNFST_STARTALG 9 +#define PKG_MNFST_DIGESTALG 10 +#define PKG_MNFST_DERKEYSIZE 11 #define PKG_SIZE_NOENCR_MNFST 3 -#define PKG_SIZE_ENCR_MNFST 8 +#define PKG_SIZE_ENCR_MNFST 12 + +// the properties related constants +#define ENCRYPTION_KEY_PROPERTY "EncryptionKey" +#define STORAGE_ENCRYPTION_KEYS_PROPERTY "StorageEncryptionKeys" +#define ENCRYPTION_ALGORITHMS_PROPERTY "EncryptionAlgorithms" +#define HAS_ENCRYPTED_ENTRIES_PROPERTY "HasEncryptedEntries" +#define HAS_NONENCRYPTED_ENTRIES_PROPERTY "HasNonEncryptedEntries" +#define IS_INCONSISTENT_PROPERTY "IsInconsistent" +#define MEDIATYPE_FALLBACK_USED_PROPERTY "MediaTypeFallbackUsed" #endif diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx index c64500cb6..bd108b340 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -32,9 +32,15 @@ #include <com/sun/star/packages/zip/ZipIOException.hpp> #include <com/sun/star/packages/NoEncryptionException.hpp> #include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/xml/crypto/XCipherContext.hpp> +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + +#include <rtl/ref.hxx> + #include <ByteGrabber.hxx> #include <HashMaps.hxx> #include <Inflater.hxx> +#include <EncryptionData.hxx> #include <mutexholder.hxx> @@ -56,7 +62,6 @@ namespace rtl typedef void* rtlCipher; class ZipEnumeration; -class EncryptionData; class ZipFile { @@ -69,7 +74,7 @@ protected: ZipUtils::Inflater aInflater; com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xStream; com::sun::star::uno::Reference < com::sun::star::io::XSeekable > xSeek; - const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > xFactory; + const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > m_xFactory; ::com::sun::star::uno::Reference < ::com::sun::star::ucb::XProgressHandler > xProgressHandler; sal_Bool bRecoveryMode; @@ -133,25 +138,41 @@ public: static sal_Bool StaticGetCipher ( const rtl::Reference < EncryptionData > & xEncryptionData, rtlCipher &rCipher, sal_Bool bDecode ); - static void StaticFillHeader ( const rtl::Reference < EncryptionData > & rData, + static ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > StaticGetDigestContextForChecksum( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xArgFactory, + const ::rtl::Reference< EncryptionData >& xEncryptionData ); + + static ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > StaticGetCipher( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xArgFactory, + const ::rtl::Reference< EncryptionData >& xEncryptionData, + bool bEncrypt ); + + static void StaticFillHeader ( const ::rtl::Reference < EncryptionData > & rData, sal_Int32 nSize, const ::rtl::OUString& aMediaType, sal_Int8 * & pHeader ); - static sal_Bool StaticFillData ( rtl::Reference < EncryptionData > & rData, + static sal_Bool StaticFillData ( ::rtl::Reference < BaseEncryptionData > & rData, + sal_Int32 &rEncAlgorithm, + sal_Int32 &rChecksumAlgorithm, + sal_Int32 &rDerivedKeySize, + sal_Int32 &rStartKeyGenID, sal_Int32 &rSize, ::rtl::OUString& aMediaType, - ::com::sun::star::uno::Reference < com::sun::star::io::XInputStream > &rStream ); + const ::com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& rStream ); static ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > StaticGetDataFromRawStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xStream, const rtl::Reference < EncryptionData > &rData ) throw ( ::com::sun::star::packages::WrongPasswordException, ::com::sun::star::packages::zip::ZipIOException, ::com::sun::star::uno::RuntimeException ); - static sal_Bool StaticHasValidPassword ( const ::com::sun::star::uno::Sequence< sal_Int8 > &aReadBuffer, - const rtl::Reference < EncryptionData > &rData ); + static sal_Bool StaticHasValidPassword ( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const ::com::sun::star::uno::Sequence< sal_Int8 > &aReadBuffer, + const ::rtl::Reference < EncryptionData > &rData ); ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream( diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx index b36f4d271..506e9137a 100644 --- a/package/inc/ZipOutputStream.hxx +++ b/package/inc/ZipOutputStream.hxx @@ -28,39 +28,48 @@ #ifndef _ZIP_OUTPUT_STREAM_HXX #define _ZIP_OUTPUT_STREAM_HXX +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/xml/crypto/XCipherContext.hpp> +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + #include <ByteChucker.hxx> #include <Deflater.hxx> #include <CRC32.hxx> -#include <rtl/cipher.h> -#include <rtl/digest.h> #include <vector> struct ZipEntry; -class EncryptionData; -namespace rtl -{ - template < class T > class Reference; -} +class ZipPackageStream; + class ZipOutputStream { protected: - com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > xStream; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > xStream; + ::std::vector < ZipEntry * > aZipList; - com::sun::star::uno::Sequence < sal_Int8 > aBuffer, aEncryptionBuffer; + + ::com::sun::star::uno::Sequence< sal_Int8 > m_aDeflateBuffer; + ::rtl::OUString sComment; ZipUtils::Deflater aDeflater; - rtlCipher aCipher; - rtlDigest aDigest; + + ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > m_xCipherContext; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > m_xDigestContext; + CRC32 aCRC; ByteChucker aChucker; ZipEntry *pCurrentEntry; sal_Int16 nMethod, nLevel, mnDigested; sal_Bool bFinished, bEncryptCurrentEntry; - EncryptionData *pCurrentEncryptData; + ZipPackageStream* m_pCurrentStream; public: - ZipOutputStream( com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > &xOStream ); + ZipOutputStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > &xOStream ); ~ZipOutputStream(); // rawWrite to support a direct write to the output stream @@ -75,7 +84,7 @@ public: void SAL_CALL setLevel( sal_Int32 nNewLevel ) throw(::com::sun::star::uno::RuntimeException); void SAL_CALL putNextEntry( ZipEntry& rEntry, - rtl::Reference < EncryptionData > &rData, + ZipPackageStream* pStream, sal_Bool bEncrypt = sal_False ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); void SAL_CALL closeEntry( ) diff --git a/package/inc/ZipPackage.hxx b/package/inc/ZipPackage.hxx index 8ea3f60f0..a4aed111e 100644 --- a/package/inc/ZipPackage.hxx +++ b/package/inc/ZipPackage.hxx @@ -36,7 +36,9 @@ #include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> #include <HashMaps.hxx> #include <com/sun/star/lang/IllegalArgumentException.hpp> #include <osl/file.h> @@ -83,13 +85,17 @@ class ZipPackage : public cppu::WeakImplHelper7 protected: SotMutexHolderRef m_aMutexHolder; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aStorageEncryptionKeys; ::com::sun::star::uno::Sequence < sal_Int8 > m_aEncryptionKey; FolderHash m_aRecent; ::rtl::OUString m_aURL; + + sal_Int32 m_nStartKeyGenerationID; + sal_Int32 m_nChecksumDigestID; + sal_Int32 m_nCommonEncryptionID; sal_Bool m_bHasEncryptedEntries; sal_Bool m_bHasNonEncryptedEntries; sal_Bool m_bInconsistent; - sal_Bool m_bUseManifest; sal_Bool m_bForceRecovery; sal_Bool m_bMediaTypeFallbackUsed; @@ -124,12 +130,17 @@ public: ZipPackage (const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > &xNewFactory); virtual ~ZipPackage( void ); ZipFile& getZipFile() { return *m_pZipFile;} - const com::sun::star::uno::Sequence < sal_Int8 > & getEncryptionKey ( ) {return m_aEncryptionKey;} sal_Int32 getFormat() const { return m_nFormat; } + sal_Int32 GetStartKeyGenID() const { return m_nStartKeyGenerationID; } + sal_Int32 GetEncAlgID() const { return m_nCommonEncryptionID; } + sal_Int32 GetChecksumAlgID() const { return m_nChecksumDigestID; } + sal_Int32 GetDefaultDerivedKeySize() const { return m_nCommonEncryptionID == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 32 : 16; } + SotMutexHolderRef GetSharedMutexRef() { return m_aMutexHolder; } void ConnectTo( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xInStream ); + const ::com::sun::star::uno::Sequence< sal_Int8 > GetEncryptionKey(); // XInitialization virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) diff --git a/package/source/zippackage/ZipPackageEntry.hxx b/package/inc/ZipPackageEntry.hxx index eef9dd9ae..18adfdc14 100644 --- a/package/source/zippackage/ZipPackageEntry.hxx +++ b/package/inc/ZipPackageEntry.hxx @@ -2,7 +2,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -39,7 +39,7 @@ class ZipPackageFolder; -class ZipPackageEntry : public cppu::WeakImplHelper5 +class ZipPackageEntry : public cppu::WeakImplHelper5 < com::sun::star::container::XNamed, com::sun::star::container::XChild, @@ -73,32 +73,32 @@ public: pParent = NULL; } // XNamed - virtual ::rtl::OUString SAL_CALL getName( ) + virtual ::rtl::OUString SAL_CALL getName( ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setName( const ::rtl::OUString& aName ) + virtual void SAL_CALL setName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); // XChild - virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); // XUnoTunnel - virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException) = 0; // XPropertySet - virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) + virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0; - virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0; - virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) + virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) + virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) + virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) + virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); }; #endif diff --git a/package/inc/ZipPackageFolder.hxx b/package/inc/ZipPackageFolder.hxx index c6ace8edf..59be1b7b3 100644 --- a/package/inc/ZipPackageFolder.hxx +++ b/package/inc/ZipPackageFolder.hxx @@ -92,10 +92,10 @@ public: void setPackageFormat_Impl( sal_Int32 nFormat ) { m_nFormat = nFormat; } void setRemoveOnInsertMode_Impl( sal_Bool bRemove ) { this->mbAllowRemoveOnInsert = bRemove; } - bool saveChild(const rtl::OUString &rShortName, const com::sun::star::packages::ContentInfo &rInfo, rtl::OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, com::sun::star::uno::Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool & rRandomPool); + bool saveChild(const rtl::OUString &rShortName, const com::sun::star::packages::ContentInfo &rInfo, rtl::OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, const com::sun::star::uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool & rRandomPool); // Recursive functions - void saveContents(rtl::OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, com::sun::star::uno::Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool & rRandomPool) + void saveContents(rtl::OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, const com::sun::star::uno::Sequence< sal_Int8 > &rEncryptionKey, rtlRandomPool & rRandomPool) throw(::com::sun::star::uno::RuntimeException); void releaseUpwardRef(); diff --git a/package/source/zippackage/ZipPackageStream.hxx b/package/inc/ZipPackageStream.hxx index 321e385a5..a3bbf73bf 100644 --- a/package/source/zippackage/ZipPackageStream.hxx +++ b/package/inc/ZipPackageStream.hxx @@ -1,8 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -30,18 +29,21 @@ #include <com/sun/star/io/XActiveDataSink.hpp> #include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/packages/XDataSinkEncrSupport.hpp> -#include <ZipPackageEntry.hxx> + #include <rtl/ref.hxx> -#include <EncryptionData.hxx> #include <cppuhelper/implbase2.hxx> + +#include <ZipPackageEntry.hxx> +#include <EncryptionData.hxx> #include <mutexholder.hxx> -#define PACKAGE_STREAM_NOTSET 0 -#define PACKAGE_STREAM_PACKAGEMEMBER 1 -#define PACKAGE_STREAM_DETECT 2 -#define PACKAGE_STREAM_DATA 3 -#define PACKAGE_STREAM_RAW 4 +#define PACKAGE_STREAM_NOTSET 0 +#define PACKAGE_STREAM_PACKAGEMEMBER 1 +#define PACKAGE_STREAM_DETECT 2 +#define PACKAGE_STREAM_DATA 3 +#define PACKAGE_STREAM_RAW 4 class ZipPackage; struct ZipEntry; @@ -55,13 +57,21 @@ class ZipPackageStream : public cppu::ImplInheritanceHelper2 protected: com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xStream; const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > m_xFactory; - ZipPackage &rZipPackage; - sal_Bool bToBeCompressed, bToBeEncrypted, bHaveOwnKey, bIsEncrypted; - rtl::Reference < EncryptionData > xEncryptionData; + ZipPackage &rZipPackage; + sal_Bool bToBeCompressed, bToBeEncrypted, bHaveOwnKey, bIsEncrypted; + + ::rtl::Reference< BaseEncryptionData > m_xBaseEncryptionData; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aStorageEncryptionKeys; + ::com::sun::star::uno::Sequence< sal_Int8 > m_aEncryptionKey; - sal_uInt8 m_nStreamMode; - sal_uInt32 m_nMagicalHackPos; - sal_uInt32 m_nMagicalHackSize; + sal_Int32 m_nImportedStartKeyAlgorithm; + sal_Int32 m_nImportedEncryptionAlgorithm; + sal_Int32 m_nImportedChecksumAlgorithm; + sal_Int32 m_nImportedDerivedKeySize; + + sal_uInt8 m_nStreamMode; + sal_uInt32 m_nMagicalHackPos; + sal_uInt32 m_nMagicalHackSize; sal_Bool m_bHasSeekable; @@ -69,58 +79,70 @@ protected: sal_Bool m_bFromManifest; - ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& GetOwnSeekStream(); + bool m_bUseWinEncoding; + + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnSeekStream(); public: - sal_Bool HasOwnKey () const { return bHaveOwnKey;} + sal_Bool HasOwnKey () const { return bHaveOwnKey;} sal_Bool IsToBeCompressed () const { return bToBeCompressed;} sal_Bool IsToBeEncrypted () const { return bToBeEncrypted;} - sal_Bool IsEncrypted () const { return bIsEncrypted;} + sal_Bool IsEncrypted () const { return bIsEncrypted;} sal_Bool IsPackageMember () const { return m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER;} sal_Bool IsFromManifest() const { return m_bFromManifest; } void SetFromManifest( sal_Bool bValue ) { m_bFromManifest = bValue; } - rtl::Reference < EncryptionData > & getEncryptionData () - { return xEncryptionData;} - const com::sun::star::uno::Sequence < sal_Int8 >& getKey () const - { return xEncryptionData->aKey;} - const com::sun::star::uno::Sequence < sal_uInt8 >& getInitialisationVector () const - { return xEncryptionData->aInitVector;} - const com::sun::star::uno::Sequence < sal_uInt8 >& getDigest () const - { return xEncryptionData->aDigest;} - const com::sun::star::uno::Sequence < sal_uInt8 >& getSalt () const - { return xEncryptionData->aSalt;} + ::rtl::Reference< EncryptionData > GetEncryptionData( bool bWinEncoding = false ); + void SetBaseEncryptionData( const ::rtl::Reference< BaseEncryptionData >& xData ); + + ::com::sun::star::uno::Sequence< sal_Int8 > GetEncryptionKey( bool bWinEncoding = false ); + + sal_Int32 GetStartKeyGenID(); + + const com::sun::star::uno::Sequence < sal_Int8 > getInitialisationVector () const + { return m_xBaseEncryptionData->m_aInitVector;} + const com::sun::star::uno::Sequence < sal_Int8 > getDigest () const + { return m_xBaseEncryptionData->m_aDigest;} + const com::sun::star::uno::Sequence < sal_Int8 > getSalt () const + { return m_xBaseEncryptionData->m_aSalt;} sal_Int32 getIterationCount () const - { return xEncryptionData->nIterationCount;} + { return m_xBaseEncryptionData->m_nIterationCount;} sal_Int32 getSize () const { return aEntry.nSize;} sal_uInt8 GetStreamMode() const { return m_nStreamMode; } sal_uInt32 GetMagicalHackPos() const { return m_nMagicalHackPos; } sal_uInt32 GetMagicalHackSize() const { return m_nMagicalHackSize; } + sal_Int32 GetEncryptionAlgorithm() const; + sal_Int32 GetBlockSize() const; void SetToBeCompressed (sal_Bool bNewValue) { bToBeCompressed = bNewValue;} void SetIsEncrypted (sal_Bool bNewValue) { bIsEncrypted = bNewValue;} - void SetToBeEncrypted (sal_Bool bNewValue) - { + void SetImportedStartKeyAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedStartKeyAlgorithm = nAlgorithm; } + void SetImportedEncryptionAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedEncryptionAlgorithm = nAlgorithm; } + void SetImportedChecksumAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedChecksumAlgorithm = nAlgorithm; } + void SetImportedDerivedKeySize( sal_Int32 nSize ) { m_nImportedDerivedKeySize = nSize; } + void SetToBeEncrypted (sal_Bool bNewValue) + { bToBeEncrypted = bNewValue; - if ( bToBeEncrypted && !xEncryptionData.is()) - xEncryptionData = new EncryptionData; - else if ( !bToBeEncrypted && xEncryptionData.is() ) - xEncryptionData.clear(); + if ( bToBeEncrypted && !m_xBaseEncryptionData.is()) + m_xBaseEncryptionData = new BaseEncryptionData; + else if ( !bToBeEncrypted && m_xBaseEncryptionData.is() ) + m_xBaseEncryptionData.clear(); } void SetPackageMember (sal_Bool bNewValue); + void setKey (const com::sun::star::uno::Sequence < sal_Int8 >& rNewKey ) - { xEncryptionData->aKey = rNewKey;} - void setInitialisationVector (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewVector ) - { xEncryptionData->aInitVector = rNewVector;} - void setSalt (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewSalt ) - { xEncryptionData->aSalt = rNewSalt;} - void setDigest (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewDigest ) - { xEncryptionData->aDigest = rNewDigest;} + { m_aEncryptionKey = rNewKey; m_aStorageEncryptionKeys.realloc( 0 ); } + void setInitialisationVector (const com::sun::star::uno::Sequence < sal_Int8 >& rNewVector ) + { m_xBaseEncryptionData->m_aInitVector = rNewVector;} + void setSalt (const com::sun::star::uno::Sequence < sal_Int8 >& rNewSalt ) + { m_xBaseEncryptionData->m_aSalt = rNewSalt;} + void setDigest (const com::sun::star::uno::Sequence < sal_Int8 >& rNewDigest ) + { m_xBaseEncryptionData->m_aDigest = rNewDigest;} void setIterationCount (const sal_Int32 nNewCount) - { xEncryptionData->nIterationCount = nNewCount;} + { m_xBaseEncryptionData->m_nIterationCount = nNewCount;} void setSize (const sal_Int32 nNewSize); ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnStreamNoWrap() { return xStream; } @@ -141,13 +163,13 @@ public: void setZipEntryOnLoading( const ZipEntry &rInEntry); ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData() throw(::com::sun::star::uno::RuntimeException); - + static const ::com::sun::star::uno::Sequence < sal_Int8 >& static_getImplementationId(); // XActiveDataSink - virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream ) + virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream ) throw(::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream( ) + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream( ) throw(::com::sun::star::uno::RuntimeException); // XDataSinkEncrSupport @@ -174,23 +196,21 @@ public: ::com::sun::star::uno::RuntimeException ); // XUnoTunnel - virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); // XPropertySet - virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) + virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); // XServiceInfo - virtual ::rtl::OUString SAL_CALL getImplementationName( ) + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); - virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); }; #endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/qa/storages/TestHelper.java b/package/qa/storages/TestHelper.java index 0c1580fc7..b0b343477 100644 --- a/package/qa/storages/TestHelper.java +++ b/package/qa/storages/TestHelper.java @@ -1434,24 +1434,24 @@ public class TestHelper { try { - byte pData[][] = new byte[1][22]; - if ( xHeadRawStream.readBytes( pData, 22 ) != 22 ) + byte pData[][] = new byte[1][38]; + if ( xHeadRawStream.readBytes( pData, 38 ) != 38 ) { Error( "Can't read header of encrypted stream '" + sStreamName + "' raw representations!" ); return false; } - if ( pData[0][0] != 0x4d || pData[0][1] != 0x47 || pData[0][2] != 0x02 || pData[0][3] != 0x05 ) + if ( pData[0][0] != 0x4d || pData[0][1] != 0x4d || pData[0][2] != 0x02 || pData[0][3] != 0x05 ) { Error( "No signature in the header of encrypted stream '" + sStreamName + "' raw representations!" ); return false; } int nVariableHeaderLength = - ( pData[0][14] + pData[0][15] * 0x100 ) // salt length - + ( pData[0][16] + pData[0][17] * 0x100 ) // iv length - + ( pData[0][18] + pData[0][19] * 0x100 ) // digest length - + ( pData[0][20] + pData[0][21] * 0x100 ); // mediatype length + ( pData[0][30] + pData[0][31] * 0x100 ) // salt length + + ( pData[0][32] + pData[0][33] * 0x100 ) // iv length + + ( pData[0][34] + pData[0][35] * 0x100 ) // digest length + + ( pData[0][36] + pData[0][37] * 0x100 ); // mediatype length xHeadRawStream.skipBytes( nVariableHeaderLength ); @@ -1467,7 +1467,7 @@ public class TestHelper { if ( nRead1 != nRead2 ) { - Error( "The encrypted stream '" + sStreamName + "' raw representations have different size!" ); + Error( "The encrypted stream '" + sStreamName + "' raw representations have different size! nRead1 - nRead2 = " + ( new Integer( nRead1 - nRead2 ) ).toString() ); return false; } diff --git a/package/source/manifest/Base64Codec.cxx b/package/source/manifest/Base64Codec.cxx index 1438d8682..5dc4ebfa4 100644 --- a/package/source/manifest/Base64Codec.cxx +++ b/package/source/manifest/Base64Codec.cxx @@ -131,11 +131,11 @@ void ThreeByteToFourByte (const sal_uInt8* pBuffer, const sal_Int32 nStart, cons sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]); } -void Base64Codec::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence < sal_uInt8 >& aPass) +void Base64Codec::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence < sal_Int8 >& aPass) { sal_Int32 i(0); sal_Int32 nBufferLength(aPass.getLength()); - const sal_uInt8* pBuffer = aPass.getConstArray(); + const sal_uInt8* pBuffer = reinterpret_cast< const sal_uInt8* >( aPass.getConstArray() ); while (i < nBufferLength) { rtl::OUStringBuffer sBuffer; @@ -185,7 +185,7 @@ void FourByteToThreeByte (sal_uInt8* pBuffer, sal_Int32& nLength, const sal_Int3 pBuffer[nStart + 2] = OneByte; } -void Base64Codec::decodeBase64(uno::Sequence< sal_uInt8 >& aBuffer, const rtl::OUString& sBuffer) +void Base64Codec::decodeBase64(uno::Sequence< sal_Int8 >& aBuffer, const rtl::OUString& sBuffer) { sal_Int32 nFirstLength((sBuffer.getLength() / 4) * 3); sal_uInt8* pBuffer = new sal_uInt8[nFirstLength]; @@ -201,7 +201,7 @@ void Base64Codec::decodeBase64(uno::Sequence< sal_uInt8 >& aBuffer, const rtl::O i += 4; k += 3; } - aBuffer = uno::Sequence<sal_uInt8>(pBuffer, nSecondLength); + aBuffer = uno::Sequence<sal_Int8>( reinterpret_cast< sal_Int8* >( pBuffer ), nSecondLength ); delete[] pBuffer; } diff --git a/package/source/manifest/Base64Codec.hxx b/package/source/manifest/Base64Codec.hxx index 941c115a8..60456ad32 100644 --- a/package/source/manifest/Base64Codec.hxx +++ b/package/source/manifest/Base64Codec.hxx @@ -40,8 +40,8 @@ class OUStringBuffer; class Base64Codec { public: - static void encodeBase64(rtl::OUStringBuffer& aStrBuffer, const com::sun::star::uno::Sequence<sal_uInt8>& aPass); - static void decodeBase64(com::sun::star::uno::Sequence<sal_uInt8>& aPass, const rtl::OUString& sBuffer); + static void encodeBase64(rtl::OUStringBuffer& aStrBuffer, const com::sun::star::uno::Sequence<sal_Int8>& aPass); + static void decodeBase64(com::sun::star::uno::Sequence<sal_Int8>& aPass, const rtl::OUString& sBuffer); }; #endif diff --git a/package/source/manifest/ManifestDefines.hxx b/package/source/manifest/ManifestDefines.hxx index 67159ee8e..dc9c47e45 100644 --- a/package/source/manifest/ManifestDefines.hxx +++ b/package/source/manifest/ManifestDefines.hxx @@ -65,6 +65,26 @@ #define CHECKSUM_TYPE "SHA1/1K" #define DERIVED_KEY_SIZE "16" +#define SHA256_URL "http://www.w3.org/2001/04/xmlenc#sha256" +//http://tools.oasis-open.org/issues/browse/OFFICE-3702 +//http://tools.oasis-open.org/issues/browse/OFFICE-3708 +#define SHA256_URL_TYPO "http://www.w3.org/2000/09/xmldsig#sha256" +#define SHA1_NAME "SHA1" +#define SHA1_URL "http://www.w3.org/2000/09/xmldsig#sha1" + +#define SHA1_1K_NAME "SHA1/1K" +#define SHA1_1K_URL "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha1-1k" +#define SHA256_1K_URL "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha256-1k" + +#define BLOWFISH_NAME "Blowfish CFB" +#define BLOWFISH_URL "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#blowfish" +#define AES128_URL "http://www.w3.org/2001/04/xmlenc#aes128-cbc" +#define AES192_URL "http://www.w3.org/2001/04/xmlenc#aes192-cbc" +#define AES256_URL "http://www.w3.org/2001/04/xmlenc#aes256-cbc" + +#define PBKDF2_NAME "PBKDF2" +#define PBKDF2_URL "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#pbkdf2" + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/manifest/ManifestExport.cxx b/package/source/manifest/ManifestExport.cxx index dfdcf2fbb..bb53541ac 100644 --- a/package/source/manifest/ManifestExport.cxx +++ b/package/source/manifest/ManifestExport.cxx @@ -239,7 +239,7 @@ ManifestExport::ManifestExport(Reference < XDocumentHandler > xHandler, const S ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList; Reference < XAttributeList > xNewAttrList (pNewAttrList); OUStringBuffer aBuffer; - Sequence < sal_uInt8 > aSequence; + Sequence < sal_Int8 > aSequence; xHandler->ignorableWhitespace ( sWhiteSpace ); if ( pDigest ) diff --git a/package/source/manifest/ManifestImport.cxx b/package/source/manifest/ManifestImport.cxx index 2f99d66b5..abd67d55b 100644 --- a/package/source/manifest/ManifestImport.cxx +++ b/package/source/manifest/ManifestImport.cxx @@ -32,6 +32,8 @@ #include <ManifestDefines.hxx> #include <Base64Codec.hxx> #include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> #include <com/sun/star/beans/PropertyValue.hpp> using namespace com::sun::star::uno; @@ -45,12 +47,14 @@ using ::rtl::OUString; ManifestImport::ManifestImport( vector < Sequence < PropertyValue > > & rNewManVector ) : nNumProperty ( 0 ) , bIgnoreEncryptData ( sal_False ) +, nDerivedKeySize( 0 ) , rManVector ( rNewManVector ) , sFileEntryElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_FILE_ENTRY ) ) , sManifestElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_MANIFEST ) ) , sEncryptionDataElement( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_ENCRYPTION_DATA ) ) , sAlgorithmElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_ALGORITHM ) ) +, sStartKeyAlgElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_START_KEY_GENERATION ) ) , sKeyDerivationElement( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_KEY_DERIVATION ) ) , sCdataAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CDATA ) ) @@ -61,7 +65,9 @@ ManifestImport::ManifestImport( vector < Sequence < PropertyValue > > & rNewManV , sSaltAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_SALT ) ) , sInitialisationVectorAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_INITIALISATION_VECTOR ) ) , sIterationCountAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_ITERATION_COUNT ) ) +, sKeySizeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_KEY_SIZE ) ) , sAlgorithmNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_ALGORITHM_NAME ) ) +, sStartKeyAlgNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_START_KEY_GENERATION_NAME ) ) , sKeyDerivationNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_KEY_DERIVATION_NAME ) ) , sChecksumAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CHECKSUM ) ) , sChecksumTypeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CHECKSUM_TYPE ) ) @@ -70,15 +76,34 @@ ManifestImport::ManifestImport( vector < Sequence < PropertyValue > > & rNewManV , sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ) , sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ) , sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ) +, sDerivedKeySizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ) , sSaltProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ) , sInitialisationVectorProperty ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ) , sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ) , sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ) +, sEncryptionAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ) +, sStartKeyAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ) +, sDigestAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ) , sWhiteSpace ( RTL_CONSTASCII_USTRINGPARAM ( " " ) ) -, sBlowfish ( RTL_CONSTASCII_USTRINGPARAM ( "Blowfish CFB" ) ) -, sPBKDF2 ( RTL_CONSTASCII_USTRINGPARAM ( "PBKDF2" ) ) -, sChecksumType ( RTL_CONSTASCII_USTRINGPARAM ( CHECKSUM_TYPE ) ) + +, sSHA256_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA256_URL ) ) +, sSHA256_URL_TYPO ( RTL_CONSTASCII_USTRINGPARAM ( SHA256_URL_TYPO ) ) +, sSHA1_Name ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_NAME ) ) +, sSHA1_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_URL ) ) + +, sSHA256_1k_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA256_1K_URL ) ) +, sSHA1_1k_Name ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_1K_NAME ) ) +, sSHA1_1k_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_1K_URL ) ) + +, sBlowfish_Name ( RTL_CONSTASCII_USTRINGPARAM ( BLOWFISH_NAME ) ) +, sBlowfish_URL ( RTL_CONSTASCII_USTRINGPARAM ( BLOWFISH_URL ) ) +, sAES128_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES128_URL ) ) +, sAES192_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES192_URL ) ) +, sAES256_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES256_URL ) ) + +, sPBKDF2_Name ( RTL_CONSTASCII_USTRINGPARAM ( PBKDF2_NAME ) ) +, sPBKDF2_URL ( RTL_CONSTASCII_USTRINGPARAM ( PBKDF2_URL ) ) { aStack.reserve( 10 ); } @@ -143,43 +168,90 @@ void SAL_CALL ManifestImport::startElement( const OUString& aName, const uno::Re if ( aConvertedName.equals( sEncryptionDataElement ) ) { // If this element exists, then this stream is encrypted and we need - // to store the initialisation vector, salt and iteration count used + // to import the initialisation vector, salt and iteration count used + nDerivedKeySize = 0; OUString aString = aConvertedAttribs[sChecksumTypeAttribute]; - if ( aString == sChecksumType && !bIgnoreEncryptData ) + if ( !bIgnoreEncryptData ) + { + if ( aString.equals( sSHA1_1k_Name ) || aString.equals( sSHA1_1k_URL ) ) + { + aSequence[nNumProperty].Name = sDigestAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA1_1K; + } + else if ( aString.equals( sSHA256_1k_URL ) ) + { + aSequence[nNumProperty].Name = sDigestAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA256_1K; + } + else + bIgnoreEncryptData = sal_True; + + if ( !bIgnoreEncryptData ) { aString = aConvertedAttribs[sChecksumAttribute]; - Sequence < sal_uInt8 > aDecodeBuffer; + Sequence < sal_Int8 > aDecodeBuffer; Base64Codec::decodeBase64 ( aDecodeBuffer, aString ); aSequence[nNumProperty].Name = sDigestProperty; aSequence[nNumProperty++].Value <<= aDecodeBuffer; } } } + } else if ( aIter->m_aConvertedName.equals( sEncryptionDataElement ) ) { if ( aConvertedName == sAlgorithmElement ) { + if ( !bIgnoreEncryptData ) + { OUString aString = aConvertedAttribs[sAlgorithmNameAttribute]; - if ( aString == sBlowfish && !bIgnoreEncryptData ) + if ( aString.equals( sBlowfish_Name ) || aString.equals( sBlowfish_URL ) ) + { + aSequence[nNumProperty].Name = sEncryptionAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8; + } + else if ( aString.equals( sAES256_URL ) ) + { + aSequence[nNumProperty].Name = sEncryptionAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; + OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 32, "Unexpected derived key length!" ); + nDerivedKeySize = 32; + } + else if ( aString.equals( sAES192_URL ) ) + { + aSequence[nNumProperty].Name = sEncryptionAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; + OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 24, "Unexpected derived key length!" ); + nDerivedKeySize = 24; + } + else if ( aString.equals( sAES128_URL ) ) + { + aSequence[nNumProperty].Name = sEncryptionAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; + OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 16, "Unexpected derived key length!" ); + nDerivedKeySize = 16; + } + else + bIgnoreEncryptData = sal_True; + + if ( !bIgnoreEncryptData ) { aString = aConvertedAttribs[sInitialisationVectorAttribute]; - Sequence < sal_uInt8 > aDecodeBuffer; + Sequence < sal_Int8 > aDecodeBuffer; Base64Codec::decodeBase64 ( aDecodeBuffer, aString ); aSequence[nNumProperty].Name = sInitialisationVectorProperty; aSequence[nNumProperty++].Value <<= aDecodeBuffer; } - else - // If we don't recognise the algorithm, then the key derivation info - // is useless to us - bIgnoreEncryptData = sal_True; + } } else if ( aConvertedName == sKeyDerivationElement ) { + if ( !bIgnoreEncryptData ) + { OUString aString = aConvertedAttribs[sKeyDerivationNameAttribute]; - if ( aString == sPBKDF2 && !bIgnoreEncryptData ) + if ( aString.equals( sPBKDF2_Name ) || aString.equals( sPBKDF2_URL ) ) { aString = aConvertedAttribs[sSaltAttribute]; - Sequence < sal_uInt8 > aDecodeBuffer; + Sequence < sal_Int8 > aDecodeBuffer; Base64Codec::decodeBase64 ( aDecodeBuffer, aString ); aSequence[nNumProperty].Name = sSaltProperty; aSequence[nNumProperty++].Value <<= aDecodeBuffer; @@ -187,10 +259,40 @@ void SAL_CALL ManifestImport::startElement( const OUString& aName, const uno::Re aString = aConvertedAttribs[sIterationCountAttribute]; aSequence[nNumProperty].Name = sIterationCountProperty; aSequence[nNumProperty++].Value <<= aString.toInt32(); + + aString = aConvertedAttribs[sKeySizeAttribute]; + if ( aString.getLength() ) + { + sal_Int32 nKey = aString.toInt32(); + OSL_ENSURE( !nDerivedKeySize || nKey == nDerivedKeySize , "Provided derived key length differs from the expected one!" ); + nDerivedKeySize = nKey; + } + else if ( !nDerivedKeySize ) + nDerivedKeySize = 16; + else if ( nDerivedKeySize != 16 ) + OSL_ENSURE( sal_False, "Default derived key length differs from the expected one!" ); + + aSequence[nNumProperty].Name = sDerivedKeySizeProperty; + aSequence[nNumProperty++].Value <<= nDerivedKeySize; + } + else + bIgnoreEncryptData = sal_True; + } + } + else if ( aConvertedName == sStartKeyAlgElement ) + { + OUString aString = aConvertedAttribs[sStartKeyAlgNameAttribute]; + if (aString.equals(sSHA256_URL) || aString.equals(sSHA256_URL_TYPO)) + { + aSequence[nNumProperty].Name = sStartKeyAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA256; + } + else if ( aString.equals( sSHA1_Name ) || aString.equals( sSHA1_URL ) ) + { + aSequence[nNumProperty].Name = sStartKeyAlgProperty; + aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA1; } else - // If we don't recognise the key derivation technique, then the - // algorithm info is useless to us bIgnoreEncryptData = sal_True; } } diff --git a/package/source/manifest/ManifestImport.hxx b/package/source/manifest/ManifestImport.hxx index 9655e712b..4b927971c 100644 --- a/package/source/manifest/ManifestImport.hxx +++ b/package/source/manifest/ManifestImport.hxx @@ -65,12 +65,14 @@ protected: sal_Int16 nNumProperty; ManifestStack aStack; sal_Bool bIgnoreEncryptData; + sal_Int32 nDerivedKeySize; ::std::vector < ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > > & rManVector; const ::rtl::OUString sFileEntryElement; const ::rtl::OUString sManifestElement; const ::rtl::OUString sEncryptionDataElement; const ::rtl::OUString sAlgorithmElement; + const ::rtl::OUString sStartKeyAlgElement; const ::rtl::OUString sKeyDerivationElement; const ::rtl::OUString sCdataAttribute; @@ -81,7 +83,9 @@ protected: const ::rtl::OUString sSaltAttribute; const ::rtl::OUString sInitialisationVectorAttribute; const ::rtl::OUString sIterationCountAttribute; + const ::rtl::OUString sKeySizeAttribute; const ::rtl::OUString sAlgorithmNameAttribute; + const ::rtl::OUString sStartKeyAlgNameAttribute; const ::rtl::OUString sKeyDerivationNameAttribute; const ::rtl::OUString sChecksumAttribute; const ::rtl::OUString sChecksumTypeAttribute; @@ -90,15 +94,34 @@ protected: const ::rtl::OUString sMediaTypeProperty; const ::rtl::OUString sVersionProperty; const ::rtl::OUString sIterationCountProperty; + const ::rtl::OUString sDerivedKeySizeProperty; const ::rtl::OUString sSaltProperty; const ::rtl::OUString sInitialisationVectorProperty; const ::rtl::OUString sSizeProperty; const ::rtl::OUString sDigestProperty; + const ::rtl::OUString sEncryptionAlgProperty; + const ::rtl::OUString sStartKeyAlgProperty; + const ::rtl::OUString sDigestAlgProperty; const ::rtl::OUString sWhiteSpace; - const ::rtl::OUString sBlowfish; - const ::rtl::OUString sPBKDF2; - const ::rtl::OUString sChecksumType; + + const ::rtl::OUString sSHA256_URL; + const ::rtl::OUString sSHA256_URL_TYPO; + const ::rtl::OUString sSHA1_Name; + const ::rtl::OUString sSHA1_URL; + + const ::rtl::OUString sSHA256_1k_URL; + const ::rtl::OUString sSHA1_1k_Name; + const ::rtl::OUString sSHA1_1k_URL; + + const ::rtl::OUString sBlowfish_Name; + const ::rtl::OUString sBlowfish_URL; + const ::rtl::OUString sAES128_URL; + const ::rtl::OUString sAES192_URL; + const ::rtl::OUString sAES256_URL; + + const ::rtl::OUString sPBKDF2_Name; + const ::rtl::OUString sPBKDF2_URL; ::rtl::OUString PushNameAndNamespaces( const ::rtl::OUString& aName, diff --git a/package/source/xstor/owriteablestream.cxx b/package/source/xstor/owriteablestream.cxx index c1c5e8f27..03e177639 100644 --- a/package/source/xstor/owriteablestream.cxx +++ b/package/source/xstor/owriteablestream.cxx @@ -47,6 +47,8 @@ #include <comphelper/storagehelper.hxx> #include <comphelper/ofopxmlhelper.hxx> +#include <PackageConstants.hxx> + #include "selfterminatefilestream.hxx" #include "owriteablestream.hxx" #include "oseekinstream.hxx" @@ -111,15 +113,14 @@ namespace { //----------------------------------------------- void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet, - const uno::Sequence< sal_Int8 >& aKey ) + const uno::Sequence< beans::NamedValue >& aKey ) { OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" ); if ( !xPropertySet.is() ) throw uno::RuntimeException(); - ::rtl::OUString aString_EncryptionKey (RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ); try { - xPropertySet->setPropertyValue( aString_EncryptionKey, uno::makeAny( aKey ) ); + xPropertySet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ), uno::makeAny( aKey ) ); } catch ( uno::Exception& aException ) { @@ -137,9 +138,8 @@ uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySe if ( !xPropertySet.is() ) throw uno::RuntimeException(); - ::rtl::OUString aString_EncryptionKey (RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ); try { - return xPropertySet->getPropertyValue( aString_EncryptionKey ); + return xPropertySet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ); } catch ( uno::Exception& aException ) { @@ -152,16 +152,65 @@ uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySe } //----------------------------------------------- -sal_Bool SequencesEqual( uno::Sequence< sal_Int8 > aSequence1, uno::Sequence< sal_Int8 > aSequence2 ) +bool SequencesEqual( const uno::Sequence< sal_Int8 >& aSequence1, const uno::Sequence< sal_Int8 >& aSequence2 ) { if ( aSequence1.getLength() != aSequence2.getLength() ) - return sal_False; + return false; for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ ) if ( aSequence1[nInd] != aSequence2[nInd] ) - return sal_False; + return false; + + return true; +} + +//----------------------------------------------- +bool SequencesEqual( const uno::Sequence< beans::NamedValue >& aSequence1, const uno::Sequence< beans::NamedValue >& aSequence2 ) +{ + if ( aSequence1.getLength() != aSequence2.getLength() ) + return false; + + for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ ) + { + bool bHasMember = false; + uno::Sequence< sal_Int8 > aMember1; + sal_Int32 nMember1 = 0; + if ( ( aSequence1[nInd].Value >>= aMember1 ) ) + { + for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ ) + { + if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) ) + { + bHasMember = true; + + uno::Sequence< sal_Int8 > aMember2; + if ( !( aSequence2[nInd2].Value >>= aMember2 ) || !SequencesEqual( aMember1, aMember2 ) ) + return false; + } + } + } + else if ( ( aSequence1[nInd].Value >>= nMember1 ) ) + { + for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ ) + { + if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) ) + { + bHasMember = true; - return sal_True; + sal_Int32 nMember2 = 0; + if ( !( aSequence2[nInd2].Value >>= nMember2 ) || nMember1 != nMember2 ) + return false; + } + } + } + else + return false; + + if ( !bHasMember ) + return false; + } + + return true; } //----------------------------------------------- @@ -395,7 +444,7 @@ sal_Bool OWriteStream_Impl::IsEncrypted() // since a new key set to the package stream it should not be removed except the case when // the stream becomes nonencrypted - uno::Sequence< sal_Int8 > aKey; + uno::Sequence< beans::NamedValue > aKey; if ( bToBeEncr ) GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey; @@ -822,8 +871,8 @@ void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputSt throw uno::RuntimeException(); // set to be encrypted but do not use encryption key - xPropertySet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ), - uno::makeAny( uno::Sequence< sal_Int8 >() ) ); + xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), + uno::makeAny( uno::Sequence< beans::NamedValue >() ) ); xPropertySet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Encrypted") ), uno::makeAny( sal_True ) ); } @@ -921,8 +970,8 @@ void OWriteStream_Impl::Commit() throw uno::RuntimeException(); // set to be encrypted but do not use encryption key - xPropertySet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ), - uno::makeAny( uno::Sequence< sal_Int8 >() ) ); + xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), + uno::makeAny( uno::Sequence< beans::NamedValue >() ) ); xPropertySet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Encrypted") ), uno::makeAny( sal_True ) ); } @@ -931,8 +980,8 @@ void OWriteStream_Impl::Commit() if ( m_nStorageType != embed::StorageFormats::PACKAGE ) throw uno::RuntimeException(); - xPropertySet->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ), - uno::makeAny( m_aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1UTF8, uno::Sequence< sal_Int8 >() ) ) ); + xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), + uno::makeAny( m_aEncryptionData.getAsConstNamedValueList() ) ); } // the stream should be free soon, after package is stored @@ -1265,7 +1314,7 @@ uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMod } else { - SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1UTF8, uno::Sequence< sal_Int8 >() ) ); + SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); try { xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); @@ -1274,32 +1323,9 @@ uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMod m_bHasCachedEncryptionData = sal_True; m_aEncryptionData = aEncryptionData; } - catch( packages::WrongPasswordException& ) - { - // retry with different encoding - SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1MS1252, uno::Sequence< sal_Int8 >() ) ); - try { - // the stream must be cashed to be resaved - xResultStream = GetStream_Impl( nStreamMode | embed::ElementModes::SEEKABLE, bHierarchyAccess ); - - m_bUseCommonEncryption = sal_False; // very important to set it to false - m_bHasCachedEncryptionData = sal_True; - m_aEncryptionData = aEncryptionData; - - // the stream must be resaved with new password encryption - if ( nStreamMode & embed::ElementModes::WRITE ) - { - FillTempGetFileName(); - m_bHasDataToFlush = sal_True; - - // TODO/LATER: should the notification be done? - if ( m_pParent ) - m_pParent->m_bIsModified = sal_True; - } - } catch( packages::WrongPasswordException& aWrongPasswordException ) { - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); + SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); AddLog( aWrongPasswordException.Message ); AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); throw; @@ -1310,20 +1336,10 @@ uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMod AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); OSL_FAIL( "Can't write encryption related properties!\n" ); - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); + SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); throw io::IOException(); // TODO: } } - catch( uno::Exception& aException ) - { - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); - - AddLog( aException.Message ); - AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); - throw; - } - - } OSL_ENSURE( xResultStream.is(), "In case stream can not be retrieved an exception must be thrown!\n" ); @@ -1625,8 +1641,7 @@ void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTar { // TODO: introduce last commited cashed password information and use it here // that means "use common pass" also should be remembered on flash - uno::Sequence< sal_Int8 > aNewKey = aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1UTF8, uno::Sequence< sal_Int8 >() ); - uno::Sequence< sal_Int8 > aOldKey = aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1MS1252, uno::Sequence< sal_Int8 >() ); + uno::Sequence< beans::NamedValue > aKey = aEncryptionData.getAsConstNamedValueList(); uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY ); if ( !xProps.is() ) @@ -1637,9 +1652,9 @@ void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTar if ( !bEncr ) throw packages::NoEncryptionException(); - uno::Sequence< sal_Int8 > aEncrKey; - xProps->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EncryptionKey") ) ) >>= aEncrKey; - if ( !SequencesEqual( aNewKey, aEncrKey ) && !SequencesEqual( aOldKey, aEncrKey ) ) + uno::Sequence< beans::NamedValue > aPackKey; + xProps->getPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) >>= aPackKey; + if ( !SequencesEqual( aKey, aPackKey ) ) throw packages::WrongPasswordException(); // the correct key must be set already @@ -1648,7 +1663,7 @@ void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTar else { uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY ); - SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1UTF8, uno::Sequence< sal_Int8 >() ) ); + SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); try { xDataToCopy = m_xPackageStream->getDataStream(); @@ -1656,42 +1671,19 @@ void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTar if ( !xDataToCopy.is() ) { OSL_FAIL( "Encrypted ZipStream must already have input stream inside!\n" ); - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); - } - } - catch( packages::WrongPasswordException& aWrongPasswordException ) - { - SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1MS1252, uno::Sequence< sal_Int8 >() ) ); - try { - xDataToCopy = m_xPackageStream->getDataStream(); - - if ( !xDataToCopy.is() ) - { - OSL_FAIL( "Encrypted ZipStream must already have input stream inside!\n" ); - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); - AddLog( aWrongPasswordException.Message ); - AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); - throw; + SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); } } catch( uno::Exception& aException ) { - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); + OSL_FAIL( "Can't open encrypted stream!" ); + SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); AddLog( aException.Message ); AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); throw; } - } - catch( uno::Exception& aException ) - { - OSL_FAIL( "Can't open encrypted stream!\n" ); - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); - AddLog( aException.Message ); - AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); - throw; - } - SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() ); + SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); } // in case of new inserted package stream it is possible that input stream still was not set diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx index ab3c5f37b..1eca31c11 100644 --- a/package/source/xstor/xstorage.cxx +++ b/package/source/xstor/xstorage.cxx @@ -46,6 +46,7 @@ #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> #include <com/sun/star/beans/NamedValue.hpp> +#include <PackageConstants.hxx> #include <cppuhelper/typeprovider.hxx> #include <cppuhelper/exc_hlp.hxx> @@ -572,7 +573,7 @@ void OStorage_Impl::GetStorageProperties() if ( !m_bControlMediaType ) { uno::Reference< beans::XPropertySet > xPackageProps( m_xPackage, uno::UNO_QUERY_THROW ); - xPackageProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaTypeFallbackUsed" ) ) ) >>= m_bMTFallbackUsed; + xPackageProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) >>= m_bMTFallbackUsed; xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ) >>= m_aMediaType; m_bControlMediaType = sal_True; @@ -750,9 +751,17 @@ void OStorage_Impl::CopyToStorage( const uno::Reference< embed::XStorage >& xDes { try { - uno::Reference< embed::XEncryptionProtectedSource2 > xEncr( xDest, uno::UNO_QUERY ); + uno::Reference< embed::XEncryptionProtectedStorage > xEncr( xDest, uno::UNO_QUERY ); if ( xEncr.is() ) + { xEncr->setEncryptionData( GetCommonRootEncryptionData().getAsConstNamedValueList() ); + + uno::Sequence< beans::NamedValue > aAlgorithms; + uno::Reference< beans::XPropertySet > xPackPropSet( m_xPackage, uno::UNO_QUERY_THROW ); + xPackPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) + >>= aAlgorithms; + xEncr->setEncryptionAlgorithms( aAlgorithms ); + } } catch( packages::NoEncryptionException& aNoEncryptionException ) { @@ -985,7 +994,9 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement, AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Handled exception" ) ) ); // If the common storage password does not allow to open the stream - // it must be copyed in raw way + // it could be copyed in raw way, the problem is that the StartKey should be the same + // in the ODF1.2 package, so an invalid package could be produced if the stream + // is copied from ODF1.1 package, where it is allowed to have different StartKeys uno::Reference< embed::XStorageRawAccess > xRawDest( xDest, uno::UNO_QUERY_THROW ); uno::Reference< io::XInputStream > xRawInStream = pElement->m_pStream->GetRawInStream(); xRawDest->insertRawEncrStreamElement( aName, xRawInStream ); @@ -2278,7 +2289,8 @@ uno::Any SAL_CALL OStorage::queryInterface( const uno::Type& rType ) ( rType , static_cast<embed::XStorageRawAccess*> ( this ) , static_cast<embed::XEncryptionProtectedSource*> ( this ) - , static_cast<embed::XEncryptionProtectedSource2*> ( this ) ); + , static_cast<embed::XEncryptionProtectedSource2*> ( this ) + , static_cast<embed::XEncryptionProtectedStorage*> ( this ) ); } else { @@ -2338,6 +2350,7 @@ uno::Sequence< uno::Type > SAL_CALL OStorage::getTypes() , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL ) , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL ) , ::getCppuType( ( const uno::Reference< util::XModifiable >* )NULL ) + , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedStorage >* )NULL ) , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource2 >* )NULL ) , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL ) , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); @@ -4697,18 +4710,23 @@ void SAL_CALL OStorage::removeEncryption() // TODO: check if the password is valid // update all streams that was encrypted with old password - uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY ); - if ( !xPackPropSet.is() ) - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - + uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW ); try { - xPackPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionKey" ) ), - uno::makeAny( uno::Sequence< sal_Int8 >() ) ); + xPackPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ), + uno::makeAny( uno::Sequence< beans::NamedValue >() ) ); m_pImpl->m_bHasCommonEncryptionData = sal_False; m_pImpl->m_aCommonEncryptionData.clear(); } + catch( uno::RuntimeException& aRException ) + { + m_pImpl->AddLog( aRException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + + OSL_FAIL( "The call must not fail, it is pretty simple!" ); + throw; + } catch( uno::Exception& aException ) { m_pImpl->AddLog( aException.Message ); @@ -4767,16 +4785,13 @@ void SAL_CALL OStorage::setEncryptionData( const uno::Sequence< beans::NamedValu uno::UNO_QUERY ), aCaught ); } - - uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY ); - if ( !xPackPropSet.is() ) - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW ); try { ::comphelper::SequenceAsHashMap aEncryptionMap( aEncryptionData ); - xPackPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionKey" ) ), - uno::makeAny( aEncryptionMap.getUnpackedValueOrDefault( PACKAGE_ENCRYPTIONDATA_SHA1UTF8, uno::Sequence< sal_Int8 >() ) ) ); + xPackPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ), + uno::makeAny( aEncryptionMap.getAsConstNamedValueList() ) ); m_pImpl->m_bHasCommonEncryptionData = sal_True; m_pImpl->m_aCommonEncryptionData = aEncryptionMap; @@ -4792,6 +4807,82 @@ void SAL_CALL OStorage::setEncryptionData( const uno::Sequence< beans::NamedValu } +//____________________________________________________________________________________________________ +// XEncryptionProtectedStorage +//____________________________________________________________________________________________________ + +//----------------------------------------------- +void SAL_CALL OStorage::setEncryptionAlgorithms( const uno::Sequence< beans::NamedValue >& aAlgorithms ) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OStorage::setEncryptionAlgorithms" ); + + ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); + + if ( !m_pImpl ) + { + ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); + throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + + if ( m_pData->m_nStorageType != embed::StorageFormats::PACKAGE ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); // the interface must be visible only for package storage + + if ( !aAlgorithms.getLength() ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected empty encryption algorithms list!") ), uno::Reference< uno::XInterface >() ); + + OSL_ENSURE( m_pData->m_bIsRoot, "setEncryptionAlgorithms() method is not available for nonroot storages!\n" ); + if ( m_pData->m_bIsRoot ) + { + try { + m_pImpl->ReadContents(); + } + catch ( uno::RuntimeException& aRuntimeException ) + { + m_pImpl->AddLog( aRuntimeException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + throw; + } + catch ( uno::Exception& aException ) + { + m_pImpl->AddLog( aException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + + uno::Any aCaught( ::cppu::getCaughtException() ); + throw lang::WrappedTargetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can not open package!\n" ) ), + uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( this ), + uno::UNO_QUERY ), + aCaught ); + } + + uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW ); + try + { + xPackPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ), + uno::makeAny( aAlgorithms ) ); + } + catch ( uno::RuntimeException& aRuntimeException ) + { + m_pImpl->AddLog( aRuntimeException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + throw; + } + catch( lang::IllegalArgumentException& aIAException ) + { + m_pImpl->AddLog( aIAException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + + throw; + } + catch( uno::Exception& aException ) + { + m_pImpl->AddLog( aException.Message ); + m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); + + throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + } + } +} //____________________________________________________________________________________________________ // XPropertySet @@ -4864,13 +4955,13 @@ void SAL_CALL OStorage::setPropertyValue( const ::rtl::OUString& aPropertyName, m_pImpl->m_bIsModified = sal_True; } } - else if ( ( m_pData->m_bIsRoot && ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasNonEncryptedEntries" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsInconsistent" ) ) + else if ( ( m_pData->m_bIsRoot && ( aPropertyName.equalsAscii( HAS_ENCRYPTED_ENTRIES_PROPERTY ) + || aPropertyName.equalsAscii( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) + || aPropertyName.equalsAscii( IS_INCONSISTENT_PROPERTY ) || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "URL" ) ) || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ) ) ) ) || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsRoot" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaTypeFallbackUsed" ) ) ) + || aPropertyName.equalsAscii( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); else throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); @@ -4944,7 +5035,7 @@ uno::Any SAL_CALL OStorage::getPropertyValue( const ::rtl::OUString& aPropertyNa if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE && ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaTypeFallbackUsed" ) ) + || aPropertyName.equalsAscii( MEDIATYPE_FALLBACK_USED_PROPERTY ) || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Version" ) ) ) ) { try @@ -5001,9 +5092,9 @@ uno::Any SAL_CALL OStorage::getPropertyValue( const ::rtl::OUString& aPropertyNa return uno::makeAny( sal_False ); // RepairPackage } else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE - && ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HasNonEncryptedEntries" ) ) - || aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsInconsistent" ) ) ) ) + && ( aPropertyName.equalsAscii( HAS_ENCRYPTED_ENTRIES_PROPERTY ) + || aPropertyName.equalsAscii( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) + || aPropertyName.equalsAscii( IS_INCONSISTENT_PROPERTY ) ) ) { try { m_pImpl->ReadContents(); diff --git a/package/source/xstor/xstorage.hxx b/package/source/xstor/xstorage.hxx index 66a626e26..46764df33 100644 --- a/package/source/xstor/xstorage.hxx +++ b/package/source/xstor/xstorage.hxx @@ -37,7 +37,7 @@ #include <com/sun/star/embed/XTransactedObject.hpp> #include <com/sun/star/embed/XTransactionBroadcaster.hpp> #include <com/sun/star/embed/XClassifiedObject.hpp> -#include <com/sun/star/embed/XEncryptionProtectedSource2.hpp> +#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp> #include <com/sun/star/embed/XRelationshipAccess.hpp> #include <com/sun/star/util/XModifiable.hpp> #include <com/sun/star/container/XNameAccess.hpp> @@ -297,7 +297,7 @@ class OStorage : public ::com::sun::star::lang::XTypeProvider , public ::com::sun::star::embed::XTransactedObject , public ::com::sun::star::embed::XTransactionBroadcaster , public ::com::sun::star::util::XModifiable - , public ::com::sun::star::embed::XEncryptionProtectedSource2 + , public ::com::sun::star::embed::XEncryptionProtectedStorage , public ::com::sun::star::beans::XPropertySet , public ::com::sun::star::embed::XOptimizedStorage , public ::com::sun::star::embed::XRelationshipAccess @@ -647,6 +647,11 @@ public: throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException ); + //____________________________________________________________________________________________________ + // XEncryptionProtectedStorage + //____________________________________________________________________________________________________ + + virtual void SAL_CALL setEncryptionAlgorithms( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aAlgorithms ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); //____________________________________________________________________________________________________ // XPropertySet diff --git a/package/source/zipapi/EntryInputStream.cxx b/package/source/zipapi/EntryInputStream.cxx deleted file mode 100644 index 00ae61f6b..000000000 --- a/package/source/zipapi/EntryInputStream.cxx +++ /dev/null @@ -1,205 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_package.hxx" -#include <EntryInputStream.hxx> -#include <com/sun/star/packages/zip/ZipConstants.hpp> -#include <rtl/cipher.h> -#include <rtl/digest.h> -#include <memory.h> // for memcpy - -using namespace com::sun::star; -using namespace com::sun::star::uno; -using namespace com::sun::star::packages::zip; -using namespace com::sun::star::packages::zip::ZipConstants; - -using ::rtl::OUString; - -/** Provides access to the compressed data in a zipfile. - * - * uncompresses the stream into memory and seeks on it 'in memory' - * This and the ZipPackageBuffer used in the ZipOutputStream are memory hogs - * and will hopefully be replaced eventually - * - * Acts on the same underlying XInputStream as both the full Zip File and other - * EntryInputStreams, and thus must maintain its current position in the stream and - * seek to it before performing any reads. - */ - -EntryInputStream::EntryInputStream( Reference < io::XInputStream > xNewInput, - const ZipEntry & rNewEntry, - const rtl::Reference < EncryptionData > &xEncryptData, - sal_Bool bGetRawStream) -: xStream( xNewInput ) -, xSeek( xNewInput, UNO_QUERY ) -, aEntry (rNewEntry ) -, nCurrent( 0 ) -, bHaveInMemory ( sal_False ) -, aInflater( sal_True ) -, aBuffer( 0 ) -, xEncryptionData (xEncryptData) -, bRawStream (bGetRawStream) -{ - if (bGetRawStream) - { - nUncompressedSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize; - nEnd = aEntry.nOffset + nUncompressedSize; - } - else - { - nEnd = aEntry.nMethod == DEFLATED ? aEntry.nOffset + aEntry.nCompressedSize : aEntry.nOffset + aEntry.nSize; - nUncompressedSize = aEntry.nSize; - } -} -void EntryInputStream::readIntoMemory() - throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) -{ - if (!bHaveInMemory) - { - Sequence < sal_Int8 > aReadBuffer; - xSeek->seek(aEntry.nOffset); - sal_Int32 nSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize; - - if (nSize <0) - throw io::BufferSizeExceededException(::rtl::OUString(), *this); - - xStream->readBytes( aReadBuffer, nSize ); // Now it holds the raw stuff from disk - - if (xEncryptionData->aSalt.getLength()) - { - // Have salt, will travel - Sequence < sal_uInt8 > aDerivedKey (16); - rtlCipherError aResult; - Sequence < sal_Int8 > aDecryptBuffer; - - // Get the key - rtl_digest_PBKDF2 ( aDerivedKey.getArray(), 16, - reinterpret_cast < const sal_uInt8 * > (xEncryptionData->aKey.getConstArray()), - xEncryptionData->aKey.getLength(), - xEncryptionData->aSalt.getConstArray(), - xEncryptionData->aSalt.getLength(), - xEncryptionData->nIterationCount ); - - rtlCipher aCipher = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream); - aResult = rtl_cipher_init( aCipher, rtl_Cipher_DirectionDecode, - aDerivedKey.getConstArray(), - aDerivedKey.getLength(), - xEncryptionData->aInitVector.getConstArray(), - xEncryptionData->aInitVector.getLength()); - OSL_ASSERT (aResult == rtl_Cipher_E_None); - aDecryptBuffer.realloc ( nSize ); - aResult = rtl_cipher_decode ( aCipher, - aReadBuffer.getConstArray(), - nSize, - reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()), - nSize); - OSL_ASSERT (aResult == rtl_Cipher_E_None); - aReadBuffer = aDecryptBuffer; // Now it holds the decrypted data - } - if (bRawStream || aEntry.nMethod == STORED) - aBuffer = aReadBuffer; // bRawStream means the caller doesn't want it decompressed - else - { - aInflater.setInputSegment(aReadBuffer, 0, nSize ); - aBuffer.realloc( aEntry.nSize ); - aInflater.doInflate(aBuffer); - aInflater.end(); - } - bHaveInMemory = sal_True; - } -} -EntryInputStream::~EntryInputStream( void ) -{ -} - -sal_Int32 SAL_CALL EntryInputStream::readBytes( Sequence< sal_Int8 >& aData, - sal_Int32 nBytesToRead ) - throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) -{ - if (nBytesToRead <0) - throw io::BufferSizeExceededException(::rtl::OUString(), *this); - if (!bHaveInMemory) - readIntoMemory(); - if (nBytesToRead + nCurrent > nUncompressedSize) - nBytesToRead = static_cast < sal_Int32> ( nUncompressedSize - nCurrent ); - - aData.realloc( nBytesToRead ); - memcpy(aData.getArray(), aBuffer.getConstArray() + nCurrent, nBytesToRead); - nCurrent+=nBytesToRead; - - return nBytesToRead; -} -sal_Int32 SAL_CALL EntryInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, - sal_Int32 nMaxBytesToRead ) - throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) -{ - return readBytes( aData, nMaxBytesToRead ); -} -void SAL_CALL EntryInputStream::skipBytes( sal_Int32 nBytesToSkip ) - throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException) -{ - if (nBytesToSkip < 0) - throw io::BufferSizeExceededException(::rtl::OUString(), *this); - - if (nBytesToSkip + nCurrent > nUncompressedSize) - nBytesToSkip = static_cast < sal_Int32 > (nUncompressedSize- nCurrent); - - nCurrent+=nBytesToSkip; -} -sal_Int32 SAL_CALL EntryInputStream::available( ) - throw(io::NotConnectedException, io::IOException, RuntimeException) -{ - return static_cast < sal_Int32 > (nUncompressedSize - nCurrent); -} -void SAL_CALL EntryInputStream::closeInput( ) - throw(io::NotConnectedException, io::IOException, RuntimeException) -{ -} - -void SAL_CALL EntryInputStream::seek( sal_Int64 location ) - throw(lang::IllegalArgumentException, io::IOException, RuntimeException) -{ - if (location > nUncompressedSize) - location = nUncompressedSize; - if (location <0) - location = 0; - nCurrent = location; -} -sal_Int64 SAL_CALL EntryInputStream::getPosition( ) - throw(io::IOException, RuntimeException) -{ - return nCurrent; -} -sal_Int64 SAL_CALL EntryInputStream::getLength( ) - throw(io::IOException, RuntimeException) -{ - return nUncompressedSize; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/EntryInputStream.hxx b/package/source/zipapi/EntryInputStream.hxx deleted file mode 100644 index cf1bf5aeb..000000000 --- a/package/source/zipapi/EntryInputStream.hxx +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef _ENTRY_INPUT_STREAM_HXX -#define _ENTRY_INPUT_STREAM_HXX - -#include <cppuhelper/implbase2.hxx> // helper for implementations -#include <com/sun/star/io/XInputStream.hpp> -#include <com/sun/star/io/XSeekable.hpp> -#include <Inflater.hxx> -#include <com/sun/star/packages/zip/ZipEntry.hpp> -#include <rtl/ref.hxx> -#include <EncryptionData.hxx> -class EntryInputStream : public cppu::WeakImplHelper2< com::sun::star::io::XInputStream, - com::sun::star::io::XSeekable > -{ -protected: - com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xStream; - com::sun::star::uno::Reference< com::sun::star::io::XSeekable > xSeek; - sal_Int64 nEnd, nCurrent, nUncompressedSize; - sal_Bool bRawStream, bHaveInMemory, bEncrypted; - com::sun::star::uno::Sequence < sal_Int8 > aBuffer; - const rtl::Reference < EncryptionData > xEncryptionData; - const com::sun::star::packages::zip::ZipEntry aEntry; - Inflater aInflater; - void readIntoMemory() - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); -public: - EntryInputStream( com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xInput, - const com::sun::star::packages::zip::ZipEntry &rNewEntry, - const rtl::Reference < EncryptionData > &xEncryptData, - sal_Bool bGetRawStream = sal_False); - virtual ~EntryInputStream(); - - // XInputStream - virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int32 SAL_CALL available( ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL closeInput( ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - // XSeekable - virtual void SAL_CALL seek( sal_Int64 location ) - throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int64 SAL_CALL getPosition( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int64 SAL_CALL getLength( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - /* -private: - void fill( void ); - */ -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/XFileStream.cxx b/package/source/zipapi/XFileStream.cxx deleted file mode 100644 index 6afe8079c..000000000 --- a/package/source/zipapi/XFileStream.cxx +++ /dev/null @@ -1,230 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_package.hxx" -#include <XFileStream.hxx> -#include <EncryptionData.hxx> -#include <com/sun/star/packages/zip/ZipConstants.hpp> -#include <PackageConstants.hxx> -#include <rtl/cipher.h> -#include <ZipFile.hxx> -#include <EncryptedDataHeader.hxx> -#include <com/sun/star/io/XOutputStream.hpp> - -using namespace com::sun::star::packages::zip::ZipConstants; -using namespace com::sun::star::io; -using namespace com::sun::star::uno; -using com::sun::star::lang::IllegalArgumentException; -using ::rtl::OUString; - -XFileStream::XFileStream( ZipEntry & rEntry, - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream, - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream, - const rtl::Reference < EncryptionData > &rData, - sal_Bool bNewRawStream, - sal_Bool bIsEncrypted ) -: maEntry ( rEntry ) -, mxData ( rData ) -, mbRawStream ( bNewRawStream ) -, mbFinished ( sal_False ) -, mxTempIn ( xNewTempStream ) -, mxTempSeek ( xNewTempStream, UNO_QUERY ) -, mxTempOut ( xNewTempStream, UNO_QUERY ) -, mxZipStream ( xNewZipStream ) -, mxZipSeek ( xNewZipStream, UNO_QUERY ) -, maInflater ( sal_True ) -, maCipher ( NULL ) -{ - mnZipCurrent = maEntry.nOffset; - if (mbRawStream) - { - mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize; - mnZipEnd = maEntry.nOffset + mnZipSize; - } - else - { - mnZipSize = maEntry.nSize; - mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize; - } - - if ( bIsEncrypted ) - { - sal_Bool bHaveEncryptData = ( !rData.isEmpty() && rData->aSalt.getLength() && rData->aInitVector.getLength() && rData->nIterationCount != 0 ) ? sal_True : sal_False; - - // if we have all the encrypted data, and want a raw stream, then prepend it to the stream, otherwise - // make a cipher so we can decrypt it - if ( bHaveEncryptData ) - { - if ( !bNewRawStream ) - ZipFile::StaticGetCipher ( rData, maCipher, sal_True ); - else - { - // Put in the EncryptedDataHeader - Sequence < sal_Int8 > aEncryptedDataHeader ( n_ConstHeaderSize + - rData->aInitVector.getLength() + - rData->aSalt.getLength() + - rData->aDigest.getLength() ); - sal_Int8 * pHeader = aEncryptedDataHeader.getArray(); - ZipFile::StaticFillHeader ( rData, rEntry.nSize, pHeader ); - mxTempOut->writeBytes ( aEncryptedDataHeader ); - mnZipSize += mxTempSeek->getPosition(); - mxTempSeek->seek ( 0 ); - } - } - } -} - -XFileStream::~XFileStream() -{ - if ( maCipher ) - rtl_cipher_destroy ( maCipher ); -} - -void XFileStream::fill( sal_Int64 nUntil) -{ - sal_Int32 nRead; - sal_Int64 nPosition = mxTempSeek->getPosition(); - mxTempSeek->seek ( mxTempSeek->getLength() ); - maBuffer.realloc ( n_ConstBufferSize ); - - while ( mxTempSeek->getLength() < nUntil ) - { - if ( !mbRawStream ) - { - while ( 0 == ( nRead = maInflater.doInflate( maBuffer ) ) ) - { - if ( maInflater.finished() || maInflater.needsDictionary() ) - { - // some error handling ? - return; - } - - sal_Int64 nDiff = mnZipEnd - mnZipCurrent; - if ( nDiff > 0 ) - { - mxZipSeek->seek ( mnZipCurrent ); - nRead = mxZipStream->readBytes ( maCompBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) ); - mnZipCurrent += nRead; - // maCompBuffer now has the uncompressed data, check if we need to decrypt - // before passing to the Inflater - if ( maCipher ) - { - Sequence < sal_Int8 > aCryptBuffer ( nRead ); - rtlCipherError aResult = rtl_cipher_decode ( maCipher, - maCompBuffer.getConstArray(), - nRead, - reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()), - nRead); - OSL_ASSERT (aResult == rtl_Cipher_E_None); - maCompBuffer = aCryptBuffer; // Now it holds the decrypted data - - } - maInflater.setInput ( maCompBuffer ); - } - else - { - // some error handling ? - return; - } - } - } - else - { - sal_Int64 nDiff = mnZipEnd - mnZipCurrent; - mxZipSeek->seek ( mnZipCurrent ); - nRead = mxZipStream->readBytes ( maBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) ); - mnZipCurrent += nRead; - } - Sequence < sal_Int8 > aTmpBuffer ( maBuffer.getConstArray(), nRead ); - mxTempOut->writeBytes ( aTmpBuffer ); - } - mxTempSeek->seek ( nPosition ); -} - -sal_Int32 SAL_CALL XFileStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) - throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) -{ - sal_Int64 nPosition = mxTempSeek->getPosition(); - if ( nPosition + nBytesToRead > mnZipSize ) - nBytesToRead = static_cast < sal_Int32 > ( mnZipSize - nPosition ); - - sal_Int64 nUntil = nBytesToRead + nPosition + n_ConstBufferSize; - if (nUntil > mnZipSize ) - nUntil = mnZipSize; - if ( nUntil > mxTempSeek->getLength() ) - fill ( nUntil ); - sal_Int32 nRead = mxTempIn->readBytes ( aData, nBytesToRead ); - return nRead; -} - -sal_Int32 SAL_CALL XFileStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) - throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) -{ - return readBytes ( aData, nMaxBytesToRead ); -} -void SAL_CALL XFileStream::skipBytes( sal_Int32 nBytesToSkip ) - throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) -{ - seek ( mxTempSeek->getPosition() + nBytesToSkip ); -} - -sal_Int32 SAL_CALL XFileStream::available( ) - throw( NotConnectedException, IOException, RuntimeException) -{ - return static_cast < sal_Int32 > ( mnZipSize - mxTempSeek->getPosition() ); -} - -void SAL_CALL XFileStream::closeInput( ) - throw( NotConnectedException, IOException, RuntimeException) -{ -} -void SAL_CALL XFileStream::seek( sal_Int64 location ) - throw( IllegalArgumentException, IOException, RuntimeException) -{ - if ( location > mnZipSize || location < 0 ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); - if ( location > mxTempSeek->getLength() ) - { - sal_Int64 nUntil = location + n_ConstBufferSize > mnZipSize ? mnZipSize : location + n_ConstBufferSize; - fill ( nUntil ); - } - mxTempSeek->seek ( location ); -} -sal_Int64 SAL_CALL XFileStream::getPosition( ) - throw(IOException, RuntimeException) -{ - return mxTempSeek->getPosition(); -} -sal_Int64 SAL_CALL XFileStream::getLength( ) - throw(IOException, RuntimeException) -{ - return mnZipSize; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/XFileStream.hxx b/package/source/zipapi/XFileStream.hxx deleted file mode 100644 index 51518de95..000000000 --- a/package/source/zipapi/XFileStream.hxx +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef _XFILE_STREAM_HXX -#define _XFILE_STREAM_HXX - -#include <com/sun/star/lang/IllegalArgumentException.hpp> -#include <com/sun/star/io/XSeekable.hpp> -#include <com/sun/star/io/XInputStream.hpp> -#include <cppuhelper/implbase2.hxx> -#include <rtl/ref.hxx> -#include <Inflater.hxx> -#include <ZipEntry.hxx> - -namespace com { namespace sun { namespace star { - namespace io { class XOutputStream; } -} } } -class EncryptionData; -typedef void* rtlCipher; -class XFileStream : public cppu::WeakImplHelper2 -< - com::sun::star::io::XInputStream, - com::sun::star::io::XSeekable -> -{ -protected: - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > mxZipStream; - com::sun::star::uno::Reference < com::sun::star::io::XSeekable > mxZipSeek; - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > mxTempIn; - com::sun::star::uno::Reference < com::sun::star::io::XSeekable > mxTempSeek; - com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > mxTempOut; - com::sun::star::uno::Sequence < sal_Int8 > maBuffer, maCompBuffer; - ZipEntry maEntry; - rtl::Reference < EncryptionData > mxData; - rtlCipher maCipher; - Inflater maInflater; - sal_Bool mbRawStream, mbFinished; - sal_Int64 mnZipCurrent, mnZipEnd, mnZipSize; - void fill( sal_Int64 nUntil ); - -public: - XFileStream( ZipEntry & rEntry, - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream, - com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream, - const rtl::Reference < EncryptionData > &rData, - sal_Bool bRawStream, - sal_Bool bIsEncrypted ); - virtual ~XFileStream(); - - // XInputStream - virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int32 SAL_CALL available( ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual void SAL_CALL closeInput( ) - throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - // XSeekable - virtual void SAL_CALL seek( sal_Int64 location ) - throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int64 SAL_CALL getPosition( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - virtual sal_Int64 SAL_CALL getLength( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); -}; -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/XMemoryStream.cxx b/package/source/zipapi/XMemoryStream.cxx deleted file mode 100644 index 8b737db6e..000000000 --- a/package/source/zipapi/XMemoryStream.cxx +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_package.hxx" -#include <XMemoryStream.hxx> - -using namespace com::sun::star::io; -using namespace com::sun::star::uno; - -XMemoryStream::XMemoryStream ( com::sun::star::uno::Sequence < sal_Int8 > & rNewBuffer ) -: ZipPackageBuffer ( rNewBuffer ) -{ -} -XMemoryStream::~XMemoryStream(void) -{ -} -::com::sun::star::uno::Any SAL_CALL XMemoryStream::queryInterface( const com::sun::star::uno::Type& rType ) - throw(com::sun::star::uno::RuntimeException) -{ - return ::cppu::queryInterface ( rType , - // OWeakObject interfaces - reinterpret_cast< XInterface* > ( this ) , - static_cast< XWeak* > ( this ) , - // my interfaces - static_cast< XInputStream* > ( this ) , - static_cast< XSeekable* > ( this ) ); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx index 1cad883f9..bb757e602 100644 --- a/package/source/zipapi/XUnbufferedStream.cxx +++ b/package/source/zipapi/XUnbufferedStream.cxx @@ -32,8 +32,9 @@ #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 <PackageConstants.hxx> -#include <rtl/cipher.h> #include <ZipFile.hxx> #include <EncryptedDataHeader.hxx> #include <algorithm> @@ -48,6 +49,7 @@ using namespace ::com::sun::star; #endif +using namespace ::com::sun::star; using namespace com::sun::star::packages::zip::ZipConstants; using namespace com::sun::star::io; using namespace com::sun::star::uno; @@ -55,7 +57,9 @@ using com::sun::star::lang::IllegalArgumentException; using com::sun::star::packages::zip::ZipIOException; using ::rtl::OUString; -XUnbufferedStream::XUnbufferedStream( SotMutexHolderRef aMutexHolder, +XUnbufferedStream::XUnbufferedStream( + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + SotMutexHolderRef aMutexHolder, ZipEntry & rEntry, Reference < XInputStream > xNewZipStream, const rtl::Reference < EncryptionData > &rData, @@ -68,7 +72,7 @@ XUnbufferedStream::XUnbufferedStream( SotMutexHolderRef aMutexHolder, , mxZipSeek ( xNewZipStream, UNO_QUERY ) , maEntry ( rEntry ) , mxData ( rData ) -, maCipher ( NULL ) +, mnBlockSize( 1 ) , maInflater ( sal_True ) , mbRawStream ( nStreamMode == UNBUFF_STREAM_RAW || nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) , mbWrappedRaw ( nStreamMode == UNBUFF_STREAM_WRAPPEDRAW ) @@ -91,11 +95,15 @@ XUnbufferedStream::XUnbufferedStream( SotMutexHolderRef aMutexHolder, mnZipSize = maEntry.nSize; mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize; } - sal_Bool bHaveEncryptData = ( rData.is() && rData->aSalt.getLength() && rData->aInitVector.getLength() && rData->nIterationCount != 0 ) ? sal_True : sal_False; + sal_Bool bHaveEncryptData = ( rData.is() && rData->m_aSalt.getLength() && rData->m_aInitVector.getLength() && rData->m_nIterationCount != 0 ) ? sal_True : sal_False; sal_Bool bMustDecrypt = ( nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False; if ( bMustDecrypt ) - ZipFile::StaticGetCipher ( rData, maCipher, sal_True ); + { + 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 @@ -104,24 +112,26 @@ XUnbufferedStream::XUnbufferedStream( SotMutexHolderRef aMutexHolder, // Make a buffer big enough to hold both the header and the data itself maHeader.realloc ( n_ConstHeaderSize + - rData->aInitVector.getLength() + - rData->aSalt.getLength() + - rData->aDigest.getLength() + + rData->m_aInitVector.getLength() + + rData->m_aSalt.getLength() + + rData->m_aDigest.getLength() + aMediaType.getLength() * sizeof( sal_Unicode ) ); sal_Int8 * pHeader = maHeader.getArray(); - ZipFile::StaticFillHeader ( rData, rEntry.nSize, aMediaType, pHeader ); + ZipFile::StaticFillHeader( rData, rEntry.nSize, aMediaType, pHeader ); mnHeaderToRead = static_cast < sal_Int16 > ( maHeader.getLength() ); } } // allows to read package raw stream -XUnbufferedStream::XUnbufferedStream( const Reference < XInputStream >& xRawStream, - const rtl::Reference < EncryptionData > &rData ) +XUnbufferedStream::XUnbufferedStream( + 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 ) -, maCipher ( NULL ) +, mnBlockSize( 1 ) , maInflater ( sal_True ) , mbRawStream ( sal_False ) , mbWrappedRaw ( sal_False ) @@ -137,8 +147,8 @@ XUnbufferedStream::XUnbufferedStream( const Reference < XInputStream >& xRawStre OSL_ENSURE( mxZipSeek.is(), "The stream must be seekable!\n" ); // skip raw header, it must be already parsed to rData - mnZipCurrent = n_ConstHeaderSize + rData->aInitVector.getLength() + - rData->aSalt.getLength() + rData->aDigest.getLength(); + mnZipCurrent = n_ConstHeaderSize + rData->m_aInitVector.getLength() + + rData->m_aSalt.getLength() + rData->m_aDigest.getLength(); try { if ( mxZipSeek.is() ) @@ -150,13 +160,12 @@ XUnbufferedStream::XUnbufferedStream( const Reference < XInputStream >& xRawStre mnZipEnd = mnZipCurrent + mnZipSize; - ZipFile::StaticGetCipher ( rData, maCipher, sal_True ); + // the raw data will not be decrypted, no need for the cipher + // m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false ); } XUnbufferedStream::~XUnbufferedStream() { - if ( maCipher ) - rtl_cipher_destroy ( maCipher ); } sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) @@ -249,7 +258,12 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa if ( nDiff > 0 ) { mxZipSeek->seek ( mnZipCurrent ); - sal_Int32 nToRead = std::min ( nDiff, std::max ( nRequestedBytes, static_cast< sal_Int32 >( 8192 ) ) ); + + 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!" ) ), @@ -258,23 +272,22 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa mnZipCurrent += nZipRead; // maCompBuffer now has the data, check if we need to decrypt // before passing to the Inflater - if ( maCipher ) + if ( m_xCipherContext.is() ) { if ( mbCheckCRC ) maCRC.update( maCompBuffer ); - Sequence < sal_Int8 > aCryptBuffer ( nZipRead ); - rtlCipherError aResult = - rtl_cipher_decode ( maCipher, - maCompBuffer.getConstArray(), - nZipRead, - reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()), - nZipRead); - if( aResult != rtl_Cipher_E_None ) { - OSL_ASSERT (aResult == rtl_Cipher_E_None); + maCompBuffer = m_xCipherContext->convertWithCipherContext( maCompBuffer ); + if ( mnZipCurrent == mnZipEnd ) + { + Sequence< sal_Int8 > aSuffix = m_xCipherContext->finalizeCipherContextAndDispose(); + if ( aSuffix.getLength() ) + { + sal_Int32 nOldLen = maCompBuffer.getLength(); + maCompBuffer.realloc( nOldLen + aSuffix.getLength() ); + rtl_copyMemory( maCompBuffer.getArray() + nOldLen, aSuffix.getConstArray(), aSuffix.getLength() ); + } } - maCompBuffer = aCryptBuffer; // Now it holds the decrypted data - } maInflater.setInput ( maCompBuffer ); } @@ -293,7 +306,7 @@ sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sa if ( mbCheckCRC && ( !mbRawStream || mbWrappedRaw ) ) { - if ( !maCipher && !mbWrappedRaw ) + if ( !m_xCipherContext.is() && !mbWrappedRaw ) maCRC.update( aData ); #if 0 diff --git a/package/source/zipapi/XUnbufferedStream.hxx b/package/source/zipapi/XUnbufferedStream.hxx index 5cf72727f..aa58ca70c 100644 --- a/package/source/zipapi/XUnbufferedStream.hxx +++ b/package/source/zipapi/XUnbufferedStream.hxx @@ -32,6 +32,8 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/xml/crypto/XCipherContext.hpp> + #include <cppuhelper/implbase1.hxx> #include <rtl/ref.hxx> #include <Inflater.hxx> @@ -44,7 +46,6 @@ #define UNBUFF_STREAM_WRAPPEDRAW 2 class EncryptionData; -typedef void* rtlCipher; class XUnbufferedStream : public cppu::WeakImplHelper1 < com::sun::star::io::XInputStream @@ -58,7 +59,8 @@ protected: com::sun::star::uno::Sequence < sal_Int8 > maCompBuffer, maHeader; ZipEntry maEntry; rtl::Reference < EncryptionData > mxData; - rtlCipher maCipher; + sal_Int32 mnBlockSize; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > m_xCipherContext; ZipUtils::Inflater maInflater; sal_Bool mbRawStream, mbWrappedRaw, mbFinished; sal_Int16 mnHeaderToRead; @@ -68,6 +70,7 @@ protected: public: XUnbufferedStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, SotMutexHolderRef aMutexHolder, ZipEntry & rEntry, com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream, @@ -78,8 +81,10 @@ public: sal_Bool bRecoveryMode ); // allows to read package raw stream - XUnbufferedStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& xRawStream, - const rtl::Reference < EncryptionData > &rData ); + XUnbufferedStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& xRawStream, + const ::rtl::Reference< EncryptionData >& rData ); virtual ~XUnbufferedStream(); diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 2e9576bf4..fb56c2815 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -32,11 +32,22 @@ #include <ZipEnumeration.hxx> #include <com/sun/star/packages/zip/ZipConstants.hpp> #include <rtl/cipher.h> +#include <com/sun/star/xml/crypto/XCipherContext.hpp> +#include <com/sun/star/xml/crypto/XDigestContext.hpp> +#include <com/sun/star/xml/crypto/XCipherContextSupplier.hpp> +#include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> + +#include <comphelper/processfactory.hxx> #include <rtl/digest.h> /* #include <XMemoryStream.hxx> #include <XFileStream.hxx> */ + +#include "blowfishcontext.hxx" +#include "sha1context.hxx" #include <XUnbufferedStream.hxx> #include <PackageConstants.hxx> #include <EncryptedDataHeader.hxx> @@ -47,10 +58,10 @@ #include <CRC32.hxx> -#include <string.h> // for memcpy #include <vector> #include <comphelper/storagehelper.hxx> +#define AES_CBC_BLOCK_SIZE 16 using namespace com::sun::star; using namespace com::sun::star::io; @@ -72,7 +83,7 @@ ZipFile::ZipFile( Reference < XInputStream > &xInput, const Reference < XMultiSe , aInflater (sal_True) , xStream(xInput) , xSeek(xInput, UNO_QUERY) -, xFactory ( xNewFactory ) +, m_xFactory ( xNewFactory ) , bRecoveryMode( sal_False ) { if (bInitialise) @@ -93,7 +104,7 @@ ZipFile::ZipFile( Reference < XInputStream > &xInput, const Reference < XMultiSe , aInflater (sal_True) , xStream(xInput) , xSeek(xInput, UNO_QUERY) -, xFactory ( xNewFactory ) +, m_xFactory ( xNewFactory ) , xProgressHandler( xProgress ) , bRecoveryMode( bForceRecovery ) { @@ -136,18 +147,18 @@ sal_Bool ZipFile::StaticGetCipher ( const rtl::Reference < EncryptionData > & xE // Get the key rtl_digest_PBKDF2 ( aDerivedKey.getArray(), 16, - reinterpret_cast < const sal_uInt8 * > (xEncryptionData->aKey.getConstArray() ), - xEncryptionData->aKey.getLength(), - reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->aSalt.getConstArray() ), - xEncryptionData->aSalt.getLength(), - xEncryptionData->nIterationCount ); + reinterpret_cast < const sal_uInt8 * > (xEncryptionData->m_aKey.getConstArray() ), + xEncryptionData->m_aKey.getLength(), + reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->m_aSalt.getConstArray() ), + xEncryptionData->m_aSalt.getLength(), + xEncryptionData->m_nIterationCount ); rCipher = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream); aResult = rtl_cipher_init( rCipher, bDecode ? rtl_Cipher_DirectionDecode : rtl_Cipher_DirectionEncode, aDerivedKey.getConstArray(), aDerivedKey.getLength(), - reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->aInitVector.getConstArray() ), - xEncryptionData->aInitVector.getLength()); + reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->m_aInitVector.getConstArray() ), + xEncryptionData->m_aInitVector.getLength()); OSL_ASSERT (aResult == rtl_Cipher_E_None); bResult = ( aResult == rtl_Cipher_E_None ); @@ -156,15 +167,85 @@ sal_Bool ZipFile::StaticGetCipher ( const rtl::Reference < EncryptionData > & xE return bResult; } +uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextForChecksum( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData ) +{ + uno::Reference< xml::crypto::XDigestContext > xDigestContext; + if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA256_1K ) + { + uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory; + if ( !xFactory.is() ) + 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.NSSInitializer" ) ) ), + uno::UNO_QUERY_THROW ); + + 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 ); + + return xDigestContext; +} + +uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData, bool bEncrypt ) +{ + uno::Reference< xml::crypto::XCipherContext > xResult; + + try + { + uno::Sequence< sal_Int8 > aDerivedKey( xEncryptionData->m_nDerivedKeySize ); + if ( rtl_Digest_E_None != rtl_digest_PBKDF2( reinterpret_cast< sal_uInt8* >( aDerivedKey.getArray() ), + aDerivedKey.getLength(), + reinterpret_cast< const sal_uInt8 * > (xEncryptionData->m_aKey.getConstArray() ), + xEncryptionData->m_aKey.getLength(), + reinterpret_cast< const sal_uInt8 * > ( xEncryptionData->m_aSalt.getConstArray() ), + xEncryptionData->m_aSalt.getLength(), + xEncryptionData->m_nIterationCount ) ) + { + throw ZipIOException( ::rtl::OUString::createFromAscii( "Can not create derived key!\n" ), + uno::Reference< XInterface >() ); + } + + 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.NSSInitializer" ) ) ), + uno::UNO_QUERY_THROW ); + + xResult = xCipherContextSupplier->getCipherContext( xEncryptionData->m_nEncAlg, aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt, uno::Sequence< beans::NamedValue >() ); + } + else if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::BLOWFISH_CFB_8 ) + { + xResult = BlowfishCFB8CipherContext::Create( aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt ); + } + else + { + throw ZipIOException( ::rtl::OUString::createFromAscii( "Unknown cipher algorithm is requested!\n" ), + uno::Reference< XInterface >() ); + } + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Can not create cipher context!" ); + } + + return xResult; +} + void ZipFile::StaticFillHeader ( const rtl::Reference < EncryptionData > & rData, sal_Int32 nSize, const ::rtl::OUString& aMediaType, sal_Int8 * & pHeader ) { // I think it's safe to restrict vector and salt length to 2 bytes ! - sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->aInitVector.getLength() ); - sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->aSalt.getLength() ); - sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->aDigest.getLength() ); + sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->m_aInitVector.getLength() ); + sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->m_aSalt.getLength() ); + sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->m_aDigest.getLength() ); sal_Int16 nMediaTypeLength = static_cast < sal_Int16 > ( aMediaType.getLength() * sizeof( sal_Unicode ) ); // First the header @@ -178,7 +259,7 @@ void ZipFile::StaticFillHeader ( const rtl::Reference < EncryptionData > & rData *(pHeader++) = ( n_ConstCurrentVersion >> 8 ) & 0xFF; // Then the iteration Count - sal_Int32 nIterationCount = rData->nIterationCount; + sal_Int32 nIterationCount = rData->m_nIterationCount; *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 0 ) & 0xFF); *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 8 ) & 0xFF); *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 16 ) & 0xFF); @@ -190,6 +271,34 @@ void ZipFile::StaticFillHeader ( const rtl::Reference < EncryptionData > & rData *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 16 ) & 0xFF); *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 24 ) & 0xFF); + // Then the encryption algorithm + sal_Int32 nEncAlgID = rData->m_nEncAlg; + *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 0 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 8 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 16 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 24 ) & 0xFF); + + // Then the checksum algorithm + sal_Int32 nChecksumAlgID = rData->m_nCheckAlg; + *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 0 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 8 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 16 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 24 ) & 0xFF); + + // Then the derived key size + sal_Int32 nDerivedKeySize = rData->m_nDerivedKeySize; + *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 0 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 8 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 16 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 24 ) & 0xFF); + + // Then the start key generation algorithm + sal_Int32 nKeyAlgID = rData->m_nStartKeyGenID; + *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 0 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 8 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 16 ) & 0xFF); + *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 24 ) & 0xFF); + // Then the salt length *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 0 ) & 0xFF); *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 8 ) & 0xFF); @@ -207,26 +316,30 @@ void ZipFile::StaticFillHeader ( const rtl::Reference < EncryptionData > & rData *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF); // Then the salt content - memcpy ( pHeader, rData->aSalt.getConstArray(), nSaltLength ); + rtl_copyMemory ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength ); pHeader += nSaltLength; // Then the IV content - memcpy ( pHeader, rData->aInitVector.getConstArray(), nIVLength ); + rtl_copyMemory ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength ); pHeader += nIVLength; // Then the digest content - memcpy ( pHeader, rData->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; } -sal_Bool ZipFile::StaticFillData ( rtl::Reference < EncryptionData > & rData, +sal_Bool ZipFile::StaticFillData ( rtl::Reference < BaseEncryptionData > & rData, + sal_Int32 &rEncAlg, + sal_Int32 &rChecksumAlg, + sal_Int32 &rDerivedKeySize, + sal_Int32 &rStartKeyGenID, sal_Int32 &rSize, ::rtl::OUString& aMediaType, - Reference < XInputStream > &rStream ) + const Reference< XInputStream >& rStream ) { sal_Bool bOk = sal_False; const sal_Int32 nHeaderSize = n_ConstHeaderSize - 4; @@ -243,13 +356,33 @@ sal_Bool ZipFile::StaticFillData ( rtl::Reference < EncryptionData > & rData, nCount |= ( pBuffer[nPos++] & 0xFF ) << 8; nCount |= ( pBuffer[nPos++] & 0xFF ) << 16; nCount |= ( pBuffer[nPos++] & 0xFF ) << 24; - rData->nIterationCount = nCount; + rData->m_nIterationCount = nCount; rSize = pBuffer[nPos++] & 0xFF; rSize |= ( pBuffer[nPos++] & 0xFF ) << 8; rSize |= ( pBuffer[nPos++] & 0xFF ) << 16; rSize |= ( pBuffer[nPos++] & 0xFF ) << 24; + rEncAlg = pBuffer[nPos++] & 0xFF; + rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 8; + rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 16; + rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 24; + + rChecksumAlg = pBuffer[nPos++] & 0xFF; + rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 8; + rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 16; + rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 24; + + rDerivedKeySize = pBuffer[nPos++] & 0xFF; + rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 8; + rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 16; + rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 24; + + rStartKeyGenID = pBuffer[nPos++] & 0xFF; + rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 8; + rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 16; + rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 24; + sal_Int16 nSaltLength = pBuffer[nPos++] & 0xFF; nSaltLength |= ( pBuffer[nPos++] & 0xFF ) << 8; sal_Int16 nIVLength = ( pBuffer[nPos++] & 0xFF ); @@ -262,16 +395,16 @@ sal_Bool ZipFile::StaticFillData ( rtl::Reference < EncryptionData > & rData, if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) ) { - rData->aSalt.realloc ( nSaltLength ); - memcpy ( rData->aSalt.getArray(), aBuffer.getConstArray(), nSaltLength ); + rData->m_aSalt.realloc ( nSaltLength ); + rtl_copyMemory ( rData->m_aSalt.getArray(), aBuffer.getConstArray(), nSaltLength ); if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) ) { - rData->aInitVector.realloc ( nIVLength ); - memcpy ( rData->aInitVector.getArray(), aBuffer.getConstArray(), nIVLength ); + rData->m_aInitVector.realloc ( nIVLength ); + rtl_copyMemory ( rData->m_aInitVector.getArray(), aBuffer.getConstArray(), nIVLength ); if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) ) { - rData->aDigest.realloc ( nDigestLength ); - memcpy ( rData->aDigest.getArray(), aBuffer.getConstArray(), nDigestLength ); + rData->m_aDigest.realloc ( nDigestLength ); + rtl_copyMemory ( rData->m_aDigest.getArray(), aBuffer.getConstArray(), nDigestLength ); if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) ) { @@ -287,7 +420,8 @@ sal_Bool ZipFile::StaticFillData ( rtl::Reference < EncryptionData > & rData, return bOk; } -Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< XInputStream >& xStream, +Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< lang::XMultiServiceFactory >& xFactory, + const Reference< XInputStream >& xStream, const rtl::Reference < EncryptionData > &rData ) throw ( packages::WrongPasswordException, ZipIOException, RuntimeException ) { @@ -295,7 +429,7 @@ Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< throw ZipIOException( OUString(RTL_CONSTASCII_USTRINGPARAM( "Encrypted stream without encryption data!\n" )), Reference< XInterface >() ); - if ( !rData->aKey.getLength() ) + if ( !rData->m_aKey.getLength() ) throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); Reference< XSeekable > xSeek( xStream, UNO_QUERY ); @@ -306,66 +440,72 @@ Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< // if we have a digest, then this file is an encrypted one and we should // check if we can decrypt it or not - OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" ); - if ( rData->aDigest.getLength() ) + 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; + if ( nSize > n_ConstDigestLength + 32 ) + nSize = n_ConstDigestLength + 32; // skip header - xSeek->seek( n_ConstHeaderSize + rData->aInitVector.getLength() + - rData->aSalt.getLength() + rData->aDigest.getLength() ); + xSeek->seek( n_ConstHeaderSize + rData->m_aInitVector.getLength() + + rData->m_aSalt.getLength() + rData->m_aDigest.getLength() ); // Only want to read enough to verify the digest Sequence < sal_Int8 > aReadBuffer ( nSize ); xStream->readBytes( aReadBuffer, nSize ); - if ( !StaticHasValidPassword( aReadBuffer, rData ) ) + if ( !StaticHasValidPassword( xFactory, aReadBuffer, rData ) ) throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } - return new XUnbufferedStream ( xStream, rData ); + return new XUnbufferedStream( xFactory, xStream, rData ); } -sal_Bool ZipFile::StaticHasValidPassword( const Sequence< sal_Int8 > &aReadBuffer, const rtl::Reference < EncryptionData > &rData ) +sal_Bool ZipFile::StaticHasValidPassword( const Reference< lang::XMultiServiceFactory >& xFactory, const Sequence< sal_Int8 > &aReadBuffer, const rtl::Reference< EncryptionData > &rData ) { - if ( !rData.is() || !rData->aKey.getLength() ) + if ( !rData.is() || !rData->m_aKey.getLength() ) return sal_False; sal_Bool bRet = sal_False; - sal_Int32 nSize = aReadBuffer.getLength(); - // make a temporary cipher - rtlCipher aCipher; - StaticGetCipher ( rData, aCipher, sal_True ); - - Sequence < sal_Int8 > aDecryptBuffer ( nSize ); - rtlDigest aDigest = rtl_digest_createSHA1(); - rtlDigestError aDigestResult; - Sequence < sal_uInt8 > aDigestSeq ( RTL_DIGEST_LENGTH_SHA1 ); - rtlCipherError aResult = rtl_cipher_decode ( aCipher, - aReadBuffer.getConstArray(), - nSize, - reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()), - nSize); - if(aResult != rtl_Cipher_E_None ) { - OSL_ASSERT ( aResult == rtl_Cipher_E_None); + uno::Reference< xml::crypto::XCipherContext > xCipher( StaticGetCipher( xFactory, rData, false ), uno::UNO_SET_THROW ); + + 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 ) + } + + if ( aDecryptBuffer2.getLength() ) + { + sal_Int32 nOldLen = aDecryptBuffer.getLength(); + aDecryptBuffer.realloc( nOldLen + aDecryptBuffer2.getLength() ); + rtl_copyMemory( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getArray(), aDecryptBuffer2.getLength() ); } - aDigestResult = rtl_digest_updateSHA1 ( aDigest, - static_cast < const void * > ( aDecryptBuffer.getConstArray() ), nSize ); - OSL_ASSERT ( aDigestResult == rtl_Digest_E_None ); + 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 ); - aDigestResult = rtl_digest_getSHA1 ( aDigest, aDigestSeq.getArray(), RTL_DIGEST_LENGTH_SHA1 ); - OSL_ASSERT ( aDigestResult == rtl_Digest_E_None ); - (void)aDigestResult; + xDigestContext->updateDigest( aDecryptBuffer ); + aDigestSeq = xDigestContext->finalizeDigestAndDispose(); // If we don't have a digest, then we have to assume that the password is correct - if ( rData->aDigest.getLength() != 0 && - ( aDigestSeq.getLength() != rData->aDigest.getLength() || + if ( rData->m_aDigest.getLength() != 0 && + ( aDigestSeq.getLength() != rData->m_aDigest.getLength() || 0 != rtl_compareMemory ( aDigestSeq.getConstArray(), - rData->aDigest.getConstArray(), + rData->m_aDigest.getConstArray(), aDigestSeq.getLength() ) ) ) { // We should probably tell the user that the password they entered was wrong @@ -373,8 +513,6 @@ sal_Bool ZipFile::StaticHasValidPassword( const Sequence< sal_Int8 > &aReadBuffe else bRet = sal_True; - rtl_digest_destroySHA1 ( aDigest ); - return bRet; } @@ -383,18 +521,20 @@ sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const rtl::Reference < E ::osl::MutexGuard aGuard( m_aMutex ); sal_Bool bRet = sal_False; - if ( rData->aKey.getLength() ) + if ( rData.is() && rData->m_aKey.getLength() ) { xSeek->seek( rEntry.nOffset ); 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 ); - bRet = StaticHasValidPassword( aReadBuffer, rData ); + bRet = StaticHasValidPassword( m_xFactory, aReadBuffer, rData ); } return bRet; } @@ -502,7 +642,7 @@ Reference < XInputStream > ZipFile::createUnbufferedStream( { ::osl::MutexGuard aGuard( m_aMutex ); - return new XUnbufferedStream ( aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode ); + return new XUnbufferedStream ( m_xFactory, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode ); } @@ -512,7 +652,7 @@ ZipEnumeration * SAL_CALL ZipFile::entries( ) } Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry, - const rtl::Reference < EncryptionData > &rData, + const rtl::Reference< EncryptionData > &rData, sal_Bool bIsEncrypted, SotMutexHolderRef aMutexHolder ) throw(IOException, ZipException, RuntimeException) @@ -529,7 +669,7 @@ Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry, // if we have a digest, then this file is an encrypted one and we should // check if we can decrypt it or not - if ( bIsEncrypted && rData.is() && rData->aDigest.getLength() ) + if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() ) bNeedRawStream = !hasValidPassword ( rEntry, rData ); return createUnbufferedStream ( aMutexHolder, @@ -540,7 +680,7 @@ Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry, } Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry, - const rtl::Reference < EncryptionData > &rData, + const rtl::Reference< EncryptionData > &rData, sal_Bool bIsEncrypted, SotMutexHolderRef aMutexHolder ) throw ( packages::WrongPasswordException, @@ -566,8 +706,8 @@ Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry, // if we have a digest, then this file is an encrypted one and we should // check if we can decrypt it or not - OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" ); - if ( rData->aDigest.getLength() && !hasValidPassword ( rEntry, rData ) ) + OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" ); + if ( rData->m_aDigest.getLength() && !hasValidPassword ( rEntry, rData ) ) throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } else diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx index 1d29e179d..26c468de6 100644 --- a/package/source/zipapi/ZipOutputStream.cxx +++ b/package/source/zipapi/ZipOutputStream.cxx @@ -39,7 +39,9 @@ #include <com/sun/star/io/XOutputStream.hpp> #include <comphelper/storagehelper.hxx> +#include <ZipPackageStream.hxx> +using namespace com::sun::star; using namespace com::sun::star::io; using namespace com::sun::star::uno; using namespace com::sun::star::packages; @@ -48,17 +50,18 @@ using namespace com::sun::star::packages::zip::ZipConstants; /** This class is used to write Zip files */ -ZipOutputStream::ZipOutputStream( Reference < XOutputStream > &xOStream ) -: xStream(xOStream) -, aBuffer(n_ConstBufferSize) +ZipOutputStream::ZipOutputStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory, + const uno::Reference < XOutputStream > &xOStream ) +: m_xFactory( xFactory ) +, xStream(xOStream) +, m_aDeflateBuffer(n_ConstBufferSize) , aDeflater(DEFAULT_COMPRESSION, sal_True) , aChucker(xOStream) , pCurrentEntry(NULL) , nMethod(DEFLATED) , bFinished(sal_False) , bEncryptCurrentEntry(sal_False) - - +, m_pCurrentStream(NULL) { } @@ -80,7 +83,7 @@ void SAL_CALL ZipOutputStream::setLevel( sal_Int32 nNewLevel ) } void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry, - rtl::Reference < EncryptionData > &xEncryptData, + ZipPackageStream* pStream, sal_Bool bEncrypt) throw(IOException, RuntimeException) { @@ -94,18 +97,20 @@ 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) { bEncryptCurrentEntry = sal_True; - ZipFile::StaticGetCipher( xEncryptData, aCipher, sal_False ); - - aDigest = rtl_digest_createSHA1(); + m_xCipherContext = ZipFile::StaticGetCipher( m_xFactory, pStream->GetEncryptionData(), true ); + m_xDigestContext = ZipFile::StaticGetDigestContextForChecksum( m_xFactory, pStream->GetEncryptionData() ); mnDigested = 0; rEntry.nFlag |= 1 << 4; - pCurrentEncryptData = xEncryptData.get(); + m_pCurrentStream = pStream; } sal_Int32 nLOCLength = writeLOC(rEntry); rEntry.nOffset = static_cast < sal_Int32 > (aChucker.GetPosition()) - nLOCLength; @@ -144,11 +149,12 @@ void SAL_CALL ZipOutputStream::closeEntry( ) } else { + if ( !bEncryptCurrentEntry ) + { pEntry->nSize = aDeflater.getTotalIn(); pEntry->nCompressedSize = aDeflater.getTotalOut(); + } pEntry->nCrc = aCRC.getValue(); - if ( bEncryptCurrentEntry ) - pEntry->nSize = pEntry->nCompressedSize; writeEXT(*pEntry); } aDeflater.reset(); @@ -165,19 +171,22 @@ void SAL_CALL ZipOutputStream::closeEntry( ) if (bEncryptCurrentEntry) { - rtlDigestError aDigestResult; - aEncryptionBuffer.realloc ( 0 ); bEncryptCurrentEntry = sal_False; - rtl_cipher_destroy ( aCipher ); - pCurrentEncryptData->aDigest.realloc ( RTL_DIGEST_LENGTH_SHA1 ); - aDigestResult = rtl_digest_getSHA1 ( aDigest, - reinterpret_cast < sal_uInt8 * > ( pCurrentEncryptData->aDigest.getArray() ), - RTL_DIGEST_LENGTH_SHA1 ); - OSL_ASSERT( aDigestResult == rtl_Digest_E_None ); - (void)aDigestResult; - rtl_digest_destroySHA1 ( aDigest ); + + m_xCipherContext.clear(); + + uno::Sequence< sal_Int8 > aDigestSeq; + if ( m_xDigestContext.is() ) + { + aDigestSeq = m_xDigestContext->finalizeDigestAndDispose(); + m_xDigestContext.clear(); + } + + if ( m_pCurrentStream ) + m_pCurrentStream->setDigest( aDigestSeq ); } pCurrentEntry = NULL; + m_pCurrentStream = NULL; } } @@ -242,42 +251,51 @@ 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()); if ( nLength > 0 ) { - Sequence < sal_Int8 > aTmpBuffer ( aBuffer.getConstArray(), nLength ); - const void *pTmpBuffer = static_cast < const void * > ( aTmpBuffer.getConstArray() ); - if (bEncryptCurrentEntry) + Sequence< sal_Int8 > aTmpBuffer ( m_aDeflateBuffer.getConstArray(), nLength ); + if (bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is()) { // Need to update our digest before encryption... - rtlDigestError aDigestResult = rtl_Digest_E_None; - sal_Int16 nDiff = n_ConstDigestLength - mnDigested; + sal_Int32 nDiff = n_ConstDigestLength - mnDigested; if ( nDiff ) { - sal_Int16 nEat = static_cast < sal_Int16 > ( nDiff > nLength ? nLength : nDiff ); - aDigestResult = rtl_digest_updateSHA1 ( aDigest, pTmpBuffer, nEat ); - mnDigested = mnDigested + nEat; + sal_Int32 nEat = ::std::min( nLength, nDiff ); + uno::Sequence< sal_Int8 > aTmpSeq( aTmpBuffer.getConstArray(), nEat ); + m_xDigestContext->updateDigest( aTmpSeq ); + mnDigested = mnDigested + static_cast< sal_Int16 >( nEat ); } - OSL_ASSERT( aDigestResult == rtl_Digest_E_None ); - (void)aDigestResult; - - aEncryptionBuffer.realloc ( nLength ); - rtlCipherError aCipherResult; - aCipherResult = rtl_cipher_encode ( aCipher, pTmpBuffer, - nLength, reinterpret_cast < sal_uInt8 * > (aEncryptionBuffer.getArray()), nLength ); - OSL_ASSERT( aCipherResult == rtl_Cipher_E_None ); - (void)aCipherResult; + 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 ); - aEncryptionBuffer.realloc ( nOldLength ); } else + { aChucker.WriteBytes ( aTmpBuffer ); } + } + + if ( aDeflater.finished() && bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) + { + uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose(); + 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 ); + } + } } void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength) throw(IOException, RuntimeException) diff --git a/package/source/zipapi/blowfishcontext.cxx b/package/source/zipapi/blowfishcontext.cxx new file mode 100644 index 000000000..1739bb15c --- /dev/null +++ b/package/source/zipapi/blowfishcontext.cxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_package.hxx" + +#include <rtl/cipher.h> +#include <rtl/ref.hxx> + +#include "blowfishcontext.hxx" + +using namespace ::com::sun::star; + +// static +uno::Reference< xml::crypto::XCipherContext > BlowfishCFB8CipherContext::Create( const uno::Sequence< sal_Int8 >& aDerivedKey, const uno::Sequence< sal_Int8 >& aInitVector, bool bEncrypt ) +{ + ::rtl::Reference< BlowfishCFB8CipherContext > xResult = new BlowfishCFB8CipherContext(); + xResult->m_pCipher = rtl_cipher_create( rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream ); + if ( !xResult->m_pCipher ) + throw uno::RuntimeException( ::rtl::OUString::createFromAscii( "Can not create cipher!\n" ), + uno::Reference< XInterface >() ); + + if ( rtl_Cipher_E_None != rtl_cipher_init( + xResult->m_pCipher, + bEncrypt ? rtl_Cipher_DirectionEncode : rtl_Cipher_DirectionDecode, + reinterpret_cast< const sal_uInt8* >( aDerivedKey.getConstArray() ), + aDerivedKey.getLength(), + reinterpret_cast< const sal_uInt8* >( aInitVector.getConstArray() ), + aInitVector.getLength() ) ) + { + throw uno::RuntimeException( ::rtl::OUString::createFromAscii( "Can not initialize cipher!\n" ), + uno::Reference< XInterface >() ); + } + + xResult->m_bEncrypt = bEncrypt; + + return uno::Reference< xml::crypto::XCipherContext >( xResult.get() ); +} + +BlowfishCFB8CipherContext::~BlowfishCFB8CipherContext() +{ + if ( m_pCipher ) + { + rtl_cipher_destroy ( m_pCipher ); + m_pCipher = NULL; + } +} + +uno::Sequence< sal_Int8 > SAL_CALL BlowfishCFB8CipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData ) + throw( lang::IllegalArgumentException, lang::DisposedException, uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pCipher ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( aData.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 >() ); + } + + return aResult; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL BlowfishCFB8CipherContext::finalizeCipherContextAndDispose() + throw( lang::DisposedException, uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pCipher ) + throw lang::DisposedException(); + + rtl_cipher_destroy ( m_pCipher ); + m_pCipher = NULL; + + return uno::Sequence< sal_Int8 >(); +} + + diff --git a/package/source/zipapi/blowfishcontext.hxx b/package/source/zipapi/blowfishcontext.hxx new file mode 100644 index 000000000..49cce2fc0 --- /dev/null +++ b/package/source/zipapi/blowfishcontext.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _BLOWFISHCONTEXT_HXX +#define _BLOWFISHCONTEXT_HXX + +#include <com/sun/star/xml/crypto/XCipherContext.hpp> + +#include <cppuhelper/implbase1.hxx> +#include <osl/mutex.hxx> + +class BlowfishCFB8CipherContext : public cppu::WeakImplHelper1< ::com::sun::star::xml::crypto::XCipherContext > +{ + ::osl::Mutex m_aMutex; + void* m_pCipher; + bool m_bEncrypt; + + BlowfishCFB8CipherContext() + : m_pCipher( NULL ) + , m_bEncrypt( false ) + {} + +public: + + virtual ~BlowfishCFB8CipherContext(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > + Create( const ::com::sun::star::uno::Sequence< sal_Int8 >& aDerivedKey, const ::com::sun::star::uno::Sequence< sal_Int8 >& aInitVector, bool bEncrypt ); + + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); +}; + +#endif // _BLOWFISHCONTEXT_HXX + diff --git a/package/source/zipapi/makefile.mk b/package/source/zipapi/makefile.mk index ec8d63694..8a07d448d 100644 --- a/package/source/zipapi/makefile.mk +++ b/package/source/zipapi/makefile.mk @@ -46,8 +46,10 @@ SLOFILES= \ $(SLO)$/CRC32.obj \ $(SLO)$/ByteChucker.obj \ $(SLO)$/ByteGrabber.obj \ + $(SLO)$/blowfishcontext.obj \ $(SLO)$/Inflater.obj \ $(SLO)$/Deflater.obj \ + $(SLO)$/sha1context.obj \ $(SLO)$/ZipEnumeration.obj \ $(SLO)$/ZipFile.obj \ $(SLO)$/ZipOutputStream.obj \ diff --git a/package/source/zipapi/sha1context.cxx b/package/source/zipapi/sha1context.cxx new file mode 100644 index 000000000..a71f20ad6 --- /dev/null +++ b/package/source/zipapi/sha1context.cxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_package.hxx" + +#include <rtl/digest.h> +#include <rtl/ref.hxx> + +#include "sha1context.hxx" + +using namespace ::com::sun::star; + +// static +uno::Reference< xml::crypto::XDigestContext > SHA1DigestContext::Create() +{ + ::rtl::Reference< SHA1DigestContext > xResult = new SHA1DigestContext(); + xResult->m_pDigest = rtl_digest_createSHA1(); + if ( !xResult->m_pDigest ) + throw uno::RuntimeException( ::rtl::OUString::createFromAscii( "Can not create cipher!\n" ), + uno::Reference< XInterface >() ); + + return uno::Reference< xml::crypto::XDigestContext >( xResult.get() ); +} + +SHA1DigestContext::~SHA1DigestContext() +{ + if ( m_pDigest ) + { + rtl_digest_destroySHA1( m_pDigest ); + m_pDigest = NULL; + } +} + +void SAL_CALL SHA1DigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData ) + throw( lang::DisposedException, uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pDigest ) + throw lang::DisposedException(); + + if ( rtl_Digest_E_None != rtl_digest_updateSHA1( m_pDigest, aData.getConstArray(), aData.getLength() ) ) + { + rtl_digest_destroySHA1( m_pDigest ); + m_pDigest = NULL; + + throw uno::RuntimeException(); + } +} + +uno::Sequence< ::sal_Int8 > SAL_CALL SHA1DigestContext::finalizeDigestAndDispose() + throw( lang::DisposedException, uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pDigest ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( RTL_DIGEST_LENGTH_SHA1 ); + if ( rtl_Digest_E_None != rtl_digest_getSHA1( m_pDigest, reinterpret_cast< sal_uInt8* >( aResult.getArray() ), aResult.getLength() ) ) + { + rtl_digest_destroySHA1( m_pDigest ); + m_pDigest = NULL; + + throw uno::RuntimeException(); + } + + rtl_digest_destroySHA1( m_pDigest ); + m_pDigest = NULL; + + return aResult; +} + + diff --git a/package/source/zipapi/XMemoryStream.hxx b/package/source/zipapi/sha1context.hxx index e6bc88e81..dbd1207ca 100644 --- a/package/source/zipapi/XMemoryStream.hxx +++ b/package/source/zipapi/sha1context.hxx @@ -1,8 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,21 +24,34 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#ifndef _XMEMORY_STREAM_HXX -#define _XMEMORY_STREAM_HXX +#ifndef _SHA1CONTEXT_HXX +#define _SHA1CONTEXT_HXX -#include <ZipPackageBuffer.hxx> +#include <com/sun/star/xml/crypto/XDigestContext.hpp> -class ZipPackage; +#include <cppuhelper/implbase1.hxx> +#include <osl/mutex.hxx> -class XMemoryStream: public ZipPackageBuffer +class SHA1DigestContext : public cppu::WeakImplHelper1< ::com::sun::star::xml::crypto::XDigestContext > { + ::osl::Mutex m_aMutex; + void* m_pDigest; + + SHA1DigestContext() + : m_pDigest( NULL ) + {} + public: - XMemoryStream ( com::sun::star::uno::Sequence < sal_Int8 > & rNewBuffer ); - virtual ~XMemoryStream(void); - virtual com::sun::star::uno::Any SAL_CALL queryInterface( const com::sun::star::uno::Type& rType ) - throw(com::sun::star::uno::RuntimeException); + + virtual ~SHA1DigestContext(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > + Create(); + + virtual void SAL_CALL updateDigest( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); + }; -#endif -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ +#endif // _SHA1CONTEXT_HXX + diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index 1f1e48acb..b4809a0a2 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -63,6 +63,8 @@ #include <com/sun/star/embed/UseBackupException.hpp> #include <com/sun/star/embed/StorageFormats.hpp> #include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> #include <cppuhelper/implbase1.hxx> #include <ContentInfo.hxx> #include <cppuhelper/typeprovider.hxx> @@ -83,6 +85,7 @@ #include <comphelper/storagehelper.hxx> #include <comphelper/ofopxmlhelper.hxx> #include <comphelper/documentconstants.hxx> +#include <comphelper/sequenceashashmap.hxx> using namespace std; using namespace osl; @@ -181,10 +184,12 @@ class DummyInputStream : public ::cppu::WeakImplHelper1< XInputStream > ZipPackage::ZipPackage (const uno::Reference < XMultiServiceFactory > &xNewFactory) : m_aMutexHolder( new SotMutexHolder ) +, m_nStartKeyGenerationID( xml::crypto::DigestID::SHA1 ) +, m_nChecksumDigestID( xml::crypto::DigestID::SHA1_1K ) +, m_nCommonEncryptionID( xml::crypto::CipherID::BLOWFISH_CFB_8 ) , m_bHasEncryptedEntries ( sal_False ) , m_bHasNonEncryptedEntries ( sal_False ) , m_bInconsistent ( sal_False ) -, m_bUseManifest ( sal_True ) , m_bForceRecovery ( sal_False ) , m_bMediaTypeFallbackUsed ( sal_False ) , m_nFormat( embed::StorageFormats::PACKAGE ) // package is the default format @@ -224,6 +229,7 @@ void ZipPackage::parseManifest() if ( m_nFormat == embed::StorageFormats::PACKAGE ) { sal_Bool bManifestParsed = sal_False; + bool bDifferentStartKeyAlgorithm = false; const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) ); if ( m_xRootFolder->hasByName( sMeta ) ) { @@ -253,6 +259,10 @@ void ZipPackage::parseManifest() const OUString sPropIterationCount ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); const OUString sPropSize ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); const OUString sPropDigest ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); + const OUString sPropDerivedKeySize ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ); + const OUString sPropDigestAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ); + const OUString sPropEncryptionAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ); + const OUString sPropStartKeyAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ); Sequence < Sequence < PropertyValue > > aManifestSequence = xReader->readManifestSequence ( xSink->getInputStream() ); sal_Int32 nLength = aManifestSequence.getLength(); @@ -264,7 +274,7 @@ void ZipPackage::parseManifest() { OUString sPath, sMediaType, sVersion; const PropertyValue *pValue = pSequence->getConstArray(); - const Any *pSalt = NULL, *pVector = NULL, *pCount = NULL, *pSize = NULL, *pDigest = NULL; + const Any *pSalt = NULL, *pVector = NULL, *pCount = NULL, *pSize = NULL, *pDigest = NULL, *pDigestAlg = NULL, *pEncryptionAlg = NULL, *pStartKeyAlg = NULL, *pDerivedKeySize = NULL; for (sal_Int32 j = 0, nNum = pSequence->getLength(); j < nNum; j++ ) { if (pValue[j].Name.equals( sPropFullPath ) ) @@ -283,6 +293,14 @@ void ZipPackage::parseManifest() pSize = &(pValue[j].Value); else if (pValue[j].Name.equals( sPropDigest ) ) pDigest = &(pValue[j].Value); + else if ( pValue[j].Name.equals( sPropDigestAlgorithm ) ) + pDigestAlg = &( pValue[j].Value ); + else if ( pValue[j].Name.equals( sPropEncryptionAlgorithm ) ) + pEncryptionAlg = &( pValue[j].Value ); + else if ( pValue[j].Name.equals( sPropStartKeyAlgorithm ) ) + pStartKeyAlg = &( pValue[j].Value ); + else if ( pValue[j].Name.equals( sPropDerivedKeySize ) ) + pDerivedKeySize = &( pValue[j].Value ); } if (sPath.getLength() && hasByHierarchicalName ( sPath ) ) @@ -303,10 +321,10 @@ void ZipPackage::parseManifest() pStream->SetMediaType ( sMediaType ); pStream->SetFromManifest( sal_True ); - if (pSalt && pVector && pCount && pSize) + if (pSalt && pVector && pCount && pSize && pDigest && pDigestAlg && pEncryptionAlg ) { - Sequence < sal_uInt8 > aSequence; - sal_Int32 nCount = 0, nSize = 0; + Sequence < sal_Int8 > aSequence; + sal_Int32 nCount = 0, nSize = 0, nDigestAlg = 0, nEncryptionAlg = 0, nDerivedKeySize = 16, nStartKeyAlg = xml::crypto::DigestID::SHA1; pStream->SetToBeEncrypted ( sal_True ); *pSalt >>= aSequence; @@ -321,18 +339,34 @@ void ZipPackage::parseManifest() *pSize >>= nSize; pStream->setSize ( nSize ); - if ( pDigest ) - { - *pDigest >>= aSequence; - pStream->setDigest ( aSequence ); - } + *pDigest >>= aSequence; + pStream->setDigest ( aSequence ); + + *pDigestAlg >>= nDigestAlg; + pStream->SetImportedChecksumAlgorithm( nDigestAlg ); + + *pEncryptionAlg >>= nEncryptionAlg; + pStream->SetImportedEncryptionAlgorithm( nEncryptionAlg ); + + if ( pDerivedKeySize ) + *pDerivedKeySize >>= nDerivedKeySize; + pStream->SetImportedDerivedKeySize( nDerivedKeySize ); + + if ( pStartKeyAlg ) + *pStartKeyAlg >>= nStartKeyAlg; + pStream->SetImportedStartKeyAlgorithm( nStartKeyAlg ); pStream->SetToBeCompressed ( sal_True ); pStream->SetToBeEncrypted ( sal_True ); pStream->SetIsEncrypted ( sal_True ); if ( !m_bHasEncryptedEntries && pStream->getName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) ) ) + { m_bHasEncryptedEntries = sal_True; + m_nStartKeyGenerationID = nStartKeyAlg; + m_nChecksumDigestID = nDigestAlg; + m_nCommonEncryptionID = nEncryptionAlg; + } } else m_bHasNonEncryptedEntries = sal_True; @@ -411,20 +445,30 @@ void ZipPackage::parseManifest() m_bInconsistent = m_pRootFolder->LookForUnexpectedODF12Streams( ::rtl::OUString() ); - sal_Bool bODF12AndOlder = ( m_pRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 ); - if ( !m_bForceRecovery && bODF12AndOlder && m_bInconsistent ) + sal_Bool bODF12AndNewer = ( m_pRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 ); + if ( !m_bForceRecovery && bODF12AndNewer ) { - // this is an ODF1.2 document that contains streams not referred in the manifest.xml; - // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent - // should be checked later - throw ZipIOException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "there are streams not referred in manifest.xml\n" ) ), - uno::Reference< uno::XInterface >() ); + if ( m_bInconsistent ) + { + // this is an ODF1.2 document that contains streams not referred in the manifest.xml; + // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent + // should be checked later + throw ZipIOException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "there are streams not referred in manifest.xml\n" ) ), + uno::Reference< uno::XInterface >() ); + } + else if ( bDifferentStartKeyAlgorithm ) + { + // all the streams should be encrypted with the same StartKey in ODF1.2 + // TODO/LATER: in future the exception should be thrown + OSL_ENSURE( false, "ODF1.2 contains different StartKey Algorithms" ); + // throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "More than one Start Key Generation algorithm is specified!" ) ), uno::Reference< uno::XInterface >() ); + } } // in case it is a correct ODF1.2 document, the version must be set // and the META-INF folder is reserved for package format - if ( bODF12AndOlder ) + if ( bODF12AndNewer ) m_xRootFolder->removeByName( sMeta ); } } @@ -981,14 +1025,12 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut ) try { - rtl::Reference < EncryptionData > xEmpty; - aZipOut.putNextEntry( *pEntry, xEmpty ); + aZipOut.putNextEntry( *pEntry, NULL ); aZipOut.write( aType, 0, nBufferLength ); aZipOut.closeEntry(); } catch ( ::com::sun::star::io::IOException & r ) { - OSL_FAIL( "Error adding mimetype to the ZipOutputStream" ); throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Error adding mimetype to the ZipOutputStream!" ) ), static_cast < OWeakObject * > ( this ), @@ -1015,19 +1057,20 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< Sequence // Convert vector into a Sequence Sequence < Sequence < PropertyValue > > aManifestSequence ( aManList.size() ); - Sequence < PropertyValue > * pSequence = aManifestSequence.getArray(); + sal_Int32 nInd = 0; for (vector < Sequence < PropertyValue > >::const_iterator aIter = aManList.begin(), aEnd = aManList.end(); aIter != aEnd; - ++aIter, ++pSequence) - *pSequence= (*aIter); + aIter++, nInd++ ) + { + aManifestSequence[nInd] = ( *aIter ); + } xWriter->writeManifestSequence ( xManOutStream, aManifestSequence ); sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() ); pBuffer->realloc( nBufferLength ); // the manifest.xml is never encrypted - so pass an empty reference - rtl::Reference < EncryptionData > xEmpty; - aZipOut.putNextEntry( *pEntry, xEmpty ); + aZipOut.putNextEntry( *pEntry, NULL ); aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); aZipOut.closeEntry(); } @@ -1089,8 +1132,7 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< Sequ pBuffer->realloc( nBufferLength ); // there is no encryption in this format currently - rtl::Reference < EncryptionData > xEmpty; - aZipOut.putNextEntry( *pEntry, xEmpty ); + aZipOut.putNextEntry( *pEntry, NULL ); aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); aZipOut.closeEntry(); } @@ -1154,7 +1196,7 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile() } // Hand it to the ZipOutputStream: - ZipOutputStream aZipOut ( xTempOut ); + ZipOutputStream aZipOut ( m_xFactory, xTempOut ); aZipOut.setMethod(DEFLATED); aZipOut.setLevel(DEFAULT_COMPRESSION); @@ -1224,12 +1266,12 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile() // call saveContents (it will recursively save sub-directories OUString aEmptyString; - m_pRootFolder->saveContents( aEmptyString, aManList, aZipOut, m_aEncryptionKey, aRandomPool ); + m_pRootFolder->saveContents( aEmptyString, aManList, aZipOut, GetEncryptionKey(), aRandomPool ); // Clean up random pool memory rtl_random_destroyPool ( aRandomPool ); - if( m_bUseManifest && m_nFormat == embed::StorageFormats::PACKAGE ) + if( m_nFormat == embed::StorageFormats::PACKAGE ) { WriteManifest( aZipOut, aManList ); } @@ -1549,6 +1591,36 @@ void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Referenc makeAny ( aException ) ); } +//-------------------------------------------------------- +const uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey() +{ + uno::Sequence< sal_Int8 > aResult; + + if ( m_aStorageEncryptionKeys.getLength() ) + { + ::rtl::OUString aNameToFind; + if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA256 ) + aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; + else if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA1 ) + aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; + else + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); + + for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ ) + if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) ) + m_aStorageEncryptionKeys[nInd].Value >>= aResult; + + // empty keys are not allowed here + // so it is not important whether there is no key, or the key is empty, it is an error + if ( !aResult.getLength() ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); + } + else + aResult = m_aEncryptionKey; + + return aResult; +} + sal_Bool SAL_CALL ZipPackage::hasPendingChanges( ) throw(RuntimeException) { @@ -1639,20 +1711,91 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const if ( m_nFormat != embed::StorageFormats::PACKAGE ) throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("HasEncryptedEntries") ) - ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("HasNonEncryptedEntries") ) - ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsInconsistent") ) - ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaTypeFallbackUsed") ) ) + if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) + ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) + ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( IS_INCONSISTENT_PROPERTY ) ) + ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) throw PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EncryptionKey") ) ) + else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) ) { - if (!( aValue >>= m_aEncryptionKey ) || m_aEncryptionKey.getLength() == 0 ) + if (!( aValue >>= m_aEncryptionKey ) ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); + + m_aStorageEncryptionKeys.realloc( 0 ); } - else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseManifest") ) ) + else if (aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) { - if (!( aValue >>= m_bUseManifest ) ) + // this property is only necessary to support raw passwords in storage API; + // because of this support the storage has to operate with more than one key dependent on storage generation algorithm; + // when this support is removed, the storage will get only one key from outside + // TODO/LATER: Get rid of this property as well as of support of raw passwords in storages + uno::Sequence< beans::NamedValue > aKeys; + if ( !( aValue >>= aKeys ) || ( aKeys.getLength() && aKeys.getLength() < 2 ) ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); + + if ( aKeys.getLength() ) + { + bool bHasSHA256 = false; + bool bHasSHA1 = false; + for ( sal_Int32 nInd = 0; nInd < aKeys.getLength(); nInd++ ) + { + if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA256UTF8 ) ) + bHasSHA256 = true; + if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA1UTF8 ) ) + bHasSHA1 = true; + } + + if ( !bHasSHA256 || !bHasSHA1 ) + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Expected keys are not provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); + } + + m_aStorageEncryptionKeys = aKeys; + m_aEncryptionKey.realloc( 0 ); + } + else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) + { + uno::Sequence< beans::NamedValue > aAlgorithms; + if ( m_pZipFile || !( aValue >>= aAlgorithms ) || aAlgorithms.getLength() == 0 ) + { + // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile ) + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); + } + + for ( sal_Int32 nInd = 0; nInd < aAlgorithms.getLength(); nInd++ ) + { + if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ) + { + sal_Int32 nID = 0; + if ( !( aAlgorithms[nInd].Value >>= nID ) + || ( nID != xml::crypto::DigestID::SHA256 && nID != xml::crypto::DigestID::SHA1 ) ) + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); + + m_nStartKeyGenerationID = nID; + } + else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionAlgorithm" ) ) ) + { + sal_Int32 nID = 0; + if ( !( aAlgorithms[nInd].Value >>= nID ) + || ( nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING && nID != xml::crypto::CipherID::BLOWFISH_CFB_8 ) ) + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); + + m_nCommonEncryptionID = nID; + } + else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ChecksumAlgorithm" ) ) ) + { + sal_Int32 nID = 0; + if ( !( aAlgorithms[nInd].Value >>= nID ) + || ( nID != xml::crypto::DigestID::SHA1_1K && nID != xml::crypto::DigestID::SHA256_1K ) ) + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); + + m_nChecksumDigestID = nID; + } + else + { + OSL_ENSURE( sal_False, "Unexpected encryption algorithm is provided!" ); + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); + } + } } else throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); @@ -1665,32 +1808,41 @@ Any SAL_CALL ZipPackage::getPropertyValue( const OUString& PropertyName ) // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); Any aAny; - if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "EncryptionKey" ) ) ) + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( ENCRYPTION_KEY_PROPERTY ) ) ) { aAny <<= m_aEncryptionKey; return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "HasEncryptedEntries" ) ) ) + else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) { - aAny <<= m_bHasEncryptedEntries; + ::comphelper::SequenceAsHashMap aAlgorithms; + aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ] <<= m_nStartKeyGenerationID; + aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionAlgorithm" ) ) ] <<= m_nCommonEncryptionID; + aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChecksumAlgorithm" ) ) ] <<= m_nChecksumDigestID; + aAny <<= aAlgorithms.getAsConstNamedValueList(); return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "HasNonEncryptedEntries" ) ) ) + if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) { - aAny <<= m_bHasNonEncryptedEntries; + aAny <<= m_aStorageEncryptionKeys; return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "IsInconsistent" ) ) ) + else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) ) { - aAny <<= m_bInconsistent; + aAny <<= m_bHasEncryptedEntries; return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "UseManifest" ) ) ) + else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) ) { - aAny <<= m_bUseManifest; + aAny <<= m_bHasNonEncryptedEntries; + return aAny; + } + else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( IS_INCONSISTENT_PROPERTY ) ) ) + { + aAny <<= m_bInconsistent; return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "MediaTypeFallbackUsed" ) ) ) + else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) { aAny <<= m_bMediaTypeFallbackUsed; return aAny; diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx index c412af1d7..534488da7 100644 --- a/package/source/zippackage/ZipPackageFolder.cxx +++ b/package/source/zippackage/ZipPackageFolder.cxx @@ -305,7 +305,7 @@ static void ImplSetStoredData( ZipEntry & rEntry, Reference < XInputStream> & rS rEntry.nCrc = aCRC32.getValue(); } -bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo &rInfo, OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) +bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo &rInfo, OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool) { bool bSuccess = true; @@ -317,6 +317,10 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo const OUString sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); const OUString sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); const OUString sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); + const ::rtl::OUString sEncryptionAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ); + const ::rtl::OUString sStartKeyAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ); + const ::rtl::OUString sDigestAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ); + const ::rtl::OUString sDerivedKeySizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ); Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST); @@ -450,7 +454,6 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo } else { - OSL_FAIL( "The package component requires that every stream either be FROM a package or it must support XSeekable!" ); bSuccess = false; return bSuccess; } @@ -458,7 +461,6 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo } catch ( Exception& ) { - OSL_FAIL( "The stream provided to the package component has problems!" ); bSuccess = false; return bSuccess; } @@ -467,9 +469,9 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo { if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) { - Sequence < sal_uInt8 > aSalt ( 16 ), aVector ( 8 ); + Sequence < sal_Int8 > aSalt ( 16 ), aVector ( rInfo.pStream->GetBlockSize() ); rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 ); - rtl_random_getBytes ( rRandomPool, aVector.getArray(), 8 ); + rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() ); sal_Int32 nIterationCount = 1024; if ( !rInfo.pStream->HasOwnKey() ) @@ -498,8 +500,20 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo if ( bRawStream || bTransportOwnEncrStreamAsRaw ) { + ::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData(); + if ( !xEncData.is() ) + throw uno::RuntimeException(); + aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest(); + aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; + aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg; + aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty; + aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID; + aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty; + aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg; + aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty; + aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize; } } } @@ -520,7 +534,6 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo if ( !xStream.is() ) { // Make sure that we actually _got_ a new one ! - OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" ); bSuccess = false; return bSuccess; } @@ -531,7 +544,7 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo if ( bRawStream ) xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() ); - rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream->getEncryptionData(), sal_False ); + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, sal_False ); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); @@ -549,12 +562,10 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo } catch ( ZipException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bSuccess = false; } catch ( IOException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bSuccess = false; } } @@ -576,7 +587,6 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo if ( !xStream.is() ) { // Make sure that we actually _got_ a new one ! - OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" ); bSuccess = false; return bSuccess; } @@ -590,7 +600,7 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo try { - rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream->getEncryptionData(), bToBeEncrypted); + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); @@ -607,19 +617,30 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo } catch ( ZipException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bSuccess = false; } catch ( IOException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bSuccess = false; } if ( bToBeEncrypted ) { + ::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData(); + if ( !xEncData.is() ) + throw uno::RuntimeException(); + aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest(); + aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; + aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg; + aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty; + aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID; + aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty; + aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg; + aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty; + aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize; + rInfo.pStream->SetIsEncrypted ( sal_True ); } } @@ -665,7 +686,7 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo return bSuccess; } -void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) +void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool ) throw(RuntimeException) { bool bWritingFailed = false; @@ -681,18 +702,15 @@ void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < Pr try { - rtl::Reference < EncryptionData > aEmptyEncr; - rZipOut.putNextEntry ( *pTempEntry, aEmptyEncr, sal_False ); + rZipOut.putNextEntry ( *pTempEntry, NULL, sal_False ); rZipOut.rawCloseEntry(); } catch ( ZipException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bWritingFailed = true; } catch ( IOException& ) { - OSL_FAIL( "Error writing ZipOutputStream" ); bWritingFailed = true; } } diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx index ce72beb5e..424053cbb 100644 --- a/package/source/zippackage/ZipPackageStream.cxx +++ b/package/source/zippackage/ZipPackageStream.cxx @@ -35,6 +35,8 @@ #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/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> #include <ZipPackageStream.hxx> @@ -75,13 +77,17 @@ ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage, , bToBeEncrypted ( sal_False ) , bHaveOwnKey ( sal_False ) , bIsEncrypted ( sal_False ) -, xEncryptionData ( ) +, m_nImportedStartKeyAlgorithm( 0 ) +, m_nImportedEncryptionAlgorithm( 0 ) +, m_nImportedChecksumAlgorithm( 0 ) +, m_nImportedDerivedKeySize( 0 ) , m_nStreamMode( PACKAGE_STREAM_NOTSET ) , m_nMagicalHackPos( 0 ) , m_nMagicalHackSize( 0 ) , m_bHasSeekable( sal_False ) , m_bCompressedIsSetFromOutside( sal_False ) , m_bFromManifest( sal_False ) +, m_bUseWinEncoding( false ) { OSL_ENSURE( m_xFactory.is(), "No factory is provided to ZipPackageStream!\n" ); @@ -138,7 +144,7 @@ void ZipPackageStream::CloseOwnStreamIfAny() } //-------------------------------------------------------------------------- -uno::Reference< io::XInputStream >& ZipPackageStream::GetOwnSeekStream() +uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream() { if ( !m_bHasSeekable && xStream.is() ) { @@ -164,7 +170,7 @@ uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCop if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() ) throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - if ( !xEncryptionData.is() ) + if ( m_xBaseEncryptionData.is() ) throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Encrypted stream without encryption data!\n" ) ), Reference< XInterface >() ); @@ -174,8 +180,8 @@ uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCop Reference< XInterface >() ); // skip header - xSeek->seek( n_ConstHeaderSize + xEncryptionData->aInitVector.getLength() + - xEncryptionData->aSalt.getLength() + xEncryptionData->aDigest.getLength() ); + xSeek->seek( n_ConstHeaderSize + getInitialisationVector().getLength() + + getSalt().getLength() + getDigest().getLength() ); // create temporary stream uno::Reference < io::XOutputStream > xTempOut( @@ -195,6 +201,85 @@ uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCop } //-------------------------------------------------------------------------- +sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const +{ + return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID(); +} + +//-------------------------------------------------------------------------- +sal_Int32 ZipPackageStream::GetBlockSize() const +{ + return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8; +} + +//-------------------------------------------------------------------------- +::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding ) +{ + ::rtl::Reference< EncryptionData > xResult; + if ( m_xBaseEncryptionData.is() ) + xResult = new EncryptionData( + *m_xBaseEncryptionData, + GetEncryptionKey( bUseWinEncoding ), + GetEncryptionAlgorithm(), + m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : rZipPackage.GetChecksumAlgID(), + m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : rZipPackage.GetDefaultDerivedKeySize(), + GetStartKeyGenID() ); + + return xResult; +} + +//-------------------------------------------------------------------------- +void ZipPackageStream::SetBaseEncryptionData( const ::rtl::Reference< BaseEncryptionData >& xData ) +{ + m_xBaseEncryptionData = xData; +} + +//-------------------------------------------------------------------------- +uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding ) +{ + uno::Sequence< sal_Int8 > aResult; + sal_Int32 nKeyGenID = GetStartKeyGenID(); + bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding ); + + if ( bHaveOwnKey && m_aStorageEncryptionKeys.getLength() ) + { + ::rtl::OUString aNameToFind; + if ( nKeyGenID == xml::crypto::DigestID::SHA256 ) + aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; + else if ( nKeyGenID == xml::crypto::DigestID::SHA1 ) + { + aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8; + } + else + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); + + for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ ) + if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) ) + m_aStorageEncryptionKeys[nInd].Value >>= aResult; + + // empty keys are not allowed here + // so it is not important whether there is no key, or the key is empty, it is an error + if ( !aResult.getLength() ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); + } + else + aResult = m_aEncryptionKey; + + if ( !aResult.getLength() || !bHaveOwnKey ) + aResult = rZipPackage.GetEncryptionKey(); + + return aResult; +} + +//-------------------------------------------------------------------------- +sal_Int32 ZipPackageStream::GetStartKeyGenID() +{ + // generally should all the streams use the same Start Key + // but if raw copy without password takes place, we should preserve the imported algorithm + return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : rZipPackage.GetStartKeyGenID(); +} + +//-------------------------------------------------------------------------- Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr ) { if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || (bAddHeaderForEncr && !bToBeEncrypted) ) @@ -204,8 +289,7 @@ Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_B if ( bToBeEncrypted ) { - aKey = ( !xEncryptionData.is() || !bHaveOwnKey ) ? rZipPackage.getEncryptionKey() : - xEncryptionData->aKey; + aKey = GetEncryptionKey(); if ( !aKey.getLength() ) throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } @@ -246,7 +330,7 @@ Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_B xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), makeAny( bToBeCompressed ) ); if ( bToBeEncrypted ) { - xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionKey" ) ), makeAny( aKey ) ); + xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ), makeAny( aKey ) ); xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ), makeAny( sal_True ) ); } @@ -317,7 +401,7 @@ sal_Bool ZipPackageStream::ParsePackageRawStream() sal_Bool bOk = sal_False; - rtl::Reference < EncryptionData > xTempEncrData; + rtl::Reference < BaseEncryptionData > xTempEncrData; sal_Int32 nMagHackSize = 0; Sequence < sal_Int8 > aHeader ( 4 ); @@ -333,17 +417,25 @@ sal_Bool ZipPackageStream::ParsePackageRawStream() if ( nHeader == n_ConstHeader ) { // this is one of our god-awful, but extremely devious hacks, everyone cheer - xTempEncrData = new EncryptionData; + xTempEncrData = new BaseEncryptionData; ::rtl::OUString aMediaType; - if ( ZipFile::StaticFillData ( xTempEncrData, nMagHackSize, aMediaType, GetOwnSeekStream() ) ) + sal_Int32 nEncAlgorithm = 0; + sal_Int32 nChecksumAlgorithm = 0; + sal_Int32 nDerivedKeySize = 0; + sal_Int32 nStartKeyGenID = 0; + if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) ) { // We'll want to skip the data we've just read, so calculate how much we just read // and remember it - m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->aSalt.getLength() - + xTempEncrData->aInitVector.getLength() - + xTempEncrData->aDigest.getLength() + m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength() + + xTempEncrData->m_aInitVector.getLength() + + xTempEncrData->m_aDigest.getLength() + aMediaType.getLength() * sizeof( sal_Unicode ); + m_nImportedEncryptionAlgorithm = nEncAlgorithm; + m_nImportedChecksumAlgorithm = nChecksumAlgorithm; + m_nImportedDerivedKeySize = nDerivedKeySize; + m_nImportedStartKeyAlgorithm = nStartKeyGenID; m_nMagicalHackSize = nMagHackSize; sMediaType = aMediaType; @@ -362,7 +454,7 @@ sal_Bool ZipPackageStream::ParsePackageRawStream() return sal_False; } - xEncryptionData = xTempEncrData; + m_xBaseEncryptionData = xTempEncrData; SetIsEncrypted ( sal_True ); // it's already compressed and encrypted bToBeEncrypted = bToBeCompressed = sal_False; @@ -385,10 +477,11 @@ void ZipPackageStream::SetPackageMember( sal_Bool bNewValue ) // XActiveDataSink //-------------------------------------------------------------------------- void SAL_CALL ZipPackageStream::setInputStream( const Reference< io::XInputStream >& aStream ) - throw(RuntimeException) + throw( RuntimeException ) { // if seekable access is required the wrapping will be done on demand xStream = aStream; + m_nImportedEncryptionAlgorithm = 0; m_bHasSeekable = sal_False; SetPackageMember ( sal_False ); aEntry.nTime = -1; @@ -397,15 +490,13 @@ void SAL_CALL ZipPackageStream::setInputStream( const Reference< io::XInputStrea //-------------------------------------------------------------------------- Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData() - throw(RuntimeException) + throw( RuntimeException ) { try { if (IsPackageMember()) { - if ( xEncryptionData.is() && !bHaveOwnKey ) - xEncryptionData->aKey = rZipPackage.getEncryptionKey(); - return rZipPackage.getZipFile().getRawData( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() ); } else if ( GetOwnSeekStream().is() ) { @@ -434,9 +525,7 @@ Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream( ) { if (IsPackageMember()) { - if ( xEncryptionData.is() && !bHaveOwnKey ) - xEncryptionData->aKey = rZipPackage.getEncryptionKey(); - return rZipPackage.getZipFile().getInputStream( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() ); } else if ( GetOwnSeekStream().is() ) { @@ -459,7 +548,7 @@ Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream( ) // XDataSinkEncrSupport //-------------------------------------------------------------------------- -Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream() +uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream() throw ( packages::WrongPasswordException, io::IOException, RuntimeException ) @@ -472,18 +561,28 @@ Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream() if ( m_nStreamMode == PACKAGE_STREAM_DETECT ) throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - if ( xEncryptionData.is() && !bHaveOwnKey ) - xEncryptionData->aKey = rZipPackage.getEncryptionKey(); - if (IsPackageMember()) { - if ( xEncryptionData.is() && !bHaveOwnKey ) - xEncryptionData->aKey = rZipPackage.getEncryptionKey(); - - return rZipPackage.getZipFile().getDataStream( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + uno::Reference< io::XInputStream > xResult; + try + { + xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + } + catch( packages::WrongPasswordException& ) + { + // workaround for the encrypted documents generated with the old OOo1.x bug. + if ( rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 && !m_bUseWinEncoding ) + { + xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + m_bUseWinEncoding = true; + } + else + throw; + } + return xResult; } else if ( m_nStreamMode == PACKAGE_STREAM_RAW ) - return ZipFile::StaticGetDataFromRawStream( GetOwnSeekStream(), xEncryptionData ); + return ZipFile::StaticGetDataFromRawStream( m_xFactory, GetOwnSeekStream(), GetEncryptionData() ); else if ( GetOwnSeekStream().is() ) { return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ); @@ -508,10 +607,10 @@ Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream() if (IsPackageMember()) { - if ( !bIsEncrypted || !xEncryptionData.is() ) + if ( !bIsEncrypted || !GetEncryptionData().is() ) throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - return rZipPackage.getZipFile().getWrappedRawStream( aEntry, xEncryptionData, sMediaType, rZipPackage.GetSharedMutexRef() ); + return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() ); } else if ( GetOwnSeekStream().is() ) { @@ -528,7 +627,7 @@ Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream() //-------------------------------------------------------------------------- -void SAL_CALL ZipPackageStream::setDataStream( const Reference< io::XInputStream >& aStream ) +void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream ) throw ( io::IOException, RuntimeException ) { @@ -541,7 +640,7 @@ void SAL_CALL ZipPackageStream::setRawStream( const Reference< io::XInputStream throw ( packages::EncryptionNotAllowedException, packages::NoRawFormatException, io::IOException, - RuntimeException) + RuntimeException ) { // wrap the stream in case it is not seekable Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xFactory ); @@ -582,7 +681,7 @@ uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream( if (IsPackageMember()) { - return rZipPackage.getZipFile().getRawData( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() ); + return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() ); } else if ( GetOwnSeekStream().is() ) { @@ -660,8 +759,8 @@ void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, 2 ); bToBeEncrypted = bEnc; - if ( bToBeEncrypted && !xEncryptionData.is()) - xEncryptionData = new EncryptionData; + if ( bToBeEncrypted && !m_xBaseEncryptionData.is()) + m_xBaseEncryptionData = new BaseEncryptionData; } else throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Encrypted property!\n" ) ), @@ -669,7 +768,7 @@ void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, 2 ); } - else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EncryptionKey") ) ) + else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) ) { if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE ) throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); @@ -685,8 +784,8 @@ void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, Sequence < sal_Int8 > aSequence ( nPathLength ); sal_Int8 *pArray = aSequence.getArray(); const sal_Unicode *pChar = sTempString.getStr(); - for ( sal_Int16 i = 0; i < nPathLength; i++) - pArray[i] = static_cast < const sal_Int8 > (pChar[i]); + for ( sal_Int16 i = 0; i < nPathLength; i++ ) + pArray[i] = static_cast < const sal_Int8 > ( pChar[i] ); aNewKey = aSequence; } else @@ -697,19 +796,57 @@ void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, if ( aNewKey.getLength() ) { - if ( !xEncryptionData.is()) - xEncryptionData = new EncryptionData; + if ( !m_xBaseEncryptionData.is() ) + m_xBaseEncryptionData = new BaseEncryptionData; - xEncryptionData->aKey = aNewKey; + m_aEncryptionKey = aNewKey; // In case of new raw stream, the stream must not be encrypted on storing bHaveOwnKey = sal_True; if ( m_nStreamMode != PACKAGE_STREAM_RAW ) bToBeEncrypted = sal_True; } else + { bHaveOwnKey = sal_False; + m_aEncryptionKey.realloc( 0 ); } - else if (aPropertyName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) ) + + m_aStorageEncryptionKeys.realloc( 0 ); + } + else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) + { + if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE ) + throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); + + uno::Sequence< beans::NamedValue > aKeys; + if ( !( aValue >>= aKeys ) ) + { + throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n" ) ), + uno::Reference< XInterface >(), + 2 ); + } + + if ( aKeys.getLength() ) + { + if ( !m_xBaseEncryptionData.is() ) + m_xBaseEncryptionData = new BaseEncryptionData; + + m_aStorageEncryptionKeys = aKeys; + + // In case of new raw stream, the stream must not be encrypted on storing + bHaveOwnKey = sal_True; + if ( m_nStreamMode != PACKAGE_STREAM_RAW ) + bToBeEncrypted = sal_True; + } + else + { + bHaveOwnKey = sal_False; + m_aStorageEncryptionKeys.realloc( 0 ); + } + + m_aEncryptionKey.realloc( 0 ); + } + else if ( aPropertyName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) ) { sal_Bool bCompr = sal_False; @@ -763,9 +900,14 @@ Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName ) aAny <<= bToBeCompressed; return aAny; } - else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionKey" ) ) ) + else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) ) + { + aAny <<= m_aEncryptionKey; + return aAny; + } + else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) { - aAny <<= !xEncryptionData.is() ? Sequence < sal_Int8 > () : xEncryptionData->aKey; + aAny <<= m_aStorageEncryptionKeys; return aAny; } else diff --git a/package/source/zippackage/zipfileaccess.cxx b/package/source/zippackage/zipfileaccess.cxx index d0dc59f07..60b148a8c 100644 --- a/package/source/zippackage/zipfileaccess.cxx +++ b/package/source/zippackage/zipfileaccess.cxx @@ -41,6 +41,7 @@ #include <EncryptionData.hxx> #include <ucbhelper/content.hxx> +#include <rtl/ref.hxx> #include <memory> @@ -252,7 +253,7 @@ uno::Any SAL_CALL OZipFileAccess::getByName( const ::rtl::OUString& aName ) throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second, - new EncryptionData(), + ::rtl::Reference< EncryptionData >(), sal_False, m_aMutexHolder ) ); @@ -367,7 +368,7 @@ uno::Reference< io::XInputStream > SAL_CALL OZipFileAccess::getStreamByPattern( if ( StringGoodForPattern_Impl( (*aIter).second.sPath, aPattern ) ) { uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second, - new EncryptionData(), + ::rtl::Reference< EncryptionData >(), sal_False, m_aMutexHolder ) ); diff --git a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx index b90052a10..4e0ad633b 100644 --- a/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx +++ b/xmlsecurity/inc/xmlsecurity/digitalsignaturesdialog.hxx @@ -134,7 +134,7 @@ public: ~DigitalSignaturesDialog(); // Initialize the dialog and the security environment, returns sal_True on success - sal_Bool Init( const rtl::OUString& rTokenName ); + sal_Bool Init(); // Set the storage which should be signed or verified void SetStorage( const cssu::Reference < css::embed::XStorage >& rxStore ); diff --git a/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx index 7401f23a7..eae0ce8f1 100644 --- a/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsecurity/xmlsignaturehelper.hxx @@ -133,10 +133,9 @@ public: XMLSignatureHelper(const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& mrCtx ); ~XMLSignatureHelper(); - // Initialize the security context with given crypto token. - // Empty string means default crypto token. + // Initialize the security context with default crypto token. // Returns true for success. - bool Init( const rtl::OUString& rTokenPath ); + bool Init(); // Set UriBinding to create input streams to open files. // Default implementation is capable to open files from disk. diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index 803288368..f53acb4f5 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -221,7 +221,7 @@ sal_Bool DocumentDigitalSignatures::ImplViewSignatures( sal_Bool bChanges = sal_False; DigitalSignaturesDialog aSignaturesDialog( NULL, mxCtx, eMode, bReadOnly, m_sODFVersion, m_bHasDocumentSignature); - bool bInit = aSignaturesDialog.Init( rtl::OUString() ); + bool bInit = aSignaturesDialog.Init(); DBG_ASSERT( bInit, "Error initializing security context!" ); if ( bInit ) { @@ -277,7 +277,7 @@ DocumentDigitalSignatures::ImplVerifySignatures( XMLSignatureHelper aSignatureHelper( mxCtx ); - bool bInit = aSignatureHelper.Init( rtl::OUString() ); + bool bInit = aSignatureHelper.Init(); DBG_ASSERT( bInit, "Error initializing security context!" ); @@ -380,7 +380,7 @@ void DocumentDigitalSignatures::manageTrustedSources( ) throw (RuntimeException Reference< dcss::xml::crypto::XSecurityEnvironment > xSecEnv; XMLSignatureHelper aSignatureHelper( mxCtx ); - if ( aSignatureHelper.Init( rtl::OUString() ) ) + if ( aSignatureHelper.Init() ) xSecEnv = aSignatureHelper.GetSecurityEnvironment(); MacroSecurity aDlg( NULL, mxCtx, xSecEnv ); @@ -392,7 +392,7 @@ void DocumentDigitalSignatures::showCertificate( { XMLSignatureHelper aSignatureHelper( mxCtx ); - bool bInit = aSignatureHelper.Init( rtl::OUString() ); + bool bInit = aSignatureHelper.Init(); DBG_ASSERT( bInit, "Error initializing security context!" ); diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index 8a45f411e..17ab79ca4 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -259,9 +259,9 @@ DigitalSignaturesDialog::~DigitalSignaturesDialog() { } -sal_Bool DigitalSignaturesDialog::Init( const rtl::OUString& rTokenName ) +sal_Bool DigitalSignaturesDialog::Init() { - bool bInit = maSignatureHelper.Init( rTokenName ); + bool bInit = maSignatureHelper.Init(); DBG_ASSERT( bInit, "Error initializing security context!" ); diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index 7673bd257..0959e1143 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -70,11 +70,9 @@ XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentCon XMLSignatureHelper::~XMLSignatureHelper() { - if ( mxSEInitializer.is() && mxSecurityContext.is() ) - mxSEInitializer->freeSecurityContext( mxSecurityContext ); } -bool XMLSignatureHelper::Init( const rtl::OUString& rTokenPath ) +bool XMLSignatureHelper::Init() { DBG_ASSERT( !mxSEInitializer.is(), "XMLSignatureHelper::Init - mxSEInitializer already set!" ); DBG_ASSERT( !mxSecurityContext.is(), "XMLSignatureHelper::Init - mxSecurityContext already set!" ); @@ -82,7 +80,7 @@ bool XMLSignatureHelper::Init( const rtl::OUString& rTokenPath ) ImplCreateSEInitializer(); if ( mxSEInitializer.is() ) - mxSecurityContext = mxSEInitializer->createSecurityContext( rTokenPath ); + mxSecurityContext = mxSEInitializer->createSecurityContext( ::rtl::OUString() ); return mxSecurityContext.is(); } diff --git a/xmlsecurity/source/xmlsec/makefile.mk b/xmlsecurity/source/xmlsec/makefile.mk index 44b668b84..36b30f4f2 100644 --- a/xmlsecurity/source/xmlsec/makefile.mk +++ b/xmlsecurity/source/xmlsec/makefile.mk @@ -49,11 +49,11 @@ CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) .ENDIF .IF "$(CRYPTO_ENGINE)" == "mscrypto" -CDEFS += -DXMLSEC_CRYPTO_MSCRYPTO -DXMLSEC_NO_XSLT -.ELSE -CDEFS += -DXMLSEC_CRYPTO_NSS -DXMLSEC_NO_XSLT +CDEFS += -DXMLSEC_CRYPTO_MSCRYPTO .ENDIF +CDEFS += -DXMLSEC_NO_XSLT + # --- Files -------------------------------------------------------- SLOFILES = \ $(SLO)$/biginteger.obj \ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx new file mode 100644 index 000000000..93a17e351 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -0,0 +1,276 @@ + /************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <precompiled_xmlsecurity.hxx> + +#include <osl/time.h> +#include <rtl/random.h> +#include <rtl/ref.hxx> + +#include "ciphercontext.hxx" + +using namespace ::com::sun::star; + +uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ) +{ + ::rtl::Reference< OCipherContext > xResult = new OCipherContext; + + xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, NULL ); + if ( xResult->m_pSlot ) + { + SECItem aKeyItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aKey.getConstArray() ) ), aKey.getLength() }; + xResult->m_pSymKey = PK11_ImportSymKey( xResult->m_pSlot, nNSSCipherID, PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, NULL ); + if ( xResult->m_pSymKey ) + { + SECItem aIVItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aInitializationVector.getConstArray() ) ), aInitializationVector.getLength() }; + xResult->m_pSecParam = PK11_ParamFromIV( nNSSCipherID, &aIVItem ); + if ( xResult->m_pSecParam ) + { + xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam); + if ( xResult->m_pContext ) + { + xResult->m_bEncryption = bEncryption; + xResult->m_bW3CPadding = bW3CPadding; + xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID ); + xResult->m_nBlockSize = PK11_GetBlockSize( nNSSCipherID, xResult->m_pSecParam ); + if ( xResult->m_nBlockSize <= SAL_MAX_INT8 ) + return xResult.get(); + } + } + } + } + + return uno::Reference< xml::crypto::XCipherContext >(); +} + +void OCipherContext::Dispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = NULL; + } + + if ( m_pSecParam ) + { + SECITEM_FreeItem( m_pSecParam, PR_TRUE ); + m_pSecParam = NULL; + } + + if ( m_pSymKey ) + { + PK11_FreeSymKey( m_pSymKey ); + m_pSymKey = NULL; + } + + if ( m_pSlot ) + { + PK11_FreeSlot( m_pSlot ); + m_pSlot = NULL; + } + + m_bDisposed = true; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData ) + throw ( lang::IllegalArgumentException, lang::DisposedException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aToConvert; + if ( aData.getLength() ) + { + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + OSL_ENSURE( nOldLastBlockLen <= m_nBlockSize, "Unexpected last block size!" ); + + sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength(); + sal_Int32 nToConvertLen = nAvailableData; + if ( m_bEncryption || !m_bW3CPadding ) + { + if ( nAvailableData % m_nBlockSize == 0 ) + nToConvertLen = nAvailableData; + else if ( nAvailableData < m_nBlockSize ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize; + } + else + { + // decryption with W3C padding needs at least one block for finalizing + if ( nAvailableData < m_nBlockSize * 2 ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize; + } + + aToConvert.realloc( nToConvertLen ); + if ( nToConvertLen == 0 ) + { + m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() ); + rtl_copyMemory( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() ); + // aToConvert stays empty + } + else if ( nToConvertLen < nOldLastBlockLen ) + { + rtl_copyMemory( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen ); + rtl_copyMemory( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen ); + m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() ); + rtl_copyMemory( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() ); + } + else + { + rtl_copyMemory( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen ); + if ( nToConvertLen > nOldLastBlockLen ) + rtl_copyMemory( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen ); + m_aLastBlock.realloc( nAvailableData - nToConvertLen ); + rtl_copyMemory( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen ); + } + } + + uno::Sequence< sal_Int8 > aResult; + OSL_ENSURE( aToConvert.getLength() % m_nBlockSize == 0, "Unexpected size of the data to encrypt!" ); + if ( aToConvert.getLength() ) + { + int nResultLen = 0; + aResult.realloc( aToConvert.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ) ), aToConvert.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + m_nConverted += aToConvert.getLength(); + aResult.realloc( nResultLen ); + } + + return aResult; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose() + throw (lang::DisposedException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + OSL_ENSURE( m_nBlockSize <= SAL_MAX_INT8, "Unexpected block size!" ); + OSL_ENSURE( m_nConverted % m_nBlockSize == 0, "Unexpected amount of bytes is already converted!" ); + sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize; + + // if it is decryption, the amount of data should be rounded to the block size even in case of padding + if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The data should contain complete blocks only." ) ), uno::Reference< uno::XInterface >() ); + + if ( m_bW3CPadding && m_bEncryption ) + { + // in this case the last block should be smaller than standtard block + // it will be increased with the padding + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize, "Unexpected size of cashed incomplete last block!" ); + + // W3CPadding handling for encryption + sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding; + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize ); + + if ( nPaddingSize > 1 ) + { + TimeValue aTime; + osl_getSystemTime( &aTime ); + rtlRandomPool aRandomPool = rtl_random_createPool(); + rtl_random_addBytes( aRandomPool, &aTime, 8 ); + rtl_random_getBytes( aRandomPool, m_aLastBlock.getArray() + nOldLastBlockLen, nPaddingSize - 1 ); + rtl_random_destroyPool ( aRandomPool ); + } + m_aLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize ); + } + + // finally should the last block be smaller than two standard blocks + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize * 2 , "Unexpected size of cashed incomplete last block!" ); + + uno::Sequence< sal_Int8 > aResult; + if ( m_aLastBlock.getLength() ) + { + int nPrefResLen = 0; + aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ) ), m_aLastBlock.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( nPrefResLen ); + m_aLastBlock.realloc( 0 ); + } + + sal_Int32 nPrefixLen = aResult.getLength(); + aResult.realloc( nPrefixLen + m_nBlockSize * 2 ); + unsigned nFinalLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( nPrefixLen + nFinalLen ); + + if ( m_bW3CPadding && !m_bEncryption ) + { + // W3CPadding handling for decryption + // aResult should have anough data, since we let m_aLastBlock be big enough in case of decryption + OSL_ENSURE( aResult.getLength() >= m_nBlockSize, "Not enough data to handle the padding!" ); + + sal_Int8 nBytesToRemove = aResult[aResult.getLength() - 1]; + if ( nBytesToRemove <= 0 || nBytesToRemove > aResult.getLength() ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( aResult.getLength() - nBytesToRemove ); + } + + Dispose(); + + return aResult; +} + diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx new file mode 100644 index 000000000..1574a6238 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _CIPHERCONTEXT_HXX +#define _CIPHERCONTEXT_HXX + +#include <com/sun/star/xml/crypto/XCipherContext.hpp> + +#include <cppuhelper/implbase1.hxx> +#include <osl/mutex.hxx> +#include <pk11pub.h> + +class OCipherContext : public cppu::WeakImplHelper1< ::com::sun::star::xml::crypto::XCipherContext > +{ +private: + ::osl::Mutex m_aMutex; + + PK11SlotInfo* m_pSlot; + PK11SymKey* m_pSymKey; + SECItem* m_pSecParam; + PK11Context* m_pContext; + + sal_Int32 m_nBlockSize; + ::com::sun::star::uno::Sequence< sal_Int8 > m_aLastBlock; + + bool m_bEncryption; + bool m_bPadding; + bool m_bW3CPadding; + sal_Int64 m_nConverted; + + bool m_bDisposed; + bool m_bBroken; + + void Dispose(); + + OCipherContext() + : m_pSlot( NULL ) + , m_pSymKey( NULL ) + , m_pSecParam( NULL ) + , m_pContext( NULL ) + , m_nBlockSize( 0 ) + , m_bEncryption( false ) + , m_bPadding( false ) + , m_bW3CPadding( false ) + , m_nConverted( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + +public: + + virtual ~OCipherContext() + { + Dispose(); + } + + static ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > Create( CK_MECHANISM_TYPE nNSSCipherID, const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aKey, const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ); + + // XCipherContext + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.cxx b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx new file mode 100644 index 000000000..4b3a0d094 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <precompiled_xmlsecurity.hxx> + +#include <pk11pub.h> +#include "digestcontext.hxx" + +using namespace ::com::sun::star; + +ODigestContext::~ODigestContext() +{ + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = NULL; + } +} + +void SAL_CALL ODigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData ) + throw (lang::DisposedException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_b1KData || m_nDigested < 1024 ) + { + uno::Sequence< sal_Int8 > aToDigest = aData; + if ( m_b1KData && m_nDigested + aData.getLength() > 1024 ) + aToDigest.realloc( 1024 - m_nDigested ); + + if ( PK11_DigestOp( m_pContext, reinterpret_cast< const unsigned char* >( aToDigest.getConstArray() ), aToDigest.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = NULL; + m_bBroken = true; + throw uno::RuntimeException(); + } + + m_nDigested += aToDigest.getLength(); + } +} + +uno::Sequence< ::sal_Int8 > SAL_CALL ODigestContext::finalizeDigestAndDispose() + throw (lang::DisposedException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( m_nDigestLength ); + unsigned int nResultLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = NULL; + m_bBroken = true; + throw uno::RuntimeException(); + } + + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = NULL; + m_bDisposed = true; + + aResult.realloc( nResultLen ); + return aResult; +} + diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.hxx b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx new file mode 100644 index 000000000..8f9ef475a --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DIGESTCONTEXT_HXX +#define _DIGESTCONTEXT_HXX + +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + +#include <cppuhelper/implbase1.hxx> +#include <osl/mutex.hxx> + +class ODigestContext : public cppu::WeakImplHelper1< ::com::sun::star::xml::crypto::XDigestContext > +{ +private: + ::osl::Mutex m_aMutex; + + PK11Context* m_pContext; + sal_Int32 m_nDigestLength; + bool m_b1KData; + sal_Int32 m_nDigested; + + bool m_bDisposed; + bool m_bBroken; + +public: + ODigestContext( PK11Context* pContext, sal_Int32 nDigestLength, bool b1KData ) + : m_pContext( pContext ) + , m_nDigestLength( nDigestLength ) + , m_b1KData( b1KData ) + , m_nDigested( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + + virtual ~ODigestContext(); + + + // XDigestContext + virtual void SAL_CALL updateDigest( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() throw (::com::sun::star::lang::DisposedException, ::com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/xmlsecurity/source/xmlsec/nss/makefile.mk b/xmlsecurity/source/xmlsec/nss/makefile.mk index de6a05957..0875de9aa 100644 --- a/xmlsecurity/source/xmlsec/nss/makefile.mk +++ b/xmlsecurity/source/xmlsec/nss/makefile.mk @@ -41,12 +41,6 @@ ENABLE_EXCEPTIONS = TRUE CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) .ENDIF -.IF "$(CRYPTO_ENGINE)" != "nss" -LIBTARGET=NO -.ENDIF - -.IF "$(CRYPTO_ENGINE)" == "nss" - .IF "$(WITH_MOZILLA)" == "NO" || "$(ENABLE_NSS_MODULE)"!="YES" .IF "$(SYSTEM_MOZILLA)" != "YES" @all: @@ -93,7 +87,11 @@ $(MOZ_INC)$/profile \ -I$(MOZ_INC)$/embed_base .ENDIF -CDEFS += -DXMLSEC_CRYPTO_NSS -DXMLSEC_NO_XSLT +.IF "$(CRYPTO_ENGINE)" == "nss" +CDEFS += -DXMLSEC_CRYPTO_NSS +.ENDIF + +CDEFS += -DXMLSEC_NO_XSLT # --- Files -------------------------------------------------------- @@ -109,13 +107,19 @@ SOLARINC += -I$(NSS_INC) .ENDIF SLOFILES = \ + $(SLO)$/nssinitializer.obj \ + $(SLO)$/digestcontext.obj \ + $(SLO)$/ciphercontext.obj \ + $(SLO)$/xsec_nss.obj + +.IF "$(CRYPTO_ENGINE)" == "nss" +SLOFILES += \ $(SLO)$/securityenvironment_nssimpl.obj \ $(SLO)$/xmlencryption_nssimpl.obj \ $(SLO)$/xmlsecuritycontext_nssimpl.obj \ $(SLO)$/xmlsignature_nssimpl.obj \ $(SLO)$/x509certificate_nssimpl.obj \ $(SLO)$/seinitializer_nssimpl.obj \ - $(SLO)$/xsec_nss.obj \ $(SLO)$/secerror.obj diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx new file mode 100644 index 000000000..ded32952d --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -0,0 +1,521 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +/* + * Turn off DEBUG Assertions + */ +#ifdef _DEBUG + #define _DEBUG_WAS_DEFINED _DEBUG + #undef _DEBUG +#else + #undef _DEBUG_WAS_DEFINED +#endif + +/* + * and turn off the additional virtual methods which are part of some interfaces when compiled + * with debug + */ +#ifdef DEBUG + #define DEBUG_WAS_DEFINED DEBUG + #undef DEBUG +#else + #undef DEBUG_WAS_DEFINED +#endif + + +#include <com/sun/star/mozilla/XMozillaBootstrap.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> + +#include <sal/types.h> +#include <rtl/instance.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <tools/debug.hxx> +#include <rtl/logfile.hxx> + +#include "seinitializer_nssimpl.hxx" +#include "../diagnose.hxx" + +#include "securityenvironment_nssimpl.hxx" +#include "digestcontext.hxx" +#include "ciphercontext.hxx" + +#include <nspr.h> +#include <cert.h> +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <nssckbi.h> + + +namespace css = ::com::sun::star; +namespace cssu = css::uno; +namespace cssl = css::lang; +namespace cssxc = css::xml::crypto; + +using namespace xmlsecurity; +using namespace com::sun::star; +using ::rtl::OUString; +using ::rtl::OString; + +#define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.NSSInitializer_NssImpl" + +#define ROOT_CERTS "Root Certs for OpenOffice.org" + +extern "C" void nsscrypto_finalize(); + + +namespace +{ + +bool nsscrypto_initialize( const css::uno::Reference< css::lang::XMultiServiceFactory > &xMSF, bool & out_nss_init ); + +struct InitNSSInitialize +{ + css::uno::Reference< css::lang::XMultiServiceFactory > mxMSF; + + InitNSSInitialize( const css::uno::Reference< css::lang::XMultiServiceFactory > &xMSF ) + : mxMSF( xMSF ) + { + } + + bool * operator()() + { + static bool bInitialized = false; + bool bNSSInit = false; + bInitialized = nsscrypto_initialize( mxMSF, bNSSInit ); + if (bNSSInit) + atexit(nsscrypto_finalize ); + return & bInitialized; + } +}; + +struct GetNSSInitStaticMutex +{ + ::osl::Mutex* operator()() + { + static ::osl::Mutex aNSSInitMutex; + return &aNSSInitMutex; + } +}; + +void deleteRootsModule() +{ + SECMODModule *RootsModule = 0; + SECMODModuleList *list = SECMOD_GetDefaultModuleList(); + SECMODListLock *lock = SECMOD_GetDefaultModuleListLock(); + SECMOD_GetReadLock(lock); + + while (!RootsModule && list) + { + SECMODModule *module = list->module; + + for (int i=0; i < module->slotCount; i++) + { + PK11SlotInfo *slot = module->slots[i]; + if (PK11_IsPresent(slot)) + { + if (PK11_HasRootCerts(slot)) + { + xmlsec_trace("The root certifificates module \"%s" + "\" is already loaded: \n%s", + module->commonName, module->dllName); + + RootsModule = SECMOD_ReferenceModule(module); + break; + } + } + } + list = list->next; + } + SECMOD_ReleaseReadLock(lock); + + if (RootsModule) + { + PRInt32 modType; + if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType)) + { + xmlsec_trace("Deleted module \"%s\".", RootsModule->commonName); + } + else + { + xmlsec_trace("Failed to delete \"%s\" : \n%s", + RootsModule->commonName, RootsModule->dllName); + } + SECMOD_DestroyModule(RootsModule); + RootsModule = 0; + } +} + +::rtl::OString getMozillaCurrentProfile( const css::uno::Reference< css::lang::XMultiServiceFactory > &rxMSF ) +{ + ::rtl::OString sResult; + // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER" + char* pEnv = getenv( "MOZILLA_CERTIFICATE_FOLDER" ); + if ( pEnv ) + { + sResult = ::rtl::OString( pEnv ); + RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using env MOZILLA_CERTIFICATE_FOLDER: %s", sResult.getStr() ); + } + else + { + mozilla::MozillaProductType productTypes[4] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Mozilla, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Default }; + int nProduct = 4; + + uno::Reference<uno::XInterface> xInstance = rxMSF->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.mozilla.MozillaBootstrap")) ); + OSL_ENSURE( xInstance.is(), "failed to create instance" ); + + uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap + = uno::Reference<mozilla::XMozillaBootstrap>(xInstance,uno::UNO_QUERY); + OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" ); + + if (xMozillaBootstrap.is()) + { + for (int i=0; i<nProduct; i++) + { + ::rtl::OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]); + + if (profile != NULL && profile.getLength()>0) + { + ::rtl::OUString sProfilePath = xMozillaBootstrap->getProfilePath( productTypes[i], profile ); + sResult = ::rtl::OUStringToOString( sProfilePath, osl_getThreadTextEncoding() ); + RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using Mozilla Profile: %s", sResult.getStr() ); + } + } + } + + RTL_LOGFILE_PRODUCT_TRACE( "XMLSEC: No Mozilla Profile found!" ); + } + + return sResult; +} + +//Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write +//the roots certificate module (libnssckbi.so), which they use, into the +//profile. This module will then already be loaded during NSS_Init (and the +//other init functions). This fails in two cases. First, FF3 was used to create +//the profile, or possibly used that profile before, and second the profile was +//used on a different platform. +// +//Then one needs to add the roots module oneself. This should be done with +//SECMOD_LoadUserModule rather then SECMOD_AddNewModule. The latter would write +//the location of the roots module to the profile, which makes FF2 and TB2 use +//it instead of there own module. +// +//When using SYSTEM_MOZILLA then the libnss3.so lib is typically found in +///usr/lib. This folder may, however, NOT contain the roots certificate +//module. That is, just providing the library name in SECMOD_LoadUserModule or +//SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH +//contains an FF or TB installation. +//ATTENTION: DO NOT call this function directly instead use initNSS +//return true - whole initialization was successful +//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite +//was successful and therefor NSS_Shutdown should be called when terminating. +bool nsscrypto_initialize( const css::uno::Reference< css::lang::XMultiServiceFactory > &xMSF, bool & out_nss_init ) +{ + bool return_value = true; + + // this method must be called only once, no need for additional lock + rtl::OString sCertDir; + + (void) xMSF; +#ifdef XMLSEC_CRYPTO_NSS + if ( xMSF.is() ) + sCertDir = getMozillaCurrentProfile( xMSF ); +#endif + xmlsec_trace( "Using profile: %s", sCertDir.getStr() ); + + PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ; + + // there might be no profile + if ( sCertDir.getLength() > 0 ) + { + if( NSS_InitReadWrite( sCertDir.getStr() ) != SECSuccess ) + { + xmlsec_trace("Initializing NSS with profile failed."); + char * error = NULL; + + PR_GetErrorText(error); + if (error) + xmlsec_trace("%s",error); + return false ; + } + } + else + { + xmlsec_trace("Initializing NSS without profile."); + if ( NSS_NoDB_Init(NULL) != SECSuccess ) + { + xmlsec_trace("Initializing NSS without profile failed."); + char * error = NULL; + PR_GetErrorText(error); + if (error) + xmlsec_trace("%s",error); + return false ; + } + } + out_nss_init = true; + +#ifdef XMLSEC_CRYPTO_NSS +#if defined SYSTEM_MOZILLA + if (!SECMOD_HasRootCerts()) + { +#endif + deleteRootsModule(); + +#if defined SYSTEM_MOZILLA + OUString rootModule(RTL_CONSTASCII_USTRINGPARAM("libnssckbi"SAL_DLLEXTENSION)); +#else + OUString rootModule(RTL_CONSTASCII_USTRINGPARAM("${OOO_BASE_DIR}/program/libnssckbi"SAL_DLLEXTENSION)); +#endif + ::rtl::Bootstrap::expandMacros(rootModule); + + OUString rootModulePath; + if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath)) + { + ::rtl::OString ospath = ::rtl::OUStringToOString(rootModulePath, osl_getThreadTextEncoding()); + ::rtl::OStringBuffer pkcs11moduleSpec; + pkcs11moduleSpec.append("name=\""); + pkcs11moduleSpec.append(ROOT_CERTS); + pkcs11moduleSpec.append("\" library=\""); + pkcs11moduleSpec.append(ospath.getStr()); + pkcs11moduleSpec.append("\""); + + SECMODModule * RootsModule = + SECMOD_LoadUserModule( + const_cast<char*>(pkcs11moduleSpec.makeStringAndClear().getStr()), + 0, // no parent + PR_FALSE); // do not recurse + + if (RootsModule) + { + + bool found = RootsModule->loaded; + + SECMOD_DestroyModule(RootsModule); + RootsModule = 0; + if (found) + xmlsec_trace("Added new root certificate module " + "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); + else + { + xmlsec_trace("FAILED to load the new root certificate module " + "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); + return_value = false; + } + } + else + { + xmlsec_trace("FAILED to add new root certifice module: " + "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); + return_value = false; + + } + } + else + { + xmlsec_trace("Adding new root certificate module failed."); + return_value = false; + } +#if SYSTEM_MOZILLA + } +#endif +#endif + + return return_value; +} + + +// must be extern "C" because we pass the function pointer to atexit +extern "C" void nsscrypto_finalize() +{ + SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS); + + if (RootsModule) + { + + if (SECSuccess == SECMOD_UnloadUserModule(RootsModule)) + { + xmlsec_trace("Unloaded module \""ROOT_CERTS"\"."); + } + else + { + xmlsec_trace("Failed unloadeding module \""ROOT_CERTS"\"."); + } + SECMOD_DestroyModule(RootsModule); + } + else + { + xmlsec_trace("Unloading module \""ROOT_CERTS + "\" failed because it was not found."); + } + PK11_LogoutAll(); + NSS_Shutdown(); +} +} // namespace + +ONSSInitializer::ONSSInitializer( + const css::uno::Reference< css::lang::XMultiServiceFactory > &rxMSF) + :mxMSF( rxMSF ) +{ +} + +ONSSInitializer::~ONSSInitializer() +{ +} + +bool ONSSInitializer::initNSS( const css::uno::Reference< css::lang::XMultiServiceFactory > &xMSF ) +{ + return *rtl_Instance< bool, InitNSSInitialize, ::osl::MutexGuard, GetNSSInitStaticMutex > + ::create( InitNSSInitialize( xMSF ), GetNSSInitStaticMutex() ); +} + +css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) + throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) +{ + SECOidTag nNSSDigestID = SEC_OID_UNKNOWN; + sal_Int32 nDigestLength = 0; + bool b1KData = false; + if ( nDigestID == css::xml::crypto::DigestID::SHA256 + || nDigestID == css::xml::crypto::DigestID::SHA256_1K ) + { + nNSSDigestID = SEC_OID_SHA256; + nDigestLength = 32; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA1 + || nDigestID == css::xml::crypto::DigestID::SHA1_1K ) + { + nNSSDigestID = SEC_OID_SHA1; + nDigestLength = 20; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K ); + } + else + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected digest requested." ) ), css::uno::Reference< css::uno::XInterface >(), 1 ); + + if ( aParams.getLength() ) + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected arguments provided for digest creation." ) ), css::uno::Reference< css::uno::XInterface >(), 2 ); + + css::uno::Reference< css::xml::crypto::XDigestContext > xResult; + if( initNSS( mxMSF ) ) + { + PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID ); + if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess ) + xResult = new ODigestContext( pContext, nDigestLength, b1KData ); + } + + return xResult; +} + +css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, ::sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) + throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) +{ + CK_MECHANISM_TYPE nNSSCipherID = 0; + bool bW3CPadding = false; + if ( nCipherID == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ) + { + nNSSCipherID = CKM_AES_CBC; + bW3CPadding = true; + + if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 ) + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected key length." ) ), css::uno::Reference< css::uno::XInterface >(), 2 ); + + if ( aParams.getLength() ) + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected arguments provided for cipher creation." ) ), css::uno::Reference< css::uno::XInterface >(), 5 ); + } + else + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected cipher requested." ) ), css::uno::Reference< css::uno::XInterface >(), 1 ); + + css::uno::Reference< css::xml::crypto::XCipherContext > xResult; + if( initNSS( mxMSF ) ) + { + if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) ) + throw css::lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected length of initialization vector." ) ), css::uno::Reference< css::uno::XInterface >(), 3 ); + + xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding ); + } + + return xResult; +} + +rtl::OUString ONSSInitializer_getImplementationName () + throw (cssu::RuntimeException) +{ + + return rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) ); +} + +sal_Bool SAL_CALL ONSSInitializer_supportsService( const rtl::OUString& ServiceName ) + throw (cssu::RuntimeException) +{ + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( NSS_SERVICE_NAME )); +} + +cssu::Sequence< rtl::OUString > SAL_CALL ONSSInitializer_getSupportedServiceNames( ) + throw (cssu::RuntimeException) +{ + cssu::Sequence < rtl::OUString > aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( NSS_SERVICE_NAME ) ); + return aRet; +} + +cssu::Reference< cssu::XInterface > SAL_CALL ONSSInitializer_createInstance( const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr) + throw( cssu::Exception ) +{ + return (cppu::OWeakObject*) new ONSSInitializer( rSMgr ); +} + +/* XServiceInfo */ +rtl::OUString SAL_CALL ONSSInitializer::getImplementationName() + throw (cssu::RuntimeException) +{ + return ONSSInitializer_getImplementationName(); +} +sal_Bool SAL_CALL ONSSInitializer::supportsService( const rtl::OUString& rServiceName ) + throw (cssu::RuntimeException) +{ + return ONSSInitializer_supportsService( rServiceName ); +} +cssu::Sequence< rtl::OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( ) + throw (cssu::RuntimeException) +{ + return ONSSInitializer_getSupportedServiceNames(); +} + diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx new file mode 100644 index 000000000..6e7fed190 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _NSSINITIALIZER_HXX +#define _NSSINITIALIZER_HXX + +#include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp> +#include <com/sun/star/xml/crypto/XCipherContextSupplier.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <cppuhelper/implbase3.hxx> + +#define NSS_SERVICE_NAME "com.sun.star.xml.crypto.NSSInitializer" + +class ONSSInitializer : public cppu::WeakImplHelper3 +< + ::com::sun::star::xml::crypto::XDigestContextSupplier, + ::com::sun::star::xml::crypto::XCipherContextSupplier, + ::com::sun::star::lang::XServiceInfo +> +{ +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + + ONSSInitializer() + {} + +public: + ONSSInitializer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF ); + virtual ~ONSSInitializer(); + + bool initNSS( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &xMSF ); + + /* XDigestContextSupplier */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > SAL_CALL getDigestContext( ::sal_Int32 nDigestID, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aParams ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + /* XCipherContextSupplier */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > SAL_CALL getCipherContext( ::sal_Int32 nCipherID, const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aKey, const ::com::sun::star::uno::Sequence< ::sal_Int8 >& aInitializationVector, ::sal_Bool bEncryption, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aParams ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + /* XServiceInfo */ + virtual rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); +}; + +rtl::OUString ONSSInitializer_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL ONSSInitializer_supportsService( const rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL ONSSInitializer_getSupportedServiceNames() + throw ( ::com::sun::star::uno::RuntimeException ); + +com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL ONSSInitializer_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr ) + throw ( ::com::sun::star::uno::Exception ); + +#endif + diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx index f18460033..c1573e814 100644 --- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -89,7 +89,29 @@ extern X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* ) ; struct UsageDescription { SECCertificateUsage usage; - char const * const description; + char const * description; + + UsageDescription() + : usage( certificateUsageCheckAllUsages ) + , description( NULL ) + {} + + UsageDescription( SECCertificateUsage i_usage, char const* i_description ) + : usage( i_usage ) + , description( i_description ) + {} + + UsageDescription( const UsageDescription& aDescription ) + : usage( aDescription.usage ) + , description( aDescription.description ) + {} + + UsageDescription& operator =( const UsageDescription& aDescription ) + { + usage = aDescription.usage; + description = aDescription.description; + return *this; + } }; @@ -868,14 +890,12 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert, // certificateUsageAnyCA // certificateUsageProtectedObjectSigner - UsageDescription arUsages[] = - { - {certificateUsageSSLClient, "certificateUsageSSLClient" }, - {certificateUsageSSLServer, "certificateUsageSSLServer" }, - {certificateUsageSSLCA, "certificateUsageSSLCA" }, - {certificateUsageEmailSigner, "certificateUsageEmailSigner"}, //only usable for end certs - {certificateUsageEmailRecipient, "certificateUsageEmailRecipient"} - }; + UsageDescription arUsages[5]; + arUsages[0] = UsageDescription( certificateUsageSSLClient, "certificateUsageSSLClient" ); + arUsages[1] = UsageDescription( certificateUsageSSLServer, "certificateUsageSSLServer" ); + arUsages[2] = UsageDescription( certificateUsageSSLCA, "certificateUsageSSLCA" ); + arUsages[3] = UsageDescription( certificateUsageEmailSigner, "certificateUsageEmailSigner" ); + arUsages[4] = UsageDescription( certificateUsageEmailRecipient, "certificateUsageEmailRecipient" ); int numUsages = SAL_N_ELEMENTS(arUsages); for (int i = 0; i < numUsages; i++) diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx index b9041e242..18dadf070 100644 --- a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx @@ -52,7 +52,6 @@ #include <sal/types.h> -#include "rtl/instance.hxx" #include "rtl/bootstrap.hxx" #include "rtl/string.hxx" #include "rtl/strbuf.hxx" @@ -62,327 +61,34 @@ #include <rtl/logfile.hxx> #include "seinitializer_nssimpl.hxx" -#include "../diagnose.hxx" - #include "securityenvironment_nssimpl.hxx" -#include <com/sun/star/mozilla/XMozillaBootstrap.hpp> -#include "nspr.h" -#include "cert.h" -#include "nss.h" -#include "secmod.h" -#include "nssckbi.h" +#include <nspr.h> +#include <cert.h> +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <nssckbi.h> -namespace cssu = com::sun::star::uno; -namespace cssl = com::sun::star::lang; -namespace cssxc = com::sun::star::xml::crypto; +namespace css = ::com::sun::star; +namespace cssu = css::uno; +namespace cssl = css::lang; +namespace cssxc = css::xml::crypto; -using namespace xmlsecurity; using namespace com::sun::star; using ::rtl::OUString; using ::rtl::OString; -#define SERVICE_NAME "com.sun.star.xml.crypto.SEInitializer" +#define SE_SERVICE_NAME "com.sun.star.xml.crypto.SEInitializer" #define IMPLEMENTATION_NAME "com.sun.star.xml.security.bridge.xmlsec.SEInitializer_NssImpl" #define SECURITY_ENVIRONMENT "com.sun.star.xml.crypto.SecurityEnvironment" #define SECURITY_CONTEXT "com.sun.star.xml.crypto.XMLSecurityContext" - -#define ROOT_CERTS "Root Certs for OpenOffice.org" - - -extern "C" void nsscrypto_finalize(); - - -namespace -{ - -bool nsscrypto_initialize( const char * sProfile, bool & out_nss_init); - -struct InitNSSInitialize -{ - //path to the database folder - const OString m_sProfile; - InitNSSInitialize(const OString & sProfile): m_sProfile(sProfile) {}; - bool * operator()() - { - static bool bInitialized = false; - bool bNSSInit = false; - bInitialized = nsscrypto_initialize(m_sProfile.getStr(), bNSSInit); - if (bNSSInit) - atexit(nsscrypto_finalize ); - return & bInitialized; - - } -}; - -bool * initNSS(const OString & sProfile) -{ - return rtl_Instance< bool, InitNSSInitialize, - ::osl::MutexGuard, ::osl::GetGlobalMutex >::create( - InitNSSInitialize(sProfile), ::osl::GetGlobalMutex()); -} - -void deleteRootsModule() -{ - SECMODModule *RootsModule = 0; - SECMODModuleList *list = SECMOD_GetDefaultModuleList(); - SECMODListLock *lock = SECMOD_GetDefaultModuleListLock(); - SECMOD_GetReadLock(lock); - - while (!RootsModule && list) - { - SECMODModule *module = list->module; - - for (int i=0; i < module->slotCount; i++) - { - PK11SlotInfo *slot = module->slots[i]; - if (PK11_IsPresent(slot)) - { - if (PK11_HasRootCerts(slot)) - { - xmlsec_trace("The root certifificates module \"%s" - "\" is already loaded: \n%s", - module->commonName, module->dllName); - - RootsModule = SECMOD_ReferenceModule(module); - break; - } - } - } - list = list->next; - } - SECMOD_ReleaseReadLock(lock); - - if (RootsModule) - { - PRInt32 modType; - if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType)) - { - xmlsec_trace("Deleted module \"%s\".", RootsModule->commonName); - } - else - { - xmlsec_trace("Failed to delete \"%s\" : \n%s", - RootsModule->commonName, RootsModule->dllName); - } - SECMOD_DestroyModule(RootsModule); - RootsModule = 0; - } -} - -//Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write -//the roots certificate module (libnssckbi.so), which they use, into the -//profile. This module will then already be loaded during NSS_Init (and the -//other init functions). This fails in two cases. First, FF3 was used to create -//the profile, or possibly used that profile before, and second the profile was -//used on a different platform. -// -//Then one needs to add the roots module oneself. This should be done with -//SECMOD_LoadUserModule rather then SECMOD_AddNewModule. The latter would write -//the location of the roots module to the profile, which makes FF2 and TB2 use -//it instead of there own module. -// -//When using SYSTEM_MOZILLA then the libnss3.so lib is typically found in -///usr/lib. This folder may, however, NOT contain the roots certificate -//module. That is, just providing the library name in SECMOD_LoadUserModule or -//SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH -//contains an FF or TB installation. -//ATTENTION: DO NOT call this function directly instead use initNSS -//return true - whole initialization was successful -//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite -//was successful and therefor NSS_Shutdown should be called when terminating. -bool nsscrypto_initialize( const char* token, bool & out_nss_init ) -{ - bool return_value = true; - - xmlsec_trace("Using profile: %s", token); - - PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ; - - //token may be an empty string - if (token != NULL && strlen(token) > 0) - { - if( NSS_InitReadWrite( token ) != SECSuccess ) - { - xmlsec_trace("Initializing NSS with profile failed."); - char * error = NULL; - - PR_GetErrorText(error); - if (error) - xmlsec_trace("%s",error); - return false ; - } - } - else - { - xmlsec_trace("Initializing NSS without profile."); - if ( NSS_NoDB_Init(NULL) != SECSuccess ) - { - xmlsec_trace("Initializing NSS without profile failed."); - char * error = NULL; - PR_GetErrorText(error); - if (error) - xmlsec_trace("%s",error); - return false ; - } - } - out_nss_init = true; - -#if defined SYSTEM_MOZILLA - if (!SECMOD_HasRootCerts()) - { -#endif - deleteRootsModule(); - -#if defined SYSTEM_MOZILLA - OUString rootModule(RTL_CONSTASCII_USTRINGPARAM("libnssckbi"SAL_DLLEXTENSION)); -#else - OUString rootModule(RTL_CONSTASCII_USTRINGPARAM("${OOO_BASE_DIR}/program/libnssckbi"SAL_DLLEXTENSION)); -#endif - ::rtl::Bootstrap::expandMacros(rootModule); - - OUString rootModulePath; - if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath)) - { - ::rtl::OString ospath = ::rtl::OUStringToOString(rootModulePath, osl_getThreadTextEncoding()); - ::rtl::OStringBuffer pkcs11moduleSpec; - pkcs11moduleSpec.append("name=\""); - pkcs11moduleSpec.append(ROOT_CERTS); - pkcs11moduleSpec.append("\" library=\""); - pkcs11moduleSpec.append(ospath.getStr()); - pkcs11moduleSpec.append("\""); - - SECMODModule * RootsModule = - SECMOD_LoadUserModule( - const_cast<char*>(pkcs11moduleSpec.makeStringAndClear().getStr()), - 0, // no parent - PR_FALSE); // do not recurse - - if (RootsModule) - { - - bool found = RootsModule->loaded; - - SECMOD_DestroyModule(RootsModule); - RootsModule = 0; - if (found) - xmlsec_trace("Added new root certificate module " - "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); - else - { - xmlsec_trace("FAILED to load the new root certificate module " - "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); - return_value = false; - } - } - else - { - xmlsec_trace("FAILED to add new root certifice module: " - "\""ROOT_CERTS"\" contained in \n%s", ospath.getStr()); - return_value = false; - - } - } - else - { - xmlsec_trace("Adding new root certificate module failed."); - return_value = false; - } -#if SYSTEM_MOZILLA - } -#endif - - return return_value; -} - - -// must be extern "C" because we pass the function pointer to atexit -extern "C" void nsscrypto_finalize() -{ - SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS); - - if (RootsModule) - { - - if (SECSuccess == SECMOD_UnloadUserModule(RootsModule)) - { - xmlsec_trace("Unloaded module \""ROOT_CERTS"\"."); - } - else - { - xmlsec_trace("Failed unloadeding module \""ROOT_CERTS"\"."); - } - SECMOD_DestroyModule(RootsModule); - } - else - { - xmlsec_trace("Unloading module \""ROOT_CERTS - "\" failed because it was not found."); - } - PK11_LogoutAll(); - NSS_Shutdown(); -} - - -bool getMozillaCurrentProfile( - const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF, - rtl::OUString& profilePath) -{ - /* - * first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER" - */ - char * env = getenv("MOZILLA_CERTIFICATE_FOLDER"); - if (env) - { - profilePath = rtl::OUString::createFromAscii( env ); - RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using env MOZILLA_CERTIFICATE_FOLDER: %s", rtl::OUStringToOString( profilePath, RTL_TEXTENCODING_ASCII_US ).getStr() ); - return true; - } - else - { - mozilla::MozillaProductType productTypes[4] = { - mozilla::MozillaProductType_Thunderbird, - mozilla::MozillaProductType_Mozilla, - mozilla::MozillaProductType_Firefox, - mozilla::MozillaProductType_Default }; - - uno::Reference<uno::XInterface> xInstance = rxMSF->createInstance( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.mozilla.MozillaBootstrap")) ); - OSL_ENSURE( xInstance.is(), "failed to create instance" ); - - uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap - = uno::Reference<mozilla::XMozillaBootstrap>(xInstance,uno::UNO_QUERY); - OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" ); - - if (xMozillaBootstrap.is()) - { - int nProduct = 4; - for (int i=0; i<nProduct; i++) - { - ::rtl::OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]); - - if (profile != NULL && profile.getLength()>0) - { - profilePath = xMozillaBootstrap->getProfilePath(productTypes[i],profile); - RTL_LOGFILE_PRODUCT_TRACE1( "XMLSEC: Using Mozilla Profile: %s", rtl::OUStringToOString( profilePath, RTL_TEXTENCODING_ASCII_US ).getStr() ); - return true; - } - } - } - - RTL_LOGFILE_PRODUCT_TRACE( "XMLSEC: No Mozilla Profile found!" ); - return false; - } -} - -} // namespace - SEInitializer_NssImpl::SEInitializer_NssImpl( - const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF) - :mxMSF( rxMSF ) + const css::uno::Reference< css::lang::XMultiServiceFactory > &rxMSF ) { + mxMSF = rxMSF; } SEInitializer_NssImpl::~SEInitializer_NssImpl() @@ -391,36 +97,13 @@ SEInitializer_NssImpl::~SEInitializer_NssImpl() /* XSEInitializer */ cssu::Reference< cssxc::XXMLSecurityContext > SAL_CALL - SEInitializer_NssImpl::createSecurityContext( - const rtl::OUString& sCertDB ) + SEInitializer_NssImpl::createSecurityContext( const ::rtl::OUString& ) throw (cssu::RuntimeException) { CERTCertDBHandle *pCertHandle = NULL ; - rtl::OString sCertDir; - if( sCertDB.getLength() ) - { - sCertDir = rtl::OUStringToOString(sCertDB, RTL_TEXTENCODING_ASCII_US); - } - else - { - static rtl::OString* pDefaultCertDir = NULL; - if ( !pDefaultCertDir ) - { - pDefaultCertDir = new rtl::OString; - rtl::OUString ouCertDir; - - if ( getMozillaCurrentProfile(mxMSF, ouCertDir) ) - *pDefaultCertDir = rtl::OUStringToOString(ouCertDir, RTL_TEXTENCODING_ASCII_US); - } - sCertDir = *pDefaultCertDir; - - } - - if( ! *initNSS( sCertDir.getStr() ) ) - { + if( !initNSS( mxMSF ) ) return NULL; - } pCertHandle = CERT_GetDefaultCertDB() ; @@ -477,18 +160,18 @@ rtl::OUString SEInitializer_NssImpl_getImplementationName () sal_Bool SAL_CALL SEInitializer_NssImpl_supportsService( const rtl::OUString& ServiceName ) throw (cssu::RuntimeException) { - return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME )); + return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SE_SERVICE_NAME )) || ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( NSS_SERVICE_NAME )); } cssu::Sequence< rtl::OUString > SAL_CALL SEInitializer_NssImpl_getSupportedServiceNames( ) throw (cssu::RuntimeException) { - cssu::Sequence < rtl::OUString > aRet(1); + cssu::Sequence < rtl::OUString > aRet(2); rtl::OUString* pArray = aRet.getArray(); - pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); + pArray[0] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( SE_SERVICE_NAME ) ); + pArray[1] = rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM ( NSS_SERVICE_NAME ) ); return aRet; } -#undef SERVICE_NAME cssu::Reference< cssu::XInterface > SAL_CALL SEInitializer_NssImpl_createInstance( const cssu::Reference< cssl::XMultiServiceFactory > & rSMgr) throw( cssu::Exception ) diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx index 53e512934..2092b9221 100644 --- a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx @@ -31,37 +31,19 @@ #include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> #include <com/sun/star/xml/crypto/XSEInitializer.hpp> -#include <com/sun/star/lang/XUnoTunnel.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <cppuhelper/implbase2.hxx> + +#include <cppuhelper/implbase1.hxx> #include <libxml/tree.h> -class SEInitializer_NssImpl : public cppu::WeakImplHelper2 +#include "nssinitializer.hxx" + +class SEInitializer_NssImpl : public cppu::ImplInheritanceHelper1 < - com::sun::star::xml::crypto::XSEInitializer, - com::sun::star::lang::XServiceInfo + ONSSInitializer, + ::com::sun::star::xml::crypto::XSEInitializer > -/****** SEInitializer_NssImpl.hxx/CLASS SEInitializer_NssImpl *********** - * - * NAME - * SEInitializer_NssImpl -- Class to initialize a Security Context - * instance - * - * FUNCTION - * Use this class to initialize a XmlSec based Security Context - * instance. After this instance is used up, use this class to free this - * instance. - * - * AUTHOR - * Michael Mi - * Email: michael.mi@sun.com - ******************************************************************************/ { -private: - com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > mxMSF; - public: SEInitializer_NssImpl(const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > &rxMSF); virtual ~SEInitializer_NssImpl(); @@ -69,7 +51,7 @@ public: /* XSEInitializer */ virtual com::sun::star::uno::Reference< com::sun::star::xml::crypto::XXMLSecurityContext > - SAL_CALL createSecurityContext( const rtl::OUString& certDB ) + SAL_CALL createSecurityContext( const ::rtl::OUString& ) throw (com::sun::star::uno::RuntimeException); virtual void SAL_CALL freeSecurityContext( const com::sun::star::uno::Reference< diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx index 71a022190..93c98398e 100644 --- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -120,13 +120,13 @@ sal_Int16 SAL_CALL X509Certificate_NssImpl :: getVersion() throw ( ::com::sun::s //Convert the time to readable local time PR_ExplodeTime( notBefore, PR_LocalTimeParameters, &explTime ) ; - dateTime.HundredthSeconds = explTime.tm_usec / 1000 ; - dateTime.Seconds = explTime.tm_sec ; - dateTime.Minutes = explTime.tm_min ; - dateTime.Hours = explTime.tm_hour ; - dateTime.Day = explTime.tm_mday ; - dateTime.Month = explTime.tm_month+1 ; - dateTime.Year = explTime.tm_year ; + dateTime.HundredthSeconds = static_cast< sal_Int16 >( explTime.tm_usec / 1000 ); + dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec ); + dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min ); + dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour ); + dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday ); + dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 ); + dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year ); return dateTime ; } else { @@ -149,13 +149,13 @@ sal_Int16 SAL_CALL X509Certificate_NssImpl :: getVersion() throw ( ::com::sun::s //Convert the time to readable local time PR_ExplodeTime( notAfter, PR_LocalTimeParameters, &explTime ) ; - dateTime.HundredthSeconds = explTime.tm_usec / 1000 ; - dateTime.Seconds = explTime.tm_sec ; - dateTime.Minutes = explTime.tm_min ; - dateTime.Hours = explTime.tm_hour ; - dateTime.Day = explTime.tm_mday ; - dateTime.Month = explTime.tm_month+1 ; - dateTime.Year = explTime.tm_year ; + dateTime.HundredthSeconds = static_cast< sal_Int16 >( explTime.tm_usec / 1000 ); + dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec ); + dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min ); + dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour ); + dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday ); + dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 ); + dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year ); return dateTime ; } else { diff --git a/xmlsecurity/source/xmlsec/nss/xsec_nss.cxx b/xmlsecurity/source/xmlsec/nss/xsec_nss.cxx index a226d961e..7b2fbd0d5 100644 --- a/xmlsecurity/source/xmlsec/nss/xsec_nss.cxx +++ b/xmlsecurity/source/xmlsec/nss/xsec_nss.cxx @@ -57,21 +57,41 @@ void* SAL_CALL nss_component_getFactory( const sal_Char* pImplName , void* pServ void* pRet = 0; Reference< XSingleServiceFactory > xFactory ; - if( pImplName != NULL && pServiceManager != NULL ) { - if( XMLSignature_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) { + if( pImplName != NULL && pServiceManager != NULL ) + { +#ifdef XMLSEC_CRYPTO_NSS + if( SEInitializer_NssImpl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { + xFactory = Reference< XSingleServiceFactory >( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + SEInitializer_NssImpl_createInstance, SEInitializer_NssImpl_getSupportedServiceNames() ) ); + } + else if( XMLSignature_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { xFactory = XMLSignature_NssImpl::impl_createFactory( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; - } else if( XMLSecurityContext_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) { + } + else if( XMLSecurityContext_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { xFactory = XMLSecurityContext_NssImpl::impl_createFactory( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; - } else if( SecurityEnvironment_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) { + } + else if( SecurityEnvironment_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { xFactory = SecurityEnvironment_NssImpl::impl_createFactory( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; - } else if( XMLEncryption_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) { + } + else if( XMLEncryption_NssImpl::impl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { xFactory = XMLEncryption_NssImpl::impl_createFactory( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; - } else if( SEInitializer_NssImpl_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) { + } +#else + if( ONSSInitializer_getImplementationName().equals( OUString::createFromAscii( pImplName ) ) ) + { xFactory = Reference< XSingleServiceFactory >( createSingleFactory( reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), OUString::createFromAscii( pImplName ), - SEInitializer_NssImpl_createInstance, SEInitializer_NssImpl_getSupportedServiceNames() ) ); + ONSSInitializer_createInstance, ONSSInitializer_getSupportedServiceNames() ) ); } +#endif } if( xFactory.is() ) { diff --git a/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx b/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx index 1eeec665c..935f0d6bf 100644 --- a/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx +++ b/xmlsecurity/source/xmlsec/xsec_xmlsec.cxx @@ -94,9 +94,7 @@ Reference< XInterface > SerialNumberAdapterImpl_createInstance( extern "C" { -#if defined( XMLSEC_CRYPTO_NSS ) extern void* nss_component_getFactory( const sal_Char*, void*, void* ); -#endif #if defined( XMLSEC_CRYPTO_MSCRYPTO ) extern void* mscrypt_component_getFactory( const sal_Char*, void*, void* ); @@ -141,11 +139,9 @@ void* SAL_CALL component_getFactory( const sal_Char* pImplName , void* pServiceM xFactory->acquire() ; pRet = xFactory.get() ; } else { -#if defined( XMLSEC_CRYPTO_NSS ) pRet = nss_component_getFactory( pImplName, pServiceManager, pRegistryKey ) ; if( pRet != NULL ) return pRet ; -#endif #if defined( XMLSEC_CRYPTO_MSCRYPTO ) pRet = mscrypt_component_getFactory( pImplName, pServiceManager, pRegistryKey ) ; diff --git a/xmlsecurity/util/makefile.mk b/xmlsecurity/util/makefile.mk index ff5a952fc..be6445094 100644 --- a/xmlsecurity/util/makefile.mk +++ b/xmlsecurity/util/makefile.mk @@ -81,10 +81,10 @@ SHL2LIBS= \ .IF "$(CRYPTO_ENGINE)" == "mscrypto" SHL2LIBS += \ $(SLB)$/xs_mscrypt.lib -.ELSE +.ENDIF + SHL2LIBS += \ $(SLB)$/xs_nss.lib -.ENDIF .ENDIF @@ -118,6 +118,8 @@ SHL2STDLIBS += $(MOZ_NSS_LIBS) .IF "$(CRYPTO_ENGINE)" == "mscrypto" SHL2STDLIBS+= $(MSCRYPTOLIBS) +# SHL2STDLIBS+= $(XMLSECLIB) $(LIBXML2LIB) $(NSS3LIB) $(NSPR4LIB) $(PLC4LIB) +SHL2STDLIBS+= $(NSS3LIB) $(NSPR4LIB) .ELSE SHL2STDLIBS+= $(NSSCRYPTOLIBS) .ENDIF @@ -127,10 +129,10 @@ SHL2DEF = $(MISC)$/$(SHL2TARGET).def DEF2NAME = $(SHL2TARGET) .IF "$(CRYPTO_ENGINE)" == "mscrypto" DEF2EXPORTFILE = exports_xsmscrypt.dxp -.ELSE -DEF2EXPORTFILE = exports_xsnss.dxp .ENDIF +DEF2EXPORTFILE = exports_xsnss.dxp + SRSFILELIST= \ $(SRS)$/component.srs \ $(SRS)$/dialogs.srs diff --git a/xmlsecurity/util/xsec_xmlsec.component b/xmlsecurity/util/xsec_xmlsec.component index de991899f..df4c2a7b2 100644 --- a/xmlsecurity/util/xsec_xmlsec.component +++ b/xmlsecurity/util/xsec_xmlsec.component @@ -32,6 +32,7 @@ <service name="com.sun.star.security.SerialNumberAdapter"/> </implementation> <implementation name="com.sun.star.xml.security.bridge.xmlsec.SEInitializer_NssImpl"> + <service name="com.sun.star.xml.crypto.NSSInitializer"/> <service name="com.sun.star.xml.crypto.SEInitializer"/> </implementation> <implementation name="com.sun.star.xml.security.bridge.xmlsec.SecurityEnvironment_NssImpl"> diff --git a/xmlsecurity/util/xsec_xmlsec.windows.component b/xmlsecurity/util/xsec_xmlsec.windows.component index fb11cc6e9..7b4ef87a9 100644 --- a/xmlsecurity/util/xsec_xmlsec.windows.component +++ b/xmlsecurity/util/xsec_xmlsec.windows.component @@ -31,6 +31,9 @@ <implementation name="com.sun.star.security.SerialNumberAdapter"> <service name="com.sun.star.security.SerialNumberAdapter"/> </implementation> + <implementation name="com.sun.star.xml.security.bridge.xmlsec.NSSInitializer_NssImpl"> + <service name="com.sun.star.xml.crypto.NSSInitializer"/> + </implementation> <implementation name="com.sun.star.xml.security.bridge.xmlsec.SEInitializer_MSCryptImpl"> <service name="com.sun.star.xml.crypto.SEInitializer"/> </implementation> |