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