1e3508121SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3e3508121SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4e3508121SAndrew Rist * or more contributor license agreements. See the NOTICE file 5e3508121SAndrew Rist * distributed with this work for additional information 6e3508121SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7e3508121SAndrew Rist * to you under the Apache License, Version 2.0 (the 8e3508121SAndrew Rist * "License"); you may not use this file except in compliance 9e3508121SAndrew Rist * with the License. You may obtain a copy of the License at 10e3508121SAndrew Rist * 11e3508121SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12e3508121SAndrew Rist * 13e3508121SAndrew Rist * Unless required by applicable law or agreed to in writing, 14e3508121SAndrew Rist * software distributed under the License is distributed on an 15e3508121SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16e3508121SAndrew Rist * KIND, either express or implied. See the License for the 17e3508121SAndrew Rist * specific language governing permissions and limitations 18e3508121SAndrew Rist * under the License. 19e3508121SAndrew Rist * 20e3508121SAndrew Rist *************************************************************/ 21e3508121SAndrew Rist 22e3508121SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #ifndef OOX_CORE_BINARYCODEC_HXX 25cdf0e10cSrcweir #define OOX_CORE_BINARYCODEC_HXX 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx> 28cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp> 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include <rtl/cipher.h> 31cdf0e10cSrcweir #include <rtl/digest.h> 32cdf0e10cSrcweir 33cdf0e10cSrcweir namespace oox { class AttributeList; } 34cdf0e10cSrcweir 35cdf0e10cSrcweir namespace oox { 36cdf0e10cSrcweir namespace core { 37cdf0e10cSrcweir 38cdf0e10cSrcweir // ============================================================================ 39cdf0e10cSrcweir 40cdf0e10cSrcweir class CodecHelper 41cdf0e10cSrcweir { 42cdf0e10cSrcweir public: 43cdf0e10cSrcweir /** Returns the password hash if it is in the required 16-bit limit. */ 44cdf0e10cSrcweir static sal_uInt16 getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement ); 45cdf0e10cSrcweir 46cdf0e10cSrcweir private: 47cdf0e10cSrcweir CodecHelper(); 48cdf0e10cSrcweir ~CodecHelper(); 49cdf0e10cSrcweir }; 50cdf0e10cSrcweir 51cdf0e10cSrcweir // ============================================================================ 52cdf0e10cSrcweir 53cdf0e10cSrcweir /** Encodes and decodes data from/to protected MS Office documents. 54cdf0e10cSrcweir 55cdf0e10cSrcweir Implements a simple XOR encoding/decoding algorithm used in MS Office 56cdf0e10cSrcweir versions up to MSO 95. 57cdf0e10cSrcweir */ 58cdf0e10cSrcweir class BinaryCodec_XOR 59cdf0e10cSrcweir { 60cdf0e10cSrcweir public: 61cdf0e10cSrcweir /** Enumerates codec types supported by this XOR codec implementation. */ 62cdf0e10cSrcweir enum CodecType 63cdf0e10cSrcweir { 64cdf0e10cSrcweir CODEC_WORD, /// MS Word XOR codec. 65cdf0e10cSrcweir CODEC_EXCEL /// MS Excel XOR codec. 66cdf0e10cSrcweir }; 67cdf0e10cSrcweir 68cdf0e10cSrcweir public: 69cdf0e10cSrcweir /** Default constructor. 70cdf0e10cSrcweir 71cdf0e10cSrcweir Two-step construction in conjunction with the initKey() and verifyKey() 72cdf0e10cSrcweir functions allows to try to initialize with different passwords (e.g. 73cdf0e10cSrcweir built-in default password used for Excel workbook protection). 74cdf0e10cSrcweir */ 75cdf0e10cSrcweir explicit BinaryCodec_XOR( CodecType eCodecType ); 76cdf0e10cSrcweir 77cdf0e10cSrcweir ~BinaryCodec_XOR(); 78cdf0e10cSrcweir 79cdf0e10cSrcweir /** Initializes the algorithm with the specified password. 80cdf0e10cSrcweir 81cdf0e10cSrcweir @param pnPassData 82cdf0e10cSrcweir Character array containing the password. Must be zero terminated, 83cdf0e10cSrcweir which results in a maximum length of 15 characters. 84cdf0e10cSrcweir */ 85cdf0e10cSrcweir void initKey( const sal_uInt8 pnPassData[ 16 ] ); 86cdf0e10cSrcweir 87cdf0e10cSrcweir /** Initializes the algorithm with the encryption data. 88cdf0e10cSrcweir 89cdf0e10cSrcweir @param aData 90cdf0e10cSrcweir The sequence contains the necessary data to initialize 91cdf0e10cSrcweir the codec. 92cdf0e10cSrcweir */ 93cdf0e10cSrcweir bool initCodec( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aData ); 94cdf0e10cSrcweir 95cdf0e10cSrcweir /** Retrieves the encryption data 96cdf0e10cSrcweir 97cdf0e10cSrcweir @return 98cdf0e10cSrcweir The sequence contains the necessary data to initialize 99cdf0e10cSrcweir the codec. 100cdf0e10cSrcweir */ 101cdf0e10cSrcweir ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > getEncryptionData(); 102cdf0e10cSrcweir 103cdf0e10cSrcweir /** Verifies the validity of the password using the passed key and hash. 104cdf0e10cSrcweir 105cdf0e10cSrcweir @precond 106cdf0e10cSrcweir The codec must be initialized with the initKey() function before 107cdf0e10cSrcweir this function can be used. 108cdf0e10cSrcweir 109cdf0e10cSrcweir @param nKey 110cdf0e10cSrcweir Password key value read from the file. 111cdf0e10cSrcweir @param nHash 112cdf0e10cSrcweir Password hash value read from the file. 113cdf0e10cSrcweir 114cdf0e10cSrcweir @return 115cdf0e10cSrcweir True = test was successful. 116cdf0e10cSrcweir */ 117cdf0e10cSrcweir bool verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const; 118cdf0e10cSrcweir 119cdf0e10cSrcweir /** Reinitializes the codec to start a new memory block. 120cdf0e10cSrcweir 121cdf0e10cSrcweir Resets the internal key offset to 0. 122cdf0e10cSrcweir 123cdf0e10cSrcweir @precond 124cdf0e10cSrcweir The codec must be initialized with the initKey() function before 125cdf0e10cSrcweir this function can be used. 126cdf0e10cSrcweir */ 127cdf0e10cSrcweir void startBlock(); 128cdf0e10cSrcweir 129cdf0e10cSrcweir /** Decodes a block of memory. 130cdf0e10cSrcweir 131cdf0e10cSrcweir @precond 132cdf0e10cSrcweir The codec must be initialized with the initKey() function before 133cdf0e10cSrcweir this function can be used. 134cdf0e10cSrcweir 135cdf0e10cSrcweir @param pnDestData 136cdf0e10cSrcweir Destination buffer. Will contain the decrypted data afterwards. 137cdf0e10cSrcweir @param pnSrcData 138cdf0e10cSrcweir Encrypted data block. 139cdf0e10cSrcweir @param nBytes 140cdf0e10cSrcweir Size of the passed data blocks. pnDestData and pnSrcData must be of 141cdf0e10cSrcweir this size. 142cdf0e10cSrcweir 143cdf0e10cSrcweir @return 144*a893be29SPedro Giffuni True = decoding was successful (no error occurred). 145cdf0e10cSrcweir */ 146cdf0e10cSrcweir bool decode( 147cdf0e10cSrcweir sal_uInt8* pnDestData, 148cdf0e10cSrcweir const sal_uInt8* pnSrcData, 149cdf0e10cSrcweir sal_Int32 nBytes ); 150cdf0e10cSrcweir 151cdf0e10cSrcweir /** Lets the cipher skip a specific amount of bytes. 152cdf0e10cSrcweir 153cdf0e10cSrcweir This function sets the cipher to the same state as if the specified 154cdf0e10cSrcweir amount of data has been decoded with one or more calls of decode(). 155cdf0e10cSrcweir 156cdf0e10cSrcweir @precond 157cdf0e10cSrcweir The codec must be initialized with the initKey() function before 158cdf0e10cSrcweir this function can be used. 159cdf0e10cSrcweir 160cdf0e10cSrcweir @param nBytes 161cdf0e10cSrcweir Number of bytes to be skipped (cipher "seeks" forward). 162cdf0e10cSrcweir 163cdf0e10cSrcweir @return 164*a893be29SPedro Giffuni True = skip was successful (no error occurred). 165cdf0e10cSrcweir */ 166cdf0e10cSrcweir bool skip( sal_Int32 nBytes ); 167cdf0e10cSrcweir 168cdf0e10cSrcweir private: 169cdf0e10cSrcweir CodecType meCodecType; /// Codec type. 170cdf0e10cSrcweir sal_uInt8 mpnKey[ 16 ]; /// Encryption key. 171cdf0e10cSrcweir sal_Int32 mnOffset; /// Key offset. 172cdf0e10cSrcweir sal_uInt16 mnBaseKey; /// Base key from password. 173cdf0e10cSrcweir sal_uInt16 mnHash; /// Hash value from password. 174cdf0e10cSrcweir }; 175cdf0e10cSrcweir 176cdf0e10cSrcweir // ============================================================================ 177cdf0e10cSrcweir 178cdf0e10cSrcweir /** Encodes and decodes data from protected MSO 97+ documents. 179cdf0e10cSrcweir 180cdf0e10cSrcweir This is a wrapper class around low level cryptographic functions from RTL. 181cdf0e10cSrcweir Implementation is based on the wvDecrypt package by Caolan McNamara: 182cdf0e10cSrcweir http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html 183cdf0e10cSrcweir */ 184cdf0e10cSrcweir class BinaryCodec_RCF 185cdf0e10cSrcweir { 186cdf0e10cSrcweir public: 187cdf0e10cSrcweir /** Default constructor. 188cdf0e10cSrcweir 189cdf0e10cSrcweir Two-step construction in conjunction with the initKey() and verifyKey() 190cdf0e10cSrcweir functions allows to try to initialize with different passwords (e.g. 191cdf0e10cSrcweir built-in default password used for Excel workbook protection). 192cdf0e10cSrcweir */ 193cdf0e10cSrcweir explicit BinaryCodec_RCF(); 194cdf0e10cSrcweir 195cdf0e10cSrcweir ~BinaryCodec_RCF(); 196cdf0e10cSrcweir 197cdf0e10cSrcweir /** Initializes the algorithm with the encryption data. 198cdf0e10cSrcweir 199cdf0e10cSrcweir @param aData 200cdf0e10cSrcweir The sequence contains the necessary data to initialize 201cdf0e10cSrcweir the codec. 202cdf0e10cSrcweir */ 203cdf0e10cSrcweir bool initCodec( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aData ); 204cdf0e10cSrcweir 205cdf0e10cSrcweir /** Retrieves the encryption data 206cdf0e10cSrcweir 207cdf0e10cSrcweir @return 208cdf0e10cSrcweir The sequence contains the necessary data to initialize 209cdf0e10cSrcweir the codec. 210cdf0e10cSrcweir */ 211cdf0e10cSrcweir ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > getEncryptionData(); 212cdf0e10cSrcweir 213cdf0e10cSrcweir /** Initializes the algorithm with the specified password and document ID. 214cdf0e10cSrcweir 215cdf0e10cSrcweir @param pnPassData 216cdf0e10cSrcweir Unicode character array containing the password. Must be zero 217cdf0e10cSrcweir terminated, which results in a maximum length of 15 characters. 218cdf0e10cSrcweir @param pnSalt 219cdf0e10cSrcweir Random salt data block read from or written to the file. 220cdf0e10cSrcweir */ 221cdf0e10cSrcweir void initKey( 222cdf0e10cSrcweir const sal_uInt16 pnPassData[ 16 ], 223cdf0e10cSrcweir const sal_uInt8 pnSalt[ 16 ] ); 224cdf0e10cSrcweir 225cdf0e10cSrcweir /** Verifies the validity of the password using the passed salt data. 226cdf0e10cSrcweir 227cdf0e10cSrcweir @precond 228cdf0e10cSrcweir The codec must be initialized with the initKey() function before 229cdf0e10cSrcweir this function can be used. 230cdf0e10cSrcweir 231cdf0e10cSrcweir @param pnVerifier 232cdf0e10cSrcweir Verifier block read from the file. 233cdf0e10cSrcweir @param pnVerifierHash 234cdf0e10cSrcweir Verifier hash read from the file. 235cdf0e10cSrcweir 236cdf0e10cSrcweir @return 237cdf0e10cSrcweir True = test was successful. 238cdf0e10cSrcweir */ 239cdf0e10cSrcweir bool verifyKey( 240cdf0e10cSrcweir const sal_uInt8 pnVerifier[ 16 ], 241cdf0e10cSrcweir const sal_uInt8 pnVerifierHash[ 16 ] ); 242cdf0e10cSrcweir 243cdf0e10cSrcweir /** Rekeys the codec using the specified counter. 244cdf0e10cSrcweir 245cdf0e10cSrcweir After reading a specific amount of data the cipher algorithm needs to 246cdf0e10cSrcweir be rekeyed using a counter that counts the data blocks. 247cdf0e10cSrcweir 248cdf0e10cSrcweir The block size is for example 512 bytes for MS Word files and 1024 249cdf0e10cSrcweir bytes for MS Excel files. 250cdf0e10cSrcweir 251cdf0e10cSrcweir @precond 252cdf0e10cSrcweir The codec must be initialized with the initKey() function before 253cdf0e10cSrcweir this function can be used. 254cdf0e10cSrcweir 255cdf0e10cSrcweir @param nCounter 256cdf0e10cSrcweir Block counter used to rekey the cipher. 257cdf0e10cSrcweir */ 258cdf0e10cSrcweir bool startBlock( sal_Int32 nCounter ); 259cdf0e10cSrcweir 260cdf0e10cSrcweir /** Decodes a block of memory. 261cdf0e10cSrcweir 262cdf0e10cSrcweir @see rtl_cipher_decode() 263cdf0e10cSrcweir 264cdf0e10cSrcweir @precond 265cdf0e10cSrcweir The codec must be initialized with the initKey() function before 266cdf0e10cSrcweir this function can be used. 267cdf0e10cSrcweir 268cdf0e10cSrcweir @param pnDestData 269cdf0e10cSrcweir Destination buffer. Will contain the decrypted data afterwards. 270cdf0e10cSrcweir @param pnSrcData 271cdf0e10cSrcweir Encrypted data block. 272cdf0e10cSrcweir @param nBytes 273cdf0e10cSrcweir Size of the passed data blocks. pnDestData and pnSrcData must be of 274cdf0e10cSrcweir this size. 275cdf0e10cSrcweir 276cdf0e10cSrcweir @return 277*a893be29SPedro Giffuni True = decoding was successful (no error occurred). 278cdf0e10cSrcweir */ 279cdf0e10cSrcweir bool decode( 280cdf0e10cSrcweir sal_uInt8* pnDestData, 281cdf0e10cSrcweir const sal_uInt8* pnSrcData, 282cdf0e10cSrcweir sal_Int32 nBytes ); 283cdf0e10cSrcweir 284cdf0e10cSrcweir /** Lets the cipher skip a specific amount of bytes. 285cdf0e10cSrcweir 286cdf0e10cSrcweir This function sets the cipher to the same state as if the specified 287cdf0e10cSrcweir amount of data has been decoded with one or more calls of decode(). 288cdf0e10cSrcweir 289cdf0e10cSrcweir @precond 290cdf0e10cSrcweir The codec must be initialized with the initKey() function before 291cdf0e10cSrcweir this function can be used. 292cdf0e10cSrcweir 293cdf0e10cSrcweir @param nBytes 294cdf0e10cSrcweir Number of bytes to be skipped (cipher "seeks" forward). 295cdf0e10cSrcweir 296cdf0e10cSrcweir @return 297*a893be29SPedro Giffuni True = skip was successful (no error occurred). 298cdf0e10cSrcweir */ 299cdf0e10cSrcweir bool skip( sal_Int32 nBytes ); 300cdf0e10cSrcweir 301cdf0e10cSrcweir private: 302cdf0e10cSrcweir void InitKeyImpl( 303cdf0e10cSrcweir const sal_uInt8 pKeyData[64], 304cdf0e10cSrcweir const sal_uInt8 pUnique[16] ); 305cdf0e10cSrcweir 306cdf0e10cSrcweir rtlCipher mhCipher; 307cdf0e10cSrcweir rtlDigest mhDigest; 308cdf0e10cSrcweir sal_uInt8 mpnDigestValue[ RTL_DIGEST_LENGTH_MD5 ]; 309cdf0e10cSrcweir sal_uInt8 mpnUnique[16]; 310cdf0e10cSrcweir }; 311cdf0e10cSrcweir 312cdf0e10cSrcweir // ============================================================================ 313cdf0e10cSrcweir 314cdf0e10cSrcweir } // namespace core 315cdf0e10cSrcweir } // namespace oox 316cdf0e10cSrcweir 317cdf0e10cSrcweir #endif 318