Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sal / rtl / digest.cxx
blob1000fc0aed025c9c963fd0859cc414765a918f2e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <string.h>
21 #include <stdlib.h>
23 #include <sal/types.h>
24 #include <osl/endian.h>
25 #include <rtl/alloc.h>
26 #include <rtl/digest.h>
28 #define RTL_DIGEST_CREATE(T) (static_cast<T*>(rtl_allocateZeroMemory(sizeof(T))))
30 #define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n))))
32 #define RTL_DIGEST_HTONL(l,c) \
33 (*((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff), \
34 *((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff), \
35 *((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff), \
36 *((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff))
38 #define RTL_DIGEST_LTOC(l,c) \
39 *((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff); \
40 *((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff); \
41 *((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff); \
42 *((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff);
44 typedef rtlDigestError (Digest_init_t) (
45 void *ctx, const sal_uInt8 *Data, sal_uInt32 DatLen);
47 typedef void (Digest_delete_t) (void *ctx);
49 typedef rtlDigestError (Digest_update_t) (
50 void *ctx, const void *Data, sal_uInt32 DatLen);
52 typedef rtlDigestError (Digest_get_t) (
53 void *ctx, sal_uInt8 *Buffer, sal_uInt32 BufLen);
55 struct Digest_Impl
57 rtlDigestAlgorithm m_algorithm;
58 sal_uInt32 m_length;
60 Digest_init_t *m_init;
61 Digest_delete_t *m_delete;
62 Digest_update_t *m_update;
63 Digest_get_t *m_get;
66 static void swapLong(sal_uInt32 *pData, sal_uInt32 nDatLen)
68 sal_uInt32 *X;
69 int i, n;
71 X = pData;
72 n = nDatLen;
74 for (i = 0; i < n; i++)
76 X[i] = OSL_SWAPDWORD(X[i]);
80 rtlDigest SAL_CALL rtl_digest_create(rtlDigestAlgorithm Algorithm)
81 SAL_THROW_EXTERN_C()
83 rtlDigest Digest = nullptr;
84 switch (Algorithm)
86 case rtl_Digest_AlgorithmMD2:
87 Digest = rtl_digest_createMD2();
88 break;
90 case rtl_Digest_AlgorithmMD5:
91 Digest = rtl_digest_createMD5();
92 break;
94 case rtl_Digest_AlgorithmSHA:
95 Digest = rtl_digest_createSHA();
96 break;
98 case rtl_Digest_AlgorithmSHA1:
99 Digest = rtl_digest_createSHA1();
100 break;
102 case rtl_Digest_AlgorithmHMAC_MD5:
103 Digest = rtl_digest_createHMAC_MD5();
104 break;
106 case rtl_Digest_AlgorithmHMAC_SHA1:
107 Digest = rtl_digest_createHMAC_SHA1();
108 break;
110 default: /* rtl_Digest_AlgorithmInvalid */
111 break;
113 return Digest;
116 rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm(rtlDigest Digest)
117 SAL_THROW_EXTERN_C()
119 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
120 if (pImpl)
121 return pImpl->m_algorithm;
122 return rtl_Digest_AlgorithmInvalid;
125 sal_uInt32 SAL_CALL rtl_digest_queryLength(rtlDigest Digest)
126 SAL_THROW_EXTERN_C()
128 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
129 if (pImpl)
130 return pImpl->m_length;
131 return 0;
134 rtlDigestError SAL_CALL rtl_digest_init(
135 rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
136 SAL_THROW_EXTERN_C()
138 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
139 if (pImpl)
141 if (pImpl->m_init)
142 return pImpl->m_init (Digest, pData, nDatLen);
143 return rtl_Digest_E_None;
145 return rtl_Digest_E_Argument;
148 rtlDigestError SAL_CALL rtl_digest_update(
149 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
150 SAL_THROW_EXTERN_C()
152 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
153 if (pImpl && pImpl->m_update)
154 return pImpl->m_update(Digest, pData, nDatLen);
155 return rtl_Digest_E_Argument;
158 rtlDigestError SAL_CALL rtl_digest_get(
159 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
160 SAL_THROW_EXTERN_C()
162 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
163 if (pImpl && pImpl->m_get)
164 return pImpl->m_get(Digest, pBuffer, nBufLen);
165 return rtl_Digest_E_Argument;
168 void SAL_CALL rtl_digest_destroy(rtlDigest Digest) SAL_THROW_EXTERN_C()
170 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
171 if (pImpl && pImpl->m_delete)
172 pImpl->m_delete(Digest);
175 #define DIGEST_CBLOCK_MD2 16
176 #define DIGEST_LBLOCK_MD2 16
178 struct DigestContextMD2
180 sal_uInt32 m_nDatLen;
181 sal_uInt8 m_pData[DIGEST_CBLOCK_MD2];
182 sal_uInt32 m_state[DIGEST_LBLOCK_MD2];
183 sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2];
186 struct DigestMD2_Impl
188 Digest_Impl m_digest;
189 DigestContextMD2 m_context;
192 static void initMD2 (DigestContextMD2 *ctx);
193 static void updateMD2 (DigestContextMD2 *ctx);
194 static void endMD2 (DigestContextMD2 *ctx);
196 static const sal_uInt32 S[256] =
198 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
199 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
200 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
201 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
202 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
203 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
204 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
205 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
206 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
207 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
208 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
209 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
210 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
211 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
212 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
213 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
214 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
215 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
216 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
217 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
218 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
219 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
220 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
221 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
222 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
223 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
224 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
225 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
226 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
227 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
228 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
229 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
232 static const Digest_Impl MD2 =
234 rtl_Digest_AlgorithmMD2,
235 RTL_DIGEST_LENGTH_MD2,
236 nullptr,
237 rtl_digest_destroyMD2,
238 rtl_digest_updateMD2,
239 rtl_digest_getMD2
242 static void initMD2(DigestContextMD2 *ctx)
244 memset(ctx, 0, sizeof(DigestContextMD2));
247 static void updateMD2(DigestContextMD2 *ctx)
249 sal_uInt8 *X;
250 sal_uInt32 *sp1, *sp2;
251 sal_uInt32 i, k, t;
253 sal_uInt32 state[48];
255 X = ctx->m_pData;
256 sp1 = ctx->m_state;
257 sp2 = ctx->m_chksum;
259 k = sp2[DIGEST_LBLOCK_MD2 - 1];
260 for (i = 0; i < 16; i++)
262 state[i + 0] = sp1[i];
263 state[i + 16] = t = X[i];
264 state[i + 32] = t ^ sp1[i];
265 k = sp2[i] ^= S[t^k];
268 t = 0;
269 for (i = 0; i < 18; i++)
271 for (k = 0; k < 48; k += 8)
273 t = state[k + 0] ^= S[t];
274 t = state[k + 1] ^= S[t];
275 t = state[k + 2] ^= S[t];
276 t = state[k + 3] ^= S[t];
277 t = state[k + 4] ^= S[t];
278 t = state[k + 5] ^= S[t];
279 t = state[k + 6] ^= S[t];
280 t = state[k + 7] ^= S[t];
282 t = ((t + i) & 0xff);
285 memcpy(sp1, state, 16 * sizeof(sal_uInt32));
286 rtl_secureZeroMemory(state, 48 * sizeof(sal_uInt32));
289 static void endMD2(DigestContextMD2 *ctx)
291 sal_uInt8 *X;
292 sal_uInt32 *C;
293 sal_uInt32 i, n;
295 X = ctx->m_pData;
296 C = ctx->m_chksum;
297 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
299 for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
300 X[i] = static_cast<sal_uInt8>(n & 0xff);
302 updateMD2(ctx);
304 for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
305 X[i] = static_cast<sal_uInt8>(C[i] & 0xff);
306 updateMD2(ctx);
309 rtlDigestError SAL_CALL rtl_digest_MD2(
310 const void *pData, sal_uInt32 nDatLen,
311 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
313 DigestMD2_Impl digest;
314 rtlDigestError result;
316 digest.m_digest = MD2;
317 initMD2(&(digest.m_context));
319 result = rtl_digest_updateMD2(&digest, pData, nDatLen);
320 if (result == rtl_Digest_E_None)
321 result = rtl_digest_getMD2(&digest, pBuffer, nBufLen);
323 rtl_secureZeroMemory(&digest, sizeof(digest));
324 return result;
327 rtlDigest SAL_CALL rtl_digest_createMD2() SAL_THROW_EXTERN_C()
329 DigestMD2_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
330 if (pImpl)
332 pImpl->m_digest = MD2;
333 initMD2(&(pImpl->m_context));
335 return static_cast<rtlDigest>(pImpl);
338 rtlDigestError SAL_CALL rtl_digest_updateMD2(
339 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
340 SAL_THROW_EXTERN_C()
342 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
343 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
345 DigestContextMD2 *ctx;
347 if (!pImpl || !pData)
348 return rtl_Digest_E_Argument;
350 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
351 return rtl_Digest_E_Algorithm;
353 if (nDatLen == 0)
354 return rtl_Digest_E_None;
356 ctx = &(pImpl->m_context);
358 if (ctx->m_nDatLen)
360 sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen;
361 sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
363 if (nDatLen < n)
365 memcpy(p, d, nDatLen);
366 ctx->m_nDatLen += nDatLen;
368 return rtl_Digest_E_None;
371 memcpy(p, d, n);
372 d += n;
373 nDatLen -= n;
375 updateMD2(ctx);
376 ctx->m_nDatLen = 0;
379 while (nDatLen >= DIGEST_CBLOCK_MD2)
381 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD2);
382 d += DIGEST_CBLOCK_MD2;
383 nDatLen -= DIGEST_CBLOCK_MD2;
385 updateMD2(ctx);
388 memcpy(ctx->m_pData, d, nDatLen);
389 ctx->m_nDatLen = nDatLen;
391 return rtl_Digest_E_None;
394 rtlDigestError SAL_CALL rtl_digest_getMD2(
395 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
396 SAL_THROW_EXTERN_C()
398 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
399 sal_uInt32 i;
401 DigestContextMD2 *ctx;
403 if (!pImpl || !pBuffer)
404 return rtl_Digest_E_Argument;
406 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
407 return rtl_Digest_E_Algorithm;
409 if (pImpl->m_digest.m_length > nBufLen)
410 return rtl_Digest_E_BufferSize;
412 ctx = &(pImpl->m_context);
414 endMD2(ctx);
415 for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
417 pBuffer[i] = static_cast<sal_uInt8>(ctx->m_state[i] & 0xff);
420 initMD2(ctx);
422 return rtl_Digest_E_None;
425 void SAL_CALL rtl_digest_destroyMD2(rtlDigest Digest) SAL_THROW_EXTERN_C()
427 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
428 if (pImpl)
430 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2)
431 rtl_freeZeroMemory(pImpl, sizeof(DigestMD2_Impl));
432 else
433 free(pImpl);
437 #define DIGEST_CBLOCK_MD5 64
438 #define DIGEST_LBLOCK_MD5 16
440 struct DigestContextMD5
442 sal_uInt32 m_nDatLen;
443 sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
444 sal_uInt32 m_nA, m_nB, m_nC, m_nD;
445 sal_uInt32 m_nL, m_nH;
448 struct DigestMD5_Impl
450 Digest_Impl m_digest;
451 DigestContextMD5 m_context;
454 static void initMD5 (DigestContextMD5 *ctx);
455 static void updateMD5 (DigestContextMD5 *ctx);
456 static void endMD5 (DigestContextMD5 *ctx);
458 #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
459 #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
460 #define H(x,y,z) ((x) ^ (y) ^ (z))
461 #define I(x,y,z) (((x) | (~(z))) ^ (y))
463 #define R0(a,b,c,d,k,s,t) { \
464 a += ((k) + (t) + F((b), (c), (d))); \
465 a = RTL_DIGEST_ROTL(a, s); \
466 a += b; }
468 #define R1(a,b,c,d,k,s,t) { \
469 a += ((k) + (t) + G((b), (c), (d))); \
470 a = RTL_DIGEST_ROTL(a, s); \
471 a += b; }
473 #define R2(a,b,c,d,k,s,t) { \
474 a += ((k) + (t) + H((b), (c), (d))); \
475 a = RTL_DIGEST_ROTL(a, s); \
476 a += b; }
478 #define R3(a,b,c,d,k,s,t) { \
479 a += ((k) + (t) + I((b), (c), (d))); \
480 a = RTL_DIGEST_ROTL(a, s); \
481 a += b; }
483 static const Digest_Impl MD5 =
485 rtl_Digest_AlgorithmMD5,
486 RTL_DIGEST_LENGTH_MD5,
487 nullptr,
488 rtl_digest_destroyMD5,
489 rtl_digest_updateMD5,
490 rtl_digest_getMD5
493 static void initMD5(DigestContextMD5 *ctx)
495 memset(ctx, 0, sizeof(DigestContextMD5));
497 ctx->m_nA = sal_uInt32(0x67452301L);
498 ctx->m_nB = sal_uInt32(0xefcdab89L);
499 ctx->m_nC = sal_uInt32(0x98badcfeL);
500 ctx->m_nD = sal_uInt32(0x10325476L);
503 static void updateMD5(DigestContextMD5 *ctx)
505 sal_uInt32 A, B, C, D;
506 sal_uInt32 *X;
508 A = ctx->m_nA;
509 B = ctx->m_nB;
510 C = ctx->m_nC;
511 D = ctx->m_nD;
512 X = ctx->m_pData;
514 R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L);
515 R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
516 R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
517 R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
518 R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL);
519 R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
520 R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
521 R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
522 R0 (A, B, C, D, X[ 8], 7, 0x698098d8L);
523 R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
524 R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
525 R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
526 R0 (A, B, C, D, X[12], 7, 0x6b901122L);
527 R0 (D, A, B, C, X[13], 12, 0xfd987193L);
528 R0 (C, D, A, B, X[14], 17, 0xa679438eL);
529 R0 (B, C, D, A, X[15], 22, 0x49b40821L);
531 R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L);
532 R1 (D, A, B, C, X[ 6], 9, 0xc040b340L);
533 R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
534 R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
535 R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL);
536 R1 (D, A, B, C, X[10], 9, 0x02441453L);
537 R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
538 R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
539 R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L);
540 R1 (D, A, B, C, X[14], 9, 0xc33707d6L);
541 R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
542 R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
543 R1 (A, B, C, D, X[13], 5, 0xa9e3e905L);
544 R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L);
545 R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
546 R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
548 R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L);
549 R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
550 R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
551 R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
552 R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L);
553 R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
554 R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
555 R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
556 R2 (A, B, C, D, X[13], 4, 0x289b7ec6L);
557 R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
558 R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
559 R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
560 R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L);
561 R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
562 R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
563 R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
565 R3 (A, B, C, D, X[ 0], 6, 0xf4292244L);
566 R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
567 R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
568 R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
569 R3 (A, B, C, D, X[12], 6, 0x655b59c3L);
570 R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
571 R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
572 R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
573 R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL);
574 R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
575 R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
576 R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
577 R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L);
578 R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
579 R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
580 R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
582 ctx->m_nA += A;
583 ctx->m_nB += B;
584 ctx->m_nC += C;
585 ctx->m_nD += D;
588 static void endMD5(DigestContextMD5 *ctx)
590 static const sal_uInt8 end[4] =
592 0x80, 0x00, 0x00, 0x00
594 const sal_uInt8 *p = end;
596 sal_uInt32 *X;
597 int i;
599 X = ctx->m_pData;
600 i = (ctx->m_nDatLen >> 2);
602 #ifdef OSL_BIGENDIAN
603 swapLong(X, i + 1);
604 #endif /* OSL_BIGENDIAN */
606 switch (ctx->m_nDatLen & 0x03)
608 case 1: X[i] &= 0x000000ff; break;
609 case 2: X[i] &= 0x0000ffff; break;
610 case 3: X[i] &= 0x00ffffff; break;
613 switch (ctx->m_nDatLen & 0x03)
615 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
616 [[fallthrough]];
617 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
618 [[fallthrough]];
619 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
620 [[fallthrough]];
621 case 3: X[i] |= static_cast<sal_uInt32>(*p) << 24;
624 i += 1;
626 if (i > (DIGEST_LBLOCK_MD5 - 2))
628 for (; i < DIGEST_LBLOCK_MD5; i++)
630 X[i] = 0;
633 updateMD5(ctx);
634 i = 0;
637 for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
638 X[i] = 0;
640 X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
641 X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
643 updateMD5(ctx);
646 rtlDigestError SAL_CALL rtl_digest_MD5(
647 const void *pData, sal_uInt32 nDatLen,
648 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
650 DigestMD5_Impl digest;
651 rtlDigestError result;
653 digest.m_digest = MD5;
654 initMD5(&(digest.m_context));
656 result = rtl_digest_update(&digest, pData, nDatLen);
657 if (result == rtl_Digest_E_None)
658 result = rtl_digest_getMD5(&digest, pBuffer, nBufLen);
660 rtl_secureZeroMemory(&digest, sizeof(digest));
661 return result;
664 rtlDigest SAL_CALL rtl_digest_createMD5() SAL_THROW_EXTERN_C()
666 DigestMD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
667 if (pImpl)
669 pImpl->m_digest = MD5;
670 initMD5(&(pImpl->m_context));
672 return static_cast<rtlDigest>(pImpl);
675 rtlDigestError SAL_CALL rtl_digest_updateMD5(
676 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
677 SAL_THROW_EXTERN_C()
679 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
680 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
682 DigestContextMD5 *ctx;
683 sal_uInt32 len;
685 if (!pImpl || !pData)
686 return rtl_Digest_E_Argument;
688 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
689 return rtl_Digest_E_Algorithm;
691 if (nDatLen == 0)
692 return rtl_Digest_E_None;
694 ctx = &(pImpl->m_context);
696 len = ctx->m_nL + (nDatLen << 3);
697 if (len < ctx->m_nL)
698 ctx->m_nH += 1;
700 ctx->m_nH += (nDatLen >> 29);
701 ctx->m_nL = len;
703 if (ctx->m_nDatLen)
705 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
706 sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
708 if (nDatLen < n)
710 memcpy(p, d, nDatLen);
711 ctx->m_nDatLen += nDatLen;
713 return rtl_Digest_E_None;
716 memcpy(p, d, n);
717 d += n;
718 nDatLen -= n;
720 #ifdef OSL_BIGENDIAN
721 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
722 #endif /* OSL_BIGENDIAN */
724 updateMD5(ctx);
725 ctx->m_nDatLen = 0;
728 while (nDatLen >= DIGEST_CBLOCK_MD5)
730 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD5);
731 d += DIGEST_CBLOCK_MD5;
732 nDatLen -= DIGEST_CBLOCK_MD5;
734 #ifdef OSL_BIGENDIAN
735 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
736 #endif /* OSL_BIGENDIAN */
738 updateMD5(ctx);
741 memcpy(ctx->m_pData, d, nDatLen);
742 ctx->m_nDatLen = nDatLen;
744 return rtl_Digest_E_None;
747 rtlDigestError SAL_CALL rtl_digest_getMD5(
748 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
749 SAL_THROW_EXTERN_C()
751 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
752 sal_uInt8 *p = pBuffer;
754 DigestContextMD5 *ctx;
756 if (!pImpl || !pBuffer)
757 return rtl_Digest_E_Argument;
759 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
760 return rtl_Digest_E_Algorithm;
762 if (pImpl->m_digest.m_length > nBufLen)
763 return rtl_Digest_E_BufferSize;
765 ctx = &(pImpl->m_context);
767 endMD5(ctx);
768 RTL_DIGEST_LTOC(ctx->m_nA, p);
769 RTL_DIGEST_LTOC(ctx->m_nB, p);
770 RTL_DIGEST_LTOC(ctx->m_nC, p);
771 RTL_DIGEST_LTOC(ctx->m_nD, p);
772 initMD5(ctx);
774 return rtl_Digest_E_None;
777 rtlDigestError SAL_CALL rtl_digest_rawMD5(
778 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
779 SAL_THROW_EXTERN_C()
781 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
782 sal_uInt8 *p = pBuffer;
784 DigestContextMD5 *ctx;
786 if (!pImpl || !pBuffer)
787 return rtl_Digest_E_Argument;
789 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
790 return rtl_Digest_E_Algorithm;
792 if (pImpl->m_digest.m_length > nBufLen)
793 return rtl_Digest_E_BufferSize;
795 ctx = &(pImpl->m_context);
797 /* not finalized */
798 RTL_DIGEST_LTOC(ctx->m_nA, p);
799 RTL_DIGEST_LTOC(ctx->m_nB, p);
800 RTL_DIGEST_LTOC(ctx->m_nC, p);
801 RTL_DIGEST_LTOC(ctx->m_nD, p);
802 initMD5(ctx);
804 return rtl_Digest_E_None;
807 void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
809 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
810 if (pImpl)
812 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
813 rtl_freeZeroMemory(pImpl, sizeof(DigestMD5_Impl));
814 else
815 free(pImpl);
819 #define DIGEST_CBLOCK_SHA 64
820 #define DIGEST_LBLOCK_SHA 16
822 typedef sal_uInt32 DigestSHA_update_t(sal_uInt32 x);
824 static sal_uInt32 updateSHA_0(sal_uInt32 x);
825 static sal_uInt32 updateSHA_1(sal_uInt32 x);
827 struct DigestContextSHA
829 DigestSHA_update_t *m_update;
830 sal_uInt32 m_nDatLen;
831 sal_uInt32 m_pData[DIGEST_LBLOCK_SHA];
832 sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE;
833 sal_uInt32 m_nL, m_nH;
836 struct DigestSHA_Impl
838 Digest_Impl m_digest;
839 DigestContextSHA m_context;
842 static void initSHA(
843 DigestContextSHA *ctx, DigestSHA_update_t *fct);
845 static void updateSHA(DigestContextSHA *ctx);
846 static void endSHA(DigestContextSHA *ctx);
848 #define K_00_19 sal_uInt32(0x5a827999L)
849 #define K_20_39 sal_uInt32(0x6ed9eba1L)
850 #define K_40_59 sal_uInt32(0x8f1bbcdcL)
851 #define K_60_79 sal_uInt32(0xca62c1d6L)
853 #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
854 #define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
855 #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
856 #define F_60_79(b,c,d) F_20_39(b,c,d)
858 #define BODY_X(i) \
859 (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
861 #define BODY_00_15(u,i,a,b,c,d,e,f) \
862 (f) = X[i]; \
863 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
864 (b) = RTL_DIGEST_ROTL((b), 30);
866 #define BODY_16_19(u,i,a,b,c,d,e,f) \
867 (f) = BODY_X((i)); \
868 (f) = X[(i)&0x0f] = (u)((f)); \
869 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
870 (b) = RTL_DIGEST_ROTL((b), 30);
872 #define BODY_20_39(u,i,a,b,c,d,e,f) \
873 (f) = BODY_X((i)); \
874 (f) = X[(i)&0x0f] = (u)((f)); \
875 (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
876 (b) = RTL_DIGEST_ROTL((b), 30);
878 #define BODY_40_59(u,i,a,b,c,d,e,f) \
879 (f) = BODY_X((i)); \
880 (f) = X[(i)&0x0f] = (u)((f)); \
881 (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
882 (b) = RTL_DIGEST_ROTL((b), 30);
884 #define BODY_60_79(u,i,a,b,c,d,e,f) \
885 (f) = BODY_X((i)); \
886 (f) = X[(i)&0x0f] = (u)((f)); \
887 (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
888 (b) = RTL_DIGEST_ROTL((b), 30);
890 static void initSHA(
891 DigestContextSHA *ctx, DigestSHA_update_t *fct)
893 memset(ctx, 0, sizeof(DigestContextSHA));
894 ctx->m_update = fct;
896 ctx->m_nA = sal_uInt32(0x67452301L);
897 ctx->m_nB = sal_uInt32(0xefcdab89L);
898 ctx->m_nC = sal_uInt32(0x98badcfeL);
899 ctx->m_nD = sal_uInt32(0x10325476L);
900 ctx->m_nE = sal_uInt32(0xc3d2e1f0L);
903 static void updateSHA(DigestContextSHA *ctx)
905 sal_uInt32 A, B, C, D, E, T;
906 sal_uInt32 *X;
908 DigestSHA_update_t *U;
909 U = ctx->m_update;
911 A = ctx->m_nA;
912 B = ctx->m_nB;
913 C = ctx->m_nC;
914 D = ctx->m_nD;
915 E = ctx->m_nE;
916 X = ctx->m_pData;
918 BODY_00_15 (U, 0, A, B, C, D, E, T);
919 BODY_00_15 (U, 1, T, A, B, C, D, E);
920 BODY_00_15 (U, 2, E, T, A, B, C, D);
921 BODY_00_15 (U, 3, D, E, T, A, B, C);
922 BODY_00_15 (U, 4, C, D, E, T, A, B);
923 BODY_00_15 (U, 5, B, C, D, E, T, A);
924 BODY_00_15 (U, 6, A, B, C, D, E, T);
925 BODY_00_15 (U, 7, T, A, B, C, D, E);
926 BODY_00_15 (U, 8, E, T, A, B, C, D);
927 BODY_00_15 (U, 9, D, E, T, A, B, C);
928 BODY_00_15 (U, 10, C, D, E, T, A, B);
929 BODY_00_15 (U, 11, B, C, D, E, T, A);
930 BODY_00_15 (U, 12, A, B, C, D, E, T);
931 BODY_00_15 (U, 13, T, A, B, C, D, E);
932 BODY_00_15 (U, 14, E, T, A, B, C, D);
933 BODY_00_15 (U, 15, D, E, T, A, B, C);
934 BODY_16_19 (U, 16, C, D, E, T, A, B);
935 BODY_16_19 (U, 17, B, C, D, E, T, A);
936 BODY_16_19 (U, 18, A, B, C, D, E, T);
937 BODY_16_19 (U, 19, T, A, B, C, D, E);
939 BODY_20_39 (U, 20, E, T, A, B, C, D);
940 BODY_20_39 (U, 21, D, E, T, A, B, C);
941 BODY_20_39 (U, 22, C, D, E, T, A, B);
942 BODY_20_39 (U, 23, B, C, D, E, T, A);
943 BODY_20_39 (U, 24, A, B, C, D, E, T);
944 BODY_20_39 (U, 25, T, A, B, C, D, E);
945 BODY_20_39 (U, 26, E, T, A, B, C, D);
946 BODY_20_39 (U, 27, D, E, T, A, B, C);
947 BODY_20_39 (U, 28, C, D, E, T, A, B);
948 BODY_20_39 (U, 29, B, C, D, E, T, A);
949 BODY_20_39 (U, 30, A, B, C, D, E, T);
950 BODY_20_39 (U, 31, T, A, B, C, D, E);
951 BODY_20_39 (U, 32, E, T, A, B, C, D);
952 BODY_20_39 (U, 33, D, E, T, A, B, C);
953 BODY_20_39 (U, 34, C, D, E, T, A, B);
954 BODY_20_39 (U, 35, B, C, D, E, T, A);
955 BODY_20_39 (U, 36, A, B, C, D, E, T);
956 BODY_20_39 (U, 37, T, A, B, C, D, E);
957 BODY_20_39 (U, 38, E, T, A, B, C, D);
958 BODY_20_39 (U, 39, D, E, T, A, B, C);
960 BODY_40_59 (U, 40, C, D, E, T, A, B);
961 BODY_40_59 (U, 41, B, C, D, E, T, A);
962 BODY_40_59 (U, 42, A, B, C, D, E, T);
963 BODY_40_59 (U, 43, T, A, B, C, D, E);
964 BODY_40_59 (U, 44, E, T, A, B, C, D);
965 BODY_40_59 (U, 45, D, E, T, A, B, C);
966 BODY_40_59 (U, 46, C, D, E, T, A, B);
967 BODY_40_59 (U, 47, B, C, D, E, T, A);
968 BODY_40_59 (U, 48, A, B, C, D, E, T);
969 BODY_40_59 (U, 49, T, A, B, C, D, E);
970 BODY_40_59 (U, 50, E, T, A, B, C, D);
971 BODY_40_59 (U, 51, D, E, T, A, B, C);
972 BODY_40_59 (U, 52, C, D, E, T, A, B);
973 BODY_40_59 (U, 53, B, C, D, E, T, A);
974 BODY_40_59 (U, 54, A, B, C, D, E, T);
975 BODY_40_59 (U, 55, T, A, B, C, D, E);
976 BODY_40_59 (U, 56, E, T, A, B, C, D);
977 BODY_40_59 (U, 57, D, E, T, A, B, C);
978 BODY_40_59 (U, 58, C, D, E, T, A, B);
979 BODY_40_59 (U, 59, B, C, D, E, T, A);
981 BODY_60_79 (U, 60, A, B, C, D, E, T);
982 BODY_60_79 (U, 61, T, A, B, C, D, E);
983 BODY_60_79 (U, 62, E, T, A, B, C, D);
984 BODY_60_79 (U, 63, D, E, T, A, B, C);
985 BODY_60_79 (U, 64, C, D, E, T, A, B);
986 BODY_60_79 (U, 65, B, C, D, E, T, A);
987 BODY_60_79 (U, 66, A, B, C, D, E, T);
988 BODY_60_79 (U, 67, T, A, B, C, D, E);
989 BODY_60_79 (U, 68, E, T, A, B, C, D);
990 BODY_60_79 (U, 69, D, E, T, A, B, C);
991 BODY_60_79 (U, 70, C, D, E, T, A, B);
992 BODY_60_79 (U, 71, B, C, D, E, T, A);
993 BODY_60_79 (U, 72, A, B, C, D, E, T);
994 BODY_60_79 (U, 73, T, A, B, C, D, E);
995 BODY_60_79 (U, 74, E, T, A, B, C, D);
996 BODY_60_79 (U, 75, D, E, T, A, B, C);
997 BODY_60_79 (U, 76, C, D, E, T, A, B);
998 BODY_60_79 (U, 77, B, C, D, E, T, A);
999 BODY_60_79 (U, 78, A, B, C, D, E, T);
1000 BODY_60_79 (U, 79, T, A, B, C, D, E);
1002 ctx->m_nA += E;
1003 ctx->m_nB += T;
1004 ctx->m_nC += A;
1005 ctx->m_nD += B;
1006 ctx->m_nE += C;
1009 static void endSHA(DigestContextSHA *ctx)
1011 static const sal_uInt8 end[4] =
1013 0x80, 0x00, 0x00, 0x00
1015 const sal_uInt8 *p = end;
1017 sal_uInt32 *X;
1018 int i;
1020 X = ctx->m_pData;
1021 i = (ctx->m_nDatLen >> 2);
1023 #ifdef OSL_BIGENDIAN
1024 swapLong(X, i + 1);
1025 #endif /* OSL_BIGENDIAN */
1027 switch (ctx->m_nDatLen & 0x03)
1029 case 1: X[i] &= 0x000000ff; break;
1030 case 2: X[i] &= 0x0000ffff; break;
1031 case 3: X[i] &= 0x00ffffff; break;
1034 switch (ctx->m_nDatLen & 0x03)
1036 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
1037 [[fallthrough]];
1038 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
1039 [[fallthrough]];
1040 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
1041 [[fallthrough]];
1042 case 3: X[i] |= static_cast<sal_uInt32>(*(p++)) << 24;
1045 swapLong(X, i + 1);
1047 i += 1;
1049 // tdf#114939 NB: this is WRONG and should be ">" not ">=" but is not
1050 // fixed as this buggy SHA1 implementation is needed for compatibility
1051 if (i >= (DIGEST_LBLOCK_SHA - 2))
1053 for (; i < DIGEST_LBLOCK_SHA; i++)
1055 X[i] = 0;
1058 updateSHA(ctx);
1059 i = 0;
1062 for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
1064 X[i] = 0;
1067 X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
1068 X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
1070 updateSHA(ctx);
1073 static const Digest_Impl SHA_0 =
1075 rtl_Digest_AlgorithmSHA,
1076 RTL_DIGEST_LENGTH_SHA,
1077 nullptr,
1078 rtl_digest_destroySHA,
1079 rtl_digest_updateSHA,
1080 rtl_digest_getSHA
1083 static sal_uInt32 updateSHA_0(sal_uInt32 x)
1085 return x;
1088 rtlDigestError SAL_CALL rtl_digest_SHA(
1089 const void *pData, sal_uInt32 nDatLen,
1090 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1092 DigestSHA_Impl digest;
1093 rtlDigestError result;
1095 digest.m_digest = SHA_0;
1096 initSHA(&(digest.m_context), updateSHA_0);
1098 result = rtl_digest_updateSHA(&digest, pData, nDatLen);
1099 if (result == rtl_Digest_E_None)
1100 result = rtl_digest_getSHA(&digest, pBuffer, nBufLen);
1102 rtl_secureZeroMemory(&digest, sizeof(digest));
1103 return result;
1106 rtlDigest SAL_CALL rtl_digest_createSHA() SAL_THROW_EXTERN_C()
1108 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1109 if (pImpl)
1111 pImpl->m_digest = SHA_0;
1112 initSHA(&(pImpl->m_context), updateSHA_0);
1114 return static_cast<rtlDigest>(pImpl);
1117 rtlDigestError SAL_CALL rtl_digest_updateSHA(
1118 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1119 SAL_THROW_EXTERN_C()
1121 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1122 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
1124 DigestContextSHA *ctx;
1125 sal_uInt32 len;
1127 if (!pImpl || !pData)
1128 return rtl_Digest_E_Argument;
1130 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1131 return rtl_Digest_E_Algorithm;
1133 if (nDatLen == 0)
1134 return rtl_Digest_E_None;
1136 ctx = &(pImpl->m_context);
1138 len = ctx->m_nL + (nDatLen << 3);
1139 if (len < ctx->m_nL)
1140 ctx->m_nH += 1;
1142 ctx->m_nH += (nDatLen >> 29);
1143 ctx->m_nL = len;
1145 if (ctx->m_nDatLen)
1147 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1148 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1150 if (nDatLen < n)
1152 memcpy(p, d, nDatLen);
1153 ctx->m_nDatLen += nDatLen;
1155 return rtl_Digest_E_None;
1158 memcpy(p, d, n);
1159 d += n;
1160 nDatLen -= n;
1162 #ifndef OSL_BIGENDIAN
1163 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1164 #endif /* OSL_BIGENDIAN */
1166 updateSHA(ctx);
1167 ctx->m_nDatLen = 0;
1170 while (nDatLen >= DIGEST_CBLOCK_SHA)
1172 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1173 d += DIGEST_CBLOCK_SHA;
1174 nDatLen -= DIGEST_CBLOCK_SHA;
1176 #ifndef OSL_BIGENDIAN
1177 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1178 #endif /* OSL_BIGENDIAN */
1180 updateSHA(ctx);
1183 memcpy(ctx->m_pData, d, nDatLen);
1184 ctx->m_nDatLen = nDatLen;
1186 return rtl_Digest_E_None;
1189 rtlDigestError SAL_CALL rtl_digest_getSHA(
1190 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1191 SAL_THROW_EXTERN_C()
1193 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1194 sal_uInt8 *p = pBuffer;
1196 DigestContextSHA *ctx;
1198 if (!pImpl || !pBuffer)
1199 return rtl_Digest_E_Argument;
1201 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1202 return rtl_Digest_E_Algorithm;
1204 if (pImpl->m_digest.m_length > nBufLen)
1205 return rtl_Digest_E_BufferSize;
1207 ctx = &(pImpl->m_context);
1209 endSHA(ctx);
1210 RTL_DIGEST_HTONL(ctx->m_nA, p);
1211 RTL_DIGEST_HTONL(ctx->m_nB, p);
1212 RTL_DIGEST_HTONL(ctx->m_nC, p);
1213 RTL_DIGEST_HTONL(ctx->m_nD, p);
1214 RTL_DIGEST_HTONL(ctx->m_nE, p);
1215 initSHA(ctx, updateSHA_0);
1217 return rtl_Digest_E_None;
1220 void SAL_CALL rtl_digest_destroySHA(rtlDigest Digest) SAL_THROW_EXTERN_C()
1222 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1223 if (pImpl)
1225 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
1226 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1227 else
1228 free(pImpl);
1232 static const Digest_Impl SHA_1 =
1234 rtl_Digest_AlgorithmSHA1,
1235 RTL_DIGEST_LENGTH_SHA1,
1236 nullptr,
1237 rtl_digest_destroySHA1,
1238 rtl_digest_updateSHA1,
1239 rtl_digest_getSHA1
1242 static sal_uInt32 updateSHA_1(sal_uInt32 x)
1244 return RTL_DIGEST_ROTL(x, 1);
1247 rtlDigestError SAL_CALL rtl_digest_SHA1(
1248 const void *pData, sal_uInt32 nDatLen,
1249 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1251 DigestSHA_Impl digest;
1252 rtlDigestError result;
1254 digest.m_digest = SHA_1;
1255 initSHA(&(digest.m_context), updateSHA_1);
1257 result = rtl_digest_updateSHA1(&digest, pData, nDatLen);
1258 if (result == rtl_Digest_E_None)
1259 result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen);
1261 rtl_secureZeroMemory(&digest, sizeof(digest));
1262 return result;
1265 rtlDigest SAL_CALL rtl_digest_createSHA1() SAL_THROW_EXTERN_C()
1267 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1268 if (pImpl)
1270 pImpl->m_digest = SHA_1;
1271 initSHA(&(pImpl->m_context), updateSHA_1);
1273 return static_cast<rtlDigest>(pImpl);
1276 rtlDigestError SAL_CALL rtl_digest_updateSHA1(
1277 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1278 SAL_THROW_EXTERN_C()
1280 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1281 const sal_uInt8 *d = static_cast< const sal_uInt8 * >(pData);
1283 DigestContextSHA *ctx;
1284 sal_uInt32 len;
1286 if (!pImpl || !pData)
1287 return rtl_Digest_E_Argument;
1289 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1290 return rtl_Digest_E_Algorithm;
1292 if (nDatLen == 0)
1293 return rtl_Digest_E_None;
1295 ctx = &(pImpl->m_context);
1297 len = ctx->m_nL + (nDatLen << 3);
1298 if (len < ctx->m_nL)
1299 ctx->m_nH += 1;
1301 ctx->m_nH += (nDatLen >> 29);
1302 ctx->m_nL = len;
1304 if (ctx->m_nDatLen)
1306 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1307 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1309 if (nDatLen < n)
1311 memcpy(p, d, nDatLen);
1312 ctx->m_nDatLen += nDatLen;
1314 return rtl_Digest_E_None;
1317 memcpy(p, d, n);
1318 d += n;
1319 nDatLen -= n;
1321 #ifndef OSL_BIGENDIAN
1322 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1323 #endif /* OSL_BIGENDIAN */
1325 updateSHA(ctx);
1326 ctx->m_nDatLen = 0;
1329 while (nDatLen >= DIGEST_CBLOCK_SHA)
1331 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1332 d += DIGEST_CBLOCK_SHA;
1333 nDatLen -= DIGEST_CBLOCK_SHA;
1335 #ifndef OSL_BIGENDIAN
1336 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1337 #endif /* OSL_BIGENDIAN */
1339 updateSHA(ctx);
1342 memcpy(ctx->m_pData, d, nDatLen);
1343 ctx->m_nDatLen = nDatLen;
1345 return rtl_Digest_E_None;
1348 rtlDigestError SAL_CALL rtl_digest_getSHA1 (
1349 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1350 SAL_THROW_EXTERN_C()
1352 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1353 sal_uInt8 *p = pBuffer;
1355 DigestContextSHA *ctx;
1357 if (!pImpl || !pBuffer)
1358 return rtl_Digest_E_Argument;
1360 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1361 return rtl_Digest_E_Algorithm;
1363 if (pImpl->m_digest.m_length > nBufLen)
1364 return rtl_Digest_E_BufferSize;
1366 ctx = &(pImpl->m_context);
1368 endSHA(ctx);
1369 RTL_DIGEST_HTONL(ctx->m_nA, p);
1370 RTL_DIGEST_HTONL(ctx->m_nB, p);
1371 RTL_DIGEST_HTONL(ctx->m_nC, p);
1372 RTL_DIGEST_HTONL(ctx->m_nD, p);
1373 RTL_DIGEST_HTONL(ctx->m_nE, p);
1374 initSHA(ctx, updateSHA_1);
1376 return rtl_Digest_E_None;
1379 void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) SAL_THROW_EXTERN_C()
1381 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1382 if (pImpl)
1384 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
1385 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1386 else
1387 free(pImpl);
1391 #define DIGEST_CBLOCK_HMAC_MD5 64
1393 struct ContextHMAC_MD5
1395 DigestMD5_Impl m_hash;
1396 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5];
1399 struct DigestHMAC_MD5_Impl
1401 Digest_Impl m_digest;
1402 ContextHMAC_MD5 m_context;
1405 static void initHMAC_MD5(ContextHMAC_MD5 * ctx);
1406 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx);
1407 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx);
1409 static const Digest_Impl HMAC_MD5 =
1411 rtl_Digest_AlgorithmHMAC_MD5,
1412 RTL_DIGEST_LENGTH_MD5,
1414 rtl_digest_initHMAC_MD5,
1415 rtl_digest_destroyHMAC_MD5,
1416 rtl_digest_updateHMAC_MD5,
1417 rtl_digest_getHMAC_MD5
1420 static void initHMAC_MD5(ContextHMAC_MD5 * ctx)
1422 DigestMD5_Impl *pImpl = &(ctx->m_hash);
1424 pImpl->m_digest = MD5;
1425 initMD5(&(pImpl->m_context));
1427 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_MD5);
1430 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx)
1432 sal_uInt32 i;
1434 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1436 ctx->m_opad[i] ^= 0x36;
1439 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
1441 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1443 ctx->m_opad[i] ^= 0x36;
1447 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx)
1449 sal_uInt32 i;
1451 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1453 ctx->m_opad[i] ^= 0x5c;
1457 rtlDigestError SAL_CALL rtl_digest_HMAC_MD5(
1458 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1459 const void *pData, sal_uInt32 nDatLen,
1460 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1462 DigestHMAC_MD5_Impl digest;
1463 rtlDigestError result;
1465 digest.m_digest = HMAC_MD5;
1467 result = rtl_digest_initHMAC_MD5(&digest, pKeyData, nKeyLen);
1468 if (result == rtl_Digest_E_None)
1470 result = rtl_digest_updateHMAC_MD5(&digest, pData, nDatLen);
1471 if (result == rtl_Digest_E_None)
1472 result = rtl_digest_getHMAC_MD5(&digest, pBuffer, nBufLen);
1475 rtl_secureZeroMemory(&digest, sizeof(digest));
1476 return result;
1479 rtlDigest SAL_CALL rtl_digest_createHMAC_MD5() SAL_THROW_EXTERN_C()
1481 DigestHMAC_MD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
1482 if (pImpl)
1484 pImpl->m_digest = HMAC_MD5;
1485 initHMAC_MD5(&(pImpl->m_context));
1487 return static_cast< rtlDigest >(pImpl);
1490 rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5(
1491 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1492 SAL_THROW_EXTERN_C()
1494 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1495 ContextHMAC_MD5 *ctx;
1497 if (!pImpl || !pKeyData)
1498 return rtl_Digest_E_Argument;
1500 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1501 return rtl_Digest_E_Algorithm;
1503 ctx = &(pImpl->m_context);
1504 initHMAC_MD5(ctx);
1506 if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
1508 /* Initialize 'opad' with hashed 'KeyData' */
1509 rtl_digest_updateMD5(&(ctx->m_hash), pKeyData, nKeyLen);
1510 rtl_digest_getMD5(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
1512 else
1514 /* Initialize 'opad' with plain 'KeyData' */
1515 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1518 ipadHMAC_MD5(ctx);
1519 opadHMAC_MD5(ctx);
1521 return rtl_Digest_E_None;
1524 rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5(
1525 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1526 SAL_THROW_EXTERN_C()
1528 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1529 ContextHMAC_MD5 *ctx;
1531 if (!pImpl || !pData)
1532 return rtl_Digest_E_Argument;
1534 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1535 return rtl_Digest_E_Algorithm;
1537 ctx = &(pImpl->m_context);
1538 rtl_digest_updateMD5(&(ctx->m_hash), pData, nDatLen);
1540 return rtl_Digest_E_None;
1543 rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5(
1544 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1545 SAL_THROW_EXTERN_C()
1547 DigestHMAC_MD5_Impl *pImpl = static_cast<DigestHMAC_MD5_Impl*>(Digest);
1548 ContextHMAC_MD5 *ctx;
1550 if (!pImpl || !pBuffer)
1551 return rtl_Digest_E_Argument;
1553 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1554 return rtl_Digest_E_Algorithm;
1556 if (pImpl->m_digest.m_length > nBufLen)
1557 return rtl_Digest_E_BufferSize;
1559 nBufLen = pImpl->m_digest.m_length;
1561 ctx = &(pImpl->m_context);
1562 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1564 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, 64);
1565 rtl_digest_updateMD5(&(ctx->m_hash), pBuffer, nBufLen);
1566 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1568 opadHMAC_MD5(ctx);
1569 ipadHMAC_MD5(ctx);
1570 opadHMAC_MD5(ctx);
1572 return rtl_Digest_E_None;
1575 void SAL_CALL rtl_digest_destroyHMAC_MD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
1577 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1578 if (pImpl)
1580 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
1581 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_MD5_Impl));
1582 else
1583 free(pImpl);
1587 #define DIGEST_CBLOCK_HMAC_SHA1 64
1589 struct ContextHMAC_SHA1
1591 DigestSHA_Impl m_hash;
1592 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1];
1595 struct DigestHMAC_SHA1_Impl
1597 Digest_Impl m_digest;
1598 ContextHMAC_SHA1 m_context;
1601 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1602 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1603 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1605 static const Digest_Impl HMAC_SHA1 =
1607 rtl_Digest_AlgorithmHMAC_SHA1,
1608 RTL_DIGEST_LENGTH_SHA1,
1609 rtl_digest_initHMAC_SHA1,
1610 rtl_digest_destroyHMAC_SHA1,
1611 rtl_digest_updateHMAC_SHA1,
1612 rtl_digest_getHMAC_SHA1
1615 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1617 DigestSHA_Impl *pImpl = &(ctx->m_hash);
1619 pImpl->m_digest = SHA_1;
1620 initSHA(&(pImpl->m_context), updateSHA_1);
1622 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_SHA1);
1625 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1627 sal_uInt32 i;
1629 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1631 ctx->m_opad[i] ^= 0x36;
1634 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
1636 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1638 ctx->m_opad[i] ^= 0x36;
1642 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1644 sal_uInt32 i;
1646 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1648 ctx->m_opad[i] ^= 0x5c;
1652 rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1(
1653 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1654 const void *pData, sal_uInt32 nDatLen,
1655 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1657 DigestHMAC_SHA1_Impl digest;
1658 rtlDigestError result;
1660 digest.m_digest = HMAC_SHA1;
1662 result = rtl_digest_initHMAC_SHA1(&digest, pKeyData, nKeyLen);
1663 if (result == rtl_Digest_E_None)
1665 result = rtl_digest_updateHMAC_SHA1(&digest, pData, nDatLen);
1666 if (result == rtl_Digest_E_None)
1667 result = rtl_digest_getHMAC_SHA1(&digest, pBuffer, nBufLen);
1670 rtl_secureZeroMemory(&digest, sizeof(digest));
1671 return result;
1674 rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1() SAL_THROW_EXTERN_C()
1676 DigestHMAC_SHA1_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
1677 if (pImpl)
1679 pImpl->m_digest = HMAC_SHA1;
1680 initHMAC_SHA1(&(pImpl->m_context));
1682 return static_cast<rtlDigest>(pImpl);
1685 rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1(
1686 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1687 SAL_THROW_EXTERN_C()
1689 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1690 ContextHMAC_SHA1 *ctx;
1692 if (!pImpl || !pKeyData)
1693 return rtl_Digest_E_Argument;
1695 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1696 return rtl_Digest_E_Algorithm;
1698 ctx = &(pImpl->m_context);
1699 initHMAC_SHA1(ctx);
1701 if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
1703 /* Initialize 'opad' with hashed 'KeyData' */
1704 rtl_digest_updateSHA1(&(ctx->m_hash), pKeyData, nKeyLen);
1705 rtl_digest_getSHA1(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
1707 else
1709 /* Initialize 'opad' with plain 'KeyData' */
1710 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1713 ipadHMAC_SHA1(ctx);
1714 opadHMAC_SHA1(ctx);
1716 return rtl_Digest_E_None;
1719 rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1(
1720 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1721 SAL_THROW_EXTERN_C()
1723 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1724 ContextHMAC_SHA1 *ctx;
1726 if (!pImpl || !pData)
1727 return rtl_Digest_E_Argument;
1729 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1730 return rtl_Digest_E_Algorithm;
1732 ctx = &(pImpl->m_context);
1733 rtl_digest_updateSHA1(&(ctx->m_hash), pData, nDatLen);
1735 return rtl_Digest_E_None;
1738 rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1(
1739 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1740 SAL_THROW_EXTERN_C()
1742 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1743 ContextHMAC_SHA1 *ctx;
1745 if (!pImpl || !pBuffer)
1746 return rtl_Digest_E_Argument;
1748 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1749 return rtl_Digest_E_Algorithm;
1751 if (pImpl->m_digest.m_length > nBufLen)
1752 return rtl_Digest_E_BufferSize;
1754 nBufLen = pImpl->m_digest.m_length;
1756 ctx = &(pImpl->m_context);
1757 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1759 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
1760 rtl_digest_updateSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1761 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1763 opadHMAC_SHA1(ctx);
1764 ipadHMAC_SHA1(ctx);
1765 opadHMAC_SHA1(ctx);
1767 return rtl_Digest_E_None;
1770 void SAL_CALL rtl_digest_destroyHMAC_SHA1(rtlDigest Digest)
1771 SAL_THROW_EXTERN_C()
1773 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1774 if (pImpl)
1776 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
1777 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_SHA1_Impl));
1778 else
1779 free(pImpl);
1783 #define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
1785 static void updatePBKDF2(
1786 rtlDigest hDigest,
1787 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2],
1788 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1789 sal_uInt32 nCount, sal_uInt32 nIndex)
1791 /* T_i = F (P, S, c, i) */
1792 sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
1793 sal_uInt32 i, k;
1795 /* U_(1) = PRF (P, S || INDEX) */
1796 rtl_digest_updateHMAC_SHA1(hDigest, pSaltData, nSaltLen);
1797 rtl_digest_updateHMAC_SHA1(hDigest, &nIndex, sizeof(nIndex));
1798 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1800 /* T = U_(1) */
1801 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1803 T[k] = U[k];
1806 /* T ^= U_(2) ^ ... ^ U_(c) */
1807 for (i = 1; i < nCount; i++)
1809 /* U_(i) = PRF (P, U_(i-1)) */
1810 rtl_digest_updateHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1811 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1813 /* T ^= U_(i) */
1814 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1816 T[k] ^= U[k];
1820 rtl_secureZeroMemory(U, DIGEST_CBLOCK_PBKDF2);
1823 rtlDigestError SAL_CALL rtl_digest_PBKDF2(
1824 sal_uInt8 *pKeyData , sal_uInt32 nKeyLen,
1825 const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
1826 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1827 sal_uInt32 nCount) SAL_THROW_EXTERN_C()
1829 DigestHMAC_SHA1_Impl digest;
1830 sal_uInt32 i = 1;
1832 if (!pKeyData || !pPassData || !pSaltData)
1833 return rtl_Digest_E_Argument;
1835 digest.m_digest = HMAC_SHA1;
1836 rtl_digest_initHMAC_SHA1(&digest, pPassData, nPassLen);
1838 /* DK = T_(1) || T_(2) || ... || T_(l) */
1839 while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
1841 /* T_(i) = F (P, S, c, i); DK ||= T_(i) */
1842 updatePBKDF2(
1843 &digest, pKeyData,
1844 pSaltData, nSaltLen,
1845 nCount, OSL_NETDWORD(i));
1847 /* Next 'KeyData' block */
1848 pKeyData += DIGEST_CBLOCK_PBKDF2;
1849 nKeyLen -= DIGEST_CBLOCK_PBKDF2;
1850 i += 1;
1853 if (nKeyLen > 0)
1855 /* Last 'KeyData' block */
1856 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
1858 /* T_i = F (P, S, c, i) */
1859 updatePBKDF2(
1860 &digest, T,
1861 pSaltData, nSaltLen,
1862 nCount, OSL_NETDWORD(i));
1864 /* DK ||= T_(i) */
1865 memcpy(pKeyData, T, nKeyLen);
1866 rtl_secureZeroMemory(T, DIGEST_CBLOCK_PBKDF2);
1869 rtl_secureZeroMemory(&digest, sizeof(digest));
1870 return rtl_Digest_E_None;
1873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */