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 <sal/types.h>
21 #include <cppunit/TestAssert.h>
22 #include <cppunit/TestFixture.h>
23 #include <cppunit/extensions/HelperMacros.h>
24 #include <cppunit/plugin/TestPlugIn.h>
25 
26 #include <memory>
27 
28 #include <rtl/digest.h>
29 #include <rtl/string.h>
30 #include <rtl/ustring.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/strbuf.hxx>
33 
34 #include <string.h>
35 
36 using namespace rtl;
37 
38 namespace
39 {
40 
41 const OString sSampleString               = "This is a sample sentence, which we use to check some crypto functions in sal.";
42 const OString sSampleString_only_one_diff = "This is a sample sentence. which we use to check some crypto functions in sal.";
43 
44 const rtlDigestAlgorithm constDigestAlgorithms[] =
45 {
46     rtl_Digest_AlgorithmMD2,
47     rtl_Digest_AlgorithmMD5,
48     rtl_Digest_AlgorithmSHA,
49     rtl_Digest_AlgorithmSHA1,
50     rtl_Digest_AlgorithmHMAC_MD5,
51     rtl_Digest_AlgorithmHMAC_SHA1,
52 };
53 
54 const sal_uInt32 constDigestAlgorithmLengths[] =
55 {
56     RTL_DIGEST_LENGTH_MD2,
57     RTL_DIGEST_LENGTH_MD5,
58     RTL_DIGEST_LENGTH_SHA,
59     RTL_DIGEST_LENGTH_SHA1,
60     RTL_DIGEST_LENGTH_HMAC_MD5,
61     RTL_DIGEST_LENGTH_HMAC_SHA1,
62 };
63 
64 const OString constSampleStringSums[] =
65 {
66     "647ee6c9d4aa5fdd374ed9d7a156acbf",
67     "b16b903e6fc0b62ae389013ed93fe531",
68     "eab2814429b2613301c8a077b806af3680548914",
69     "2bc5bdb7506a2cdc2fd27fc8b9889343012d5008",
70     "0b1b0e1a6f2e4420326354b031063605",
71     "1998c6a556915be76451bfb587fa7c34d849936e"
72 };
73 
74 // Create hex-value string from the digest value to keep the string size minimal
createHex(const sal_uInt8 * pKeyBuffer,sal_uInt32 nKeyLen)75 OString createHex(const sal_uInt8* pKeyBuffer, sal_uInt32 nKeyLen)
76 {
77     OStringBuffer aBuffer(nKeyLen * 2 + 1);
78     for (sal_uInt32 i = 0; i < nKeyLen; ++i)
79     {
80         sal_Int32 nValue = static_cast<sal_Int32>(pKeyBuffer[i]);
81         if (nValue < 16)
82             aBuffer.append('0');
83         aBuffer.append(nValue, 16);
84     }
85     return aBuffer.makeStringAndClear();
86 }
87 
getDigest(const OString & aMessage,rtlDigestAlgorithm aAlgorithm)88 OString getDigest(const OString& aMessage, rtlDigestAlgorithm aAlgorithm)
89 {
90     rtlDigest handle = rtl_digest_create(aAlgorithm);
91 
92     const sal_uInt8* pData = reinterpret_cast<const sal_uInt8*>(aMessage.getStr());
93     sal_uInt32       nSize = aMessage.getLength();
94 
95     rtl_digest_init(handle, pData, nSize);
96     rtl_digest_update(handle, pData, nSize);
97 
98     sal_uInt32 nKeyLen = rtl_digest_queryLength(handle);
99     std::unique_ptr<sal_uInt8[]> pKeyBuffer(new sal_uInt8[nKeyLen]);
100 
101     rtl_digest_get(handle, pKeyBuffer.get(), nKeyLen);
102     OString aSum = createHex(pKeyBuffer.get(), nKeyLen);
103 
104     rtl_digest_destroy( handle );
105     return aSum;
106 }
107 
108 class DigestTest : public CppUnit::TestFixture
109 {
110 public:
testCreate()111     void testCreate()
112     {
113         for (size_t i = 0; i < SAL_N_ELEMENTS(constDigestAlgorithms); i++)
114         {
115             rtlDigest handle = rtl_digest_create( constDigestAlgorithms[i] );
116             CPPUNIT_ASSERT_MESSAGE("create digest", handle != nullptr);
117             rtl_digest_destroy( handle );
118         }
119 
120         rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmInvalid );
121         CPPUNIT_ASSERT_EQUAL_MESSAGE("create invalid digest", static_cast<rtlDigest>(nullptr), handle);
122         rtl_digest_destroy( handle );
123     }
124 
testQuery()125     void testQuery()
126     {
127         for (size_t i = 0; i < SAL_N_ELEMENTS(constDigestAlgorithms); i++)
128         {
129             rtlDigest handle = rtl_digest_create(constDigestAlgorithms[i]);
130             rtlDigestAlgorithm aAlgo = rtl_digest_queryAlgorithm(handle);
131             CPPUNIT_ASSERT_EQUAL_MESSAGE("query handle", aAlgo, constDigestAlgorithms[i]);
132             rtl_digest_destroy( handle );
133         }
134 
135     }
136 
testQueryLength()137     void testQueryLength()
138     {
139         rtlDigest handle;
140         sal_uInt32 nAlgoLength;
141 
142         for (size_t i = 0; i < SAL_N_ELEMENTS(constDigestAlgorithms); i++)
143         {
144             handle = rtl_digest_create(constDigestAlgorithms[i]);
145             nAlgoLength = rtl_digest_queryLength(handle);
146             CPPUNIT_ASSERT_EQUAL_MESSAGE("query Length", nAlgoLength, constDigestAlgorithmLengths[i]);
147             rtl_digest_destroy( handle );
148         }
149 
150         handle = rtl_digest_create( rtl_Digest_AlgorithmInvalid );
151         nAlgoLength = rtl_digest_queryLength(handle);
152         CPPUNIT_ASSERT_EQUAL_MESSAGE("query length", static_cast<sal_uInt32>(0), nAlgoLength);
153         rtl_digest_destroy( handle );
154     }
155 
testInit()156     void testInit()
157     {
158         rtlDigestError aError;
159         rtlDigest handle;
160 
161         handle = nullptr;
162         aError = rtl_digest_init(handle, nullptr, 0);
163         CPPUNIT_ASSERT_EQUAL_MESSAGE("init(NULL, 0, 0)", rtl_Digest_E_Argument, aError);
164 
165         handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
166         aError = rtl_digest_init(handle, nullptr, 0);
167         CPPUNIT_ASSERT_EQUAL_MESSAGE("init(handle, 0, 0)", rtl_Digest_E_None, aError);
168         rtl_digest_destroy( handle );
169 
170         for (size_t i = 0; i < SAL_N_ELEMENTS(constDigestAlgorithms); i++)
171         {
172             handle = rtl_digest_create(constDigestAlgorithms[i]);
173 
174             OString aMessage = sSampleString;
175             const sal_uInt8* pData = reinterpret_cast<const sal_uInt8*>(aMessage.getStr());
176             sal_uInt32       nSize = aMessage.getLength();
177 
178             aError = rtl_digest_init(handle, pData, nSize);
179             CPPUNIT_ASSERT_EQUAL_MESSAGE("init(handle, pData, nSize)", rtl_Digest_E_None, aError);
180 
181             rtl_digest_update(handle, pData, nSize);
182 
183             sal_uInt32 nKeyLen = rtl_digest_queryLength( handle );
184             std::unique_ptr<sal_uInt8[]> pKeyBuffer(new sal_uInt8[nKeyLen]);
185 
186             rtl_digest_get( handle, pKeyBuffer.get(), nKeyLen );
187             createHex(pKeyBuffer.get(), nKeyLen);
188 
189             rtl_digest_destroy( handle );
190         }
191     }
192 
testEqual()193     void testEqual()
194     {
195         {
196             OString aMsg1 = sSampleString;
197             OString aMsg2 = sSampleString;
198 
199             OString aSum1 = getDigest(aMsg1, rtl_Digest_AlgorithmMD5);
200             OString aSum2 = getDigest(aMsg2, rtl_Digest_AlgorithmMD5);
201 
202             CPPUNIT_ASSERT_MESSAGE("md5sum must have a length", aSum1.getLength() == 32 && aSum2.getLength() == 32 );
203             CPPUNIT_ASSERT_EQUAL_MESSAGE("source is the same, dest must be also the same", aSum1, aSum2);
204         }
205 
206         {
207             OString aMsg1 = sSampleString;
208             OString aMsg2 = sSampleString_only_one_diff;
209 
210             OString aSum1 = getDigest(aMsg1, rtl_Digest_AlgorithmMD5);
211             OString aSum2 = getDigest(aMsg2, rtl_Digest_AlgorithmMD5);
212 
213             CPPUNIT_ASSERT_MESSAGE("md5sum must have a length", aSum1.getLength() == 32 && aSum2.getLength() == 32 );
214             CPPUNIT_ASSERT_MESSAGE("differ only in one char", aSum1 != aSum2);
215         }
216     }
217 
testCheckSum()218     void testCheckSum()
219     {
220         for (size_t i = 0; i < SAL_N_ELEMENTS(constDigestAlgorithms); i++)
221         {
222             OString aSum = getDigest(sSampleString, constDigestAlgorithms[i]);
223             CPPUNIT_ASSERT_EQUAL_MESSAGE("Checksum of sample string is wrong.", constSampleStringSums[i], aSum);
224         }
225     }
226 
runCheckPBKDF2(OString & sPassword,bool bClearSalt,sal_uInt32 nCount)227     OString runCheckPBKDF2(OString& sPassword, bool bClearSalt, sal_uInt32 nCount)
228     {
229         sal_uInt32 nKeyLen = RTL_DIGEST_LENGTH_HMAC_SHA1;
230         std::unique_ptr<sal_uInt8[]> pKeyBuffer(new sal_uInt8[nKeyLen]);
231 
232         memset(pKeyBuffer.get(), 0, nKeyLen);
233 
234         sal_uInt8 const * pPassword = reinterpret_cast<sal_uInt8 const *>(sPassword.getStr());
235         sal_Int32  nPasswordLen = sPassword.getLength();
236 
237         sal_uInt32   nSaltDataLen = RTL_DIGEST_LENGTH_HMAC_SHA1;
238         std::unique_ptr<sal_uInt8[]> pSaltData(new sal_uInt8[nSaltDataLen]);
239         memset(pSaltData.get(), 0, nSaltDataLen);
240 
241         if (!bClearSalt)
242         {
243             // wilful contamination
244             pSaltData[0] = 1;
245         }
246 
247         rtlDigestError aError = rtl_digest_PBKDF2(pKeyBuffer.get(), nKeyLen, pPassword, nPasswordLen, pSaltData.get(), nSaltDataLen, nCount);
248 
249         CPPUNIT_ASSERT_EQUAL(rtl_Digest_E_None, aError);
250 
251         OString aKey = createHex(pKeyBuffer.get(), nKeyLen);
252 
253         // OString sSalt = createHex(pSaltData, nSaltDataLen);
254         // printf("Salt: %s\n", sSalt.getStr());
255 
256         // CPPUNIT_ASSERT_MESSAGE("md5sum of sample string is wrong. Code changes or sample problems, please check.", aStr.equals(sSampleString_PBKDF2) );
257         return aKey;
258     }
259 
testPBKDF2()260     void testPBKDF2()
261     {
262         OString  aPassword = "Password";
263 
264         // all permutations
265         runCheckPBKDF2(aPassword, false, 1);
266         runCheckPBKDF2(aPassword, false, 2);
267         runCheckPBKDF2(aPassword, true,  1);
268         runCheckPBKDF2(aPassword, true,  2);
269         runCheckPBKDF2(aPassword, false, 3);
270         runCheckPBKDF2(aPassword, false, 4);
271         runCheckPBKDF2(aPassword, true,  3);
272         runCheckPBKDF2(aPassword, true,  4);
273     }
274 
testUpdate()275     void testUpdate()
276     {
277         rtlDigestError aError;
278         rtlDigest aHandle;
279 
280         aHandle = nullptr;
281         aError = rtl_digest_update(aHandle, nullptr, 0);
282         CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
283 
284         aHandle = nullptr;
285         aError = rtl_digest_updateMD2(aHandle, nullptr, 0);
286         CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
287 
288         aError = rtl_digest_updateMD5(aHandle, nullptr, 0);
289         CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
290 
291         aHandle = rtl_digest_create( rtl_Digest_AlgorithmMD2 );
292         CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
293 
294         const sal_uInt8* pData = reinterpret_cast<const sal_uInt8*>(sSampleString.getStr());
295         sal_uInt32       nSize = sSampleString.getLength();
296 
297         aError = rtl_digest_updateMD2(aHandle, nullptr, 0);
298         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
299 
300         aError = rtl_digest_updateMD2(aHandle, pData, 0);
301         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_None, aError);
302 
303         rtl_digest_destroyMD2(aHandle);
304 
305         // use wrong Algorithm!!! This is volitional!
306         aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD2);
307         CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
308 
309         aError = rtl_digest_updateMD5(aHandle, pData, nSize);
310         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'handle' wrong", rtl_Digest_E_Algorithm, aError);
311 
312         rtl_digest_destroyMD5(aHandle);
313 
314         aHandle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
315         CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD5", aHandle != nullptr);
316 
317         aError = rtl_digest_updateMD5(aHandle, nullptr, 0);
318         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
319 
320         aError = rtl_digest_updateMD5(aHandle, pData, 0);
321         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_None, aError);
322 
323         rtl_digest_destroyMD5(aHandle);
324     }
325 
testGet()326     void testGet()
327     {
328         rtlDigest aHandle;
329         rtlDigestError aError;
330 
331         aHandle = nullptr;
332         aError = rtl_digest_get(aHandle, nullptr, 0);
333         CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
334 
335         aHandle = nullptr;
336         aError = rtl_digest_getMD5(aHandle, nullptr, 0);
337         CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
338 
339         // test with wrong algorithm
340         aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD2);
341         CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
342 
343         sal_uInt32 nKeyLen = rtl_digest_queryLength(aHandle);
344         std::unique_ptr<sal_uInt8[]> pKeyBuffer(new sal_uInt8[nKeyLen]);
345 
346         aError = rtl_digest_getMD5(aHandle, nullptr, 0);
347         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle 2. parameter wrong", rtl_Digest_E_Argument, aError);
348 
349         aError = rtl_digest_getMD5(aHandle, pKeyBuffer.get(), 0);
350         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'handle' wrong", rtl_Digest_E_Algorithm, aError);
351 
352         rtl_digest_destroyMD2(aHandle);
353 
354         aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD5);
355         CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD5", aHandle != nullptr);
356 
357         aError = rtl_digest_getMD5(aHandle, nullptr, nKeyLen);
358         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
359 
360         aError = rtl_digest_getMD5(aHandle, pKeyBuffer.get(), 0);
361         CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_BufferSize, aError);
362 
363         rtl_digest_destroyMD5(aHandle);
364     }
365 
testSHA1SumForBiggerInputData()366     void testSHA1SumForBiggerInputData()
367     {
368         // The test data was extracted from oox encrypted document (salt + password).
369         // First  case: 16 bytes salt + 34 bytes password (12345678901234567)
370         // Second case: 16 bytes salt + 36 bytes password (123456789012345678)
371         {
372             const unsigned char aData[] = {
373                     0x37, 0x5f, 0x47, 0x7a, 0xd2, 0x13, 0xbe, 0xd2, 0x3c, 0x23, 0x33, 0x39,
374                     0x68, 0x21, 0x03, 0x6d, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00,
375                     0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x30, 0x00,
376                     0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
377                     0x37, 0x00
378             };
379 
380             std::unique_ptr<sal_uInt8[]> pResult(new sal_uInt8[RTL_DIGEST_LENGTH_SHA1]);
381 
382             OString sExpected = "06f460d693aecdd3b5cbe8365408eccfc570f32a";
383 
384             rtl_digest_SHA1(aData, sizeof(aData), pResult.get(), RTL_DIGEST_LENGTH_SHA1);
385 
386             OString sKey = createHex(pResult.get(), RTL_DIGEST_LENGTH_SHA1);
387 
388             CPPUNIT_ASSERT_EQUAL(sExpected, sKey);
389         }
390 
391         // tdf#114939, verify that rtl_digest_SHA1 computes broken results for certain input (which
392         // is not fixed for compatibility reasons):
393         {
394             sal_uInt8 result[RTL_DIGEST_LENGTH_SHA1];
395             rtl_digest_SHA1(
396                 RTL_CONSTASCII_STRINGPARAM("1012345678901234567890123456789012345678901234567890"),
397                 result, RTL_DIGEST_LENGTH_SHA1);
398             // Rather than correct "9cb1dab34448c1ea460da1f8736869c8852f212f":
399             CPPUNIT_ASSERT_EQUAL(
400                 OString("90a461ee9cc69cedaeb25c2dc5cc62544ebd5241"),
401                 createHex(result, RTL_DIGEST_LENGTH_SHA1));
402         }
403     }
404 
testMD5()405     void testMD5()
406     {
407         unsigned char const data[] = {
408             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
409             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
410             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
411             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
412             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
413             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
414             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
415             0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
416         };
417         OString const expected[] = {
418             "d41d8cd98f00b204e9800998ecf8427e",
419             "cfcd208495d565ef66e7dff9f98764da",
420             "b4b147bc522828731f1a016bfa72c073",
421             "c6f057b86584942e415435ffb1fa93d4",
422             "4a7d1ed414474e4033ac29ccb8653d9b",
423             "dcddb75469b4b4875094e14561e573d8",
424             "670b14728ad9902aecba32e22fa4f6bd",
425             "29c3eea3f305d6b823f562ac4be35217",
426             "dd4b21e9ef71e1291183a46b913ae6f2",
427             "4c93008615c2d041e33ebac605d14b5b",
428             "f1b708bba17f1ce948dc979f4d7092bc",
429             "645a8aca5a5b84527c57ee2f153f1946",
430             "35b9ab5a36f3234dd26db357fd4a0dc1",
431             "4aad0d9ff11812ebdd5e376fdbef6222",
432             "c47532bbb1e2883c902071591ae1ec9b",
433             "5284047f4ffb4e04824a2fd1d1f0cd62",
434             "1e4a1b03d1b6cd8a174a826f76e009f4",
435             "0e7b9f29a828b6f953b482fc299e536b",
436             "3ea032bf79e8c116b05f4698d5a8e044",
437             "15f47c8a3e5e9685307dd65a653b8dc0",
438             "cc545187d0745132de1e9941db0ef6ce",
439             "0585e303e79acd837c3a3e2a2bec8b18",
440             "b28ccfdee4b9f39ba18b58a4f61a03d1",
441             "d018229b1183c926c10ea688350afec8",
442             "660719b4a7591769583a7c8d20c6dfa4",
443             "1e2432adacf481836265fcc62ee8f3e3",
444             "6e88e2af74c1d9d7d7d652b90d03751e",
445             "780ca685003cec1d617beaa6f346e1be",
446             "7f2e1dcfd6e2a3f5c38f31e640136ff6",
447             "1a3dee46117aeb8010cf365b8653faa8",
448             "1d0064395af3c745f6c3194e92373d7a",
449             "b52582043219f2deb2d3c9cb05d6448a",
450             "cd9e459ea708a948d5c2f5a6ca8838cf",
451             "00de800ecd7a4fb2813986c987e46d51",
452             "15336d4b38561a82bd24c9398b781aed",
453             "5fe699d3c461ab5a795505f59d5adf15",
454             "c5e0eb03cbb4bea95ce3f8f48fca77d5",
455             "355c1410373ef02fff2b03844d72c7d4",
456             "02df97da8207de2b3afa69c151ca8958",
457             "82c66dbf3e73f87ffc9564b2098d6a4f",
458             "b373e3ddc3438d7c10c76f3ad9d4c401",
459             "fac901a4a3dbc4461541731a33a31d15",
460             "f573e011b414bf3f9dd284f7dad29592",
461             "11694570cc5dda099669f2ba3660a70d",
462             "60997cc8aef7fedd9995e6b3ca89ce26",
463             "63c5fcf83c2275fe64e880dd8dfc5cd6",
464             "c7a0a100057ebbfc63ee169562026aea",
465             "42c2dec247919384edece38033458627",
466             "b505acf9fc996902b0c547a2abfc62b2",
467             "2fa7a1321d6b5fa0e04ad46785f574f3",
468             "86d2bfc0bab44eecf21e1432be7b3efc",
469             "7ca318f12a0955a3e637dc5645a2f96e",
470             "3eda02765b8fb8bb9b20c735f4537827",
471             "26dead12262c9a5c115b01e0a3c805b6",
472             "978b0444e93c5f7d714575f28a77dca1",
473             "d7fe636bd28e2ee2ba4d6c5898318699",
474             "ce992c2ad906967c63c3f9ab0c2294a9",
475             "1f3b814e9d417e9fd8750299982feb1f",
476             "1a2f42174eaa78ce6a67d75e98a59cb6",
477             "17c772c45c9a09f6e56b7228ddd161a7",
478             "5b19445b70b493c78f3bc06eb7962315",
479             "e590c24cc612bdedd522dfe23bb29b42",
480             "4d78c699a0167bc0cfce8a5c5a715c0e",
481             "5703db92acb9d45e3975822c9206453f",
482             "10eab6008d5642cf42abd2aa41f847cb",
483         };
484         rtlDigest digest = rtl_digest_createMD5();
485         for (size_t i = 0; i < sizeof(data); ++i)
486         {
487             rtl_digest_updateMD5(digest, &data, i);
488             sal_uInt8 buf[RTL_DIGEST_LENGTH_MD5];
489             rtl_digest_getMD5(digest, &buf[0], sizeof(buf));
490             OString const sResult = createHex(&buf[0], sizeof(buf));
491             CPPUNIT_ASSERT_EQUAL(expected[i], sResult);
492         }
493         rtl_digest_destroyMD5(digest);
494     }
495 
496     CPPUNIT_TEST_SUITE(DigestTest);
497     CPPUNIT_TEST(testCreate);
498     CPPUNIT_TEST(testQuery);
499     CPPUNIT_TEST(testQueryLength);
500     CPPUNIT_TEST(testInit);
501     CPPUNIT_TEST(testEqual);
502     CPPUNIT_TEST(testCheckSum);
503     CPPUNIT_TEST(testPBKDF2);
504     CPPUNIT_TEST(testUpdate);
505     CPPUNIT_TEST(testGet);
506     CPPUNIT_TEST(testSHA1SumForBiggerInputData);
507     CPPUNIT_TEST(testMD5);
508 
509     CPPUNIT_TEST_SUITE_END();
510 };
511 
512 CPPUNIT_TEST_SUITE_REGISTRATION(DigestTest);
513 
514 } // namespace rtl_digest
515 
516 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
517