xref: /trunk/main/sal/rtl/source/digest.c (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #define _RTL_DIGEST_C_ "$Revision: 1.9 $"
29 
30 #include <sal/types.h>
31 #include <sal/macros.h>
32 #include <osl/endian.h>
33 #include <rtl/alloc.h>
34 #include <rtl/memory.h>
35 #include <rtl/digest.h>
36 
37 /*========================================================================
38  *
39  * rtlDigest internals.
40  *
41  *======================================================================*/
42 #define RTL_DIGEST_CREATE(T) ((T*)(rtl_allocateZeroMemory(sizeof(T))))
43 
44 #define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n))))
45 
46 #define RTL_DIGEST_HTONL(l,c) \
47     (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \
48      *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
49      *((c)++) = (sal_uInt8)(((l) >>  8L) & 0xff), \
50      *((c)++) = (sal_uInt8)(((l)       ) & 0xff))
51 
52 #define RTL_DIGEST_LTOC(l,c) \
53     (*((c)++) = (sal_uInt8)(((l)       ) & 0xff), \
54      *((c)++) = (sal_uInt8)(((l) >>  8L) & 0xff), \
55      *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
56      *((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff))
57 
58 typedef rtlDigestError (SAL_CALL Digest_init_t) (
59     void *ctx, const sal_uInt8 *Data, sal_uInt32 DatLen);
60 
61 typedef void (SAL_CALL Digest_delete_t) (void *ctx);
62 
63 typedef rtlDigestError (SAL_CALL Digest_update_t) (
64     void *ctx, const void *Data, sal_uInt32 DatLen);
65 
66 typedef rtlDigestError (SAL_CALL Digest_get_t) (
67     void *ctx, sal_uInt8 *Buffer, sal_uInt32 BufLen);
68 
69 typedef struct digest_impl_st
70 {
71     rtlDigestAlgorithm  m_algorithm;
72     sal_uInt32          m_length;
73 
74     Digest_init_t      *m_init;
75     Digest_delete_t    *m_delete;
76     Digest_update_t    *m_update;
77     Digest_get_t       *m_get;
78 } Digest_Impl;
79 
80 /*
81  * __rtl_digest_swapLong.
82  */
83 static void __rtl_digest_swapLong (sal_uInt32 *pData, sal_uInt32 nDatLen)
84 {
85     register sal_uInt32 *X;
86     register int         i, n;
87 
88     X = pData;
89     n = nDatLen;
90 
91     for (i = 0; i < n; i++)
92         X[i] = OSL_SWAPDWORD(X[i]);
93 }
94 
95 /*========================================================================
96  *
97  * rtlDigest implementation.
98  *
99  *======================================================================*/
100 /*
101  * rtl_digest_create.
102  */
103 rtlDigest SAL_CALL rtl_digest_create (rtlDigestAlgorithm Algorithm)
104 {
105     rtlDigest Digest = (rtlDigest)NULL;
106     switch (Algorithm)
107     {
108         case rtl_Digest_AlgorithmMD2:
109             Digest = rtl_digest_createMD2();
110             break;
111 
112         case rtl_Digest_AlgorithmMD5:
113             Digest = rtl_digest_createMD5();
114             break;
115 
116         case rtl_Digest_AlgorithmSHA:
117             Digest = rtl_digest_createSHA();
118             break;
119 
120         case rtl_Digest_AlgorithmSHA1:
121             Digest = rtl_digest_createSHA1();
122             break;
123 
124         case rtl_Digest_AlgorithmHMAC_MD5:
125             Digest = rtl_digest_createHMAC_MD5();
126             break;
127 
128         case rtl_Digest_AlgorithmHMAC_SHA1:
129             Digest = rtl_digest_createHMAC_SHA1();
130             break;
131 
132         default: /* rtl_Digest_AlgorithmInvalid */
133             break;
134     }
135     return Digest;
136 }
137 
138 /*
139  * rtl_digest_queryAlgorithm.
140  */
141 rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm (rtlDigest Digest)
142 {
143     Digest_Impl *pImpl = (Digest_Impl *)Digest;
144     if (pImpl)
145         return pImpl->m_algorithm;
146     else
147         return rtl_Digest_AlgorithmInvalid;
148 }
149 
150 /*
151  * rtl_digest_queryLength.
152  */
153 sal_uInt32 SAL_CALL rtl_digest_queryLength (rtlDigest Digest)
154 {
155     Digest_Impl *pImpl = (Digest_Impl *)Digest;
156     if (pImpl)
157         return pImpl->m_length;
158     else
159         return 0;
160 }
161 
162 /*
163  * rtl_digest_init.
164  */
165 rtlDigestError SAL_CALL rtl_digest_init (
166     rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
167 {
168     Digest_Impl *pImpl = (Digest_Impl *)Digest;
169     if (pImpl)
170     {
171         if (pImpl->m_init)
172             return pImpl->m_init (Digest, pData, nDatLen);
173         else
174             return rtl_Digest_E_None;
175     }
176     return rtl_Digest_E_Argument;
177 }
178 
179 /*
180  * rtl_digest_update.
181  */
182 rtlDigestError SAL_CALL rtl_digest_update (
183     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
184 {
185     Digest_Impl *pImpl = (Digest_Impl *)Digest;
186     if (pImpl && pImpl->m_update)
187         return pImpl->m_update (Digest, pData, nDatLen);
188     else
189         return rtl_Digest_E_Argument;
190 }
191 
192 /*
193  * rtl_digest_get.
194  */
195 rtlDigestError SAL_CALL rtl_digest_get (
196     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
197 {
198     Digest_Impl *pImpl = (Digest_Impl *)Digest;
199     if (pImpl && pImpl->m_get)
200         return pImpl->m_get (Digest, pBuffer, nBufLen);
201     else
202         return rtl_Digest_E_Argument;
203 }
204 
205 /*
206  * rtl_digest_destroy.
207  */
208 void SAL_CALL rtl_digest_destroy (rtlDigest Digest)
209 {
210     Digest_Impl *pImpl = (Digest_Impl *)Digest;
211     if (pImpl && pImpl->m_delete)
212         pImpl->m_delete (Digest);
213 }
214 
215 /*========================================================================
216  *
217  * rtl_digest_MD2 internals.
218  *
219  *======================================================================*/
220 #define DIGEST_CBLOCK_MD2 16
221 #define DIGEST_LBLOCK_MD2 16
222 
223 typedef struct digestMD2_context_st
224 {
225     sal_uInt32 m_nDatLen;
226     sal_uInt8  m_pData[DIGEST_CBLOCK_MD2];
227     sal_uInt32 m_state[DIGEST_LBLOCK_MD2];
228     sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2];
229 } DigestContextMD2;
230 
231 typedef struct digestMD2_impl_st
232 {
233     Digest_Impl      m_digest;
234     DigestContextMD2 m_context;
235 } DigestMD2_Impl;
236 
237 static void __rtl_digest_initMD2   (DigestContextMD2 *ctx);
238 static void __rtl_digest_updateMD2 (DigestContextMD2 *ctx);
239 static void __rtl_digest_endMD2    (DigestContextMD2 *ctx);
240 
241 static const sal_uInt32 S[256] =
242 {
243     0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
244     0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
245     0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
246     0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
247     0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
248     0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
249     0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
250     0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
251     0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
252     0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
253     0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
254     0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
255     0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
256     0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
257     0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
258     0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
259     0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
260     0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
261     0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
262     0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
263     0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
264     0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
265     0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
266     0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
267     0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
268     0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
269     0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
270     0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
271     0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
272     0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
273     0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
274     0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
275 };
276 
277 /*
278  * __rtl_digest_MD2.
279  */
280 static const Digest_Impl __rtl_digest_MD2 =
281 {
282     rtl_Digest_AlgorithmMD2,
283     RTL_DIGEST_LENGTH_MD2,
284 
285     NULL,
286     rtl_digest_destroyMD2,
287     rtl_digest_updateMD2,
288     rtl_digest_getMD2
289 };
290 
291 /*
292  * __rtl_digest_initMD2.
293  */
294 static void __rtl_digest_initMD2 (DigestContextMD2 *ctx)
295 {
296     rtl_zeroMemory (ctx, sizeof (DigestContextMD2));
297 }
298 
299 /*
300  * __rtl_digest_updateMD2.
301  */
302 static void __rtl_digest_updateMD2 (DigestContextMD2 *ctx)
303 {
304     register sal_uInt8  *X;
305     register sal_uInt32 *sp1, *sp2;
306     register sal_uInt32  i, k, t;
307 
308     sal_uInt32 state[48];
309 
310     X   = ctx->m_pData;
311     sp1 = ctx->m_state;
312     sp2 = ctx->m_chksum;
313 
314     k = sp2[DIGEST_LBLOCK_MD2 - 1];
315     for (i = 0; i < 16; i++)
316     {
317         state[i +  0] = sp1[i];
318         state[i + 16] = t = X[i];
319         state[i + 32] = t ^ sp1[i];
320         k = sp2[i] ^= S[t^k];
321     }
322 
323     t = 0;
324     for (i = 0; i < 18; i++)
325     {
326         for (k = 0; k < 48; k += 8)
327         {
328             t = state[k + 0] ^= S[t];
329             t = state[k + 1] ^= S[t];
330             t = state[k + 2] ^= S[t];
331             t = state[k + 3] ^= S[t];
332             t = state[k + 4] ^= S[t];
333             t = state[k + 5] ^= S[t];
334             t = state[k + 6] ^= S[t];
335             t = state[k + 7] ^= S[t];
336         }
337         t = ((t + i) & 0xff);
338     }
339 
340     rtl_copyMemory (sp1, state, 16 * sizeof(sal_uInt32));
341     rtl_zeroMemory (state, 48 * sizeof(sal_uInt32));
342 }
343 
344 /*
345  * __rtl_digest_endMD2.
346  */
347 static void __rtl_digest_endMD2 (DigestContextMD2 *ctx)
348 {
349     register sal_uInt8  *X;
350     register sal_uInt32 *C;
351     sal_uInt32           i, n;
352 
353     X = ctx->m_pData;
354     C = ctx->m_chksum;
355     n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
356 
357     for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
358         X[i] = (sal_uInt8)(n & 0xff);
359     __rtl_digest_updateMD2 (ctx);
360 
361     for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
362         X[i] = (sal_uInt8)(C[i] & 0xff);
363     __rtl_digest_updateMD2 (ctx);
364 }
365 
366 /*========================================================================
367  *
368  * rtl_digest_MD2 implementation.
369  *
370  *======================================================================*/
371 /*
372  * rtl_digest_MD2.
373  */
374 rtlDigestError SAL_CALL rtl_digest_MD2 (
375     const void *pData,   sal_uInt32 nDatLen,
376     sal_uInt8  *pBuffer, sal_uInt32 nBufLen)
377 {
378     DigestMD2_Impl digest;
379     rtlDigestError result;
380 
381     digest.m_digest = __rtl_digest_MD2;
382     __rtl_digest_initMD2 (&(digest.m_context));
383 
384     result = rtl_digest_updateMD2 (&digest, pData, nDatLen);
385     if (result == rtl_Digest_E_None)
386         result = rtl_digest_getMD2 (&digest, pBuffer, nBufLen);
387 
388     rtl_zeroMemory (&digest, sizeof (digest));
389     return (result);
390 }
391 
392 /*
393  * rtl_digest_createMD2.
394  */
395 rtlDigest SAL_CALL rtl_digest_createMD2 (void)
396 {
397     DigestMD2_Impl *pImpl = (DigestMD2_Impl*)NULL;
398     pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
399     if (pImpl)
400     {
401         pImpl->m_digest = __rtl_digest_MD2;
402         __rtl_digest_initMD2 (&(pImpl->m_context));
403     }
404     return ((rtlDigest)pImpl);
405 }
406 
407 /*
408  * rtl_digest_updateMD2.
409  */
410 rtlDigestError SAL_CALL rtl_digest_updateMD2 (
411     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
412 {
413     DigestMD2_Impl   *pImpl = (DigestMD2_Impl *)Digest;
414     const sal_uInt8  *d     = (const sal_uInt8 *)pData;
415 
416     DigestContextMD2 *ctx;
417 
418     if ((pImpl == NULL) || (pData == NULL))
419         return rtl_Digest_E_Argument;
420 
421     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2))
422         return rtl_Digest_E_Algorithm;
423 
424     if (nDatLen == 0)
425         return rtl_Digest_E_None;
426 
427     ctx = &(pImpl->m_context);
428 
429     if (ctx->m_nDatLen)
430     {
431         sal_uInt8  *p = ctx->m_pData + ctx->m_nDatLen;
432         sal_uInt32  n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
433 
434         if (nDatLen < n)
435         {
436             rtl_copyMemory (p, d, nDatLen);
437             ctx->m_nDatLen += nDatLen;
438 
439             return rtl_Digest_E_None;
440         }
441 
442         rtl_copyMemory (p, d, n);
443         d       += n;
444         nDatLen -= n;
445 
446         __rtl_digest_updateMD2 (ctx);
447         ctx->m_nDatLen = 0;
448     }
449 
450     while (nDatLen >= DIGEST_CBLOCK_MD2)
451     {
452         rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_MD2);
453         d       += DIGEST_CBLOCK_MD2;
454         nDatLen -= DIGEST_CBLOCK_MD2;
455 
456         __rtl_digest_updateMD2 (ctx);
457     }
458 
459     rtl_copyMemory (ctx->m_pData, d, nDatLen);
460     ctx->m_nDatLen = nDatLen;
461 
462     return rtl_Digest_E_None;
463 }
464 
465 /*
466  * rtl_digest_getMD2.
467  */
468 rtlDigestError SAL_CALL rtl_digest_getMD2 (
469     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
470 {
471     DigestMD2_Impl   *pImpl = (DigestMD2_Impl *)Digest;
472     sal_uInt32        i;
473 
474     DigestContextMD2 *ctx;
475 
476     if ((pImpl == NULL) || (pBuffer == NULL))
477         return rtl_Digest_E_Argument;
478 
479     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2))
480         return rtl_Digest_E_Algorithm;
481 
482     if (!(pImpl->m_digest.m_length <= nBufLen))
483         return rtl_Digest_E_BufferSize;
484 
485     ctx = &(pImpl->m_context);
486 
487     __rtl_digest_endMD2 (ctx);
488     for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
489         pBuffer[i] = (sal_uInt8)(ctx->m_state[i] & 0xff);
490     __rtl_digest_initMD2 (ctx);
491 
492     return rtl_Digest_E_None;
493 }
494 
495 /*
496  * rtl_digest_destroyMD2.
497  */
498 void SAL_CALL rtl_digest_destroyMD2 (rtlDigest Digest)
499 {
500     DigestMD2_Impl *pImpl = (DigestMD2_Impl *)Digest;
501     if (pImpl)
502     {
503         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2)
504             rtl_freeZeroMemory (pImpl, sizeof (DigestMD2_Impl));
505         else
506             rtl_freeMemory (pImpl);
507     }
508 }
509 
510 /*========================================================================
511  *
512  * rtl_digest_MD5 internals.
513  *
514  *======================================================================*/
515 #define DIGEST_CBLOCK_MD5 64
516 #define DIGEST_LBLOCK_MD5 16
517 
518 typedef struct digestMD5_context_st
519 {
520     sal_uInt32 m_nDatLen;
521     sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
522     sal_uInt32 m_nA, m_nB, m_nC, m_nD;
523     sal_uInt32 m_nL, m_nH;
524 } DigestContextMD5;
525 
526 typedef struct digestMD5_impl_st
527 {
528     Digest_Impl      m_digest;
529     DigestContextMD5 m_context;
530 } DigestMD5_Impl;
531 
532 static void __rtl_digest_initMD5   (DigestContextMD5 *ctx);
533 static void __rtl_digest_updateMD5 (DigestContextMD5 *ctx);
534 static void __rtl_digest_endMD5    (DigestContextMD5 *ctx);
535 
536 #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
537 #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
538 #define H(x,y,z) ((x) ^ (y) ^ (z))
539 #define I(x,y,z) (((x) | (~(z))) ^ (y))
540 
541 #define R0(a,b,c,d,k,s,t) { \
542     a += ((k) + (t) + F((b), (c), (d))); \
543     a  = RTL_DIGEST_ROTL(a, s); \
544     a += b; }
545 
546 #define R1(a,b,c,d,k,s,t) { \
547     a += ((k) + (t) + G((b), (c), (d))); \
548     a  = RTL_DIGEST_ROTL(a, s); \
549     a += b; }
550 
551 #define R2(a,b,c,d,k,s,t) { \
552     a += ((k) + (t) + H((b), (c), (d))); \
553     a  = RTL_DIGEST_ROTL(a, s); \
554     a += b; }
555 
556 #define R3(a,b,c,d,k,s,t) { \
557     a += ((k) + (t) + I((b), (c), (d))); \
558     a  = RTL_DIGEST_ROTL(a, s); \
559     a += b; }
560 
561 /*
562  * __rtl_digest_MD5.
563  */
564 static const Digest_Impl __rtl_digest_MD5 =
565 {
566     rtl_Digest_AlgorithmMD5,
567     RTL_DIGEST_LENGTH_MD5,
568 
569     NULL,
570     rtl_digest_destroyMD5,
571     rtl_digest_updateMD5,
572     rtl_digest_getMD5
573 };
574 
575 /*
576  * __rtl_digest_initMD5.
577  */
578 static void __rtl_digest_initMD5 (DigestContextMD5 *ctx)
579 {
580     rtl_zeroMemory (ctx, sizeof (DigestContextMD5));
581 
582     ctx->m_nA = (sal_uInt32)0x67452301L;
583     ctx->m_nB = (sal_uInt32)0xefcdab89L;
584     ctx->m_nC = (sal_uInt32)0x98badcfeL;
585     ctx->m_nD = (sal_uInt32)0x10325476L;
586 }
587 
588 /*
589  * __rtl_digest_updateMD5.
590  */
591 static void __rtl_digest_updateMD5 (DigestContextMD5 *ctx)
592 {
593     register sal_uInt32  A, B, C, D;
594     register sal_uInt32 *X;
595 
596     A = ctx->m_nA;
597     B = ctx->m_nB;
598     C = ctx->m_nC;
599     D = ctx->m_nD;
600     X = ctx->m_pData;
601 
602     R0 (A, B, C, D, X[ 0],  7, 0xd76aa478L);
603     R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
604     R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
605     R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
606     R0 (A, B, C, D, X[ 4],  7, 0xf57c0fafL);
607     R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
608     R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
609     R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
610     R0 (A, B, C, D, X[ 8],  7, 0x698098d8L);
611     R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
612     R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
613     R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
614     R0 (A, B, C, D, X[12],  7, 0x6b901122L);
615     R0 (D, A, B, C, X[13], 12, 0xfd987193L);
616     R0 (C, D, A, B, X[14], 17, 0xa679438eL);
617     R0 (B, C, D, A, X[15], 22, 0x49b40821L);
618 
619     R1 (A, B, C, D, X[ 1],  5, 0xf61e2562L);
620     R1 (D, A, B, C, X[ 6],  9, 0xc040b340L);
621     R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
622     R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
623     R1 (A, B, C, D, X[ 5],  5, 0xd62f105dL);
624     R1 (D, A, B, C, X[10],  9, 0x02441453L);
625     R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
626     R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
627     R1 (A, B, C, D, X[ 9],  5, 0x21e1cde6L);
628     R1 (D, A, B, C, X[14],  9, 0xc33707d6L);
629     R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
630     R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
631     R1 (A, B, C, D, X[13],  5, 0xa9e3e905L);
632     R1 (D, A, B, C, X[ 2],  9, 0xfcefa3f8L);
633     R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
634     R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
635 
636     R2 (A, B, C, D, X[ 5],  4, 0xfffa3942L);
637     R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
638     R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
639     R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
640     R2 (A, B, C, D, X[ 1],  4, 0xa4beea44L);
641     R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
642     R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
643     R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
644     R2 (A, B, C, D, X[13],  4, 0x289b7ec6L);
645     R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
646     R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
647     R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
648     R2 (A, B, C, D, X[ 9],  4, 0xd9d4d039L);
649     R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
650     R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
651     R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
652 
653     R3 (A, B, C, D, X[ 0],  6, 0xf4292244L);
654     R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
655     R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
656     R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
657     R3 (A, B, C, D, X[12],  6, 0x655b59c3L);
658     R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
659     R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
660     R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
661     R3 (A, B, C, D, X[ 8],  6, 0x6fa87e4fL);
662     R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
663     R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
664     R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
665     R3 (A, B, C, D, X[ 4],  6, 0xf7537e82L);
666     R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
667     R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
668     R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
669 
670     ctx->m_nA += A;
671     ctx->m_nB += B;
672     ctx->m_nC += C;
673     ctx->m_nD += D;
674 }
675 
676 /*
677  * __rtl_digest_endMD5.
678  */
679 static void __rtl_digest_endMD5 (DigestContextMD5 *ctx)
680 {
681     static const sal_uInt8 end[4] =
682     {
683         0x80, 0x00, 0x00, 0x00
684     };
685     register const sal_uInt8 *p = end;
686 
687     register sal_uInt32 *X;
688     register int         i;
689 
690     X = ctx->m_pData;
691     i = (ctx->m_nDatLen >> 2);
692 
693 #ifdef OSL_BIGENDIAN
694     __rtl_digest_swapLong (X, i + 1);
695 #endif /* OSL_BIGENDIAN */
696 
697     switch (ctx->m_nDatLen & 0x03)
698     {
699         case 1: X[i] &= 0x000000ff; break;
700         case 2: X[i] &= 0x0000ffff; break;
701         case 3: X[i] &= 0x00ffffff; break;
702     }
703 
704     switch (ctx->m_nDatLen & 0x03)
705     {
706         case 0: X[i]  = ((sal_uInt32)(*(p++))) <<  0L;
707         case 1: X[i] |= ((sal_uInt32)(*(p++))) <<  8L;
708         case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L;
709         case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L;
710     }
711 
712     i += 1;
713 
714     if (i >= (DIGEST_LBLOCK_MD5 - 2))
715     {
716         for (; i < DIGEST_LBLOCK_MD5; i++)
717             X[i] = 0;
718         __rtl_digest_updateMD5 (ctx);
719         i = 0;
720     }
721 
722     for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
723         X[i] = 0;
724 
725     X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
726     X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
727 
728     __rtl_digest_updateMD5 (ctx);
729 }
730 
731 /*========================================================================
732  *
733  * rtl_digest_MD5 implementation.
734  *
735  *======================================================================*/
736 /*
737  * rtl_digest_MD5.
738  */
739 rtlDigestError SAL_CALL rtl_digest_MD5 (
740     const void *pData,   sal_uInt32 nDatLen,
741     sal_uInt8  *pBuffer, sal_uInt32 nBufLen)
742 {
743     DigestMD5_Impl digest;
744     rtlDigestError result;
745 
746     digest.m_digest = __rtl_digest_MD5;
747     __rtl_digest_initMD5 (&(digest.m_context));
748 
749     result = rtl_digest_update (&digest, pData, nDatLen);
750     if (result == rtl_Digest_E_None)
751         result = rtl_digest_getMD5 (&digest, pBuffer, nBufLen);
752 
753     rtl_zeroMemory (&digest, sizeof (digest));
754     return (result);
755 }
756 
757 /*
758  * rtl_digest_createMD5.
759  */
760 rtlDigest SAL_CALL rtl_digest_createMD5 (void)
761 {
762     DigestMD5_Impl *pImpl = (DigestMD5_Impl*)NULL;
763     pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
764     if (pImpl)
765     {
766         pImpl->m_digest = __rtl_digest_MD5;
767         __rtl_digest_initMD5 (&(pImpl->m_context));
768     }
769     return ((rtlDigest)pImpl);
770 }
771 
772 /*
773  * rtl_digest_updateMD5.
774  */
775 rtlDigestError SAL_CALL rtl_digest_updateMD5 (
776     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
777 {
778     DigestMD5_Impl   *pImpl = (DigestMD5_Impl *)Digest;
779     const sal_uInt8  *d     = (const sal_uInt8 *)pData;
780 
781     DigestContextMD5 *ctx;
782     sal_uInt32        len;
783 
784     if ((pImpl == NULL) || (pData == NULL))
785         return rtl_Digest_E_Argument;
786 
787     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
788         return rtl_Digest_E_Algorithm;
789 
790     if (nDatLen == 0)
791         return rtl_Digest_E_None;
792 
793     ctx = &(pImpl->m_context);
794 
795     len = ctx->m_nL + (nDatLen << 3);
796     if (len < ctx->m_nL) ctx->m_nH += 1;
797     ctx->m_nH += (nDatLen >> 29);
798     ctx->m_nL  = len;
799 
800     if (ctx->m_nDatLen)
801     {
802         sal_uInt8  *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
803         sal_uInt32  n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
804 
805         if (nDatLen < n)
806         {
807             rtl_copyMemory (p, d, nDatLen);
808             ctx->m_nDatLen += nDatLen;
809 
810             return rtl_Digest_E_None;
811         }
812 
813         rtl_copyMemory (p, d, n);
814         d       += n;
815         nDatLen -= n;
816 
817 #ifdef OSL_BIGENDIAN
818         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_MD5);
819 #endif /* OSL_BIGENDIAN */
820 
821         __rtl_digest_updateMD5 (ctx);
822         ctx->m_nDatLen = 0;
823     }
824 
825     while (nDatLen >= DIGEST_CBLOCK_MD5)
826     {
827         rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_MD5);
828         d       += DIGEST_CBLOCK_MD5;
829         nDatLen -= DIGEST_CBLOCK_MD5;
830 
831 #ifdef OSL_BIGENDIAN
832         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_MD5);
833 #endif /* OSL_BIGENDIAN */
834 
835         __rtl_digest_updateMD5 (ctx);
836     }
837 
838     rtl_copyMemory (ctx->m_pData, d, nDatLen);
839     ctx->m_nDatLen = nDatLen;
840 
841     return rtl_Digest_E_None;
842 }
843 
844 /*
845  * rtl_digest_getMD5.
846  */
847 rtlDigestError SAL_CALL rtl_digest_getMD5 (
848     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
849 {
850     DigestMD5_Impl   *pImpl = (DigestMD5_Impl *)Digest;
851     sal_uInt8        *p     = pBuffer;
852 
853     DigestContextMD5 *ctx;
854 
855     if ((pImpl == NULL) || (pBuffer == NULL))
856         return rtl_Digest_E_Argument;
857 
858     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
859         return rtl_Digest_E_Algorithm;
860 
861     if (!(pImpl->m_digest.m_length <= nBufLen))
862         return rtl_Digest_E_BufferSize;
863 
864     ctx = &(pImpl->m_context);
865 
866     __rtl_digest_endMD5 (ctx);
867     RTL_DIGEST_LTOC (ctx->m_nA, p);
868     RTL_DIGEST_LTOC (ctx->m_nB, p);
869     RTL_DIGEST_LTOC (ctx->m_nC, p);
870     RTL_DIGEST_LTOC (ctx->m_nD, p);
871     __rtl_digest_initMD5 (ctx);
872 
873     return rtl_Digest_E_None;
874 }
875 
876 /*
877  * rtl_digest_rawMD5.
878  */
879 rtlDigestError SAL_CALL rtl_digest_rawMD5 (
880     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
881 {
882     DigestMD5_Impl   *pImpl = (DigestMD5_Impl *)Digest;
883     sal_uInt8        *p     = pBuffer;
884 
885     DigestContextMD5 *ctx;
886 
887     if ((pImpl == NULL) || (pBuffer == NULL))
888         return rtl_Digest_E_Argument;
889 
890     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
891         return rtl_Digest_E_Algorithm;
892 
893     if (!(pImpl->m_digest.m_length <= nBufLen))
894         return rtl_Digest_E_BufferSize;
895 
896     ctx = &(pImpl->m_context);
897 
898     /* __rtl_digest_endMD5 (ctx); *//* not finalized */
899     RTL_DIGEST_LTOC (ctx->m_nA, p);
900     RTL_DIGEST_LTOC (ctx->m_nB, p);
901     RTL_DIGEST_LTOC (ctx->m_nC, p);
902     RTL_DIGEST_LTOC (ctx->m_nD, p);
903     __rtl_digest_initMD5 (ctx);
904 
905     return rtl_Digest_E_None;
906 }
907 
908 /*
909  * rtl_digest_destroyMD5.
910  */
911 void SAL_CALL rtl_digest_destroyMD5 (rtlDigest Digest)
912 {
913     DigestMD5_Impl *pImpl = (DigestMD5_Impl *)Digest;
914     if (pImpl)
915     {
916         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
917             rtl_freeZeroMemory (pImpl, sizeof (DigestMD5_Impl));
918         else
919             rtl_freeMemory (pImpl);
920     }
921 }
922 
923 /*========================================================================
924  *
925  * rtl_digest_(SHA|SHA1) common internals.
926  *
927  *======================================================================*/
928 #define DIGEST_CBLOCK_SHA 64
929 #define DIGEST_LBLOCK_SHA 16
930 
931 typedef sal_uInt32 DigestSHA_update_t (sal_uInt32 x);
932 
933 static sal_uInt32 __rtl_digest_updateSHA_0 (sal_uInt32 x);
934 static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x);
935 
936 typedef struct digestSHA_context_st
937 {
938     DigestSHA_update_t *m_update;
939     sal_uInt32          m_nDatLen;
940     sal_uInt32          m_pData[DIGEST_LBLOCK_SHA];
941     sal_uInt32          m_nA, m_nB, m_nC, m_nD, m_nE;
942     sal_uInt32          m_nL, m_nH;
943 } DigestContextSHA;
944 
945 typedef struct digestSHA_impl_st
946 {
947     Digest_Impl      m_digest;
948     DigestContextSHA m_context;
949 } DigestSHA_Impl;
950 
951 static void __rtl_digest_initSHA (
952     DigestContextSHA *ctx, DigestSHA_update_t *fct);
953 
954 static void __rtl_digest_updateSHA (DigestContextSHA *ctx);
955 static void __rtl_digest_endSHA    (DigestContextSHA *ctx);
956 
957 #define K_00_19 (sal_uInt32)0x5a827999L
958 #define K_20_39 (sal_uInt32)0x6ed9eba1L
959 #define K_40_59 (sal_uInt32)0x8f1bbcdcL
960 #define K_60_79 (sal_uInt32)0xca62c1d6L
961 
962 #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
963 #define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
964 #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
965 #define F_60_79(b,c,d) F_20_39(b,c,d)
966 
967 #define BODY_X(i) \
968     (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
969 
970 #define BODY_00_15(u,i,a,b,c,d,e,f) \
971     (f)  = X[i]; \
972     (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
973     (b)  = RTL_DIGEST_ROTL((b), 30);
974 
975 #define BODY_16_19(u,i,a,b,c,d,e,f) \
976     (f)  = BODY_X((i)); \
977     (f)  = X[(i)&0x0f] = (u)((f)); \
978     (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
979     (b)  = RTL_DIGEST_ROTL((b), 30);
980 
981 #define BODY_20_39(u,i,a,b,c,d,e,f) \
982     (f)  = BODY_X((i)); \
983     (f)  = X[(i)&0x0f] = (u)((f)); \
984     (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
985     (b)  = RTL_DIGEST_ROTL((b), 30);
986 
987 #define BODY_40_59(u,i,a,b,c,d,e,f) \
988     (f)  = BODY_X((i)); \
989     (f)  = X[(i)&0x0f] = (u)((f)); \
990     (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
991     (b)  = RTL_DIGEST_ROTL((b), 30);
992 
993 #define BODY_60_79(u,i,a,b,c,d,e,f) \
994     (f)  = BODY_X((i)); \
995     (f)  = X[(i)&0x0f] = (u)((f)); \
996     (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
997     (b)  = RTL_DIGEST_ROTL((b), 30);
998 
999 /*
1000  * __rtl_digest_initSHA.
1001  */
1002 static void __rtl_digest_initSHA (
1003     DigestContextSHA *ctx, DigestSHA_update_t *fct)
1004 {
1005     rtl_zeroMemory (ctx, sizeof (DigestContextSHA));
1006     ctx->m_update = fct;
1007 
1008     ctx->m_nA = (sal_uInt32)0x67452301L;
1009     ctx->m_nB = (sal_uInt32)0xefcdab89L;
1010     ctx->m_nC = (sal_uInt32)0x98badcfeL;
1011     ctx->m_nD = (sal_uInt32)0x10325476L;
1012     ctx->m_nE = (sal_uInt32)0xc3d2e1f0L;
1013 }
1014 
1015 /*
1016  * __rtl_digest_updateSHA.
1017  */
1018 static void __rtl_digest_updateSHA (DigestContextSHA *ctx)
1019 {
1020     register sal_uInt32  A, B, C, D, E, T;
1021     register sal_uInt32 *X;
1022 
1023     register DigestSHA_update_t *U;
1024     U = ctx->m_update;
1025 
1026     A = ctx->m_nA;
1027     B = ctx->m_nB;
1028     C = ctx->m_nC;
1029     D = ctx->m_nD;
1030     E = ctx->m_nE;
1031     X = ctx->m_pData;
1032 
1033     BODY_00_15 (U,  0, A, B, C, D, E, T);
1034     BODY_00_15 (U,  1, T, A, B, C, D, E);
1035     BODY_00_15 (U,  2, E, T, A, B, C, D);
1036     BODY_00_15 (U,  3, D, E, T, A, B, C);
1037     BODY_00_15 (U,  4, C, D, E, T, A, B);
1038     BODY_00_15 (U,  5, B, C, D, E, T, A);
1039     BODY_00_15 (U,  6, A, B, C, D, E, T);
1040     BODY_00_15 (U,  7, T, A, B, C, D, E);
1041     BODY_00_15 (U,  8, E, T, A, B, C, D);
1042     BODY_00_15 (U,  9, D, E, T, A, B, C);
1043     BODY_00_15 (U, 10, C, D, E, T, A, B);
1044     BODY_00_15 (U, 11, B, C, D, E, T, A);
1045     BODY_00_15 (U, 12, A, B, C, D, E, T);
1046     BODY_00_15 (U, 13, T, A, B, C, D, E);
1047     BODY_00_15 (U, 14, E, T, A, B, C, D);
1048     BODY_00_15 (U, 15, D, E, T, A, B, C);
1049     BODY_16_19 (U, 16, C, D, E, T, A, B);
1050     BODY_16_19 (U, 17, B, C, D, E, T, A);
1051     BODY_16_19 (U, 18, A, B, C, D, E, T);
1052     BODY_16_19 (U, 19, T, A, B, C, D, E);
1053 
1054     BODY_20_39 (U, 20, E, T, A, B, C, D);
1055     BODY_20_39 (U, 21, D, E, T, A, B, C);
1056     BODY_20_39 (U, 22, C, D, E, T, A, B);
1057     BODY_20_39 (U, 23, B, C, D, E, T, A);
1058     BODY_20_39 (U, 24, A, B, C, D, E, T);
1059     BODY_20_39 (U, 25, T, A, B, C, D, E);
1060     BODY_20_39 (U, 26, E, T, A, B, C, D);
1061     BODY_20_39 (U, 27, D, E, T, A, B, C);
1062     BODY_20_39 (U, 28, C, D, E, T, A, B);
1063     BODY_20_39 (U, 29, B, C, D, E, T, A);
1064     BODY_20_39 (U, 30, A, B, C, D, E, T);
1065     BODY_20_39 (U, 31, T, A, B, C, D, E);
1066     BODY_20_39 (U, 32, E, T, A, B, C, D);
1067     BODY_20_39 (U, 33, D, E, T, A, B, C);
1068     BODY_20_39 (U, 34, C, D, E, T, A, B);
1069     BODY_20_39 (U, 35, B, C, D, E, T, A);
1070     BODY_20_39 (U, 36, A, B, C, D, E, T);
1071     BODY_20_39 (U, 37, T, A, B, C, D, E);
1072     BODY_20_39 (U, 38, E, T, A, B, C, D);
1073     BODY_20_39 (U, 39, D, E, T, A, B, C);
1074 
1075     BODY_40_59 (U, 40, C, D, E, T, A, B);
1076     BODY_40_59 (U, 41, B, C, D, E, T, A);
1077     BODY_40_59 (U, 42, A, B, C, D, E, T);
1078     BODY_40_59 (U, 43, T, A, B, C, D, E);
1079     BODY_40_59 (U, 44, E, T, A, B, C, D);
1080     BODY_40_59 (U, 45, D, E, T, A, B, C);
1081     BODY_40_59 (U, 46, C, D, E, T, A, B);
1082     BODY_40_59 (U, 47, B, C, D, E, T, A);
1083     BODY_40_59 (U, 48, A, B, C, D, E, T);
1084     BODY_40_59 (U, 49, T, A, B, C, D, E);
1085     BODY_40_59 (U, 50, E, T, A, B, C, D);
1086     BODY_40_59 (U, 51, D, E, T, A, B, C);
1087     BODY_40_59 (U, 52, C, D, E, T, A, B);
1088     BODY_40_59 (U, 53, B, C, D, E, T, A);
1089     BODY_40_59 (U, 54, A, B, C, D, E, T);
1090     BODY_40_59 (U, 55, T, A, B, C, D, E);
1091     BODY_40_59 (U, 56, E, T, A, B, C, D);
1092     BODY_40_59 (U, 57, D, E, T, A, B, C);
1093     BODY_40_59 (U, 58, C, D, E, T, A, B);
1094     BODY_40_59 (U, 59, B, C, D, E, T, A);
1095 
1096     BODY_60_79 (U, 60, A, B, C, D, E, T);
1097     BODY_60_79 (U, 61, T, A, B, C, D, E);
1098     BODY_60_79 (U, 62, E, T, A, B, C, D);
1099     BODY_60_79 (U, 63, D, E, T, A, B, C);
1100     BODY_60_79 (U, 64, C, D, E, T, A, B);
1101     BODY_60_79 (U, 65, B, C, D, E, T, A);
1102     BODY_60_79 (U, 66, A, B, C, D, E, T);
1103     BODY_60_79 (U, 67, T, A, B, C, D, E);
1104     BODY_60_79 (U, 68, E, T, A, B, C, D);
1105     BODY_60_79 (U, 69, D, E, T, A, B, C);
1106     BODY_60_79 (U, 70, C, D, E, T, A, B);
1107     BODY_60_79 (U, 71, B, C, D, E, T, A);
1108     BODY_60_79 (U, 72, A, B, C, D, E, T);
1109     BODY_60_79 (U, 73, T, A, B, C, D, E);
1110     BODY_60_79 (U, 74, E, T, A, B, C, D);
1111     BODY_60_79 (U, 75, D, E, T, A, B, C);
1112     BODY_60_79 (U, 76, C, D, E, T, A, B);
1113     BODY_60_79 (U, 77, B, C, D, E, T, A);
1114     BODY_60_79 (U, 78, A, B, C, D, E, T);
1115     BODY_60_79 (U, 79, T, A, B, C, D, E);
1116 
1117     ctx->m_nA += E;
1118     ctx->m_nB += T;
1119     ctx->m_nC += A;
1120     ctx->m_nD += B;
1121     ctx->m_nE += C;
1122 }
1123 
1124 /*
1125  * __rtl_digest_endSHA.
1126  */
1127 static void __rtl_digest_endSHA (DigestContextSHA *ctx)
1128 {
1129     static const sal_uInt8 end[4] =
1130     {
1131         0x80, 0x00, 0x00, 0x00
1132     };
1133     register const sal_uInt8 *p = end;
1134 
1135     register sal_uInt32 *X;
1136     register int         i;
1137 
1138     X = ctx->m_pData;
1139     i = (ctx->m_nDatLen >> 2);
1140 
1141 #ifdef OSL_BIGENDIAN
1142     __rtl_digest_swapLong (X, i + 1);
1143 #endif /* OSL_BIGENDIAN */
1144 
1145     switch (ctx->m_nDatLen & 0x03)
1146     {
1147         case 1: X[i] &= 0x000000ff; break;
1148         case 2: X[i] &= 0x0000ffff; break;
1149         case 3: X[i] &= 0x00ffffff; break;
1150     }
1151 
1152     switch (ctx->m_nDatLen & 0x03)
1153     {
1154         case 0: X[i]  = ((sal_uInt32)(*(p++))) <<  0L;
1155         case 1: X[i] |= ((sal_uInt32)(*(p++))) <<  8L;
1156         case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L;
1157         case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L;
1158     }
1159 
1160     __rtl_digest_swapLong (X, i + 1);
1161 
1162     i += 1;
1163 
1164     if (i >= (DIGEST_LBLOCK_SHA - 2))
1165     {
1166         for (; i < DIGEST_LBLOCK_SHA; i++)
1167             X[i] = 0;
1168         __rtl_digest_updateSHA (ctx);
1169         i = 0;
1170     }
1171 
1172     for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
1173         X[i] = 0;
1174 
1175     X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
1176     X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
1177 
1178     __rtl_digest_updateSHA (ctx);
1179 }
1180 
1181 /*========================================================================
1182  *
1183  * rtl_digest_SHA internals.
1184  *
1185  *======================================================================*/
1186 /*
1187  * __rtl_digest_SHA_0.
1188  */
1189 static const Digest_Impl __rtl_digest_SHA_0 =
1190 {
1191     rtl_Digest_AlgorithmSHA,
1192     RTL_DIGEST_LENGTH_SHA,
1193 
1194     NULL,
1195     rtl_digest_destroySHA,
1196     rtl_digest_updateSHA,
1197     rtl_digest_getSHA
1198 };
1199 
1200 /*
1201  * __rtl_digest_updateSHA_0.
1202  */
1203 static sal_uInt32 __rtl_digest_updateSHA_0 (sal_uInt32 x)
1204 {
1205     return x;
1206 }
1207 
1208 /*========================================================================
1209  *
1210  * rtl_digest_SHA implementation.
1211  *
1212  *======================================================================*/
1213 /*
1214  * rtl_digest_SHA.
1215  */
1216 rtlDigestError SAL_CALL rtl_digest_SHA (
1217     const void *pData,   sal_uInt32 nDatLen,
1218     sal_uInt8  *pBuffer, sal_uInt32 nBufLen)
1219 {
1220     DigestSHA_Impl digest;
1221     rtlDigestError result;
1222 
1223     digest.m_digest = __rtl_digest_SHA_0;
1224     __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_0);
1225 
1226     result = rtl_digest_updateSHA (&digest, pData, nDatLen);
1227     if (result == rtl_Digest_E_None)
1228         result = rtl_digest_getSHA (&digest, pBuffer, nBufLen);
1229 
1230     rtl_zeroMemory (&digest, sizeof (digest));
1231     return (result);
1232 }
1233 
1234 /*
1235  * rtl_digest_createSHA.
1236  */
1237 rtlDigest SAL_CALL rtl_digest_createSHA (void)
1238 {
1239     DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL;
1240     pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1241     if (pImpl)
1242     {
1243         pImpl->m_digest = __rtl_digest_SHA_0;
1244         __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_0);
1245     }
1246     return ((rtlDigest)pImpl);
1247 }
1248 
1249 /*
1250  * rtl_digest_updateSHA.
1251  */
1252 rtlDigestError SAL_CALL rtl_digest_updateSHA (
1253     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1254 {
1255     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
1256     const sal_uInt8  *d     = (const sal_uInt8 *)pData;
1257 
1258     DigestContextSHA *ctx;
1259     sal_uInt32        len;
1260 
1261     if ((pImpl == NULL) || (pData == NULL))
1262         return rtl_Digest_E_Argument;
1263 
1264     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA))
1265         return rtl_Digest_E_Algorithm;
1266 
1267     if (nDatLen == 0)
1268         return rtl_Digest_E_None;
1269 
1270     ctx = &(pImpl->m_context);
1271 
1272     len = ctx->m_nL + (nDatLen << 3);
1273     if (len < ctx->m_nL) ctx->m_nH += 1;
1274     ctx->m_nH += (nDatLen >> 29);
1275     ctx->m_nL  = len;
1276 
1277     if (ctx->m_nDatLen)
1278     {
1279         sal_uInt8  *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
1280         sal_uInt32  n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1281 
1282         if (nDatLen < n)
1283         {
1284             rtl_copyMemory (p, d, nDatLen);
1285             ctx->m_nDatLen += nDatLen;
1286 
1287             return rtl_Digest_E_None;
1288         }
1289 
1290         rtl_copyMemory (p, d, n);
1291         d       += n;
1292         nDatLen -= n;
1293 
1294 #ifndef OSL_BIGENDIAN
1295         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
1296 #endif /* OSL_BIGENDIAN */
1297 
1298         __rtl_digest_updateSHA (ctx);
1299         ctx->m_nDatLen = 0;
1300     }
1301 
1302     while (nDatLen >= DIGEST_CBLOCK_SHA)
1303     {
1304         rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1305         d       += DIGEST_CBLOCK_SHA;
1306         nDatLen -= DIGEST_CBLOCK_SHA;
1307 
1308 #ifndef OSL_BIGENDIAN
1309         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
1310 #endif /* OSL_BIGENDIAN */
1311 
1312         __rtl_digest_updateSHA (ctx);
1313     }
1314 
1315     rtl_copyMemory (ctx->m_pData, d, nDatLen);
1316     ctx->m_nDatLen = nDatLen;
1317 
1318     return rtl_Digest_E_None;
1319 }
1320 
1321 /*
1322  * rtl_digest_getSHA.
1323  */
1324 rtlDigestError SAL_CALL rtl_digest_getSHA (
1325     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1326 {
1327     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
1328     sal_uInt8        *p     = pBuffer;
1329 
1330     DigestContextSHA *ctx;
1331 
1332     if ((pImpl == NULL) || (pBuffer == NULL))
1333         return rtl_Digest_E_Argument;
1334 
1335     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA))
1336         return rtl_Digest_E_Algorithm;
1337 
1338     if (!(pImpl->m_digest.m_length <= nBufLen))
1339         return rtl_Digest_E_BufferSize;
1340 
1341     ctx = &(pImpl->m_context);
1342 
1343     __rtl_digest_endSHA (ctx);
1344     RTL_DIGEST_HTONL (ctx->m_nA, p);
1345     RTL_DIGEST_HTONL (ctx->m_nB, p);
1346     RTL_DIGEST_HTONL (ctx->m_nC, p);
1347     RTL_DIGEST_HTONL (ctx->m_nD, p);
1348     RTL_DIGEST_HTONL (ctx->m_nE, p);
1349     __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_0);
1350 
1351     return rtl_Digest_E_None;
1352 }
1353 
1354 /*
1355  * rtl_digest_destroySHA.
1356  */
1357 void SAL_CALL rtl_digest_destroySHA (rtlDigest Digest)
1358 {
1359     DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
1360     if (pImpl)
1361     {
1362         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
1363             rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl));
1364         else
1365             rtl_freeMemory (pImpl);
1366     }
1367 }
1368 
1369 /*========================================================================
1370  *
1371  * rtl_digest_SHA1 internals.
1372  *
1373  *======================================================================*/
1374 /*
1375  * __rtl_digest_SHA_1.
1376  */
1377 static const Digest_Impl __rtl_digest_SHA_1 =
1378 {
1379     rtl_Digest_AlgorithmSHA1,
1380     RTL_DIGEST_LENGTH_SHA1,
1381 
1382     NULL,
1383     rtl_digest_destroySHA1,
1384     rtl_digest_updateSHA1,
1385     rtl_digest_getSHA1
1386 };
1387 
1388 /*
1389  * __rtl_digest_updateSHA_1.
1390  */
1391 static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x)
1392 {
1393     return RTL_DIGEST_ROTL (x, 1);
1394 }
1395 
1396 /*========================================================================
1397  *
1398  * rtl_digest_SHA1 implementation.
1399  *
1400  *======================================================================*/
1401 /*
1402  * rtl_digest_SHA1.
1403  */
1404 rtlDigestError SAL_CALL rtl_digest_SHA1 (
1405     const void *pData,   sal_uInt32 nDatLen,
1406     sal_uInt8  *pBuffer, sal_uInt32 nBufLen)
1407 {
1408     DigestSHA_Impl digest;
1409     rtlDigestError result;
1410 
1411     digest.m_digest = __rtl_digest_SHA_1;
1412     __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_1);
1413 
1414     result = rtl_digest_updateSHA1 (&digest, pData, nDatLen);
1415     if (result == rtl_Digest_E_None)
1416         result = rtl_digest_getSHA1 (&digest, pBuffer, nBufLen);
1417 
1418     rtl_zeroMemory (&digest, sizeof (digest));
1419     return (result);
1420 }
1421 
1422 /*
1423  * rtl_digest_createSHA1.
1424  */
1425 rtlDigest SAL_CALL rtl_digest_createSHA1 (void)
1426 {
1427     DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL;
1428     pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
1429     if (pImpl)
1430     {
1431         pImpl->m_digest = __rtl_digest_SHA_1;
1432         __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1);
1433     }
1434     return ((rtlDigest)pImpl);
1435 }
1436 
1437 /*
1438  * rtl_digest_updateSHA1.
1439  */
1440 rtlDigestError SAL_CALL rtl_digest_updateSHA1 (
1441     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1442 {
1443     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
1444     const sal_uInt8  *d     = (const sal_uInt8 *)pData;
1445 
1446     DigestContextSHA *ctx;
1447     sal_uInt32        len;
1448 
1449     if ((pImpl == NULL) || (pData == NULL))
1450         return rtl_Digest_E_Argument;
1451 
1452     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
1453         return rtl_Digest_E_Algorithm;
1454 
1455     if (nDatLen == 0)
1456         return rtl_Digest_E_None;
1457 
1458     ctx = &(pImpl->m_context);
1459 
1460     len = ctx->m_nL + (nDatLen << 3);
1461     if (len < ctx->m_nL) ctx->m_nH += 1;
1462     ctx->m_nH += (nDatLen >> 29);
1463     ctx->m_nL  = len;
1464 
1465     if (ctx->m_nDatLen)
1466     {
1467         sal_uInt8  *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
1468         sal_uInt32  n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
1469 
1470         if (nDatLen < n)
1471         {
1472             rtl_copyMemory (p, d, nDatLen);
1473             ctx->m_nDatLen += nDatLen;
1474 
1475             return rtl_Digest_E_None;
1476         }
1477 
1478         rtl_copyMemory (p, d, n);
1479         d       += n;
1480         nDatLen -= n;
1481 
1482 #ifndef OSL_BIGENDIAN
1483         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
1484 #endif /* OSL_BIGENDIAN */
1485 
1486         __rtl_digest_updateSHA (ctx);
1487         ctx->m_nDatLen = 0;
1488     }
1489 
1490     while (nDatLen >= DIGEST_CBLOCK_SHA)
1491     {
1492         rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA);
1493         d       += DIGEST_CBLOCK_SHA;
1494         nDatLen -= DIGEST_CBLOCK_SHA;
1495 
1496 #ifndef OSL_BIGENDIAN
1497         __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
1498 #endif /* OSL_BIGENDIAN */
1499 
1500         __rtl_digest_updateSHA (ctx);
1501     }
1502 
1503     rtl_copyMemory (ctx->m_pData, d, nDatLen);
1504     ctx->m_nDatLen = nDatLen;
1505 
1506     return rtl_Digest_E_None;
1507 }
1508 
1509 /*
1510  * rtl_digest_getSHA1.
1511  */
1512 rtlDigestError SAL_CALL rtl_digest_getSHA1 (
1513     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1514 {
1515     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
1516     sal_uInt8        *p     = pBuffer;
1517 
1518     DigestContextSHA *ctx;
1519 
1520     if ((pImpl == NULL) || (pBuffer == NULL))
1521         return rtl_Digest_E_Argument;
1522 
1523     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
1524         return rtl_Digest_E_Algorithm;
1525 
1526     if (!(pImpl->m_digest.m_length <= nBufLen))
1527         return rtl_Digest_E_BufferSize;
1528 
1529     ctx = &(pImpl->m_context);
1530 
1531     __rtl_digest_endSHA (ctx);
1532     RTL_DIGEST_HTONL (ctx->m_nA, p);
1533     RTL_DIGEST_HTONL (ctx->m_nB, p);
1534     RTL_DIGEST_HTONL (ctx->m_nC, p);
1535     RTL_DIGEST_HTONL (ctx->m_nD, p);
1536     RTL_DIGEST_HTONL (ctx->m_nE, p);
1537     __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_1);
1538 
1539     return rtl_Digest_E_None;
1540 }
1541 
1542 /*
1543  * rtl_digest_destroySHA1.
1544  */
1545 void SAL_CALL rtl_digest_destroySHA1 (rtlDigest Digest)
1546 {
1547     DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
1548     if (pImpl)
1549     {
1550         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
1551             rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl));
1552         else
1553             rtl_freeMemory (pImpl);
1554     }
1555 }
1556 
1557 /*========================================================================
1558  *
1559  * rtl_digest_HMAC_MD5 internals.
1560  *
1561  *======================================================================*/
1562 #define DIGEST_CBLOCK_HMAC_MD5 64
1563 
1564 typedef struct _contextHMAC_MD5_st
1565 {
1566     DigestMD5_Impl m_hash;
1567     sal_uInt8      m_opad[DIGEST_CBLOCK_HMAC_MD5];
1568 } ContextHMAC_MD5;
1569 
1570 typedef struct _digestHMAC_MD5_impl_st
1571 {
1572     Digest_Impl     m_digest;
1573     ContextHMAC_MD5 m_context;
1574 } DigestHMAC_MD5_Impl;
1575 
1576 static void __rtl_digest_initHMAC_MD5 (ContextHMAC_MD5 * ctx);
1577 static void __rtl_digest_ipadHMAC_MD5 (ContextHMAC_MD5 * ctx);
1578 static void __rtl_digest_opadHMAC_MD5 (ContextHMAC_MD5 * ctx);
1579 
1580 /*
1581  * __rtl_digest_HMAC_MD5.
1582  */
1583 static const Digest_Impl __rtl_digest_HMAC_MD5 =
1584 {
1585     rtl_Digest_AlgorithmHMAC_MD5,
1586     RTL_DIGEST_LENGTH_MD5,
1587 
1588     rtl_digest_initHMAC_MD5,
1589     rtl_digest_destroyHMAC_MD5,
1590     rtl_digest_updateHMAC_MD5,
1591     rtl_digest_getHMAC_MD5
1592 };
1593 
1594 /*
1595  * __rtl_digest_initHMAC_MD5.
1596  */
1597 static void __rtl_digest_initHMAC_MD5 (ContextHMAC_MD5 * ctx)
1598 {
1599     DigestMD5_Impl *pImpl = &(ctx->m_hash);
1600 
1601     pImpl->m_digest = __rtl_digest_MD5;
1602     __rtl_digest_initMD5 (&(pImpl->m_context));
1603 
1604     rtl_zeroMemory (ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
1605 }
1606 
1607 /*
1608  * __rtl_digest_ipadHMAC_MD5.
1609  */
1610 static void __rtl_digest_ipadHMAC_MD5 (ContextHMAC_MD5 * ctx)
1611 {
1612     register sal_uInt32 i;
1613 
1614     for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1615         ctx->m_opad[i] ^= 0x36;
1616     rtl_digest_updateMD5 (
1617         &(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
1618     for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1619         ctx->m_opad[i] ^= 0x36;
1620 }
1621 
1622 /*
1623  * __rtl_digest_opadHMAC_MD5.
1624  */
1625 static void __rtl_digest_opadHMAC_MD5 (ContextHMAC_MD5 * ctx)
1626 {
1627     register sal_uInt32 i;
1628 
1629     for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
1630         ctx->m_opad[i] ^= 0x5c;
1631 }
1632 
1633 /*========================================================================
1634  *
1635  * rtl_digest_HMAC_MD5 implementation.
1636  *
1637  *======================================================================*/
1638 /*
1639  * rtl_digest_HMAC_MD5.
1640  */
1641 rtlDigestError SAL_CALL rtl_digest_HMAC_MD5 (
1642     const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1643     const void      *pData,    sal_uInt32 nDatLen,
1644     sal_uInt8       *pBuffer,  sal_uInt32 nBufLen)
1645 {
1646     DigestHMAC_MD5_Impl digest;
1647     rtlDigestError      result;
1648 
1649     digest.m_digest = __rtl_digest_HMAC_MD5;
1650 
1651     result = rtl_digest_initHMAC_MD5 (&digest, pKeyData, nKeyLen);
1652     if (result == rtl_Digest_E_None)
1653     {
1654         result = rtl_digest_updateHMAC_MD5 (&digest, pData, nDatLen);
1655         if (result == rtl_Digest_E_None)
1656             result = rtl_digest_getHMAC_MD5 (&digest, pBuffer, nBufLen);
1657     }
1658 
1659     rtl_zeroMemory (&digest, sizeof (digest));
1660     return (result);
1661 }
1662 
1663 /*
1664  * rtl_digest_createHMAC_MD5.
1665  */
1666 rtlDigest SAL_CALL rtl_digest_createHMAC_MD5 (void)
1667 {
1668     DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)NULL;
1669     pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
1670     if (pImpl)
1671     {
1672         pImpl->m_digest = __rtl_digest_HMAC_MD5;
1673         __rtl_digest_initHMAC_MD5 (&(pImpl->m_context));
1674     }
1675     return ((rtlDigest)pImpl);
1676 }
1677 
1678 /*
1679  * rtl_digest_initHMAC_MD5.
1680  */
1681 rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5 (
1682     rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1683 {
1684     DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
1685     ContextHMAC_MD5     *ctx;
1686 
1687     if ((pImpl == NULL) || (pKeyData == NULL))
1688         return rtl_Digest_E_Argument;
1689 
1690     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
1691         return rtl_Digest_E_Algorithm;
1692 
1693     ctx = &(pImpl->m_context);
1694     __rtl_digest_initHMAC_MD5 (ctx);
1695 
1696     if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
1697     {
1698         /* Initialize 'opad' with hashed 'KeyData' */
1699         rtl_digest_updateMD5 (
1700             &(ctx->m_hash), pKeyData, nKeyLen);
1701         rtl_digest_getMD5 (
1702             &(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
1703     }
1704     else
1705     {
1706         /* Initialize 'opad' with plain 'KeyData' */
1707         rtl_copyMemory (ctx->m_opad, pKeyData, nKeyLen);
1708     }
1709 
1710     __rtl_digest_ipadHMAC_MD5 (ctx);
1711     __rtl_digest_opadHMAC_MD5 (ctx);
1712 
1713     return rtl_Digest_E_None;
1714 }
1715 
1716 /*
1717  * rtl_digest_updateHMAC_MD5.
1718  */
1719 rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5 (
1720     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1721 {
1722     DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
1723     ContextHMAC_MD5     *ctx;
1724 
1725     if ((pImpl == NULL) || (pData == NULL))
1726         return rtl_Digest_E_Argument;
1727 
1728     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
1729         return rtl_Digest_E_Algorithm;
1730 
1731     ctx = &(pImpl->m_context);
1732     rtl_digest_updateMD5 (&(ctx->m_hash), pData, nDatLen);
1733 
1734     return rtl_Digest_E_None;
1735 }
1736 
1737 /*
1738  * rtl_digest_getHMAC_MD5.
1739  */
1740 rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5 (
1741     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1742 {
1743     DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
1744     ContextHMAC_MD5     *ctx;
1745 
1746     if ((pImpl == NULL) || (pBuffer == NULL))
1747         return rtl_Digest_E_Argument;
1748 
1749     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
1750         return rtl_Digest_E_Algorithm;
1751 
1752     if (!(pImpl->m_digest.m_length <= nBufLen))
1753         return rtl_Digest_E_BufferSize;
1754 
1755     nBufLen = pImpl->m_digest.m_length;
1756 
1757     ctx = &(pImpl->m_context);
1758     rtl_digest_getMD5 (&(ctx->m_hash), pBuffer, nBufLen);
1759 
1760     rtl_digest_updateMD5 (&(ctx->m_hash), ctx->m_opad, 64);
1761     rtl_digest_updateMD5 (&(ctx->m_hash), pBuffer, nBufLen);
1762     rtl_digest_getMD5    (&(ctx->m_hash), pBuffer, nBufLen);
1763 
1764     __rtl_digest_opadHMAC_MD5 (ctx);
1765     __rtl_digest_ipadHMAC_MD5 (ctx);
1766     __rtl_digest_opadHMAC_MD5 (ctx);
1767 
1768     return rtl_Digest_E_None;
1769 }
1770 
1771 /*
1772  * rtl_digest_destroyHMAC_MD5.
1773  */
1774 void SAL_CALL rtl_digest_destroyHMAC_MD5 (rtlDigest Digest)
1775 {
1776     DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
1777     if (pImpl)
1778     {
1779         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
1780             rtl_freeZeroMemory (pImpl, sizeof (DigestHMAC_MD5_Impl));
1781         else
1782             rtl_freeMemory (pImpl);
1783     }
1784 }
1785 
1786 /*========================================================================
1787  *
1788  * rtl_digest_HMAC_SHA1 internals.
1789  *
1790  *======================================================================*/
1791 #define DIGEST_CBLOCK_HMAC_SHA1 64
1792 
1793 typedef struct _contextHMAC_SHA1_st
1794 {
1795     DigestSHA_Impl m_hash;
1796     sal_uInt8      m_opad[DIGEST_CBLOCK_HMAC_SHA1];
1797 } ContextHMAC_SHA1;
1798 
1799 typedef struct _digestHMAC_SHA1_impl_st
1800 {
1801     Digest_Impl      m_digest;
1802     ContextHMAC_SHA1 m_context;
1803 } DigestHMAC_SHA1_Impl;
1804 
1805 static void __rtl_digest_initHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
1806 static void __rtl_digest_ipadHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
1807 static void __rtl_digest_opadHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
1808 
1809 /*
1810  * __rtl_digest_HMAC_SHA1.
1811  */
1812 static const Digest_Impl __rtl_digest_HMAC_SHA1 =
1813 {
1814     rtl_Digest_AlgorithmHMAC_SHA1,
1815     RTL_DIGEST_LENGTH_SHA1,
1816 
1817     rtl_digest_initHMAC_SHA1,
1818     rtl_digest_destroyHMAC_SHA1,
1819     rtl_digest_updateHMAC_SHA1,
1820     rtl_digest_getHMAC_SHA1
1821 };
1822 
1823 /*
1824  * __rtl_digest_initHMAC_SHA1.
1825  */
1826 static void __rtl_digest_initHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
1827 {
1828     DigestSHA_Impl *pImpl = &(ctx->m_hash);
1829 
1830     pImpl->m_digest = __rtl_digest_SHA_1;
1831     __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1);
1832 
1833     rtl_zeroMemory (ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
1834 }
1835 
1836 /*
1837  * __rtl_digest_ipadHMAC_SHA1.
1838  */
1839 static void __rtl_digest_ipadHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
1840 {
1841     register sal_uInt32 i;
1842 
1843     for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1844         ctx->m_opad[i] ^= 0x36;
1845     rtl_digest_updateSHA1 (
1846         &(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
1847     for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1848         ctx->m_opad[i] ^= 0x36;
1849 }
1850 
1851 /*
1852  * __rtl_digest_opadHMAC_SHA1.
1853  */
1854 static void __rtl_digest_opadHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
1855 {
1856     register sal_uInt32 i;
1857 
1858     for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
1859         ctx->m_opad[i] ^= 0x5c;
1860 }
1861 
1862 /*========================================================================
1863  *
1864  * rtl_digest_HMAC_SHA1 implementation.
1865  *
1866  *======================================================================*/
1867 /*
1868  * rtl_digest_HMAC_SHA1.
1869  */
1870 rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1 (
1871     const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
1872     const void      *pData,    sal_uInt32 nDatLen,
1873     sal_uInt8       *pBuffer,  sal_uInt32 nBufLen)
1874 {
1875     DigestHMAC_SHA1_Impl digest;
1876     rtlDigestError       result;
1877 
1878     digest.m_digest = __rtl_digest_HMAC_SHA1;
1879 
1880     result = rtl_digest_initHMAC_SHA1 (&digest, pKeyData, nKeyLen);
1881     if (result == rtl_Digest_E_None)
1882     {
1883         result = rtl_digest_updateHMAC_SHA1 (&digest, pData, nDatLen);
1884         if (result == rtl_Digest_E_None)
1885             result = rtl_digest_getHMAC_SHA1 (&digest, pBuffer, nBufLen);
1886     }
1887 
1888     rtl_zeroMemory (&digest, sizeof (digest));
1889     return (result);
1890 }
1891 
1892 /*
1893  * rtl_digest_createHMAC_SHA1.
1894  */
1895 rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1 (void)
1896 {
1897     DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)NULL;
1898     pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
1899     if (pImpl)
1900     {
1901         pImpl->m_digest = __rtl_digest_HMAC_SHA1;
1902         __rtl_digest_initHMAC_SHA1 (&(pImpl->m_context));
1903     }
1904     return ((rtlDigest)pImpl);
1905 }
1906 
1907 /*
1908  * rtl_digest_initHMAC_SHA1.
1909  */
1910 rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1 (
1911     rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
1912 {
1913     DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
1914     ContextHMAC_SHA1     *ctx;
1915 
1916     if ((pImpl == NULL) || (pKeyData == NULL))
1917         return rtl_Digest_E_Argument;
1918 
1919     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
1920         return rtl_Digest_E_Algorithm;
1921 
1922     ctx = &(pImpl->m_context);
1923     __rtl_digest_initHMAC_SHA1 (ctx);
1924 
1925     if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
1926     {
1927         /* Initialize 'opad' with hashed 'KeyData' */
1928         rtl_digest_updateSHA1 (
1929             &(ctx->m_hash), pKeyData, nKeyLen);
1930         rtl_digest_getSHA1 (
1931             &(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
1932     }
1933     else
1934     {
1935         /* Initialize 'opad' with plain 'KeyData' */
1936         rtl_copyMemory (ctx->m_opad, pKeyData, nKeyLen);
1937     }
1938 
1939     __rtl_digest_ipadHMAC_SHA1 (ctx);
1940     __rtl_digest_opadHMAC_SHA1 (ctx);
1941 
1942     return rtl_Digest_E_None;
1943 }
1944 
1945 /*
1946  * rtl_digest_updateHMAC_SHA1.
1947  */
1948 rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1 (
1949     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
1950 {
1951     DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
1952     ContextHMAC_SHA1     *ctx;
1953 
1954     if ((pImpl == NULL) || (pData == NULL))
1955         return rtl_Digest_E_Argument;
1956 
1957     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
1958         return rtl_Digest_E_Algorithm;
1959 
1960     ctx = &(pImpl->m_context);
1961     rtl_digest_updateSHA1 (&(ctx->m_hash), pData, nDatLen);
1962 
1963     return rtl_Digest_E_None;
1964 }
1965 
1966 /*
1967  * rtl_digest_getHMAC_SHA1.
1968  */
1969 rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1 (
1970     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
1971 {
1972     DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
1973     ContextHMAC_SHA1     *ctx;
1974 
1975     if ((pImpl == NULL) || (pBuffer == NULL))
1976         return rtl_Digest_E_Argument;
1977 
1978     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
1979         return rtl_Digest_E_Algorithm;
1980 
1981     if (!(pImpl->m_digest.m_length <= nBufLen))
1982         return rtl_Digest_E_BufferSize;
1983 
1984     nBufLen = pImpl->m_digest.m_length;
1985 
1986     ctx = &(pImpl->m_context);
1987     rtl_digest_getSHA1 (&(ctx->m_hash), pBuffer, nBufLen);
1988 
1989     rtl_digest_updateSHA1 (&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
1990     rtl_digest_updateSHA1 (&(ctx->m_hash), pBuffer, nBufLen);
1991     rtl_digest_getSHA1    (&(ctx->m_hash), pBuffer, nBufLen);
1992 
1993     __rtl_digest_opadHMAC_SHA1 (ctx);
1994     __rtl_digest_ipadHMAC_SHA1 (ctx);
1995     __rtl_digest_opadHMAC_SHA1 (ctx);
1996 
1997     return rtl_Digest_E_None;
1998 }
1999 
2000 /*
2001  * rtl_digest_destroyHMAC_SHA1.
2002  */
2003 void SAL_CALL rtl_digest_destroyHMAC_SHA1 (rtlDigest Digest)
2004 {
2005     DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
2006     if (pImpl)
2007     {
2008         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
2009             rtl_freeZeroMemory (pImpl, sizeof (DigestHMAC_SHA1_Impl));
2010         else
2011             rtl_freeMemory (pImpl);
2012     }
2013 }
2014 
2015 /*========================================================================
2016  *
2017  * rtl_digest_PBKDF2 internals.
2018  *
2019  *======================================================================*/
2020 #define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
2021 
2022 /*
2023  * __rtl_digest_updatePBKDF2.
2024  */
2025 static void __rtl_digest_updatePBKDF2 (
2026     rtlDigest        hDigest,
2027     sal_uInt8        T[DIGEST_CBLOCK_PBKDF2],
2028     const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
2029     sal_uInt32       nCount,    sal_uInt32 nIndex)
2030 {
2031     /* T_i = F (P, S, c, i) */
2032     sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
2033     register  sal_uInt32 i, k;
2034 
2035     /* U_(1) = PRF (P, S || INDEX) */
2036     rtl_digest_updateHMAC_SHA1 (hDigest, pSaltData, nSaltLen);
2037     rtl_digest_updateHMAC_SHA1 (hDigest, &nIndex, sizeof(nIndex));
2038     rtl_digest_getHMAC_SHA1    (hDigest, U, DIGEST_CBLOCK_PBKDF2);
2039 
2040     /* T = U_(1) */
2041     for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) T[k] = U[k];
2042 
2043     /* T ^= U_(2) ^ ... ^ U_(c) */
2044     for (i = 1; i < nCount; i++)
2045     {
2046         /* U_(i) = PRF (P, U_(i-1)) */
2047         rtl_digest_updateHMAC_SHA1 (hDigest, U, DIGEST_CBLOCK_PBKDF2);
2048         rtl_digest_getHMAC_SHA1    (hDigest, U, DIGEST_CBLOCK_PBKDF2);
2049 
2050         /* T ^= U_(i) */
2051         for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) T[k] ^= U[k];
2052     }
2053 
2054     rtl_zeroMemory (U, DIGEST_CBLOCK_PBKDF2);
2055 }
2056 
2057 /*========================================================================
2058  *
2059  * rtl_digest_PBKDF2 implementation.
2060  *
2061  *======================================================================*/
2062 /*
2063  * rtl_digest_PBKDF2.
2064  */
2065 rtlDigestError SAL_CALL rtl_digest_PBKDF2 (
2066     sal_uInt8       *pKeyData , sal_uInt32 nKeyLen,
2067     const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
2068     const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
2069     sal_uInt32       nCount)
2070 {
2071     DigestHMAC_SHA1_Impl digest;
2072     sal_uInt32           i = 1;
2073 
2074     if ((pKeyData == NULL) || (pPassData == NULL) || (pSaltData == NULL))
2075         return rtl_Digest_E_Argument;
2076 
2077     digest.m_digest = __rtl_digest_HMAC_SHA1;
2078     rtl_digest_initHMAC_SHA1 (&digest, pPassData, nPassLen);
2079 
2080     /* DK = T_(1) || T_(2) || ... || T_(l) */
2081     while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
2082     {
2083         /* T_(i) = F (P, S, c, i); DK ||= T_(i) */
2084         __rtl_digest_updatePBKDF2 (
2085             &digest, pKeyData,
2086             pSaltData, nSaltLen,
2087             nCount, OSL_NETDWORD(i));
2088 
2089         /* Next 'KeyData' block */
2090         pKeyData += DIGEST_CBLOCK_PBKDF2;
2091         nKeyLen  -= DIGEST_CBLOCK_PBKDF2;
2092         i += 1;
2093     }
2094     if (nKeyLen > 0)
2095     {
2096         /* Last 'KeyData' block */
2097         sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
2098 
2099         /* T_i = F (P, S, c, i) */
2100         __rtl_digest_updatePBKDF2 (
2101             &digest, T,
2102             pSaltData, nSaltLen,
2103             nCount, OSL_NETDWORD(i));
2104 
2105         /* DK ||= T_(i) */
2106         rtl_copyMemory (pKeyData, T, nKeyLen);
2107         rtl_zeroMemory (T, DIGEST_CBLOCK_PBKDF2);
2108     }
2109 
2110     rtl_zeroMemory (&digest, sizeof (digest));
2111     return rtl_Digest_E_None;
2112 }
2113 
2114 /*========================================================================
2115  *
2116  * The End.
2117  *
2118  *======================================================================*/
2119