| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #ifndef OOX_CORE_BINARYCODEC_HXX |
| #define OOX_CORE_BINARYCODEC_HXX |
| |
| #include <com/sun/star/uno/Sequence.hxx> |
| #include <com/sun/star/beans/NamedValue.hpp> |
| |
| #include <rtl/cipher.h> |
| #include <rtl/digest.h> |
| |
| namespace oox { class AttributeList; } |
| |
| namespace oox { |
| namespace core { |
| |
| // ============================================================================ |
| |
| class CodecHelper |
| { |
| public: |
| /** Returns the password hash if it is in the required 16-bit limit. */ |
| static sal_uInt16 getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement ); |
| |
| private: |
| CodecHelper(); |
| ~CodecHelper(); |
| }; |
| |
| // ============================================================================ |
| |
| /** Encodes and decodes data from/to protected MS Office documents. |
| |
| Implements a simple XOR encoding/decoding algorithm used in MS Office |
| versions up to MSO 95. |
| */ |
| class BinaryCodec_XOR |
| { |
| public: |
| /** Enumerates codec types supported by this XOR codec implementation. */ |
| enum CodecType |
| { |
| CODEC_WORD, /// MS Word XOR codec. |
| CODEC_EXCEL /// MS Excel XOR codec. |
| }; |
| |
| public: |
| /** Default constructor. |
| |
| Two-step construction in conjunction with the initKey() and verifyKey() |
| functions allows to try to initialize with different passwords (e.g. |
| built-in default password used for Excel workbook protection). |
| */ |
| explicit BinaryCodec_XOR( CodecType eCodecType ); |
| |
| ~BinaryCodec_XOR(); |
| |
| /** Initializes the algorithm with the specified password. |
| |
| @param pnPassData |
| Character array containing the password. Must be zero terminated, |
| which results in a maximum length of 15 characters. |
| */ |
| void initKey( const sal_uInt8 pnPassData[ 16 ] ); |
| |
| /** Initializes the algorithm with the encryption data. |
| |
| @param aData |
| The sequence contains the necessary data to initialize |
| the codec. |
| */ |
| bool initCodec( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aData ); |
| |
| /** Retrieves the encryption data |
| |
| @return |
| The sequence contains the necessary data to initialize |
| the codec. |
| */ |
| ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > getEncryptionData(); |
| |
| /** Verifies the validity of the password using the passed key and hash. |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param nKey |
| Password key value read from the file. |
| @param nHash |
| Password hash value read from the file. |
| |
| @return |
| True = test was successful. |
| */ |
| bool verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const; |
| |
| /** Reinitializes the codec to start a new memory block. |
| |
| Resets the internal key offset to 0. |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| */ |
| void startBlock(); |
| |
| /** Decodes a block of memory. |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param pnDestData |
| Destination buffer. Will contain the decrypted data afterwards. |
| @param pnSrcData |
| Encrypted data block. |
| @param nBytes |
| Size of the passed data blocks. pnDestData and pnSrcData must be of |
| this size. |
| |
| @return |
| True = decoding was successful (no error occured). |
| */ |
| bool decode( |
| sal_uInt8* pnDestData, |
| const sal_uInt8* pnSrcData, |
| sal_Int32 nBytes ); |
| |
| /** Lets the cipher skip a specific amount of bytes. |
| |
| This function sets the cipher to the same state as if the specified |
| amount of data has been decoded with one or more calls of decode(). |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param nBytes |
| Number of bytes to be skipped (cipher "seeks" forward). |
| |
| @return |
| True = skip was successful (no error occured). |
| */ |
| bool skip( sal_Int32 nBytes ); |
| |
| private: |
| CodecType meCodecType; /// Codec type. |
| sal_uInt8 mpnKey[ 16 ]; /// Encryption key. |
| sal_Int32 mnOffset; /// Key offset. |
| sal_uInt16 mnBaseKey; /// Base key from password. |
| sal_uInt16 mnHash; /// Hash value from password. |
| }; |
| |
| // ============================================================================ |
| |
| /** Encodes and decodes data from protected MSO 97+ documents. |
| |
| This is a wrapper class around low level cryptographic functions from RTL. |
| Implementation is based on the wvDecrypt package by Caolan McNamara: |
| http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html |
| */ |
| class BinaryCodec_RCF |
| { |
| public: |
| /** Default constructor. |
| |
| Two-step construction in conjunction with the initKey() and verifyKey() |
| functions allows to try to initialize with different passwords (e.g. |
| built-in default password used for Excel workbook protection). |
| */ |
| explicit BinaryCodec_RCF(); |
| |
| ~BinaryCodec_RCF(); |
| |
| /** Initializes the algorithm with the encryption data. |
| |
| @param aData |
| The sequence contains the necessary data to initialize |
| the codec. |
| */ |
| bool initCodec( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aData ); |
| |
| /** Retrieves the encryption data |
| |
| @return |
| The sequence contains the necessary data to initialize |
| the codec. |
| */ |
| ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > getEncryptionData(); |
| |
| /** Initializes the algorithm with the specified password and document ID. |
| |
| @param pnPassData |
| Unicode character array containing the password. Must be zero |
| terminated, which results in a maximum length of 15 characters. |
| @param pnSalt |
| Random salt data block read from or written to the file. |
| */ |
| void initKey( |
| const sal_uInt16 pnPassData[ 16 ], |
| const sal_uInt8 pnSalt[ 16 ] ); |
| |
| /** Verifies the validity of the password using the passed salt data. |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param pnVerifier |
| Verifier block read from the file. |
| @param pnVerifierHash |
| Verifier hash read from the file. |
| |
| @return |
| True = test was successful. |
| */ |
| bool verifyKey( |
| const sal_uInt8 pnVerifier[ 16 ], |
| const sal_uInt8 pnVerifierHash[ 16 ] ); |
| |
| /** Rekeys the codec using the specified counter. |
| |
| After reading a specific amount of data the cipher algorithm needs to |
| be rekeyed using a counter that counts the data blocks. |
| |
| The block size is for example 512 bytes for MS Word files and 1024 |
| bytes for MS Excel files. |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param nCounter |
| Block counter used to rekey the cipher. |
| */ |
| bool startBlock( sal_Int32 nCounter ); |
| |
| /** Decodes a block of memory. |
| |
| @see rtl_cipher_decode() |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param pnDestData |
| Destination buffer. Will contain the decrypted data afterwards. |
| @param pnSrcData |
| Encrypted data block. |
| @param nBytes |
| Size of the passed data blocks. pnDestData and pnSrcData must be of |
| this size. |
| |
| @return |
| True = decoding was successful (no error occured). |
| */ |
| bool decode( |
| sal_uInt8* pnDestData, |
| const sal_uInt8* pnSrcData, |
| sal_Int32 nBytes ); |
| |
| /** Lets the cipher skip a specific amount of bytes. |
| |
| This function sets the cipher to the same state as if the specified |
| amount of data has been decoded with one or more calls of decode(). |
| |
| @precond |
| The codec must be initialized with the initKey() function before |
| this function can be used. |
| |
| @param nBytes |
| Number of bytes to be skipped (cipher "seeks" forward). |
| |
| @return |
| True = skip was successful (no error occured). |
| */ |
| bool skip( sal_Int32 nBytes ); |
| |
| private: |
| void InitKeyImpl( |
| const sal_uInt8 pKeyData[64], |
| const sal_uInt8 pUnique[16] ); |
| |
| rtlCipher mhCipher; |
| rtlDigest mhDigest; |
| sal_uInt8 mpnDigestValue[ RTL_DIGEST_LENGTH_MD5 ]; |
| sal_uInt8 mpnUnique[16]; |
| }; |
| |
| // ============================================================================ |
| |
| } // namespace core |
| } // namespace oox |
| |
| #endif |