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