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