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 #include "oox/core/binarycodec.hxx" 29 30 #include <algorithm> 31 #include <string.h> 32 #include "oox/helper/attributelist.hxx" 33 34 #include <comphelper/sequenceashashmap.hxx> 35 #include <comphelper/docpasswordhelper.hxx> 36 37 using namespace ::com::sun::star; 38 39 namespace oox { 40 namespace core { 41 42 // ============================================================================ 43 44 namespace { 45 46 /** Rotates rnValue left by nBits bits. */ 47 template< typename Type > 48 inline void lclRotateLeft( Type& rnValue, size_t nBits ) 49 { 50 OSL_ENSURE( nBits < sizeof( Type ) * 8, "lclRotateLeft - rotation count overflow" ); 51 rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) ); 52 } 53 54 /** Rotates the lower nWidth bits of rnValue left by nBits bits. */ 55 template< typename Type > 56 inline void lclRotateLeft( Type& rnValue, size_t nBits, size_t nWidth ) 57 { 58 OSL_ENSURE( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8), "lclRotateLeft - rotation count overflow" ); 59 Type nMask = static_cast< Type >( (1UL << nWidth) - 1 ); 60 rnValue = static_cast< Type >( 61 ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask ); 62 } 63 64 sal_Int32 lclGetLen( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) 65 { 66 sal_Int32 nLen = 0; 67 while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen; 68 return nLen; 69 } 70 71 sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) 72 { 73 sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize ); 74 if( nLen <= 0 ) return 0; 75 76 sal_uInt16 nKey = 0; 77 sal_uInt16 nKeyBase = 0x8000; 78 sal_uInt16 nKeyEnd = 0xFFFF; 79 const sal_uInt8* pnChar = pnPassData + nLen - 1; 80 for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, --pnChar ) 81 { 82 sal_uInt8 cChar = *pnChar & 0x7F; 83 for( size_t nBit = 0; nBit < 8; ++nBit ) 84 { 85 lclRotateLeft( nKeyBase, 1 ); 86 if( nKeyBase & 1 ) nKeyBase ^= 0x1020; 87 if( cChar & 1 ) nKey ^= nKeyBase; 88 cChar >>= 1; 89 lclRotateLeft( nKeyEnd, 1 ); 90 if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020; 91 } 92 } 93 return nKey ^ nKeyEnd; 94 } 95 96 sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Int32 nBufferSize ) 97 { 98 sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize ); 99 100 sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen ); 101 if( nLen > 0 ) 102 nHash ^= 0xCE4B; 103 104 const sal_uInt8* pnChar = pnPassData; 105 for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar ) 106 { 107 sal_uInt16 cChar = *pnChar; 108 size_t nRot = static_cast< size_t >( (nIndex + 1) % 15 ); 109 lclRotateLeft( cChar, nRot, 15 ); 110 nHash ^= cChar; 111 } 112 return nHash; 113 } 114 115 } // namespace 116 117 // ============================================================================ 118 119 /*static*/ sal_uInt16 CodecHelper::getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement ) 120 { 121 sal_Int32 nPasswordHash = rAttribs.getIntegerHex( nElement, 0 ); 122 OSL_ENSURE( (0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16), "CodecHelper::getPasswordHash - invalid password hash" ); 123 return static_cast< sal_uInt16 >( ((0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16)) ? nPasswordHash : 0 ); 124 } 125 126 // ============================================================================ 127 128 BinaryCodec_XOR::BinaryCodec_XOR( CodecType eCodecType ) : 129 meCodecType( eCodecType ), 130 mnOffset( 0 ), 131 mnBaseKey( 0 ), 132 mnHash( 0 ) 133 { 134 (void)memset( mpnKey, 0, sizeof( mpnKey ) ); 135 } 136 137 BinaryCodec_XOR::~BinaryCodec_XOR() 138 { 139 (void)memset( mpnKey, 0, sizeof( mpnKey ) ); 140 mnBaseKey = mnHash = 0; 141 } 142 143 void BinaryCodec_XOR::initKey( const sal_uInt8 pnPassData[ 16 ] ) 144 { 145 // calculate base key and hash from passed password 146 mnBaseKey = lclGetKey( pnPassData, 16 ); 147 mnHash = lclGetHash( pnPassData, 16 ); 148 149 static const sal_uInt8 spnFillChars[] = 150 { 151 0xBB, 0xFF, 0xFF, 0xBA, 152 0xFF, 0xFF, 0xB9, 0x80, 153 0x00, 0xBE, 0x0F, 0x00, 154 0xBF, 0x0F, 0x00 155 }; 156 157 (void)memcpy( mpnKey, pnPassData, 16 ); 158 sal_Int32 nIndex; 159 sal_Int32 nLen = lclGetLen( pnPassData, 16 ); 160 const sal_uInt8* pnFillChar = spnFillChars; 161 for( nIndex = nLen; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnFillChar ) 162 mpnKey[ nIndex ] = *pnFillChar; 163 164 // rotation of key values is application dependent 165 size_t nRotateSize = 0; 166 switch( meCodecType ) 167 { 168 case CODEC_WORD: nRotateSize = 7; break; 169 case CODEC_EXCEL: nRotateSize = 2; break; 170 // compiler will warn, if new codec type is introduced and not handled here 171 } 172 173 // use little-endian base key to create key array 174 sal_uInt8 pnBaseKeyLE[ 2 ]; 175 pnBaseKeyLE[ 0 ] = static_cast< sal_uInt8 >( mnBaseKey ); 176 pnBaseKeyLE[ 1 ] = static_cast< sal_uInt8 >( mnBaseKey >> 8 ); 177 sal_uInt8* pnKeyChar = mpnKey; 178 for( nIndex = 0; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnKeyChar ) 179 { 180 *pnKeyChar ^= pnBaseKeyLE[ nIndex & 1 ]; 181 lclRotateLeft( *pnKeyChar, nRotateSize ); 182 } 183 } 184 185 bool BinaryCodec_XOR::initCodec( const uno::Sequence< beans::NamedValue >& aData ) 186 { 187 bool bResult = sal_False; 188 189 ::comphelper::SequenceAsHashMap aHashData( aData ); 190 uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ), uno::Sequence< sal_Int8 >() ); 191 192 if ( aKey.getLength() == 16 ) 193 { 194 (void)memcpy( mpnKey, aKey.getConstArray(), 16 ); 195 bResult = sal_True; 196 197 mnBaseKey = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ), (sal_Int16)0 ); 198 mnHash = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ), (sal_Int16)0 ); 199 } 200 else 201 OSL_ENSURE( sal_False, "Unexpected key size!\n" ); 202 203 return bResult; 204 } 205 206 uno::Sequence< beans::NamedValue > BinaryCodec_XOR::getEncryptionData() 207 { 208 ::comphelper::SequenceAsHashMap aHashData; 209 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ) ] <<= uno::Sequence<sal_Int8>( (sal_Int8*)mpnKey, 16 ); 210 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ) ] <<= (sal_Int16)mnBaseKey; 211 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ) ] <<= (sal_Int16)mnHash; 212 213 return aHashData.getAsConstNamedValueList(); 214 } 215 216 bool BinaryCodec_XOR::verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const 217 { 218 return (nKey == mnBaseKey) && (nHash == mnHash); 219 } 220 221 void BinaryCodec_XOR::startBlock() 222 { 223 mnOffset = 0; 224 } 225 226 bool BinaryCodec_XOR::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes ) 227 { 228 const sal_uInt8* pnCurrKey = mpnKey + mnOffset; 229 const sal_uInt8* pnKeyLast = mpnKey + 0x0F; 230 231 // switch/case outside of the for loop (performance) 232 const sal_uInt8* pnSrcDataEnd = pnSrcData + nBytes; 233 switch( meCodecType ) 234 { 235 case CODEC_WORD: 236 { 237 for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData ) 238 { 239 sal_uInt8 nData = *pnSrcData ^ *pnCurrKey; 240 if( (*pnSrcData != 0) && (nData != 0) ) 241 *pnDestData = nData; 242 if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; 243 } 244 } 245 break; 246 case CODEC_EXCEL: 247 { 248 for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData ) 249 { 250 *pnDestData = *pnSrcData; 251 lclRotateLeft( *pnDestData, 3 ); 252 *pnDestData ^= *pnCurrKey; 253 if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey; 254 } 255 } 256 break; 257 // compiler will warn, if new codec type is introduced and not handled here 258 } 259 260 // update offset and leave 261 return skip( nBytes ); 262 } 263 264 bool BinaryCodec_XOR::skip( sal_Int32 nBytes ) 265 { 266 mnOffset = static_cast< sal_Int32 >( (mnOffset + nBytes) & 0x0F ); 267 return true; 268 } 269 270 // ============================================================================ 271 272 BinaryCodec_RCF::BinaryCodec_RCF() 273 { 274 mhCipher = rtl_cipher_create( rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream ); 275 OSL_ENSURE( mhCipher != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create cipher" ); 276 277 mhDigest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); 278 OSL_ENSURE( mhDigest != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create digest" ); 279 280 (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) ); 281 (void)memset (mpnUnique, 0, sizeof(mpnUnique)); 282 } 283 284 BinaryCodec_RCF::~BinaryCodec_RCF() 285 { 286 (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) ); 287 (void)memset (mpnUnique, 0, sizeof(mpnUnique)); 288 rtl_digest_destroy( mhDigest ); 289 rtl_cipher_destroy( mhCipher ); 290 } 291 292 bool BinaryCodec_RCF::initCodec( const uno::Sequence< beans::NamedValue >& aData ) 293 { 294 bool bResult = sal_False; 295 296 ::comphelper::SequenceAsHashMap aHashData( aData ); 297 uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ), uno::Sequence< sal_Int8 >() ); 298 299 if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 ) 300 { 301 (void)memcpy( mpnDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 ); 302 uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ), uno::Sequence< sal_Int8 >() ); 303 if ( aUniqueID.getLength() == 16 ) 304 { 305 (void)memcpy( mpnUnique, aUniqueID.getConstArray(), 16 ); 306 bResult = sal_False; 307 } 308 else 309 OSL_ENSURE( sal_False, "Unexpected document ID!\n" ); 310 } 311 else 312 OSL_ENSURE( sal_False, "Unexpected key size!\n" ); 313 314 return bResult; 315 } 316 317 uno::Sequence< beans::NamedValue > BinaryCodec_RCF::getEncryptionData() 318 { 319 ::comphelper::SequenceAsHashMap aHashData; 320 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnDigestValue, RTL_DIGEST_LENGTH_MD5 ); 321 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnUnique, 16 ); 322 323 return aHashData.getAsConstNamedValueList(); 324 } 325 326 void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnSalt[ 16 ] ) 327 { 328 uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pnPassData, uno::Sequence< sal_Int8 >( (sal_Int8*)pnSalt, 16 ) ); 329 // Fill raw digest of above updates into DigestValue. 330 331 if ( aKey.getLength() == sizeof(mpnDigestValue) ) 332 (void)memcpy ( mpnDigestValue, (const sal_uInt8*)aKey.getConstArray(), sizeof(mpnDigestValue) ); 333 else 334 memset( mpnDigestValue, 0, sizeof(mpnDigestValue) ); 335 336 (void)memcpy( mpnUnique, pnSalt, 16 ); 337 } 338 339 bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnVerifier[ 16 ], const sal_uInt8 pnVerifierHash[ 16 ] ) 340 { 341 if( !startBlock( 0 ) ) 342 return false; 343 344 sal_uInt8 pnDigest[ RTL_DIGEST_LENGTH_MD5 ]; 345 sal_uInt8 pnBuffer[ 64 ]; 346 347 // decode salt data into buffer 348 rtl_cipher_decode( mhCipher, pnVerifier, 16, pnBuffer, sizeof( pnBuffer ) ); 349 350 pnBuffer[ 16 ] = 0x80; 351 (void)memset( pnBuffer + 17, 0, sizeof( pnBuffer ) - 17 ); 352 pnBuffer[ 56 ] = 0x80; 353 354 // fill raw digest of buffer into digest 355 rtl_digest_updateMD5( mhDigest, pnBuffer, sizeof( pnBuffer ) ); 356 rtl_digest_rawMD5( mhDigest, pnDigest, sizeof( pnDigest ) ); 357 358 // decode original salt digest into buffer 359 rtl_cipher_decode( mhCipher, pnVerifierHash, 16, pnBuffer, sizeof( pnBuffer ) ); 360 361 // compare buffer with computed digest 362 bool bResult = memcmp( pnBuffer, pnDigest, sizeof( pnDigest ) ) == 0; 363 364 // erase buffer and digest arrays and leave 365 (void)memset( pnBuffer, 0, sizeof( pnBuffer ) ); 366 (void)memset( pnDigest, 0, sizeof( pnDigest ) ); 367 return bResult; 368 } 369 370 bool BinaryCodec_RCF::startBlock( sal_Int32 nCounter ) 371 { 372 // initialize key data array 373 sal_uInt8 pnKeyData[ 64 ]; 374 (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); 375 376 // fill 40 bit of digest value into [0..4] 377 (void)memcpy( pnKeyData, mpnDigestValue, 5 ); 378 379 // fill little-endian counter into [5..8], static_cast masks out unneeded bits 380 pnKeyData[ 5 ] = static_cast< sal_uInt8 >( nCounter ); 381 pnKeyData[ 6 ] = static_cast< sal_uInt8 >( nCounter >> 8 ); 382 pnKeyData[ 7 ] = static_cast< sal_uInt8 >( nCounter >> 16 ); 383 pnKeyData[ 8 ] = static_cast< sal_uInt8 >( nCounter >> 24 ); 384 385 pnKeyData[ 9 ] = 0x80; 386 pnKeyData[ 56 ] = 0x48; 387 388 // fill raw digest of key data into key data 389 (void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) ); 390 (void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 ); 391 392 // initialize cipher with key data (for decoding) 393 rtlCipherError eResult = 394 rtl_cipher_init( mhCipher, rtl_Cipher_DirectionDecode, pnKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0 ); 395 396 // rrase key data array and leave 397 (void)memset( pnKeyData, 0, sizeof( pnKeyData ) ); 398 return eResult == rtl_Cipher_E_None; 399 } 400 401 bool BinaryCodec_RCF::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes ) 402 { 403 rtlCipherError eResult = rtl_cipher_decode( mhCipher, 404 pnSrcData, static_cast< sal_Size >( nBytes ), 405 pnDestData, static_cast< sal_Size >( nBytes ) ); 406 return eResult == rtl_Cipher_E_None; 407 } 408 409 bool BinaryCodec_RCF::skip( sal_Int32 nBytes ) 410 { 411 // decode dummy data in memory to update internal state of RC4 cipher 412 sal_uInt8 pnDummy[ 1024 ]; 413 sal_Int32 nBytesLeft = nBytes; 414 bool bResult = true; 415 while( bResult && (nBytesLeft > 0) ) 416 { 417 sal_Int32 nBlockLen = ::std::min( nBytesLeft, static_cast< sal_Int32 >( sizeof( pnDummy ) ) ); 418 bResult = decode( pnDummy, pnDummy, nBlockLen ); 419 nBytesLeft -= nBlockLen; 420 } 421 return bResult; 422 } 423 424 // ============================================================================ 425 426 } // namespace core 427 } // namespace oox 428