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