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