Fix GNU C++ version check
[LibreOffice.git] / sal / rtl / digest.cxx
bloba87570b32b86bd00c4368192e24935fe973ec0fe
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 namespace {
57 struct Digest_Impl
59 rtlDigestAlgorithm m_algorithm;
60 sal_uInt32 m_length;
62 Digest_init_t *m_init;
63 Digest_delete_t *m_delete;
64 Digest_update_t *m_update;
65 Digest_get_t *m_get;
70 static void swapLong(sal_uInt32 *pData, sal_uInt32 nDatLen)
72 sal_uInt32 *X;
73 int i, n;
75 X = pData;
76 n = nDatLen;
78 for (i = 0; i < n; i++)
80 X[i] = OSL_SWAPDWORD(X[i]);
84 rtlDigest SAL_CALL rtl_digest_create(rtlDigestAlgorithm Algorithm) noexcept
86 rtlDigest Digest = nullptr;
87 switch (Algorithm)
89 case rtl_Digest_AlgorithmMD2:
90 Digest = rtl_digest_createMD2();
91 break;
93 case rtl_Digest_AlgorithmMD5:
94 Digest = rtl_digest_createMD5();
95 break;
97 case rtl_Digest_AlgorithmSHA:
98 Digest = rtl_digest_createSHA();
99 break;
101 case rtl_Digest_AlgorithmSHA1:
102 Digest = rtl_digest_createSHA1();
103 break;
105 case rtl_Digest_AlgorithmHMAC_MD5:
106 Digest = rtl_digest_createHMAC_MD5();
107 break;
109 case rtl_Digest_AlgorithmHMAC_SHA1:
110 Digest = rtl_digest_createHMAC_SHA1();
111 break;
113 default: /* rtl_Digest_AlgorithmInvalid */
114 break;
116 return Digest;
119 rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm(rtlDigest Digest) noexcept
121 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
122 if (pImpl)
123 return pImpl->m_algorithm;
124 return rtl_Digest_AlgorithmInvalid;
127 sal_uInt32 SAL_CALL rtl_digest_queryLength(rtlDigest Digest) noexcept
129 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
130 if (pImpl)
131 return pImpl->m_length;
132 return 0;
135 rtlDigestError SAL_CALL rtl_digest_init(
136 rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen) noexcept
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) noexcept
151 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
152 if (pImpl && pImpl->m_update)
153 return pImpl->m_update(Digest, pData, nDatLen);
154 return rtl_Digest_E_Argument;
157 rtlDigestError SAL_CALL rtl_digest_get(
158 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
160 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
161 if (pImpl && pImpl->m_get)
162 return pImpl->m_get(Digest, pBuffer, nBufLen);
163 return rtl_Digest_E_Argument;
166 void SAL_CALL rtl_digest_destroy(rtlDigest Digest) noexcept
168 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
169 if (pImpl && pImpl->m_delete)
170 pImpl->m_delete(Digest);
173 constexpr auto DIGEST_CBLOCK_MD2 = 16;
174 constexpr auto DIGEST_LBLOCK_MD2 = 16;
176 namespace {
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;
194 static void initMD2 (DigestContextMD2 *ctx);
195 static void updateMD2 (DigestContextMD2 *ctx);
196 static void endMD2 (DigestContextMD2 *ctx);
198 const sal_uInt32 S[256] =
200 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
201 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
202 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
203 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
204 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
205 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
206 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
207 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
208 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
209 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
210 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
211 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
212 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
213 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
214 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
215 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
216 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
217 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
218 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
219 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
220 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
221 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
222 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
223 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
224 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
225 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
226 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
227 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
228 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
229 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
230 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
231 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
234 const Digest_Impl MD2 =
236 rtl_Digest_AlgorithmMD2,
237 RTL_DIGEST_LENGTH_MD2,
238 nullptr,
239 rtl_digest_destroyMD2,
240 rtl_digest_updateMD2,
241 rtl_digest_getMD2
244 static void initMD2(DigestContextMD2 *ctx)
246 memset(ctx, 0, sizeof(DigestContextMD2));
249 static void updateMD2(DigestContextMD2 *ctx)
251 sal_uInt8 *X;
252 sal_uInt32 *sp1, *sp2;
253 sal_uInt32 i, k, t;
255 sal_uInt32 state[48];
257 X = ctx->m_pData;
258 sp1 = ctx->m_state;
259 sp2 = ctx->m_chksum;
261 k = sp2[DIGEST_LBLOCK_MD2 - 1];
262 for (i = 0; i < 16; i++)
264 state[i + 0] = sp1[i];
265 state[i + 16] = t = X[i];
266 state[i + 32] = t ^ sp1[i];
267 k = sp2[i] ^= S[t^k];
270 t = 0;
271 for (i = 0; i < 18; i++)
273 for (k = 0; k < 48; k += 8)
275 t = state[k + 0] ^= S[t];
276 t = state[k + 1] ^= S[t];
277 t = state[k + 2] ^= S[t];
278 t = state[k + 3] ^= S[t];
279 t = state[k + 4] ^= S[t];
280 t = state[k + 5] ^= S[t];
281 t = state[k + 6] ^= S[t];
282 t = state[k + 7] ^= S[t];
284 t = ((t + i) & 0xff);
287 memcpy(sp1, state, 16 * sizeof(sal_uInt32));
288 rtl_secureZeroMemory(state, 48 * sizeof(sal_uInt32));
291 static void endMD2(DigestContextMD2 *ctx)
293 sal_uInt8 *X;
294 sal_uInt32 *C;
295 sal_uInt32 i, n;
297 X = ctx->m_pData;
298 C = ctx->m_chksum;
299 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
301 for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
302 X[i] = static_cast<sal_uInt8>(n & 0xff);
304 updateMD2(ctx);
306 for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
307 X[i] = static_cast<sal_uInt8>(C[i] & 0xff);
308 updateMD2(ctx);
311 rtlDigestError SAL_CALL rtl_digest_MD2(
312 const void *pData, sal_uInt32 nDatLen,
313 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
315 DigestMD2_Impl digest;
316 rtlDigestError result;
318 digest.m_digest = MD2;
319 initMD2(&(digest.m_context));
321 result = rtl_digest_updateMD2(&digest, pData, nDatLen);
322 if (result == rtl_Digest_E_None)
323 result = rtl_digest_getMD2(&digest, pBuffer, nBufLen);
325 rtl_secureZeroMemory(&digest, sizeof(digest));
326 return result;
329 rtlDigest SAL_CALL rtl_digest_createMD2() noexcept
331 DigestMD2_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
332 if (pImpl)
334 pImpl->m_digest = MD2;
335 initMD2(&(pImpl->m_context));
337 return static_cast<rtlDigest>(pImpl);
340 rtlDigestError SAL_CALL rtl_digest_updateMD2(
341 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
343 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
344 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
346 DigestContextMD2 *ctx;
348 if (!pImpl || !pData)
349 return rtl_Digest_E_Argument;
351 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
352 return rtl_Digest_E_Algorithm;
354 if (nDatLen == 0)
355 return rtl_Digest_E_None;
357 ctx = &(pImpl->m_context);
359 if (ctx->m_nDatLen)
361 sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen;
362 sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
364 if (nDatLen < n)
366 memcpy(p, d, nDatLen);
367 ctx->m_nDatLen += nDatLen;
369 return rtl_Digest_E_None;
372 memcpy(p, d, n);
373 d += n;
374 nDatLen -= n;
376 updateMD2(ctx);
377 ctx->m_nDatLen = 0;
380 while (nDatLen >= DIGEST_CBLOCK_MD2)
382 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD2);
383 d += DIGEST_CBLOCK_MD2;
384 nDatLen -= DIGEST_CBLOCK_MD2;
386 updateMD2(ctx);
389 memcpy(ctx->m_pData, d, nDatLen);
390 ctx->m_nDatLen = nDatLen;
392 return rtl_Digest_E_None;
395 rtlDigestError SAL_CALL rtl_digest_getMD2(
396 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
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) noexcept
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 namespace {
442 struct DigestContextMD5
444 sal_uInt32 m_nDatLen;
445 sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
446 sal_uInt32 m_nA, m_nB, m_nC, m_nD;
447 sal_uInt32 m_nL, m_nH;
450 struct DigestMD5_Impl
452 Digest_Impl m_digest;
453 DigestContextMD5 m_context;
458 static void initMD5 (DigestContextMD5 *ctx);
459 static void updateMD5 (DigestContextMD5 *ctx);
460 static void endMD5 (DigestContextMD5 *ctx);
462 #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
463 #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
464 #define H(x,y,z) ((x) ^ (y) ^ (z))
465 #define I(x,y,z) (((x) | (~(z))) ^ (y))
467 #define R0(a,b,c,d,k,s,t) { \
468 a += ((k) + (t) + F((b), (c), (d))); \
469 a = RTL_DIGEST_ROTL(a, s); \
470 a += b; }
472 #define R1(a,b,c,d,k,s,t) { \
473 a += ((k) + (t) + G((b), (c), (d))); \
474 a = RTL_DIGEST_ROTL(a, s); \
475 a += b; }
477 #define R2(a,b,c,d,k,s,t) { \
478 a += ((k) + (t) + H((b), (c), (d))); \
479 a = RTL_DIGEST_ROTL(a, s); \
480 a += b; }
482 #define R3(a,b,c,d,k,s,t) { \
483 a += ((k) + (t) + I((b), (c), (d))); \
484 a = RTL_DIGEST_ROTL(a, s); \
485 a += b; }
487 const Digest_Impl MD5 =
489 rtl_Digest_AlgorithmMD5,
490 RTL_DIGEST_LENGTH_MD5,
491 nullptr,
492 rtl_digest_destroyMD5,
493 rtl_digest_updateMD5,
494 rtl_digest_getMD5
497 static void initMD5(DigestContextMD5 *ctx)
499 memset(ctx, 0, sizeof(DigestContextMD5));
501 ctx->m_nA = sal_uInt32(0x67452301L);
502 ctx->m_nB = sal_uInt32(0xefcdab89L);
503 ctx->m_nC = sal_uInt32(0x98badcfeL);
504 ctx->m_nD = sal_uInt32(0x10325476L);
507 static void updateMD5(DigestContextMD5 *ctx)
509 sal_uInt32 A, B, C, D;
510 sal_uInt32 *X;
512 A = ctx->m_nA;
513 B = ctx->m_nB;
514 C = ctx->m_nC;
515 D = ctx->m_nD;
516 X = ctx->m_pData;
518 R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L);
519 R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
520 R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
521 R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
522 R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL);
523 R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
524 R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
525 R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
526 R0 (A, B, C, D, X[ 8], 7, 0x698098d8L);
527 R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
528 R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
529 R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
530 R0 (A, B, C, D, X[12], 7, 0x6b901122L);
531 R0 (D, A, B, C, X[13], 12, 0xfd987193L);
532 R0 (C, D, A, B, X[14], 17, 0xa679438eL);
533 R0 (B, C, D, A, X[15], 22, 0x49b40821L);
535 R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L);
536 R1 (D, A, B, C, X[ 6], 9, 0xc040b340L);
537 R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
538 R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
539 R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL);
540 R1 (D, A, B, C, X[10], 9, 0x02441453L);
541 R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
542 R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
543 R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L);
544 R1 (D, A, B, C, X[14], 9, 0xc33707d6L);
545 R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
546 R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
547 R1 (A, B, C, D, X[13], 5, 0xa9e3e905L);
548 R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L);
549 R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
550 R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
552 R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L);
553 R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
554 R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
555 R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
556 R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L);
557 R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
558 R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
559 R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
560 R2 (A, B, C, D, X[13], 4, 0x289b7ec6L);
561 R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
562 R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
563 R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
564 R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L);
565 R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
566 R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
567 R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
569 R3 (A, B, C, D, X[ 0], 6, 0xf4292244L);
570 R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
571 R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
572 R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
573 R3 (A, B, C, D, X[12], 6, 0x655b59c3L);
574 R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
575 R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
576 R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
577 R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL);
578 R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
579 R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
580 R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
581 R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L);
582 R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
583 R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
584 R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
586 ctx->m_nA += A;
587 ctx->m_nB += B;
588 ctx->m_nC += C;
589 ctx->m_nD += D;
592 static void endMD5(DigestContextMD5 *ctx)
594 static const sal_uInt8 end[4] =
596 0x80, 0x00, 0x00, 0x00
598 const sal_uInt8 *p = end;
600 sal_uInt32 *X;
601 int i;
603 X = ctx->m_pData;
604 i = (ctx->m_nDatLen >> 2);
606 #ifdef OSL_BIGENDIAN
607 swapLong(X, i + 1);
608 #endif /* OSL_BIGENDIAN */
610 switch (ctx->m_nDatLen & 0x03)
612 case 1: X[i] &= 0x000000ff; break;
613 case 2: X[i] &= 0x0000ffff; break;
614 case 3: X[i] &= 0x00ffffff; break;
617 switch (ctx->m_nDatLen & 0x03)
619 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
620 [[fallthrough]];
621 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
622 [[fallthrough]];
623 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
624 [[fallthrough]];
625 case 3: X[i] |= static_cast<sal_uInt32>(*p) << 24;
628 i += 1;
630 if (i > (DIGEST_LBLOCK_MD5 - 2))
632 for (; i < DIGEST_LBLOCK_MD5; i++)
634 X[i] = 0;
637 updateMD5(ctx);
638 i = 0;
641 for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
642 X[i] = 0;
644 X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
645 X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
647 updateMD5(ctx);
650 rtlDigestError SAL_CALL rtl_digest_MD5(
651 const void *pData, sal_uInt32 nDatLen,
652 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
654 DigestMD5_Impl digest;
655 rtlDigestError result;
657 digest.m_digest = MD5;
658 initMD5(&(digest.m_context));
660 result = rtl_digest_update(&digest, pData, nDatLen);
661 if (result == rtl_Digest_E_None)
662 result = rtl_digest_getMD5(&digest, pBuffer, nBufLen);
664 rtl_secureZeroMemory(&digest, sizeof(digest));
665 return result;
668 rtlDigest SAL_CALL rtl_digest_createMD5() noexcept
670 DigestMD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
671 if (pImpl)
673 pImpl->m_digest = MD5;
674 initMD5(&(pImpl->m_context));
676 return static_cast<rtlDigest>(pImpl);
679 rtlDigestError SAL_CALL rtl_digest_updateMD5(
680 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
682 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
683 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
685 DigestContextMD5 *ctx;
686 sal_uInt32 len;
688 if (!pImpl || !pData)
689 return rtl_Digest_E_Argument;
691 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
692 return rtl_Digest_E_Algorithm;
694 if (nDatLen == 0)
695 return rtl_Digest_E_None;
697 ctx = &(pImpl->m_context);
699 len = ctx->m_nL + (nDatLen << 3);
700 if (len < ctx->m_nL)
701 ctx->m_nH += 1;
703 ctx->m_nH += (nDatLen >> 29);
704 ctx->m_nL = len;
706 if (ctx->m_nDatLen)
708 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
709 sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
711 if (nDatLen < n)
713 memcpy(p, d, nDatLen);
714 ctx->m_nDatLen += nDatLen;
716 return rtl_Digest_E_None;
719 memcpy(p, d, n);
720 d += n;
721 nDatLen -= n;
723 #ifdef OSL_BIGENDIAN
724 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
725 #endif /* OSL_BIGENDIAN */
727 updateMD5(ctx);
728 ctx->m_nDatLen = 0;
731 while (nDatLen >= DIGEST_CBLOCK_MD5)
733 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD5);
734 d += DIGEST_CBLOCK_MD5;
735 nDatLen -= DIGEST_CBLOCK_MD5;
737 #ifdef OSL_BIGENDIAN
738 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
739 #endif /* OSL_BIGENDIAN */
741 updateMD5(ctx);
744 memcpy(ctx->m_pData, d, nDatLen);
745 ctx->m_nDatLen = nDatLen;
747 return rtl_Digest_E_None;
750 rtlDigestError SAL_CALL rtl_digest_getMD5(
751 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
753 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
754 sal_uInt8 *p = pBuffer;
756 DigestContextMD5 *ctx;
758 if (!pImpl || !pBuffer)
759 return rtl_Digest_E_Argument;
761 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
762 return rtl_Digest_E_Algorithm;
764 if (pImpl->m_digest.m_length > nBufLen)
765 return rtl_Digest_E_BufferSize;
767 ctx = &(pImpl->m_context);
769 endMD5(ctx);
770 RTL_DIGEST_LTOC(ctx->m_nA, p);
771 RTL_DIGEST_LTOC(ctx->m_nB, p);
772 RTL_DIGEST_LTOC(ctx->m_nC, p);
773 RTL_DIGEST_LTOC(ctx->m_nD, p);
774 initMD5(ctx);
776 return rtl_Digest_E_None;
779 rtlDigestError SAL_CALL rtl_digest_rawMD5(
780 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
782 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
783 sal_uInt8 *p = pBuffer;
785 DigestContextMD5 *ctx;
787 if (!pImpl || !pBuffer)
788 return rtl_Digest_E_Argument;
790 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
791 return rtl_Digest_E_Algorithm;
793 if (pImpl->m_digest.m_length > nBufLen)
794 return rtl_Digest_E_BufferSize;
796 ctx = &(pImpl->m_context);
798 /* not finalized */
799 RTL_DIGEST_LTOC(ctx->m_nA, p);
800 RTL_DIGEST_LTOC(ctx->m_nB, p);
801 RTL_DIGEST_LTOC(ctx->m_nC, p);
802 RTL_DIGEST_LTOC(ctx->m_nD, p);
803 initMD5(ctx);
805 return rtl_Digest_E_None;
808 void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) noexcept
810 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
811 if (pImpl)
813 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
814 rtl_freeZeroMemory(pImpl, sizeof(DigestMD5_Impl));
815 else
816 free(pImpl);
820 #define DIGEST_CBLOCK_SHA 64
821 #define DIGEST_LBLOCK_SHA 16
823 typedef sal_uInt32 DigestSHA_update_t(sal_uInt32 x);
825 static sal_uInt32 updateSHA_0(sal_uInt32 x);
826 static sal_uInt32 updateSHA_1(sal_uInt32 x);
828 namespace {
830 struct DigestContextSHA
832 DigestSHA_update_t *m_update;
833 sal_uInt32 m_nDatLen;
834 sal_uInt32 m_pData[DIGEST_LBLOCK_SHA];
835 sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE;
836 sal_uInt32 m_nL, m_nH;
839 struct DigestSHA_Impl
841 Digest_Impl m_digest;
842 DigestContextSHA m_context;
847 static void initSHA(
848 DigestContextSHA *ctx, DigestSHA_update_t *fct);
850 static void updateSHA(DigestContextSHA *ctx);
851 static void endSHA(DigestContextSHA *ctx);
853 #define K_00_19 sal_uInt32(0x5a827999L)
854 #define K_20_39 sal_uInt32(0x6ed9eba1L)
855 #define K_40_59 sal_uInt32(0x8f1bbcdcL)
856 #define K_60_79 sal_uInt32(0xca62c1d6L)
858 #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
859 #define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
860 #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
861 #define F_60_79(b,c,d) F_20_39(b,c,d)
863 #define BODY_X(i) \
864 (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
866 #define BODY_00_15(u,i,a,b,c,d,e,f) \
867 (f) = X[i]; \
868 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
869 (b) = RTL_DIGEST_ROTL((b), 30);
871 #define BODY_16_19(u,i,a,b,c,d,e,f) \
872 (f) = BODY_X((i)); \
873 (f) = X[(i)&0x0f] = (u)((f)); \
874 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
875 (b) = RTL_DIGEST_ROTL((b), 30);
877 #define BODY_20_39(u,i,a,b,c,d,e,f) \
878 (f) = BODY_X((i)); \
879 (f) = X[(i)&0x0f] = (u)((f)); \
880 (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
881 (b) = RTL_DIGEST_ROTL((b), 30);
883 #define BODY_40_59(u,i,a,b,c,d,e,f) \
884 (f) = BODY_X((i)); \
885 (f) = X[(i)&0x0f] = (u)((f)); \
886 (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
887 (b) = RTL_DIGEST_ROTL((b), 30);
889 #define BODY_60_79(u,i,a,b,c,d,e,f) \
890 (f) = BODY_X((i)); \
891 (f) = X[(i)&0x0f] = (u)((f)); \
892 (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
893 (b) = RTL_DIGEST_ROTL((b), 30);
895 static void initSHA(
896 DigestContextSHA *ctx, DigestSHA_update_t *fct)
898 memset(ctx, 0, sizeof(DigestContextSHA));
899 ctx->m_update = fct;
901 ctx->m_nA = sal_uInt32(0x67452301L);
902 ctx->m_nB = sal_uInt32(0xefcdab89L);
903 ctx->m_nC = sal_uInt32(0x98badcfeL);
904 ctx->m_nD = sal_uInt32(0x10325476L);
905 ctx->m_nE = sal_uInt32(0xc3d2e1f0L);
908 static void updateSHA(DigestContextSHA *ctx)
910 sal_uInt32 A, B, C, D, E, T;
911 sal_uInt32 *X;
913 DigestSHA_update_t *U;
914 U = ctx->m_update;
916 A = ctx->m_nA;
917 B = ctx->m_nB;
918 C = ctx->m_nC;
919 D = ctx->m_nD;
920 E = ctx->m_nE;
921 X = ctx->m_pData;
923 BODY_00_15 (U, 0, A, B, C, D, E, T);
924 BODY_00_15 (U, 1, T, A, B, C, D, E);
925 BODY_00_15 (U, 2, E, T, A, B, C, D);
926 BODY_00_15 (U, 3, D, E, T, A, B, C);
927 BODY_00_15 (U, 4, C, D, E, T, A, B);
928 BODY_00_15 (U, 5, B, C, D, E, T, A);
929 BODY_00_15 (U, 6, A, B, C, D, E, T);
930 BODY_00_15 (U, 7, T, A, B, C, D, E);
931 BODY_00_15 (U, 8, E, T, A, B, C, D);
932 BODY_00_15 (U, 9, D, E, T, A, B, C);
933 BODY_00_15 (U, 10, C, D, E, T, A, B);
934 BODY_00_15 (U, 11, B, C, D, E, T, A);
935 BODY_00_15 (U, 12, A, B, C, D, E, T);
936 BODY_00_15 (U, 13, T, A, B, C, D, E);
937 BODY_00_15 (U, 14, E, T, A, B, C, D);
938 BODY_00_15 (U, 15, D, E, T, A, B, C);
939 BODY_16_19 (U, 16, C, D, E, T, A, B);
940 BODY_16_19 (U, 17, B, C, D, E, T, A);
941 BODY_16_19 (U, 18, A, B, C, D, E, T);
942 BODY_16_19 (U, 19, T, A, B, C, D, E);
944 BODY_20_39 (U, 20, E, T, A, B, C, D);
945 BODY_20_39 (U, 21, D, E, T, A, B, C);
946 BODY_20_39 (U, 22, C, D, E, T, A, B);
947 BODY_20_39 (U, 23, B, C, D, E, T, A);
948 BODY_20_39 (U, 24, A, B, C, D, E, T);
949 BODY_20_39 (U, 25, T, A, B, C, D, E);
950 BODY_20_39 (U, 26, E, T, A, B, C, D);
951 BODY_20_39 (U, 27, D, E, T, A, B, C);
952 BODY_20_39 (U, 28, C, D, E, T, A, B);
953 BODY_20_39 (U, 29, B, C, D, E, T, A);
954 BODY_20_39 (U, 30, A, B, C, D, E, T);
955 BODY_20_39 (U, 31, T, A, B, C, D, E);
956 BODY_20_39 (U, 32, E, T, A, B, C, D);
957 BODY_20_39 (U, 33, D, E, T, A, B, C);
958 BODY_20_39 (U, 34, C, D, E, T, A, B);
959 BODY_20_39 (U, 35, B, C, D, E, T, A);
960 BODY_20_39 (U, 36, A, B, C, D, E, T);
961 BODY_20_39 (U, 37, T, A, B, C, D, E);
962 BODY_20_39 (U, 38, E, T, A, B, C, D);
963 BODY_20_39 (U, 39, D, E, T, A, B, C);
965 BODY_40_59 (U, 40, C, D, E, T, A, B);
966 BODY_40_59 (U, 41, B, C, D, E, T, A);
967 BODY_40_59 (U, 42, A, B, C, D, E, T);
968 BODY_40_59 (U, 43, T, A, B, C, D, E);
969 BODY_40_59 (U, 44, E, T, A, B, C, D);
970 BODY_40_59 (U, 45, D, E, T, A, B, C);
971 BODY_40_59 (U, 46, C, D, E, T, A, B);
972 BODY_40_59 (U, 47, B, C, D, E, T, A);
973 BODY_40_59 (U, 48, A, B, C, D, E, T);
974 BODY_40_59 (U, 49, T, A, B, C, D, E);
975 BODY_40_59 (U, 50, E, T, A, B, C, D);
976 BODY_40_59 (U, 51, D, E, T, A, B, C);
977 BODY_40_59 (U, 52, C, D, E, T, A, B);
978 BODY_40_59 (U, 53, B, C, D, E, T, A);
979 BODY_40_59 (U, 54, A, B, C, D, E, T);
980 BODY_40_59 (U, 55, T, A, B, C, D, E);
981 BODY_40_59 (U, 56, E, T, A, B, C, D);
982 BODY_40_59 (U, 57, D, E, T, A, B, C);
983 BODY_40_59 (U, 58, C, D, E, T, A, B);
984 BODY_40_59 (U, 59, B, C, D, E, T, A);
986 BODY_60_79 (U, 60, A, B, C, D, E, T);
987 BODY_60_79 (U, 61, T, A, B, C, D, E);
988 BODY_60_79 (U, 62, E, T, A, B, C, D);
989 BODY_60_79 (U, 63, D, E, T, A, B, C);
990 BODY_60_79 (U, 64, C, D, E, T, A, B);
991 BODY_60_79 (U, 65, B, C, D, E, T, A);
992 BODY_60_79 (U, 66, A, B, C, D, E, T);
993 BODY_60_79 (U, 67, T, A, B, C, D, E);
994 BODY_60_79 (U, 68, E, T, A, B, C, D);
995 BODY_60_79 (U, 69, D, E, T, A, B, C);
996 BODY_60_79 (U, 70, C, D, E, T, A, B);
997 BODY_60_79 (U, 71, B, C, D, E, T, A);
998 BODY_60_79 (U, 72, A, B, C, D, E, T);
999 BODY_60_79 (U, 73, T, A, B, C, D, E);
1000 BODY_60_79 (U, 74, E, T, A, B, C, D);
1001 BODY_60_79 (U, 75, D, E, T, A, B, C);
1002 BODY_60_79 (U, 76, C, D, E, T, A, B);
1003 BODY_60_79 (U, 77, B, C, D, E, T, A);
1004 BODY_60_79 (U, 78, A, B, C, D, E, T);
1005 BODY_60_79 (U, 79, T, A, B, C, D, E);
1007 ctx->m_nA += E;
1008 ctx->m_nB += T;
1009 ctx->m_nC += A;
1010 ctx->m_nD += B;
1011 ctx->m_nE += C;
1014 static void endSHA(DigestContextSHA *ctx)
1016 static const sal_uInt8 end[4] =
1018 0x80, 0x00, 0x00, 0x00
1020 const sal_uInt8 *p = end;
1022 sal_uInt32 *X;
1023 int i;
1025 X = ctx->m_pData;
1026 i = (ctx->m_nDatLen >> 2);
1028 #ifdef OSL_BIGENDIAN
1029 swapLong(X, i + 1);
1030 #endif /* OSL_BIGENDIAN */
1032 switch (ctx->m_nDatLen & 0x03)
1034 case 1: X[i] &= 0x000000ff; break;
1035 case 2: X[i] &= 0x0000ffff; break;
1036 case 3: X[i] &= 0x00ffffff; break;
1039 switch (ctx->m_nDatLen & 0x03)
1041 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
1042 [[fallthrough]];
1043 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
1044 [[fallthrough]];
1045 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
1046 [[fallthrough]];
1047 case 3: X[i] |= static_cast<sal_uInt32>(*(p++)) << 24;
1050 swapLong(X, i + 1);
1052 i += 1;
1054 // tdf#114939 NB: this is WRONG and should be ">" not ">=" but is not
1055 // fixed as this buggy SHA1 implementation is needed for compatibility
1056 if (i >= (DIGEST_LBLOCK_SHA - 2))
1058 for (; i < DIGEST_LBLOCK_SHA; i++)
1060 X[i] = 0;
1063 updateSHA(ctx);
1064 i = 0;
1067 for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
1069 X[i] = 0;
1072 X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
1073 X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
1075 updateSHA(ctx);
1078 const Digest_Impl SHA_0 =
1080 rtl_Digest_AlgorithmSHA,
1081 RTL_DIGEST_LENGTH_SHA,
1082 nullptr,
1083 rtl_digest_destroySHA,
1084 rtl_digest_updateSHA,
1085 rtl_digest_getSHA
1088 static sal_uInt32 updateSHA_0(sal_uInt32 x)
1090 return x;
1093 rtlDigestError SAL_CALL rtl_digest_SHA(
1094 const void *pData, sal_uInt32 nDatLen,
1095 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1097 DigestSHA_Impl digest;
1098 rtlDigestError result;
1100 digest.m_digest = SHA_0;
1101 initSHA(&(digest.m_context), updateSHA_0);
1103 result = rtl_digest_updateSHA(&digest, pData, nDatLen);
1104 if (result == rtl_Digest_E_None)
1105 result = rtl_digest_getSHA(&digest, pBuffer, nBufLen);
1107 rtl_secureZeroMemory(&digest, sizeof(digest));
1108 return result;
1111 rtlDigest SAL_CALL rtl_digest_createSHA() noexcept
1113 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1114 if (pImpl)
1116 pImpl->m_digest = SHA_0;
1117 initSHA(&(pImpl->m_context), updateSHA_0);
1119 return static_cast<rtlDigest>(pImpl);
1122 rtlDigestError SAL_CALL rtl_digest_updateSHA(
1123 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
1125 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1126 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
1128 DigestContextSHA *ctx;
1129 sal_uInt32 len;
1131 if (!pImpl || !pData)
1132 return rtl_Digest_E_Argument;
1134 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1135 return rtl_Digest_E_Algorithm;
1137 if (nDatLen == 0)
1138 return rtl_Digest_E_None;
1140 ctx = &(pImpl->m_context);
1142 len = ctx->m_nL + (nDatLen << 3);
1143 if (len < ctx->m_nL)
1144 ctx->m_nH += 1;
1146 ctx->m_nH += (nDatLen >> 29);
1147 ctx->m_nL = len;
1149 if (ctx->m_nDatLen)
1151 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1152 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1154 if (nDatLen < n)
1156 memcpy(p, d, nDatLen);
1157 ctx->m_nDatLen += nDatLen;
1159 return rtl_Digest_E_None;
1162 memcpy(p, d, n);
1163 d += n;
1164 nDatLen -= n;
1166 #ifndef OSL_BIGENDIAN
1167 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1168 #endif /* OSL_BIGENDIAN */
1170 updateSHA(ctx);
1171 ctx->m_nDatLen = 0;
1174 while (nDatLen >= DIGEST_CBLOCK_SHA)
1176 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1177 d += DIGEST_CBLOCK_SHA;
1178 nDatLen -= DIGEST_CBLOCK_SHA;
1180 #ifndef OSL_BIGENDIAN
1181 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1182 #endif /* OSL_BIGENDIAN */
1184 updateSHA(ctx);
1187 memcpy(ctx->m_pData, d, nDatLen);
1188 ctx->m_nDatLen = nDatLen;
1190 return rtl_Digest_E_None;
1193 rtlDigestError SAL_CALL rtl_digest_getSHA(
1194 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1196 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1197 sal_uInt8 *p = pBuffer;
1199 DigestContextSHA *ctx;
1201 if (!pImpl || !pBuffer)
1202 return rtl_Digest_E_Argument;
1204 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1205 return rtl_Digest_E_Algorithm;
1207 if (pImpl->m_digest.m_length > nBufLen)
1208 return rtl_Digest_E_BufferSize;
1210 ctx = &(pImpl->m_context);
1212 endSHA(ctx);
1213 RTL_DIGEST_HTONL(ctx->m_nA, p);
1214 RTL_DIGEST_HTONL(ctx->m_nB, p);
1215 RTL_DIGEST_HTONL(ctx->m_nC, p);
1216 RTL_DIGEST_HTONL(ctx->m_nD, p);
1217 RTL_DIGEST_HTONL(ctx->m_nE, p);
1218 initSHA(ctx, updateSHA_0);
1220 return rtl_Digest_E_None;
1223 void SAL_CALL rtl_digest_destroySHA(rtlDigest Digest) noexcept
1225 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1226 if (pImpl)
1228 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
1229 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1230 else
1231 free(pImpl);
1235 const Digest_Impl SHA_1 =
1237 rtl_Digest_AlgorithmSHA1,
1238 RTL_DIGEST_LENGTH_SHA1,
1239 nullptr,
1240 rtl_digest_destroySHA1,
1241 rtl_digest_updateSHA1,
1242 rtl_digest_getSHA1
1245 static sal_uInt32 updateSHA_1(sal_uInt32 x)
1247 return RTL_DIGEST_ROTL(x, 1);
1250 rtlDigestError SAL_CALL rtl_digest_SHA1(
1251 const void *pData, sal_uInt32 nDatLen,
1252 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1254 DigestSHA_Impl digest;
1255 rtlDigestError result;
1257 digest.m_digest = SHA_1;
1258 initSHA(&(digest.m_context), updateSHA_1);
1260 result = rtl_digest_updateSHA1(&digest, pData, nDatLen);
1261 if (result == rtl_Digest_E_None)
1262 result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen);
1264 rtl_secureZeroMemory(&digest, sizeof(digest));
1265 return result;
1268 rtlDigest SAL_CALL rtl_digest_createSHA1() noexcept
1270 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1271 if (pImpl)
1273 pImpl->m_digest = SHA_1;
1274 initSHA(&(pImpl->m_context), updateSHA_1);
1276 return static_cast<rtlDigest>(pImpl);
1279 rtlDigestError SAL_CALL rtl_digest_updateSHA1(
1280 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
1282 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1283 const sal_uInt8 *d = static_cast< const sal_uInt8 * >(pData);
1285 DigestContextSHA *ctx;
1286 sal_uInt32 len;
1288 if (!pImpl || !pData)
1289 return rtl_Digest_E_Argument;
1291 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1292 return rtl_Digest_E_Algorithm;
1294 if (nDatLen == 0)
1295 return rtl_Digest_E_None;
1297 ctx = &(pImpl->m_context);
1299 len = ctx->m_nL + (nDatLen << 3);
1300 if (len < ctx->m_nL)
1301 ctx->m_nH += 1;
1303 ctx->m_nH += (nDatLen >> 29);
1304 ctx->m_nL = len;
1306 if (ctx->m_nDatLen)
1308 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1309 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1311 if (nDatLen < n)
1313 memcpy(p, d, nDatLen);
1314 ctx->m_nDatLen += nDatLen;
1316 return rtl_Digest_E_None;
1319 memcpy(p, d, n);
1320 d += n;
1321 nDatLen -= n;
1323 #ifndef OSL_BIGENDIAN
1324 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1325 #endif /* OSL_BIGENDIAN */
1327 updateSHA(ctx);
1328 ctx->m_nDatLen = 0;
1331 while (nDatLen >= DIGEST_CBLOCK_SHA)
1333 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1334 d += DIGEST_CBLOCK_SHA;
1335 nDatLen -= DIGEST_CBLOCK_SHA;
1337 #ifndef OSL_BIGENDIAN
1338 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1339 #endif /* OSL_BIGENDIAN */
1341 updateSHA(ctx);
1344 memcpy(ctx->m_pData, d, nDatLen);
1345 ctx->m_nDatLen = nDatLen;
1347 return rtl_Digest_E_None;
1350 rtlDigestError SAL_CALL rtl_digest_getSHA1 (
1351 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1353 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1354 sal_uInt8 *p = pBuffer;
1356 DigestContextSHA *ctx;
1358 if (!pImpl || !pBuffer)
1359 return rtl_Digest_E_Argument;
1361 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1362 return rtl_Digest_E_Algorithm;
1364 if (pImpl->m_digest.m_length > nBufLen)
1365 return rtl_Digest_E_BufferSize;
1367 ctx = &(pImpl->m_context);
1369 endSHA(ctx);
1370 RTL_DIGEST_HTONL(ctx->m_nA, p);
1371 RTL_DIGEST_HTONL(ctx->m_nB, p);
1372 RTL_DIGEST_HTONL(ctx->m_nC, p);
1373 RTL_DIGEST_HTONL(ctx->m_nD, p);
1374 RTL_DIGEST_HTONL(ctx->m_nE, p);
1375 initSHA(ctx, updateSHA_1);
1377 return rtl_Digest_E_None;
1380 void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) noexcept
1382 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1383 if (pImpl)
1385 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
1386 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1387 else
1388 free(pImpl);
1392 #define DIGEST_CBLOCK_HMAC_MD5 64
1394 namespace {
1396 struct ContextHMAC_MD5
1398 DigestMD5_Impl m_hash;
1399 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5];
1402 struct DigestHMAC_MD5_Impl
1404 Digest_Impl m_digest;
1405 ContextHMAC_MD5 m_context;
1410 static void initHMAC_MD5(ContextHMAC_MD5 * ctx);
1411 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx);
1412 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx);
1414 const Digest_Impl HMAC_MD5 =
1416 rtl_Digest_AlgorithmHMAC_MD5,
1417 RTL_DIGEST_LENGTH_MD5,
1419 rtl_digest_initHMAC_MD5,
1420 rtl_digest_destroyHMAC_MD5,
1421 rtl_digest_updateHMAC_MD5,
1422 rtl_digest_getHMAC_MD5
1425 static void initHMAC_MD5(ContextHMAC_MD5 * ctx)
1427 DigestMD5_Impl *pImpl = &(ctx->m_hash);
1429 pImpl->m_digest = MD5;
1430 initMD5(&(pImpl->m_context));
1432 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_MD5);
1435 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx)
1437 sal_uInt32 i;
1439 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1441 ctx->m_opad[i] ^= 0x36;
1444 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
1446 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1448 ctx->m_opad[i] ^= 0x36;
1452 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx)
1454 sal_uInt32 i;
1456 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1458 ctx->m_opad[i] ^= 0x5c;
1462 rtlDigestError SAL_CALL rtl_digest_HMAC_MD5(
1463 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1464 const void *pData, sal_uInt32 nDatLen,
1465 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1467 DigestHMAC_MD5_Impl digest;
1468 rtlDigestError result;
1470 digest.m_digest = HMAC_MD5;
1472 result = rtl_digest_initHMAC_MD5(&digest, pKeyData, nKeyLen);
1473 if (result == rtl_Digest_E_None)
1475 result = rtl_digest_updateHMAC_MD5(&digest, pData, nDatLen);
1476 if (result == rtl_Digest_E_None)
1477 result = rtl_digest_getHMAC_MD5(&digest, pBuffer, nBufLen);
1480 rtl_secureZeroMemory(&digest, sizeof(digest));
1481 return result;
1484 rtlDigest SAL_CALL rtl_digest_createHMAC_MD5() noexcept
1486 DigestHMAC_MD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
1487 if (pImpl)
1489 pImpl->m_digest = HMAC_MD5;
1490 initHMAC_MD5(&(pImpl->m_context));
1492 return static_cast< rtlDigest >(pImpl);
1495 rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5(
1496 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen) noexcept
1498 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1499 ContextHMAC_MD5 *ctx;
1501 if (!pImpl || !pKeyData)
1502 return rtl_Digest_E_Argument;
1504 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1505 return rtl_Digest_E_Algorithm;
1507 ctx = &(pImpl->m_context);
1508 initHMAC_MD5(ctx);
1510 if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
1512 /* Initialize 'opad' with hashed 'KeyData' */
1513 rtl_digest_updateMD5(&(ctx->m_hash), pKeyData, nKeyLen);
1514 rtl_digest_getMD5(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
1516 else
1518 /* Initialize 'opad' with plain 'KeyData' */
1519 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1522 ipadHMAC_MD5(ctx);
1523 opadHMAC_MD5(ctx);
1525 return rtl_Digest_E_None;
1528 rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5(
1529 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
1531 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1532 ContextHMAC_MD5 *ctx;
1534 if (!pImpl || !pData)
1535 return rtl_Digest_E_Argument;
1537 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1538 return rtl_Digest_E_Algorithm;
1540 ctx = &(pImpl->m_context);
1541 rtl_digest_updateMD5(&(ctx->m_hash), pData, nDatLen);
1543 return rtl_Digest_E_None;
1546 rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5(
1547 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1549 DigestHMAC_MD5_Impl *pImpl = static_cast<DigestHMAC_MD5_Impl*>(Digest);
1550 ContextHMAC_MD5 *ctx;
1552 if (!pImpl || !pBuffer)
1553 return rtl_Digest_E_Argument;
1555 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1556 return rtl_Digest_E_Algorithm;
1558 if (pImpl->m_digest.m_length > nBufLen)
1559 return rtl_Digest_E_BufferSize;
1561 nBufLen = pImpl->m_digest.m_length;
1563 ctx = &(pImpl->m_context);
1564 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1566 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, 64);
1567 rtl_digest_updateMD5(&(ctx->m_hash), pBuffer, nBufLen);
1568 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1570 opadHMAC_MD5(ctx);
1571 ipadHMAC_MD5(ctx);
1572 opadHMAC_MD5(ctx);
1574 return rtl_Digest_E_None;
1577 void SAL_CALL rtl_digest_destroyHMAC_MD5(rtlDigest Digest) noexcept
1579 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1580 if (pImpl)
1582 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
1583 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_MD5_Impl));
1584 else
1585 free(pImpl);
1589 #define DIGEST_CBLOCK_HMAC_SHA1 64
1591 namespace {
1593 struct ContextHMAC_SHA1
1595 DigestSHA_Impl m_hash;
1596 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1];
1599 struct DigestHMAC_SHA1_Impl
1601 Digest_Impl m_digest;
1602 ContextHMAC_SHA1 m_context;
1607 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1608 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1609 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1611 const Digest_Impl HMAC_SHA1 =
1613 rtl_Digest_AlgorithmHMAC_SHA1,
1614 RTL_DIGEST_LENGTH_SHA1,
1615 rtl_digest_initHMAC_SHA1,
1616 rtl_digest_destroyHMAC_SHA1,
1617 rtl_digest_updateHMAC_SHA1,
1618 rtl_digest_getHMAC_SHA1
1621 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1623 DigestSHA_Impl *pImpl = &(ctx->m_hash);
1625 pImpl->m_digest = SHA_1;
1626 initSHA(&(pImpl->m_context), updateSHA_1);
1628 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_SHA1);
1631 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1633 sal_uInt32 i;
1635 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1637 ctx->m_opad[i] ^= 0x36;
1640 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
1642 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1644 ctx->m_opad[i] ^= 0x36;
1648 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1650 sal_uInt32 i;
1652 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1654 ctx->m_opad[i] ^= 0x5c;
1658 rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1(
1659 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1660 const void *pData, sal_uInt32 nDatLen,
1661 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1663 DigestHMAC_SHA1_Impl digest;
1664 rtlDigestError result;
1666 digest.m_digest = HMAC_SHA1;
1668 result = rtl_digest_initHMAC_SHA1(&digest, pKeyData, nKeyLen);
1669 if (result == rtl_Digest_E_None)
1671 result = rtl_digest_updateHMAC_SHA1(&digest, pData, nDatLen);
1672 if (result == rtl_Digest_E_None)
1673 result = rtl_digest_getHMAC_SHA1(&digest, pBuffer, nBufLen);
1676 rtl_secureZeroMemory(&digest, sizeof(digest));
1677 return result;
1680 rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1() noexcept
1682 DigestHMAC_SHA1_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
1683 if (pImpl)
1685 pImpl->m_digest = HMAC_SHA1;
1686 initHMAC_SHA1(&(pImpl->m_context));
1688 return static_cast<rtlDigest>(pImpl);
1691 rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1(
1692 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen) noexcept
1694 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1695 ContextHMAC_SHA1 *ctx;
1697 if (!pImpl || !pKeyData)
1698 return rtl_Digest_E_Argument;
1700 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1701 return rtl_Digest_E_Algorithm;
1703 ctx = &(pImpl->m_context);
1704 initHMAC_SHA1(ctx);
1706 if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
1708 /* Initialize 'opad' with hashed 'KeyData' */
1709 rtl_digest_updateSHA1(&(ctx->m_hash), pKeyData, nKeyLen);
1710 rtl_digest_getSHA1(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
1712 else
1714 /* Initialize 'opad' with plain 'KeyData' */
1715 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1718 ipadHMAC_SHA1(ctx);
1719 opadHMAC_SHA1(ctx);
1721 return rtl_Digest_E_None;
1724 rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1(
1725 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept
1727 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1728 ContextHMAC_SHA1 *ctx;
1730 if (!pImpl || !pData)
1731 return rtl_Digest_E_Argument;
1733 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1734 return rtl_Digest_E_Algorithm;
1736 ctx = &(pImpl->m_context);
1737 rtl_digest_updateSHA1(&(ctx->m_hash), pData, nDatLen);
1739 return rtl_Digest_E_None;
1742 rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1(
1743 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
1745 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1746 ContextHMAC_SHA1 *ctx;
1748 if (!pImpl || !pBuffer)
1749 return rtl_Digest_E_Argument;
1751 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1752 return rtl_Digest_E_Algorithm;
1754 if (pImpl->m_digest.m_length > nBufLen)
1755 return rtl_Digest_E_BufferSize;
1757 nBufLen = pImpl->m_digest.m_length;
1759 ctx = &(pImpl->m_context);
1760 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1762 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
1763 rtl_digest_updateSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1764 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1766 opadHMAC_SHA1(ctx);
1767 ipadHMAC_SHA1(ctx);
1768 opadHMAC_SHA1(ctx);
1770 return rtl_Digest_E_None;
1773 void SAL_CALL rtl_digest_destroyHMAC_SHA1(rtlDigest Digest) noexcept
1775 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1776 if (pImpl)
1778 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
1779 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_SHA1_Impl));
1780 else
1781 free(pImpl);
1785 #define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
1787 static void updatePBKDF2(
1788 rtlDigest hDigest,
1789 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2],
1790 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1791 sal_uInt32 nCount, sal_uInt32 nIndex)
1793 /* T_i = F (P, S, c, i) */
1794 sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
1795 sal_uInt32 i, k;
1797 /* U_(1) = PRF (P, S || INDEX) */
1798 rtl_digest_updateHMAC_SHA1(hDigest, pSaltData, nSaltLen);
1799 rtl_digest_updateHMAC_SHA1(hDigest, &nIndex, sizeof(nIndex));
1800 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1802 /* T = U_(1) */
1803 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1805 T[k] = U[k];
1808 /* T ^= U_(2) ^ ... ^ U_(c) */
1809 for (i = 1; i < nCount; i++)
1811 /* U_(i) = PRF (P, U_(i-1)) */
1812 rtl_digest_updateHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1813 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1815 /* T ^= U_(i) */
1816 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1818 T[k] ^= U[k];
1822 rtl_secureZeroMemory(U, DIGEST_CBLOCK_PBKDF2);
1825 rtlDigestError SAL_CALL rtl_digest_PBKDF2(
1826 sal_uInt8 *pKeyData , sal_uInt32 nKeyLen,
1827 const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
1828 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1829 sal_uInt32 nCount) noexcept
1831 DigestHMAC_SHA1_Impl digest;
1832 sal_uInt32 i = 1;
1834 if (!pKeyData || !pPassData || !pSaltData)
1835 return rtl_Digest_E_Argument;
1837 digest.m_digest = HMAC_SHA1;
1838 rtl_digest_initHMAC_SHA1(&digest, pPassData, nPassLen);
1840 /* DK = T_(1) || T_(2) || ... || T_(l) */
1841 while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
1843 /* T_(i) = F (P, S, c, i); DK ||= T_(i) */
1844 updatePBKDF2(
1845 &digest, pKeyData,
1846 pSaltData, nSaltLen,
1847 nCount, OSL_NETDWORD(i));
1849 /* Next 'KeyData' block */
1850 pKeyData += DIGEST_CBLOCK_PBKDF2;
1851 nKeyLen -= DIGEST_CBLOCK_PBKDF2;
1852 i += 1;
1855 if (nKeyLen > 0)
1857 /* Last 'KeyData' block */
1858 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
1860 /* T_i = F (P, S, c, i) */
1861 updatePBKDF2(
1862 &digest, T,
1863 pSaltData, nSaltLen,
1864 nCount, OSL_NETDWORD(i));
1866 /* DK ||= T_(i) */
1867 memcpy(pKeyData, T, nKeyLen);
1868 rtl_secureZeroMemory(T, DIGEST_CBLOCK_PBKDF2);
1871 rtl_secureZeroMemory(&digest, sizeof(digest));
1872 return rtl_Digest_E_None;
1875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */