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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 #include "filter/msfilter/mscodec.hxx"
27
28 #include <osl/diagnose.h>
29 #include <algorithm>
30 #include <string.h>
31 #include <tools/solar.h>
32
33 #include <comphelper/sequenceashashmap.hxx>
34 #include <comphelper/docpasswordhelper.hxx>
35
36 #define DEBUG_MSO_ENCRYPTION_STD97 0
37
38 #if DEBUG_MSO_ENCRYPTION_STD97
39 #include <stdio.h>
40 #endif
41
42 using namespace ::com::sun::star;
43
44 namespace msfilter {
45
46 // ============================================================================
47
48 namespace {
49
50 /** Rotates rnValue left by nBits bits. */
51 template< typename Type >
lclRotateLeft(Type & rnValue,int nBits)52 inline void lclRotateLeft( Type& rnValue, int nBits )
53 {
54 OSL_ASSERT(
55 nBits >= 0 &&
56 sal::static_int_cast< unsigned int >(nBits) < sizeof( Type ) * 8 );
57 rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) );
58 }
59
60 /** Rotates the lower nWidth bits of rnValue left by nBits bits. */
61 template< typename Type >
lclRotateLeft(Type & rnValue,sal_uInt8 nBits,sal_uInt8 nWidth)62 inline void lclRotateLeft( Type& rnValue, sal_uInt8 nBits, sal_uInt8 nWidth )
63 {
64 OSL_ASSERT( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8) );
65 Type nMask = static_cast< Type >( (1UL << nWidth) - 1 );
66 rnValue = static_cast< Type >(
67 ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask );
68 }
69
lclGetLen(const sal_uInt8 * pnPassData,sal_Size nBufferSize)70 sal_Size lclGetLen( const sal_uInt8* pnPassData, sal_Size nBufferSize )
71 {
72 sal_Size nLen = 0;
73 while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen;
74 return nLen;
75 }
76
lclGetKey(const sal_uInt8 * pnPassData,sal_Size nBufferSize)77 sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, sal_Size nBufferSize )
78 {
79 sal_Size nLen = lclGetLen( pnPassData, nBufferSize );
80 if( !nLen ) return 0;
81
82 sal_uInt16 nKey = 0;
83 sal_uInt16 nKeyBase = 0x8000;
84 sal_uInt16 nKeyEnd = 0xFFFF;
85 const sal_uInt8* pnChar = pnPassData + nLen - 1;
86 for( sal_Size nIndex = 0; nIndex < nLen; ++nIndex, --pnChar )
87 {
88 sal_uInt8 cChar = *pnChar & 0x7F;
89 for( sal_uInt8 nBit = 0; nBit < 8; ++nBit )
90 {
91 lclRotateLeft( nKeyBase, 1 );
92 if( nKeyBase & 1 ) nKeyBase ^= 0x1020;
93 if( cChar & 1 ) nKey ^= nKeyBase;
94 cChar >>= 1;
95 lclRotateLeft( nKeyEnd, 1 );
96 if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020;
97 }
98 }
99 return nKey ^ nKeyEnd;
100 }
101
lclGetHash(const sal_uInt8 * pnPassData,sal_Size nBufferSize)102 sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Size nBufferSize )
103 {
104 sal_Size nLen = lclGetLen( pnPassData, nBufferSize );
105
106 sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen );
107 if( nLen )
108 nHash ^= 0xCE4B;
109
110 const sal_uInt8* pnChar = pnPassData;
111 for( sal_Size nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar )
112 {
113 sal_uInt16 cChar = *pnChar;
114 sal_uInt8 nRot = static_cast< sal_uInt8 >( (nIndex + 1) % 15 );
115 lclRotateLeft( cChar, nRot, 15 );
116 nHash ^= cChar;
117 }
118 return nHash;
119 }
120
121
122 } // namespace
123
124 // ============================================================================
125
MSCodec_Xor95(int nRotateDistance)126 MSCodec_Xor95::MSCodec_Xor95(int nRotateDistance) :
127 mnOffset( 0 ),
128 mnKey( 0 ),
129 mnHash( 0 ),
130 mnRotateDistance( nRotateDistance )
131 {
132 (void)memset( mpnKey, 0, sizeof( mpnKey ) );
133 }
134
~MSCodec_Xor95()135 MSCodec_Xor95::~MSCodec_Xor95()
136 {
137 (void)memset( mpnKey, 0, sizeof( mpnKey ) );
138 mnKey = mnHash = 0;
139 }
140
InitKey(const sal_uInt8 pnPassData[16])141 void MSCodec_Xor95::InitKey( const sal_uInt8 pnPassData[ 16 ] )
142 {
143 mnKey = lclGetKey( pnPassData, 16 );
144 mnHash = lclGetHash( pnPassData, 16 );
145
146 (void)memcpy( mpnKey, pnPassData, 16 );
147
148 static const sal_uInt8 spnFillChars[] =
149 {
150 0xBB, 0xFF, 0xFF, 0xBA,
151 0xFF, 0xFF, 0xB9, 0x80,
152 0x00, 0xBE, 0x0F, 0x00,
153 0xBF, 0x0F, 0x00
154 };
155
156 sal_Size nIndex;
157 sal_Size nLen = lclGetLen( pnPassData, 16 );
158 const sal_uInt8* pnFillChar = spnFillChars;
159 for( nIndex = nLen; nIndex < sizeof( mpnKey ); ++nIndex, ++pnFillChar )
160 mpnKey[ nIndex ] = *pnFillChar;
161
162 SVBT16 pnOrigKey;
163 ShortToSVBT16( mnKey, pnOrigKey );
164 sal_uInt8* pnKeyChar = mpnKey;
165 for( nIndex = 0; nIndex < sizeof( mpnKey ); ++nIndex, ++pnKeyChar )
166 {
167 *pnKeyChar ^= pnOrigKey[ nIndex & 0x01 ];
168 lclRotateLeft( *pnKeyChar, mnRotateDistance );
169 }
170 }
171
InitCodec(const uno::Sequence<beans::NamedValue> & aData)172 sal_Bool MSCodec_Xor95::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
173 {
174 sal_Bool bResult = sal_False;
175
176 ::comphelper::SequenceAsHashMap aHashData( aData );
177 uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );
178
179 if ( aKey.getLength() == 16 )
180 {
181 (void)memcpy( mpnKey, aKey.getConstArray(), 16 );
182 bResult = sal_True;
183
184 mnKey = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ), (sal_Int16)0 );
185 mnHash = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ), (sal_Int16)0 );
186 }
187 else
188 OSL_ENSURE( sal_False, "Unexpected key size!\n" );
189
190 return bResult;
191 }
192
GetEncryptionData()193 uno::Sequence< beans::NamedValue > MSCodec_Xor95::GetEncryptionData()
194 {
195 ::comphelper::SequenceAsHashMap aHashData;
196 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ) ] <<= uno::Sequence<sal_Int8>( (sal_Int8*)mpnKey, 16 );
197 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ) ] <<= (sal_Int16)mnKey;
198 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ) ] <<= (sal_Int16)mnHash;
199
200 return aHashData.getAsConstNamedValueList();
201 }
202
VerifyKey(sal_uInt16 nKey,sal_uInt16 nHash) const203 bool MSCodec_Xor95::VerifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const
204 {
205 return (nKey == mnKey) && (nHash == mnHash);
206 }
207
InitCipher()208 void MSCodec_Xor95::InitCipher()
209 {
210 mnOffset = 0;
211 }
212
Decode(sal_uInt8 * pnData,sal_Size nBytes)213 void MSCodec_XorXLS95::Decode( sal_uInt8* pnData, sal_Size nBytes )
214 {
215 const sal_uInt8* pnCurrKey = mpnKey + mnOffset;
216 const sal_uInt8* pnKeyLast = mpnKey + 0x0F;
217
218 for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData )
219 {
220 lclRotateLeft( *pnData, 3 );
221 *pnData ^= *pnCurrKey;
222 if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey;
223 }
224
225 // update mnOffset
226 Skip( nBytes );
227 }
228
Decode(sal_uInt8 * pnData,sal_Size nBytes)229 void MSCodec_XorWord95::Decode( sal_uInt8* pnData, sal_Size nBytes )
230 {
231 const sal_uInt8* pnCurrKey = mpnKey + mnOffset;
232 const sal_uInt8* pnKeyLast = mpnKey + 0x0F;
233
234 for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData )
235 {
236 const sal_uInt8 cChar = *pnData ^ *pnCurrKey;
237 if (*pnData && cChar)
238 *pnData = cChar;
239 if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey;
240 }
241
242 // update mnOffset
243 Skip( nBytes );
244 }
245
246
Skip(sal_Size nBytes)247 void MSCodec_Xor95::Skip( sal_Size nBytes )
248 {
249 mnOffset = (mnOffset + nBytes) & 0x0F;
250 }
251
252 // ============================================================================
253
MSCodec_Std97()254 MSCodec_Std97::MSCodec_Std97 ()
255 {
256 m_hCipher = rtl_cipher_create (
257 rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream);
258 OSL_ASSERT(m_hCipher != 0);
259
260 m_hDigest = rtl_digest_create (
261 rtl_Digest_AlgorithmMD5);
262 OSL_ASSERT(m_hDigest != 0);
263
264 (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue));
265 (void)memset (m_pDocId, 0, sizeof(m_pDocId));
266 }
267
~MSCodec_Std97()268 MSCodec_Std97::~MSCodec_Std97 ()
269 {
270 (void)memset (m_pDigestValue, 0, sizeof(m_pDigestValue));
271 (void)memset (m_pDocId, 0, sizeof(m_pDocId));
272 rtl_digest_destroy (m_hDigest);
273 rtl_cipher_destroy (m_hCipher);
274 }
275
276 #if 0
277 #if DEBUG_MSO_ENCRYPTION_STD97
278 static void lcl_PrintKeyData(const sal_uInt8* pKeyData, const char* msg)
279 {
280 printf("pKeyData: (%s)\n", msg);
281 for (int j = 0; j < 4; ++j)
282 {
283 for (int i = 0; i < 16; ++i)
284 printf("%2.2x ", pKeyData[j*16+i]);
285 printf("\n");
286 }
287 }
288 #else
289 static void lcl_PrintKeyData(const sal_uInt8* /*pKeyData*/, const char* /*msg*/)
290 {
291 }
292 #endif
293 #endif
294
295 #if DEBUG_MSO_ENCRYPTION_STD97
lcl_PrintDigest(const sal_uInt8 * pDigest,const char * msg)296 static void lcl_PrintDigest(const sal_uInt8* pDigest, const char* msg)
297 {
298 printf("digest: (%s)\n", msg);
299 for (int i = 0; i < 16; ++i)
300 printf("%2.2x ", pDigest[i]);
301 printf("\n");
302 }
303 #else
lcl_PrintDigest(const sal_uInt8 *,const char *)304 static void lcl_PrintDigest(const sal_uInt8* /*pDigest*/, const char* /*msg*/)
305 {
306 }
307 #endif
308
InitCodec(const uno::Sequence<beans::NamedValue> & aData)309 sal_Bool MSCodec_Std97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
310 {
311 #if DEBUG_MSO_ENCRYPTION_STD97
312 fprintf(stdout, "MSCodec_Std97::InitCodec: --begin\n");fflush(stdout);
313 #endif
314 sal_Bool bResult = sal_False;
315
316 ::comphelper::SequenceAsHashMap aHashData( aData );
317 uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );
318
319 if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 )
320 {
321 (void)memcpy( m_pDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 );
322 uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ), uno::Sequence< sal_Int8 >() );
323 if ( aUniqueID.getLength() == 16 )
324 {
325 (void)memcpy( m_pDocId, aUniqueID.getConstArray(), 16 );
326 bResult = sal_True;
327 lcl_PrintDigest(m_pDigestValue, "digest value");
328 lcl_PrintDigest(m_pDocId, "DocId value");
329 }
330 else
331 OSL_ENSURE( sal_False, "Unexpected document ID!\n" );
332 }
333 else
334 OSL_ENSURE( sal_False, "Unexpected key size!\n" );
335
336 return bResult;
337 }
338
GetEncryptionData()339 uno::Sequence< beans::NamedValue > MSCodec_Std97::GetEncryptionData()
340 {
341 ::comphelper::SequenceAsHashMap aHashData;
342 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)m_pDigestValue, RTL_DIGEST_LENGTH_MD5 );
343 aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)m_pDocId, 16 );
344
345 return aHashData.getAsConstNamedValueList();
346 }
347
InitKey(const sal_uInt16 pPassData[16],const sal_uInt8 pDocId[16])348 void MSCodec_Std97::InitKey (
349 const sal_uInt16 pPassData[16],
350 const sal_uInt8 pDocId[16])
351 {
352 #if DEBUG_MSO_ENCRYPTION_STD97
353 fprintf(stdout, "MSCodec_Std97::InitKey: --begin\n");fflush(stdout);
354 #endif
355 uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pPassData, uno::Sequence< sal_Int8 >( (sal_Int8*)pDocId, 16 ) );
356 // Fill raw digest of above updates into DigestValue.
357
358 if ( aKey.getLength() == sizeof(m_pDigestValue) )
359 (void)memcpy ( m_pDigestValue, aKey.getConstArray(), sizeof(m_pDigestValue) );
360 else
361 memset( m_pDigestValue, 0, sizeof(m_pDigestValue) );
362
363 lcl_PrintDigest(m_pDigestValue, "digest value");
364
365 (void)memcpy (m_pDocId, pDocId, 16);
366
367 lcl_PrintDigest(m_pDocId, "DocId value");
368 }
369
VerifyKey(const sal_uInt8 pSaltData[16],const sal_uInt8 pSaltDigest[16])370 bool MSCodec_Std97::VerifyKey (
371 const sal_uInt8 pSaltData[16],
372 const sal_uInt8 pSaltDigest[16])
373 {
374 // both the salt data and salt digest (hash) come from the document being imported.
375
376 #if DEBUG_MSO_ENCRYPTION_STD97
377 fprintf(stdout, "MSCodec_Std97::VerifyKey: \n");
378 lcl_PrintDigest(pSaltData, "salt data");
379 lcl_PrintDigest(pSaltDigest, "salt hash");
380 #endif
381 bool result = false;
382
383 if (InitCipher(0))
384 {
385 sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
386 GetDigestFromSalt(pSaltData, pDigest);
387
388 sal_uInt8 pBuffer[16];
389 // Decode original SaltDigest into Buffer.
390 rtl_cipher_decode (
391 m_hCipher, pSaltDigest, 16, pBuffer, sizeof(pBuffer));
392
393 // Compare Buffer with computed Digest.
394 result = (memcmp (pBuffer, pDigest, sizeof(pDigest)) == 0);
395
396 // Erase Buffer and Digest arrays.
397 (void)memset (pBuffer, 0, sizeof(pBuffer));
398 (void)memset (pDigest, 0, sizeof(pDigest));
399 }
400
401 return (result);
402 }
403
InitCipher(sal_uInt32 nCounter)404 bool MSCodec_Std97::InitCipher (sal_uInt32 nCounter)
405 {
406 rtlCipherError result;
407 sal_uInt8 pKeyData[64]; // 512-bit message block
408
409 // Initialize KeyData array.
410 (void)memset (pKeyData, 0, sizeof(pKeyData));
411
412 // Fill 40 bit of DigestValue into [0..4].
413 (void)memcpy (pKeyData, m_pDigestValue, 5);
414
415 // Fill counter into [5..8].
416 pKeyData[ 5] = sal_uInt8((nCounter >> 0) & 0xff);
417 pKeyData[ 6] = sal_uInt8((nCounter >> 8) & 0xff);
418 pKeyData[ 7] = sal_uInt8((nCounter >> 16) & 0xff);
419 pKeyData[ 8] = sal_uInt8((nCounter >> 24) & 0xff);
420
421 pKeyData[ 9] = 0x80;
422 pKeyData[56] = 0x48;
423
424 // Fill raw digest of KeyData into KeyData.
425 (void)rtl_digest_updateMD5 (
426 m_hDigest, pKeyData, sizeof(pKeyData));
427 (void)rtl_digest_rawMD5 (
428 m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5);
429
430 // Initialize Cipher with KeyData (for decoding).
431 result = rtl_cipher_init (
432 m_hCipher, rtl_Cipher_DirectionBoth,
433 pKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0);
434
435 // Erase KeyData array and leave.
436 (void)memset (pKeyData, 0, sizeof(pKeyData));
437
438 return (result == rtl_Cipher_E_None);
439 }
440
CreateSaltDigest(const sal_uInt8 nSaltData[16],sal_uInt8 nSaltDigest[16])441 bool MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] )
442 {
443 #if DEBUG_MSO_ENCRYPTION_STD97
444 lcl_PrintDigest(nSaltData, "salt data");
445 #endif
446 bool result = false;
447
448 if (InitCipher(0))
449 {
450 sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
451 GetDigestFromSalt(nSaltData, pDigest);
452
453 rtl_cipher_decode (
454 m_hCipher, pDigest, 16, pDigest, sizeof(pDigest));
455
456 (void)memcpy(nSaltDigest, pDigest, 16);
457 }
458
459 return (result);
460 }
461
Encode(const void * pData,sal_Size nDatLen,sal_uInt8 * pBuffer,sal_Size nBufLen)462 bool MSCodec_Std97::Encode (
463 const void *pData, sal_Size nDatLen,
464 sal_uInt8 *pBuffer, sal_Size nBufLen)
465 {
466 rtlCipherError result;
467
468 result = rtl_cipher_encode (
469 m_hCipher, pData, nDatLen, pBuffer, nBufLen);
470
471 return (result == rtl_Cipher_E_None);
472 }
473
Decode(const void * pData,sal_Size nDatLen,sal_uInt8 * pBuffer,sal_Size nBufLen)474 bool MSCodec_Std97::Decode (
475 const void *pData, sal_Size nDatLen,
476 sal_uInt8 *pBuffer, sal_Size nBufLen)
477 {
478 rtlCipherError result;
479
480 result = rtl_cipher_decode (
481 m_hCipher, pData, nDatLen, pBuffer, nBufLen);
482
483 return (result == rtl_Cipher_E_None);
484 }
485
Skip(sal_Size nDatLen)486 bool MSCodec_Std97::Skip( sal_Size nDatLen )
487 {
488 sal_uInt8 pnDummy[ 1024 ];
489 sal_Size nDatLeft = nDatLen;
490 bool bResult = true;
491
492 while (bResult && nDatLeft)
493 {
494 sal_Size nBlockLen = ::std::min< sal_Size >( nDatLeft, sizeof(pnDummy) );
495 bResult = Decode( pnDummy, nBlockLen, pnDummy, nBlockLen );
496 nDatLeft -= nBlockLen;
497 }
498
499 return bResult;
500 }
501
GetDigestFromSalt(const sal_uInt8 pSaltData[16],sal_uInt8 pDigest[16])502 void MSCodec_Std97::GetDigestFromSalt( const sal_uInt8 pSaltData[16], sal_uInt8 pDigest[16] )
503 {
504 sal_uInt8 pBuffer[64];
505 sal_uInt8 pDigestLocal[16];
506
507 // Decode SaltData into Buffer.
508 rtl_cipher_decode (
509 m_hCipher, pSaltData, 16, pBuffer, sizeof(pBuffer));
510
511 // set the 129th bit to make the buffer 128-bit in length.
512 pBuffer[16] = 0x80;
513
514 // erase the rest of the buffer with zeros.
515 (void)memset (pBuffer + 17, 0, sizeof(pBuffer) - 17);
516
517 // set the 441st bit.
518 pBuffer[56] = 0x80;
519
520 // Fill raw digest of Buffer into Digest.
521 rtl_digest_updateMD5 (
522 m_hDigest, pBuffer, sizeof(pBuffer));
523 rtl_digest_rawMD5 (
524 m_hDigest, pDigestLocal, sizeof(pDigestLocal));
525
526 memcpy(pDigest, pDigestLocal, 16);
527 }
528
GetEncryptKey(const sal_uInt8 pSalt[16],sal_uInt8 pSaltData[16],sal_uInt8 pSaltDigest[16])529 void MSCodec_Std97::GetEncryptKey (
530 const sal_uInt8 pSalt[16],
531 sal_uInt8 pSaltData[16],
532 sal_uInt8 pSaltDigest[16])
533 {
534 if (InitCipher(0))
535 {
536 sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
537 sal_uInt8 pBuffer[64];
538
539 rtl_cipher_encode (
540 m_hCipher, pSalt, 16, pSaltData, sizeof(pBuffer));
541
542 (void)memcpy( pBuffer, pSalt, 16 );
543
544 pBuffer[16] = 0x80;
545 (void)memset (pBuffer + 17, 0, sizeof(pBuffer) - 17);
546 pBuffer[56] = 0x80;
547
548 rtl_digest_updateMD5 (
549 m_hDigest, pBuffer, sizeof(pBuffer));
550 rtl_digest_rawMD5 (
551 m_hDigest, pDigest, sizeof(pDigest));
552
553 rtl_cipher_encode (
554 m_hCipher, pDigest, 16, pSaltDigest, 16);
555
556 (void)memset (pBuffer, 0, sizeof(pBuffer));
557 (void)memset (pDigest, 0, sizeof(pDigest));
558 }
559 }
560
GetDocId(sal_uInt8 pDocId[16])561 void MSCodec_Std97::GetDocId( sal_uInt8 pDocId[16] )
562 {
563 if ( sizeof( m_pDocId ) == 16 )
564 (void)memcpy( pDocId, m_pDocId, 16 );
565 }
566
567 // ============================================================================
568
569 } // namespace svx
570
571