add fetch to dependencies of gbuildtojson / Rdb target
[LibreOffice.git] / sal / rtl / digest.cxx
blobde52ecae51076d36bdc1a530d497ff0c39c6f298
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)
85 SAL_THROW_EXTERN_C()
87 rtlDigest Digest = nullptr;
88 switch (Algorithm)
90 case rtl_Digest_AlgorithmMD2:
91 Digest = rtl_digest_createMD2();
92 break;
94 case rtl_Digest_AlgorithmMD5:
95 Digest = rtl_digest_createMD5();
96 break;
98 case rtl_Digest_AlgorithmSHA:
99 Digest = rtl_digest_createSHA();
100 break;
102 case rtl_Digest_AlgorithmSHA1:
103 Digest = rtl_digest_createSHA1();
104 break;
106 case rtl_Digest_AlgorithmHMAC_MD5:
107 Digest = rtl_digest_createHMAC_MD5();
108 break;
110 case rtl_Digest_AlgorithmHMAC_SHA1:
111 Digest = rtl_digest_createHMAC_SHA1();
112 break;
114 default: /* rtl_Digest_AlgorithmInvalid */
115 break;
117 return Digest;
120 rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm(rtlDigest Digest)
121 SAL_THROW_EXTERN_C()
123 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
124 if (pImpl)
125 return pImpl->m_algorithm;
126 return rtl_Digest_AlgorithmInvalid;
129 sal_uInt32 SAL_CALL rtl_digest_queryLength(rtlDigest Digest)
130 SAL_THROW_EXTERN_C()
132 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
133 if (pImpl)
134 return pImpl->m_length;
135 return 0;
138 rtlDigestError SAL_CALL rtl_digest_init(
139 rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
140 SAL_THROW_EXTERN_C()
142 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
143 if (pImpl)
145 if (pImpl->m_init)
146 return pImpl->m_init (Digest, pData, nDatLen);
147 return rtl_Digest_E_None;
149 return rtl_Digest_E_Argument;
152 rtlDigestError SAL_CALL rtl_digest_update(
153 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
154 SAL_THROW_EXTERN_C()
156 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
157 if (pImpl && pImpl->m_update)
158 return pImpl->m_update(Digest, pData, nDatLen);
159 return rtl_Digest_E_Argument;
162 rtlDigestError SAL_CALL rtl_digest_get(
163 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
164 SAL_THROW_EXTERN_C()
166 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
167 if (pImpl && pImpl->m_get)
168 return pImpl->m_get(Digest, pBuffer, nBufLen);
169 return rtl_Digest_E_Argument;
172 void SAL_CALL rtl_digest_destroy(rtlDigest Digest) SAL_THROW_EXTERN_C()
174 Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
175 if (pImpl && pImpl->m_delete)
176 pImpl->m_delete(Digest);
179 constexpr auto DIGEST_CBLOCK_MD2 = 16;
180 constexpr auto DIGEST_LBLOCK_MD2 = 16;
182 namespace {
184 struct DigestContextMD2
186 sal_uInt32 m_nDatLen;
187 sal_uInt8 m_pData[DIGEST_CBLOCK_MD2];
188 sal_uInt32 m_state[DIGEST_LBLOCK_MD2];
189 sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2];
192 struct DigestMD2_Impl
194 Digest_Impl m_digest;
195 DigestContextMD2 m_context;
200 static void initMD2 (DigestContextMD2 *ctx);
201 static void updateMD2 (DigestContextMD2 *ctx);
202 static void endMD2 (DigestContextMD2 *ctx);
204 const sal_uInt32 S[256] =
206 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
207 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
208 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
209 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
210 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
211 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
212 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
213 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
214 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
215 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
216 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
217 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
218 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
219 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
220 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
221 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
222 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
223 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
224 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
225 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
226 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
227 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
228 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
229 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
230 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
231 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
232 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
233 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
234 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
235 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
236 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
237 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
240 const Digest_Impl MD2 =
242 rtl_Digest_AlgorithmMD2,
243 RTL_DIGEST_LENGTH_MD2,
244 nullptr,
245 rtl_digest_destroyMD2,
246 rtl_digest_updateMD2,
247 rtl_digest_getMD2
250 static void initMD2(DigestContextMD2 *ctx)
252 memset(ctx, 0, sizeof(DigestContextMD2));
255 static void updateMD2(DigestContextMD2 *ctx)
257 sal_uInt8 *X;
258 sal_uInt32 *sp1, *sp2;
259 sal_uInt32 i, k, t;
261 sal_uInt32 state[48];
263 X = ctx->m_pData;
264 sp1 = ctx->m_state;
265 sp2 = ctx->m_chksum;
267 k = sp2[DIGEST_LBLOCK_MD2 - 1];
268 for (i = 0; i < 16; i++)
270 state[i + 0] = sp1[i];
271 state[i + 16] = t = X[i];
272 state[i + 32] = t ^ sp1[i];
273 k = sp2[i] ^= S[t^k];
276 t = 0;
277 for (i = 0; i < 18; i++)
279 for (k = 0; k < 48; k += 8)
281 t = state[k + 0] ^= S[t];
282 t = state[k + 1] ^= S[t];
283 t = state[k + 2] ^= S[t];
284 t = state[k + 3] ^= S[t];
285 t = state[k + 4] ^= S[t];
286 t = state[k + 5] ^= S[t];
287 t = state[k + 6] ^= S[t];
288 t = state[k + 7] ^= S[t];
290 t = ((t + i) & 0xff);
293 memcpy(sp1, state, 16 * sizeof(sal_uInt32));
294 rtl_secureZeroMemory(state, 48 * sizeof(sal_uInt32));
297 static void endMD2(DigestContextMD2 *ctx)
299 sal_uInt8 *X;
300 sal_uInt32 *C;
301 sal_uInt32 i, n;
303 X = ctx->m_pData;
304 C = ctx->m_chksum;
305 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
307 for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
308 X[i] = static_cast<sal_uInt8>(n & 0xff);
310 updateMD2(ctx);
312 for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
313 X[i] = static_cast<sal_uInt8>(C[i] & 0xff);
314 updateMD2(ctx);
317 rtlDigestError SAL_CALL rtl_digest_MD2(
318 const void *pData, sal_uInt32 nDatLen,
319 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
321 DigestMD2_Impl digest;
322 rtlDigestError result;
324 digest.m_digest = MD2;
325 initMD2(&(digest.m_context));
327 result = rtl_digest_updateMD2(&digest, pData, nDatLen);
328 if (result == rtl_Digest_E_None)
329 result = rtl_digest_getMD2(&digest, pBuffer, nBufLen);
331 rtl_secureZeroMemory(&digest, sizeof(digest));
332 return result;
335 rtlDigest SAL_CALL rtl_digest_createMD2() SAL_THROW_EXTERN_C()
337 DigestMD2_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
338 if (pImpl)
340 pImpl->m_digest = MD2;
341 initMD2(&(pImpl->m_context));
343 return static_cast<rtlDigest>(pImpl);
346 rtlDigestError SAL_CALL rtl_digest_updateMD2(
347 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
348 SAL_THROW_EXTERN_C()
350 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
351 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
353 DigestContextMD2 *ctx;
355 if (!pImpl || !pData)
356 return rtl_Digest_E_Argument;
358 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
359 return rtl_Digest_E_Algorithm;
361 if (nDatLen == 0)
362 return rtl_Digest_E_None;
364 ctx = &(pImpl->m_context);
366 if (ctx->m_nDatLen)
368 sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen;
369 sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
371 if (nDatLen < n)
373 memcpy(p, d, nDatLen);
374 ctx->m_nDatLen += nDatLen;
376 return rtl_Digest_E_None;
379 memcpy(p, d, n);
380 d += n;
381 nDatLen -= n;
383 updateMD2(ctx);
384 ctx->m_nDatLen = 0;
387 while (nDatLen >= DIGEST_CBLOCK_MD2)
389 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD2);
390 d += DIGEST_CBLOCK_MD2;
391 nDatLen -= DIGEST_CBLOCK_MD2;
393 updateMD2(ctx);
396 memcpy(ctx->m_pData, d, nDatLen);
397 ctx->m_nDatLen = nDatLen;
399 return rtl_Digest_E_None;
402 rtlDigestError SAL_CALL rtl_digest_getMD2(
403 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
404 SAL_THROW_EXTERN_C()
406 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
407 sal_uInt32 i;
409 DigestContextMD2 *ctx;
411 if (!pImpl || !pBuffer)
412 return rtl_Digest_E_Argument;
414 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
415 return rtl_Digest_E_Algorithm;
417 if (pImpl->m_digest.m_length > nBufLen)
418 return rtl_Digest_E_BufferSize;
420 ctx = &(pImpl->m_context);
422 endMD2(ctx);
423 for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
425 pBuffer[i] = static_cast<sal_uInt8>(ctx->m_state[i] & 0xff);
428 initMD2(ctx);
430 return rtl_Digest_E_None;
433 void SAL_CALL rtl_digest_destroyMD2(rtlDigest Digest) SAL_THROW_EXTERN_C()
435 DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
436 if (pImpl)
438 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2)
439 rtl_freeZeroMemory(pImpl, sizeof(DigestMD2_Impl));
440 else
441 free(pImpl);
445 #define DIGEST_CBLOCK_MD5 64
446 #define DIGEST_LBLOCK_MD5 16
448 namespace {
450 struct DigestContextMD5
452 sal_uInt32 m_nDatLen;
453 sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
454 sal_uInt32 m_nA, m_nB, m_nC, m_nD;
455 sal_uInt32 m_nL, m_nH;
458 struct DigestMD5_Impl
460 Digest_Impl m_digest;
461 DigestContextMD5 m_context;
466 static void initMD5 (DigestContextMD5 *ctx);
467 static void updateMD5 (DigestContextMD5 *ctx);
468 static void endMD5 (DigestContextMD5 *ctx);
470 #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
471 #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
472 #define H(x,y,z) ((x) ^ (y) ^ (z))
473 #define I(x,y,z) (((x) | (~(z))) ^ (y))
475 #define R0(a,b,c,d,k,s,t) { \
476 a += ((k) + (t) + F((b), (c), (d))); \
477 a = RTL_DIGEST_ROTL(a, s); \
478 a += b; }
480 #define R1(a,b,c,d,k,s,t) { \
481 a += ((k) + (t) + G((b), (c), (d))); \
482 a = RTL_DIGEST_ROTL(a, s); \
483 a += b; }
485 #define R2(a,b,c,d,k,s,t) { \
486 a += ((k) + (t) + H((b), (c), (d))); \
487 a = RTL_DIGEST_ROTL(a, s); \
488 a += b; }
490 #define R3(a,b,c,d,k,s,t) { \
491 a += ((k) + (t) + I((b), (c), (d))); \
492 a = RTL_DIGEST_ROTL(a, s); \
493 a += b; }
495 const Digest_Impl MD5 =
497 rtl_Digest_AlgorithmMD5,
498 RTL_DIGEST_LENGTH_MD5,
499 nullptr,
500 rtl_digest_destroyMD5,
501 rtl_digest_updateMD5,
502 rtl_digest_getMD5
505 static void initMD5(DigestContextMD5 *ctx)
507 memset(ctx, 0, sizeof(DigestContextMD5));
509 ctx->m_nA = sal_uInt32(0x67452301L);
510 ctx->m_nB = sal_uInt32(0xefcdab89L);
511 ctx->m_nC = sal_uInt32(0x98badcfeL);
512 ctx->m_nD = sal_uInt32(0x10325476L);
515 static void updateMD5(DigestContextMD5 *ctx)
517 sal_uInt32 A, B, C, D;
518 sal_uInt32 *X;
520 A = ctx->m_nA;
521 B = ctx->m_nB;
522 C = ctx->m_nC;
523 D = ctx->m_nD;
524 X = ctx->m_pData;
526 R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L);
527 R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
528 R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
529 R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
530 R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL);
531 R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
532 R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
533 R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
534 R0 (A, B, C, D, X[ 8], 7, 0x698098d8L);
535 R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
536 R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
537 R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
538 R0 (A, B, C, D, X[12], 7, 0x6b901122L);
539 R0 (D, A, B, C, X[13], 12, 0xfd987193L);
540 R0 (C, D, A, B, X[14], 17, 0xa679438eL);
541 R0 (B, C, D, A, X[15], 22, 0x49b40821L);
543 R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L);
544 R1 (D, A, B, C, X[ 6], 9, 0xc040b340L);
545 R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
546 R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
547 R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL);
548 R1 (D, A, B, C, X[10], 9, 0x02441453L);
549 R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
550 R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
551 R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L);
552 R1 (D, A, B, C, X[14], 9, 0xc33707d6L);
553 R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
554 R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
555 R1 (A, B, C, D, X[13], 5, 0xa9e3e905L);
556 R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L);
557 R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
558 R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
560 R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L);
561 R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
562 R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
563 R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
564 R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L);
565 R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
566 R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
567 R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
568 R2 (A, B, C, D, X[13], 4, 0x289b7ec6L);
569 R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
570 R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
571 R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
572 R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L);
573 R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
574 R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
575 R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
577 R3 (A, B, C, D, X[ 0], 6, 0xf4292244L);
578 R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
579 R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
580 R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
581 R3 (A, B, C, D, X[12], 6, 0x655b59c3L);
582 R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
583 R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
584 R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
585 R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL);
586 R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
587 R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
588 R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
589 R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L);
590 R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
591 R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
592 R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
594 ctx->m_nA += A;
595 ctx->m_nB += B;
596 ctx->m_nC += C;
597 ctx->m_nD += D;
600 static void endMD5(DigestContextMD5 *ctx)
602 static const sal_uInt8 end[4] =
604 0x80, 0x00, 0x00, 0x00
606 const sal_uInt8 *p = end;
608 sal_uInt32 *X;
609 int i;
611 X = ctx->m_pData;
612 i = (ctx->m_nDatLen >> 2);
614 #ifdef OSL_BIGENDIAN
615 swapLong(X, i + 1);
616 #endif /* OSL_BIGENDIAN */
618 switch (ctx->m_nDatLen & 0x03)
620 case 1: X[i] &= 0x000000ff; break;
621 case 2: X[i] &= 0x0000ffff; break;
622 case 3: X[i] &= 0x00ffffff; break;
625 switch (ctx->m_nDatLen & 0x03)
627 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
628 [[fallthrough]];
629 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
630 [[fallthrough]];
631 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
632 [[fallthrough]];
633 case 3: X[i] |= static_cast<sal_uInt32>(*p) << 24;
636 i += 1;
638 if (i > (DIGEST_LBLOCK_MD5 - 2))
640 for (; i < DIGEST_LBLOCK_MD5; i++)
642 X[i] = 0;
645 updateMD5(ctx);
646 i = 0;
649 for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
650 X[i] = 0;
652 X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
653 X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
655 updateMD5(ctx);
658 rtlDigestError SAL_CALL rtl_digest_MD5(
659 const void *pData, sal_uInt32 nDatLen,
660 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
662 DigestMD5_Impl digest;
663 rtlDigestError result;
665 digest.m_digest = MD5;
666 initMD5(&(digest.m_context));
668 result = rtl_digest_update(&digest, pData, nDatLen);
669 if (result == rtl_Digest_E_None)
670 result = rtl_digest_getMD5(&digest, pBuffer, nBufLen);
672 rtl_secureZeroMemory(&digest, sizeof(digest));
673 return result;
676 rtlDigest SAL_CALL rtl_digest_createMD5() SAL_THROW_EXTERN_C()
678 DigestMD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
679 if (pImpl)
681 pImpl->m_digest = MD5;
682 initMD5(&(pImpl->m_context));
684 return static_cast<rtlDigest>(pImpl);
687 rtlDigestError SAL_CALL rtl_digest_updateMD5(
688 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
689 SAL_THROW_EXTERN_C()
691 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
692 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
694 DigestContextMD5 *ctx;
695 sal_uInt32 len;
697 if (!pImpl || !pData)
698 return rtl_Digest_E_Argument;
700 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
701 return rtl_Digest_E_Algorithm;
703 if (nDatLen == 0)
704 return rtl_Digest_E_None;
706 ctx = &(pImpl->m_context);
708 len = ctx->m_nL + (nDatLen << 3);
709 if (len < ctx->m_nL)
710 ctx->m_nH += 1;
712 ctx->m_nH += (nDatLen >> 29);
713 ctx->m_nL = len;
715 if (ctx->m_nDatLen)
717 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
718 sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
720 if (nDatLen < n)
722 memcpy(p, d, nDatLen);
723 ctx->m_nDatLen += nDatLen;
725 return rtl_Digest_E_None;
728 memcpy(p, d, n);
729 d += n;
730 nDatLen -= n;
732 #ifdef OSL_BIGENDIAN
733 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
734 #endif /* OSL_BIGENDIAN */
736 updateMD5(ctx);
737 ctx->m_nDatLen = 0;
740 while (nDatLen >= DIGEST_CBLOCK_MD5)
742 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD5);
743 d += DIGEST_CBLOCK_MD5;
744 nDatLen -= DIGEST_CBLOCK_MD5;
746 #ifdef OSL_BIGENDIAN
747 swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
748 #endif /* OSL_BIGENDIAN */
750 updateMD5(ctx);
753 memcpy(ctx->m_pData, d, nDatLen);
754 ctx->m_nDatLen = nDatLen;
756 return rtl_Digest_E_None;
759 rtlDigestError SAL_CALL rtl_digest_getMD5(
760 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
761 SAL_THROW_EXTERN_C()
763 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
764 sal_uInt8 *p = pBuffer;
766 DigestContextMD5 *ctx;
768 if (!pImpl || !pBuffer)
769 return rtl_Digest_E_Argument;
771 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
772 return rtl_Digest_E_Algorithm;
774 if (pImpl->m_digest.m_length > nBufLen)
775 return rtl_Digest_E_BufferSize;
777 ctx = &(pImpl->m_context);
779 endMD5(ctx);
780 RTL_DIGEST_LTOC(ctx->m_nA, p);
781 RTL_DIGEST_LTOC(ctx->m_nB, p);
782 RTL_DIGEST_LTOC(ctx->m_nC, p);
783 RTL_DIGEST_LTOC(ctx->m_nD, p);
784 initMD5(ctx);
786 return rtl_Digest_E_None;
789 rtlDigestError SAL_CALL rtl_digest_rawMD5(
790 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
791 SAL_THROW_EXTERN_C()
793 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
794 sal_uInt8 *p = pBuffer;
796 DigestContextMD5 *ctx;
798 if (!pImpl || !pBuffer)
799 return rtl_Digest_E_Argument;
801 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
802 return rtl_Digest_E_Algorithm;
804 if (pImpl->m_digest.m_length > nBufLen)
805 return rtl_Digest_E_BufferSize;
807 ctx = &(pImpl->m_context);
809 /* not finalized */
810 RTL_DIGEST_LTOC(ctx->m_nA, p);
811 RTL_DIGEST_LTOC(ctx->m_nB, p);
812 RTL_DIGEST_LTOC(ctx->m_nC, p);
813 RTL_DIGEST_LTOC(ctx->m_nD, p);
814 initMD5(ctx);
816 return rtl_Digest_E_None;
819 void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
821 DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
822 if (pImpl)
824 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
825 rtl_freeZeroMemory(pImpl, sizeof(DigestMD5_Impl));
826 else
827 free(pImpl);
831 #define DIGEST_CBLOCK_SHA 64
832 #define DIGEST_LBLOCK_SHA 16
834 typedef sal_uInt32 DigestSHA_update_t(sal_uInt32 x);
836 static sal_uInt32 updateSHA_0(sal_uInt32 x);
837 static sal_uInt32 updateSHA_1(sal_uInt32 x);
839 namespace {
841 struct DigestContextSHA
843 DigestSHA_update_t *m_update;
844 sal_uInt32 m_nDatLen;
845 sal_uInt32 m_pData[DIGEST_LBLOCK_SHA];
846 sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE;
847 sal_uInt32 m_nL, m_nH;
850 struct DigestSHA_Impl
852 Digest_Impl m_digest;
853 DigestContextSHA m_context;
858 static void initSHA(
859 DigestContextSHA *ctx, DigestSHA_update_t *fct);
861 static void updateSHA(DigestContextSHA *ctx);
862 static void endSHA(DigestContextSHA *ctx);
864 #define K_00_19 sal_uInt32(0x5a827999L)
865 #define K_20_39 sal_uInt32(0x6ed9eba1L)
866 #define K_40_59 sal_uInt32(0x8f1bbcdcL)
867 #define K_60_79 sal_uInt32(0xca62c1d6L)
869 #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
870 #define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
871 #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
872 #define F_60_79(b,c,d) F_20_39(b,c,d)
874 #define BODY_X(i) \
875 (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
877 #define BODY_00_15(u,i,a,b,c,d,e,f) \
878 (f) = X[i]; \
879 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
880 (b) = RTL_DIGEST_ROTL((b), 30);
882 #define BODY_16_19(u,i,a,b,c,d,e,f) \
883 (f) = BODY_X((i)); \
884 (f) = X[(i)&0x0f] = (u)((f)); \
885 (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
886 (b) = RTL_DIGEST_ROTL((b), 30);
888 #define BODY_20_39(u,i,a,b,c,d,e,f) \
889 (f) = BODY_X((i)); \
890 (f) = X[(i)&0x0f] = (u)((f)); \
891 (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
892 (b) = RTL_DIGEST_ROTL((b), 30);
894 #define BODY_40_59(u,i,a,b,c,d,e,f) \
895 (f) = BODY_X((i)); \
896 (f) = X[(i)&0x0f] = (u)((f)); \
897 (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
898 (b) = RTL_DIGEST_ROTL((b), 30);
900 #define BODY_60_79(u,i,a,b,c,d,e,f) \
901 (f) = BODY_X((i)); \
902 (f) = X[(i)&0x0f] = (u)((f)); \
903 (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
904 (b) = RTL_DIGEST_ROTL((b), 30);
906 static void initSHA(
907 DigestContextSHA *ctx, DigestSHA_update_t *fct)
909 memset(ctx, 0, sizeof(DigestContextSHA));
910 ctx->m_update = fct;
912 ctx->m_nA = sal_uInt32(0x67452301L);
913 ctx->m_nB = sal_uInt32(0xefcdab89L);
914 ctx->m_nC = sal_uInt32(0x98badcfeL);
915 ctx->m_nD = sal_uInt32(0x10325476L);
916 ctx->m_nE = sal_uInt32(0xc3d2e1f0L);
919 static void updateSHA(DigestContextSHA *ctx)
921 sal_uInt32 A, B, C, D, E, T;
922 sal_uInt32 *X;
924 DigestSHA_update_t *U;
925 U = ctx->m_update;
927 A = ctx->m_nA;
928 B = ctx->m_nB;
929 C = ctx->m_nC;
930 D = ctx->m_nD;
931 E = ctx->m_nE;
932 X = ctx->m_pData;
934 BODY_00_15 (U, 0, A, B, C, D, E, T);
935 BODY_00_15 (U, 1, T, A, B, C, D, E);
936 BODY_00_15 (U, 2, E, T, A, B, C, D);
937 BODY_00_15 (U, 3, D, E, T, A, B, C);
938 BODY_00_15 (U, 4, C, D, E, T, A, B);
939 BODY_00_15 (U, 5, B, C, D, E, T, A);
940 BODY_00_15 (U, 6, A, B, C, D, E, T);
941 BODY_00_15 (U, 7, T, A, B, C, D, E);
942 BODY_00_15 (U, 8, E, T, A, B, C, D);
943 BODY_00_15 (U, 9, D, E, T, A, B, C);
944 BODY_00_15 (U, 10, C, D, E, T, A, B);
945 BODY_00_15 (U, 11, B, C, D, E, T, A);
946 BODY_00_15 (U, 12, A, B, C, D, E, T);
947 BODY_00_15 (U, 13, T, A, B, C, D, E);
948 BODY_00_15 (U, 14, E, T, A, B, C, D);
949 BODY_00_15 (U, 15, D, E, T, A, B, C);
950 BODY_16_19 (U, 16, C, D, E, T, A, B);
951 BODY_16_19 (U, 17, B, C, D, E, T, A);
952 BODY_16_19 (U, 18, A, B, C, D, E, T);
953 BODY_16_19 (U, 19, T, A, B, C, D, E);
955 BODY_20_39 (U, 20, E, T, A, B, C, D);
956 BODY_20_39 (U, 21, D, E, T, A, B, C);
957 BODY_20_39 (U, 22, C, D, E, T, A, B);
958 BODY_20_39 (U, 23, B, C, D, E, T, A);
959 BODY_20_39 (U, 24, A, B, C, D, E, T);
960 BODY_20_39 (U, 25, T, A, B, C, D, E);
961 BODY_20_39 (U, 26, E, T, A, B, C, D);
962 BODY_20_39 (U, 27, D, E, T, A, B, C);
963 BODY_20_39 (U, 28, C, D, E, T, A, B);
964 BODY_20_39 (U, 29, B, C, D, E, T, A);
965 BODY_20_39 (U, 30, A, B, C, D, E, T);
966 BODY_20_39 (U, 31, T, A, B, C, D, E);
967 BODY_20_39 (U, 32, E, T, A, B, C, D);
968 BODY_20_39 (U, 33, D, E, T, A, B, C);
969 BODY_20_39 (U, 34, C, D, E, T, A, B);
970 BODY_20_39 (U, 35, B, C, D, E, T, A);
971 BODY_20_39 (U, 36, A, B, C, D, E, T);
972 BODY_20_39 (U, 37, T, A, B, C, D, E);
973 BODY_20_39 (U, 38, E, T, A, B, C, D);
974 BODY_20_39 (U, 39, D, E, T, A, B, C);
976 BODY_40_59 (U, 40, C, D, E, T, A, B);
977 BODY_40_59 (U, 41, B, C, D, E, T, A);
978 BODY_40_59 (U, 42, A, B, C, D, E, T);
979 BODY_40_59 (U, 43, T, A, B, C, D, E);
980 BODY_40_59 (U, 44, E, T, A, B, C, D);
981 BODY_40_59 (U, 45, D, E, T, A, B, C);
982 BODY_40_59 (U, 46, C, D, E, T, A, B);
983 BODY_40_59 (U, 47, B, C, D, E, T, A);
984 BODY_40_59 (U, 48, A, B, C, D, E, T);
985 BODY_40_59 (U, 49, T, A, B, C, D, E);
986 BODY_40_59 (U, 50, E, T, A, B, C, D);
987 BODY_40_59 (U, 51, D, E, T, A, B, C);
988 BODY_40_59 (U, 52, C, D, E, T, A, B);
989 BODY_40_59 (U, 53, B, C, D, E, T, A);
990 BODY_40_59 (U, 54, A, B, C, D, E, T);
991 BODY_40_59 (U, 55, T, A, B, C, D, E);
992 BODY_40_59 (U, 56, E, T, A, B, C, D);
993 BODY_40_59 (U, 57, D, E, T, A, B, C);
994 BODY_40_59 (U, 58, C, D, E, T, A, B);
995 BODY_40_59 (U, 59, B, C, D, E, T, A);
997 BODY_60_79 (U, 60, A, B, C, D, E, T);
998 BODY_60_79 (U, 61, T, A, B, C, D, E);
999 BODY_60_79 (U, 62, E, T, A, B, C, D);
1000 BODY_60_79 (U, 63, D, E, T, A, B, C);
1001 BODY_60_79 (U, 64, C, D, E, T, A, B);
1002 BODY_60_79 (U, 65, B, C, D, E, T, A);
1003 BODY_60_79 (U, 66, A, B, C, D, E, T);
1004 BODY_60_79 (U, 67, T, A, B, C, D, E);
1005 BODY_60_79 (U, 68, E, T, A, B, C, D);
1006 BODY_60_79 (U, 69, D, E, T, A, B, C);
1007 BODY_60_79 (U, 70, C, D, E, T, A, B);
1008 BODY_60_79 (U, 71, B, C, D, E, T, A);
1009 BODY_60_79 (U, 72, A, B, C, D, E, T);
1010 BODY_60_79 (U, 73, T, A, B, C, D, E);
1011 BODY_60_79 (U, 74, E, T, A, B, C, D);
1012 BODY_60_79 (U, 75, D, E, T, A, B, C);
1013 BODY_60_79 (U, 76, C, D, E, T, A, B);
1014 BODY_60_79 (U, 77, B, C, D, E, T, A);
1015 BODY_60_79 (U, 78, A, B, C, D, E, T);
1016 BODY_60_79 (U, 79, T, A, B, C, D, E);
1018 ctx->m_nA += E;
1019 ctx->m_nB += T;
1020 ctx->m_nC += A;
1021 ctx->m_nD += B;
1022 ctx->m_nE += C;
1025 static void endSHA(DigestContextSHA *ctx)
1027 static const sal_uInt8 end[4] =
1029 0x80, 0x00, 0x00, 0x00
1031 const sal_uInt8 *p = end;
1033 sal_uInt32 *X;
1034 int i;
1036 X = ctx->m_pData;
1037 i = (ctx->m_nDatLen >> 2);
1039 #ifdef OSL_BIGENDIAN
1040 swapLong(X, i + 1);
1041 #endif /* OSL_BIGENDIAN */
1043 switch (ctx->m_nDatLen & 0x03)
1045 case 1: X[i] &= 0x000000ff; break;
1046 case 2: X[i] &= 0x0000ffff; break;
1047 case 3: X[i] &= 0x00ffffff; break;
1050 switch (ctx->m_nDatLen & 0x03)
1052 case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
1053 [[fallthrough]];
1054 case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
1055 [[fallthrough]];
1056 case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
1057 [[fallthrough]];
1058 case 3: X[i] |= static_cast<sal_uInt32>(*(p++)) << 24;
1061 swapLong(X, i + 1);
1063 i += 1;
1065 // tdf#114939 NB: this is WRONG and should be ">" not ">=" but is not
1066 // fixed as this buggy SHA1 implementation is needed for compatibility
1067 if (i >= (DIGEST_LBLOCK_SHA - 2))
1069 for (; i < DIGEST_LBLOCK_SHA; i++)
1071 X[i] = 0;
1074 updateSHA(ctx);
1075 i = 0;
1078 for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
1080 X[i] = 0;
1083 X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
1084 X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
1086 updateSHA(ctx);
1089 const Digest_Impl SHA_0 =
1091 rtl_Digest_AlgorithmSHA,
1092 RTL_DIGEST_LENGTH_SHA,
1093 nullptr,
1094 rtl_digest_destroySHA,
1095 rtl_digest_updateSHA,
1096 rtl_digest_getSHA
1099 static sal_uInt32 updateSHA_0(sal_uInt32 x)
1101 return x;
1104 rtlDigestError SAL_CALL rtl_digest_SHA(
1105 const void *pData, sal_uInt32 nDatLen,
1106 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1108 DigestSHA_Impl digest;
1109 rtlDigestError result;
1111 digest.m_digest = SHA_0;
1112 initSHA(&(digest.m_context), updateSHA_0);
1114 result = rtl_digest_updateSHA(&digest, pData, nDatLen);
1115 if (result == rtl_Digest_E_None)
1116 result = rtl_digest_getSHA(&digest, pBuffer, nBufLen);
1118 rtl_secureZeroMemory(&digest, sizeof(digest));
1119 return result;
1122 rtlDigest SAL_CALL rtl_digest_createSHA() SAL_THROW_EXTERN_C()
1124 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1125 if (pImpl)
1127 pImpl->m_digest = SHA_0;
1128 initSHA(&(pImpl->m_context), updateSHA_0);
1130 return static_cast<rtlDigest>(pImpl);
1133 rtlDigestError SAL_CALL rtl_digest_updateSHA(
1134 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1135 SAL_THROW_EXTERN_C()
1137 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1138 const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
1140 DigestContextSHA *ctx;
1141 sal_uInt32 len;
1143 if (!pImpl || !pData)
1144 return rtl_Digest_E_Argument;
1146 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1147 return rtl_Digest_E_Algorithm;
1149 if (nDatLen == 0)
1150 return rtl_Digest_E_None;
1152 ctx = &(pImpl->m_context);
1154 len = ctx->m_nL + (nDatLen << 3);
1155 if (len < ctx->m_nL)
1156 ctx->m_nH += 1;
1158 ctx->m_nH += (nDatLen >> 29);
1159 ctx->m_nL = len;
1161 if (ctx->m_nDatLen)
1163 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1164 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1166 if (nDatLen < n)
1168 memcpy(p, d, nDatLen);
1169 ctx->m_nDatLen += nDatLen;
1171 return rtl_Digest_E_None;
1174 memcpy(p, d, n);
1175 d += n;
1176 nDatLen -= n;
1178 #ifndef OSL_BIGENDIAN
1179 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1180 #endif /* OSL_BIGENDIAN */
1182 updateSHA(ctx);
1183 ctx->m_nDatLen = 0;
1186 while (nDatLen >= DIGEST_CBLOCK_SHA)
1188 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1189 d += DIGEST_CBLOCK_SHA;
1190 nDatLen -= DIGEST_CBLOCK_SHA;
1192 #ifndef OSL_BIGENDIAN
1193 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1194 #endif /* OSL_BIGENDIAN */
1196 updateSHA(ctx);
1199 memcpy(ctx->m_pData, d, nDatLen);
1200 ctx->m_nDatLen = nDatLen;
1202 return rtl_Digest_E_None;
1205 rtlDigestError SAL_CALL rtl_digest_getSHA(
1206 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1207 SAL_THROW_EXTERN_C()
1209 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1210 sal_uInt8 *p = pBuffer;
1212 DigestContextSHA *ctx;
1214 if (!pImpl || !pBuffer)
1215 return rtl_Digest_E_Argument;
1217 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
1218 return rtl_Digest_E_Algorithm;
1220 if (pImpl->m_digest.m_length > nBufLen)
1221 return rtl_Digest_E_BufferSize;
1223 ctx = &(pImpl->m_context);
1225 endSHA(ctx);
1226 RTL_DIGEST_HTONL(ctx->m_nA, p);
1227 RTL_DIGEST_HTONL(ctx->m_nB, p);
1228 RTL_DIGEST_HTONL(ctx->m_nC, p);
1229 RTL_DIGEST_HTONL(ctx->m_nD, p);
1230 RTL_DIGEST_HTONL(ctx->m_nE, p);
1231 initSHA(ctx, updateSHA_0);
1233 return rtl_Digest_E_None;
1236 void SAL_CALL rtl_digest_destroySHA(rtlDigest Digest) SAL_THROW_EXTERN_C()
1238 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1239 if (pImpl)
1241 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
1242 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1243 else
1244 free(pImpl);
1248 const Digest_Impl SHA_1 =
1250 rtl_Digest_AlgorithmSHA1,
1251 RTL_DIGEST_LENGTH_SHA1,
1252 nullptr,
1253 rtl_digest_destroySHA1,
1254 rtl_digest_updateSHA1,
1255 rtl_digest_getSHA1
1258 static sal_uInt32 updateSHA_1(sal_uInt32 x)
1260 return RTL_DIGEST_ROTL(x, 1);
1263 rtlDigestError SAL_CALL rtl_digest_SHA1(
1264 const void *pData, sal_uInt32 nDatLen,
1265 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1267 DigestSHA_Impl digest;
1268 rtlDigestError result;
1270 digest.m_digest = SHA_1;
1271 initSHA(&(digest.m_context), updateSHA_1);
1273 result = rtl_digest_updateSHA1(&digest, pData, nDatLen);
1274 if (result == rtl_Digest_E_None)
1275 result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen);
1277 rtl_secureZeroMemory(&digest, sizeof(digest));
1278 return result;
1281 rtlDigest SAL_CALL rtl_digest_createSHA1() SAL_THROW_EXTERN_C()
1283 DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1284 if (pImpl)
1286 pImpl->m_digest = SHA_1;
1287 initSHA(&(pImpl->m_context), updateSHA_1);
1289 return static_cast<rtlDigest>(pImpl);
1292 rtlDigestError SAL_CALL rtl_digest_updateSHA1(
1293 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1294 SAL_THROW_EXTERN_C()
1296 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1297 const sal_uInt8 *d = static_cast< const sal_uInt8 * >(pData);
1299 DigestContextSHA *ctx;
1300 sal_uInt32 len;
1302 if (!pImpl || !pData)
1303 return rtl_Digest_E_Argument;
1305 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1306 return rtl_Digest_E_Algorithm;
1308 if (nDatLen == 0)
1309 return rtl_Digest_E_None;
1311 ctx = &(pImpl->m_context);
1313 len = ctx->m_nL + (nDatLen << 3);
1314 if (len < ctx->m_nL)
1315 ctx->m_nH += 1;
1317 ctx->m_nH += (nDatLen >> 29);
1318 ctx->m_nL = len;
1320 if (ctx->m_nDatLen)
1322 sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
1323 sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1325 if (nDatLen < n)
1327 memcpy(p, d, nDatLen);
1328 ctx->m_nDatLen += nDatLen;
1330 return rtl_Digest_E_None;
1333 memcpy(p, d, n);
1334 d += n;
1335 nDatLen -= n;
1337 #ifndef OSL_BIGENDIAN
1338 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1339 #endif /* OSL_BIGENDIAN */
1341 updateSHA(ctx);
1342 ctx->m_nDatLen = 0;
1345 while (nDatLen >= DIGEST_CBLOCK_SHA)
1347 memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1348 d += DIGEST_CBLOCK_SHA;
1349 nDatLen -= DIGEST_CBLOCK_SHA;
1351 #ifndef OSL_BIGENDIAN
1352 swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
1353 #endif /* OSL_BIGENDIAN */
1355 updateSHA(ctx);
1358 memcpy(ctx->m_pData, d, nDatLen);
1359 ctx->m_nDatLen = nDatLen;
1361 return rtl_Digest_E_None;
1364 rtlDigestError SAL_CALL rtl_digest_getSHA1 (
1365 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1366 SAL_THROW_EXTERN_C()
1368 DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
1369 sal_uInt8 *p = pBuffer;
1371 DigestContextSHA *ctx;
1373 if (!pImpl || !pBuffer)
1374 return rtl_Digest_E_Argument;
1376 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
1377 return rtl_Digest_E_Algorithm;
1379 if (pImpl->m_digest.m_length > nBufLen)
1380 return rtl_Digest_E_BufferSize;
1382 ctx = &(pImpl->m_context);
1384 endSHA(ctx);
1385 RTL_DIGEST_HTONL(ctx->m_nA, p);
1386 RTL_DIGEST_HTONL(ctx->m_nB, p);
1387 RTL_DIGEST_HTONL(ctx->m_nC, p);
1388 RTL_DIGEST_HTONL(ctx->m_nD, p);
1389 RTL_DIGEST_HTONL(ctx->m_nE, p);
1390 initSHA(ctx, updateSHA_1);
1392 return rtl_Digest_E_None;
1395 void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) SAL_THROW_EXTERN_C()
1397 DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
1398 if (pImpl)
1400 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
1401 rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
1402 else
1403 free(pImpl);
1407 #define DIGEST_CBLOCK_HMAC_MD5 64
1409 namespace {
1411 struct ContextHMAC_MD5
1413 DigestMD5_Impl m_hash;
1414 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5];
1417 struct DigestHMAC_MD5_Impl
1419 Digest_Impl m_digest;
1420 ContextHMAC_MD5 m_context;
1425 static void initHMAC_MD5(ContextHMAC_MD5 * ctx);
1426 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx);
1427 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx);
1429 const Digest_Impl HMAC_MD5 =
1431 rtl_Digest_AlgorithmHMAC_MD5,
1432 RTL_DIGEST_LENGTH_MD5,
1434 rtl_digest_initHMAC_MD5,
1435 rtl_digest_destroyHMAC_MD5,
1436 rtl_digest_updateHMAC_MD5,
1437 rtl_digest_getHMAC_MD5
1440 static void initHMAC_MD5(ContextHMAC_MD5 * ctx)
1442 DigestMD5_Impl *pImpl = &(ctx->m_hash);
1444 pImpl->m_digest = MD5;
1445 initMD5(&(pImpl->m_context));
1447 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_MD5);
1450 static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx)
1452 sal_uInt32 i;
1454 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1456 ctx->m_opad[i] ^= 0x36;
1459 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
1461 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1463 ctx->m_opad[i] ^= 0x36;
1467 static void opadHMAC_MD5(ContextHMAC_MD5 * ctx)
1469 sal_uInt32 i;
1471 for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1473 ctx->m_opad[i] ^= 0x5c;
1477 rtlDigestError SAL_CALL rtl_digest_HMAC_MD5(
1478 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1479 const void *pData, sal_uInt32 nDatLen,
1480 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1482 DigestHMAC_MD5_Impl digest;
1483 rtlDigestError result;
1485 digest.m_digest = HMAC_MD5;
1487 result = rtl_digest_initHMAC_MD5(&digest, pKeyData, nKeyLen);
1488 if (result == rtl_Digest_E_None)
1490 result = rtl_digest_updateHMAC_MD5(&digest, pData, nDatLen);
1491 if (result == rtl_Digest_E_None)
1492 result = rtl_digest_getHMAC_MD5(&digest, pBuffer, nBufLen);
1495 rtl_secureZeroMemory(&digest, sizeof(digest));
1496 return result;
1499 rtlDigest SAL_CALL rtl_digest_createHMAC_MD5() SAL_THROW_EXTERN_C()
1501 DigestHMAC_MD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
1502 if (pImpl)
1504 pImpl->m_digest = HMAC_MD5;
1505 initHMAC_MD5(&(pImpl->m_context));
1507 return static_cast< rtlDigest >(pImpl);
1510 rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5(
1511 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1512 SAL_THROW_EXTERN_C()
1514 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1515 ContextHMAC_MD5 *ctx;
1517 if (!pImpl || !pKeyData)
1518 return rtl_Digest_E_Argument;
1520 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1521 return rtl_Digest_E_Algorithm;
1523 ctx = &(pImpl->m_context);
1524 initHMAC_MD5(ctx);
1526 if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
1528 /* Initialize 'opad' with hashed 'KeyData' */
1529 rtl_digest_updateMD5(&(ctx->m_hash), pKeyData, nKeyLen);
1530 rtl_digest_getMD5(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
1532 else
1534 /* Initialize 'opad' with plain 'KeyData' */
1535 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1538 ipadHMAC_MD5(ctx);
1539 opadHMAC_MD5(ctx);
1541 return rtl_Digest_E_None;
1544 rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5(
1545 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1546 SAL_THROW_EXTERN_C()
1548 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1549 ContextHMAC_MD5 *ctx;
1551 if (!pImpl || !pData)
1552 return rtl_Digest_E_Argument;
1554 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1555 return rtl_Digest_E_Algorithm;
1557 ctx = &(pImpl->m_context);
1558 rtl_digest_updateMD5(&(ctx->m_hash), pData, nDatLen);
1560 return rtl_Digest_E_None;
1563 rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5(
1564 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1565 SAL_THROW_EXTERN_C()
1567 DigestHMAC_MD5_Impl *pImpl = static_cast<DigestHMAC_MD5_Impl*>(Digest);
1568 ContextHMAC_MD5 *ctx;
1570 if (!pImpl || !pBuffer)
1571 return rtl_Digest_E_Argument;
1573 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
1574 return rtl_Digest_E_Algorithm;
1576 if (pImpl->m_digest.m_length > nBufLen)
1577 return rtl_Digest_E_BufferSize;
1579 nBufLen = pImpl->m_digest.m_length;
1581 ctx = &(pImpl->m_context);
1582 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1584 rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, 64);
1585 rtl_digest_updateMD5(&(ctx->m_hash), pBuffer, nBufLen);
1586 rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
1588 opadHMAC_MD5(ctx);
1589 ipadHMAC_MD5(ctx);
1590 opadHMAC_MD5(ctx);
1592 return rtl_Digest_E_None;
1595 void SAL_CALL rtl_digest_destroyHMAC_MD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
1597 DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
1598 if (pImpl)
1600 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
1601 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_MD5_Impl));
1602 else
1603 free(pImpl);
1607 #define DIGEST_CBLOCK_HMAC_SHA1 64
1609 namespace {
1611 struct ContextHMAC_SHA1
1613 DigestSHA_Impl m_hash;
1614 sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1];
1617 struct DigestHMAC_SHA1_Impl
1619 Digest_Impl m_digest;
1620 ContextHMAC_SHA1 m_context;
1625 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1626 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1627 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
1629 const Digest_Impl HMAC_SHA1 =
1631 rtl_Digest_AlgorithmHMAC_SHA1,
1632 RTL_DIGEST_LENGTH_SHA1,
1633 rtl_digest_initHMAC_SHA1,
1634 rtl_digest_destroyHMAC_SHA1,
1635 rtl_digest_updateHMAC_SHA1,
1636 rtl_digest_getHMAC_SHA1
1639 static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1641 DigestSHA_Impl *pImpl = &(ctx->m_hash);
1643 pImpl->m_digest = SHA_1;
1644 initSHA(&(pImpl->m_context), updateSHA_1);
1646 memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_SHA1);
1649 static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1651 sal_uInt32 i;
1653 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1655 ctx->m_opad[i] ^= 0x36;
1658 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
1660 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1662 ctx->m_opad[i] ^= 0x36;
1666 static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
1668 sal_uInt32 i;
1670 for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1672 ctx->m_opad[i] ^= 0x5c;
1676 rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1(
1677 const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1678 const void *pData, sal_uInt32 nDatLen,
1679 sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
1681 DigestHMAC_SHA1_Impl digest;
1682 rtlDigestError result;
1684 digest.m_digest = HMAC_SHA1;
1686 result = rtl_digest_initHMAC_SHA1(&digest, pKeyData, nKeyLen);
1687 if (result == rtl_Digest_E_None)
1689 result = rtl_digest_updateHMAC_SHA1(&digest, pData, nDatLen);
1690 if (result == rtl_Digest_E_None)
1691 result = rtl_digest_getHMAC_SHA1(&digest, pBuffer, nBufLen);
1694 rtl_secureZeroMemory(&digest, sizeof(digest));
1695 return result;
1698 rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1() SAL_THROW_EXTERN_C()
1700 DigestHMAC_SHA1_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
1701 if (pImpl)
1703 pImpl->m_digest = HMAC_SHA1;
1704 initHMAC_SHA1(&(pImpl->m_context));
1706 return static_cast<rtlDigest>(pImpl);
1709 rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1(
1710 rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1711 SAL_THROW_EXTERN_C()
1713 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1714 ContextHMAC_SHA1 *ctx;
1716 if (!pImpl || !pKeyData)
1717 return rtl_Digest_E_Argument;
1719 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1720 return rtl_Digest_E_Algorithm;
1722 ctx = &(pImpl->m_context);
1723 initHMAC_SHA1(ctx);
1725 if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
1727 /* Initialize 'opad' with hashed 'KeyData' */
1728 rtl_digest_updateSHA1(&(ctx->m_hash), pKeyData, nKeyLen);
1729 rtl_digest_getSHA1(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
1731 else
1733 /* Initialize 'opad' with plain 'KeyData' */
1734 memcpy(ctx->m_opad, pKeyData, nKeyLen);
1737 ipadHMAC_SHA1(ctx);
1738 opadHMAC_SHA1(ctx);
1740 return rtl_Digest_E_None;
1743 rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1(
1744 rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1745 SAL_THROW_EXTERN_C()
1747 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1748 ContextHMAC_SHA1 *ctx;
1750 if (!pImpl || !pData)
1751 return rtl_Digest_E_Argument;
1753 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1754 return rtl_Digest_E_Algorithm;
1756 ctx = &(pImpl->m_context);
1757 rtl_digest_updateSHA1(&(ctx->m_hash), pData, nDatLen);
1759 return rtl_Digest_E_None;
1762 rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1(
1763 rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1764 SAL_THROW_EXTERN_C()
1766 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1767 ContextHMAC_SHA1 *ctx;
1769 if (!pImpl || !pBuffer)
1770 return rtl_Digest_E_Argument;
1772 if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
1773 return rtl_Digest_E_Algorithm;
1775 if (pImpl->m_digest.m_length > nBufLen)
1776 return rtl_Digest_E_BufferSize;
1778 nBufLen = pImpl->m_digest.m_length;
1780 ctx = &(pImpl->m_context);
1781 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1783 rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
1784 rtl_digest_updateSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1785 rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
1787 opadHMAC_SHA1(ctx);
1788 ipadHMAC_SHA1(ctx);
1789 opadHMAC_SHA1(ctx);
1791 return rtl_Digest_E_None;
1794 void SAL_CALL rtl_digest_destroyHMAC_SHA1(rtlDigest Digest)
1795 SAL_THROW_EXTERN_C()
1797 DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
1798 if (pImpl)
1800 if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
1801 rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_SHA1_Impl));
1802 else
1803 free(pImpl);
1807 #define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
1809 static void updatePBKDF2(
1810 rtlDigest hDigest,
1811 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2],
1812 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1813 sal_uInt32 nCount, sal_uInt32 nIndex)
1815 /* T_i = F (P, S, c, i) */
1816 sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
1817 sal_uInt32 i, k;
1819 /* U_(1) = PRF (P, S || INDEX) */
1820 rtl_digest_updateHMAC_SHA1(hDigest, pSaltData, nSaltLen);
1821 rtl_digest_updateHMAC_SHA1(hDigest, &nIndex, sizeof(nIndex));
1822 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1824 /* T = U_(1) */
1825 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1827 T[k] = U[k];
1830 /* T ^= U_(2) ^ ... ^ U_(c) */
1831 for (i = 1; i < nCount; i++)
1833 /* U_(i) = PRF (P, U_(i-1)) */
1834 rtl_digest_updateHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1835 rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
1837 /* T ^= U_(i) */
1838 for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
1840 T[k] ^= U[k];
1844 rtl_secureZeroMemory(U, DIGEST_CBLOCK_PBKDF2);
1847 rtlDigestError SAL_CALL rtl_digest_PBKDF2(
1848 sal_uInt8 *pKeyData , sal_uInt32 nKeyLen,
1849 const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
1850 const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
1851 sal_uInt32 nCount) SAL_THROW_EXTERN_C()
1853 DigestHMAC_SHA1_Impl digest;
1854 sal_uInt32 i = 1;
1856 if (!pKeyData || !pPassData || !pSaltData)
1857 return rtl_Digest_E_Argument;
1859 digest.m_digest = HMAC_SHA1;
1860 rtl_digest_initHMAC_SHA1(&digest, pPassData, nPassLen);
1862 /* DK = T_(1) || T_(2) || ... || T_(l) */
1863 while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
1865 /* T_(i) = F (P, S, c, i); DK ||= T_(i) */
1866 updatePBKDF2(
1867 &digest, pKeyData,
1868 pSaltData, nSaltLen,
1869 nCount, OSL_NETDWORD(i));
1871 /* Next 'KeyData' block */
1872 pKeyData += DIGEST_CBLOCK_PBKDF2;
1873 nKeyLen -= DIGEST_CBLOCK_PBKDF2;
1874 i += 1;
1877 if (nKeyLen > 0)
1879 /* Last 'KeyData' block */
1880 sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
1882 /* T_i = F (P, S, c, i) */
1883 updatePBKDF2(
1884 &digest, T,
1885 pSaltData, nSaltLen,
1886 nCount, OSL_NETDWORD(i));
1888 /* DK ||= T_(i) */
1889 memcpy(pKeyData, T, nKeyLen);
1890 rtl_secureZeroMemory(T, DIGEST_CBLOCK_PBKDF2);
1893 rtl_secureZeroMemory(&digest, sizeof(digest));
1894 return rtl_Digest_E_None;
1897 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */