File indexing completed on 2024-05-12 16:35:44

0001 /*************************************************************************
0002  * This implementation has been taken from the OpenOffice 1.0 and modified
0003  * to use Calligra Sheets data types.
0004  *
0005  *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
0006  *
0007  *  Sun has made the contents of this file available subject to the
0008  *  terms of GNU Lesser General Public License Version 2.1 as
0009  *  specified in sal/rtl/source/digest.c in the OpenOffice package.
0010  *
0011  *
0012  *  Sun Microsystems Inc., October, 2000
0013  *
0014  *  GNU Lesser General Public License Version 2.1
0015  *  =============================================
0016  *  Copyright 2000 by Sun Microsystems, Inc.
0017  *  901 San Antonio Road, Palo Alto, CA 94303, USA
0018  *
0019  *  This library is free software; you can redistribute it and/or
0020  *  modify it under the terms of the GNU Lesser General Public
0021  *  License version 2.1, as published by the Free Software Foundation.
0022  *
0023  *  This library is distributed in the hope that it will be useful,
0024  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0025  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0026  *  Lesser General Public License for more details.
0027  *
0028  *  You should have received a copy of the GNU Lesser General Public
0029  *  License along with this library; if not, write to the Free Software
0030  *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
0031    Boston, MA 02110-1301, USA
0032  *
0033  *  All Rights Reserved.
0034  *
0035  *  Contributor(s): Matthias Huetsch <matthias.huetsch@sun.com>
0036  *
0037  *
0038  ************************************************************************/
0039 
0040 #include "Digest.h"
0041 
0042 #include <stdlib.h>
0043 #include <string.h>
0044 
0045 #include <KoConfig.h> // WORDS_BIGENDIAN
0046 
0047 #include "SheetsDebug.h"
0048 
0049 typedef quint8 sal_uInt8;
0050 typedef quint16 sal_uInt16;
0051 typedef quint32 sal_uInt32;
0052 
0053 void rtl_freeZeroMemory(void * p, sal_uInt32 n);
0054 void rtl_freeMemory(void * p);
0055 void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes);
0056 void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes);
0057 
0058 #ifndef OSL_LOBYTE
0059 # define OSL_LOBYTE(w)           ((sal_uInt8)((sal_uInt16)(w) & 0xFF))
0060 #endif
0061 #ifndef OSL_HIBYTE
0062 # define OSL_HIBYTE(w)           ((sal_uInt8)(((sal_uInt16)(w) >> 8) & 0xFF))
0063 #endif
0064 #ifndef OSL_MAKEWORD
0065 # define OSL_MAKEWORD(bl, bh)    ((sal_uInt16)((bl) & 0xFF) | (((sal_uInt16)(bh) & 0xFF) << 8))
0066 #endif
0067 #ifndef OSL_MAKEDWORD
0068 # define OSL_MAKEDWORD(wl, wh)   ((sal_uInt32)((wl) & 0xFFFF) | (((sal_uInt32)(wh) & 0xFFFF) << 16))
0069 #endif
0070 #ifndef OSL_LOWORD
0071 # define OSL_LOWORD(d)           ((sal_uInt16)((sal_uInt32)(d) & 0xFFFF))
0072 #endif
0073 #ifndef OSL_HIWORD
0074 # define OSL_HIWORD(d)           ((sal_uInt16)(((sal_uInt32)(d) >> 16) & 0xFFFF))
0075 #endif
0076 
0077 /** Define macros for swapping between byte orders.
0078  */
0079 #ifndef OSL_SWAPWORD
0080 # define OSL_SWAPWORD(w)         OSL_MAKEWORD(OSL_HIBYTE(w),OSL_LOBYTE(w))
0081 #endif
0082 #ifndef OSL_SWAPDWORD
0083 # define OSL_SWAPDWORD(d)        OSL_MAKEDWORD(OSL_SWAPWORD(OSL_HIWORD(d)),OSL_SWAPWORD(OSL_LOWORD(d)))
0084 #endif
0085 
0086 
0087 /*========================================================================
0088  *
0089  * rtlDigest.
0090  *
0091  *======================================================================*/
0092 /** Digest Handle opaque type.
0093  */
0094 typedef void* rtlDigest;
0095 
0096 /** Digest Algorithm enumeration.
0097     @see rtl_digest_create()
0098  */
0099 enum __rtl_DigestAlgorithm {
0100     rtl_Digest_AlgorithmMD2,
0101     rtl_Digest_AlgorithmMD5,
0102     rtl_Digest_AlgorithmSHA,
0103     rtl_Digest_AlgorithmSHA1,
0104 
0105     rtl_Digest_AlgorithmHMAC_MD5,
0106     rtl_Digest_AlgorithmHMAC_SHA1,
0107 
0108     rtl_Digest_AlgorithmInvalid,
0109     rtl_Digest_Algorithm_FORCE_EQUAL_SIZE
0110 };
0111 
0112 /** Digest Algorithm type.
0113  */
0114 typedef enum __rtl_DigestAlgorithm rtlDigestAlgorithm;
0115 
0116 
0117 /** Error Code enumeration.
0118  */
0119 enum __rtl_DigestError {
0120     rtl_Digest_E_None,
0121     rtl_Digest_E_Argument,
0122     rtl_Digest_E_Algorithm,
0123     rtl_Digest_E_BufferSize,
0124     rtl_Digest_E_Memory,
0125     rtl_Digest_E_Unknown,
0126     rtl_Digest_E_FORCE_EQUAL_SIZE
0127 };
0128 
0129 /** Error Code type.
0130  */
0131 typedef enum __rtl_DigestError rtlDigestError;
0132 
0133 typedef rtlDigestError Digest_init_t(void * ctx, const sal_uInt8 * Data, sal_uInt32 DatLen);
0134 
0135 typedef void Digest_delete_t(void *ctx);
0136 
0137 typedef rtlDigestError Digest_update_t(void * ctx, const void * Data, sal_uInt32 DatLen);
0138 
0139 typedef rtlDigestError Digest_get_t(void * ctx, sal_uInt8 * Buffer, sal_uInt32 BufLen);
0140 
0141 /*========================================================================
0142  *
0143  * rtl_digest_SHA1 interface.
0144  *
0145  *======================================================================*/
0146 #define RTL_DIGEST_LENGTH_SHA1 20
0147 
0148 /** Create a SHA1 Digest.handle.
0149     @details The SHA1 digest algorithm is specified in
0150     FIPS PUB 180-1 (Supersedes FIPS PUB 180)
0151       Secure Hash Standard
0152 
0153     @see rtl_digest_create()
0154  */
0155 rtlDigest rtl_digest_createSHA1(void);
0156 
0157 
0158 /** Destroy a SHA1 Digest.handle.
0159     @see rtl_digest_destroy()
0160  */
0161 void rtl_digest_destroySHA1(rtlDigest Digest);
0162 
0163 
0164 /** Update a SHA1 digest with given data.
0165     @see rtl_digest_update()
0166  */
0167 rtlDigestError rtl_digest_updateSHA1(rtlDigest Digest, const void * pData, uint nDatLen);
0168 
0169 
0170 /** Finalize a SHA1 digest and retrieve the digest value.
0171     @see rtl_digest_get()
0172  */
0173 rtlDigestError rtl_digest_getSHA1(rtlDigest Digest, sal_uInt8 * pBuffer, uint nBufLen);
0174 
0175 
0176 /** Evaluate a SHA1 digest value from given data.
0177     @details This function performs an optimized call sequence on a
0178  single data buffer, avoiding digest creation and destruction.
0179 
0180  @see rtl_digest_updateSHA1()
0181  @see rtl_digest_getSHA1()
0182 
0183  @param  pData   [in] data buffer.
0184  @param  nDatLen [in] data length.
0185  @param  pBuffer [in] digest value buffer.
0186  @param  nBufLen [in] digest value length.
0187 
0188  @return rtl_Digest_E_None upon success.
0189  */
0190 rtlDigestError rtl_digest_SHA1(const void * pData,      uint nDatLen,
0191                                unsigned char * pBuffer, uint nBufLen);
0192 
0193 
0194 /*========================================================================
0195  *
0196  * rtlDigest internals.
0197  *
0198  *======================================================================*/
0199 
0200 void rtl_zeroMemory(void * Ptr, sal_uInt32 Bytes)
0201 {
0202     memset(Ptr, 0, Bytes);
0203 }
0204 
0205 void rtl_copyMemory(void *Dst, const void *Src, sal_uInt32 Bytes)
0206 {
0207     memcpy(Dst, Src, Bytes);
0208 }
0209 
0210 void rtl_freeMemory(void * p)
0211 {
0212     free(p);
0213 }
0214 
0215 void rtl_freeZeroMemory(void * p, sal_uInt32 n)
0216 {
0217     if (p) {
0218         memset(p, 0, n);
0219         free(p);
0220     }
0221 }
0222 
0223 #define RTL_DIGEST_CREATE(T) ((T*)(malloc(sizeof(T))))
0224 
0225 #define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n))))
0226 
0227 #define RTL_DIGEST_HTONL(l,c) \
0228     (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \
0229      *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
0230      *((c)++) = (sal_uInt8)(((l) >>  8L) & 0xff), \
0231      *((c)++) = (sal_uInt8)(((l)       ) & 0xff))
0232 
0233 #define RTL_DIGEST_LTOC(l,c) \
0234     (*((c)++) = (sal_uInt8)(((l)       ) & 0xff), \
0235      *((c)++) = (sal_uInt8)(((l) >>  8L) & 0xff), \
0236      *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
0237      *((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff))
0238 
0239 typedef struct digest_impl_st {
0240     rtlDigestAlgorithm  m_algorithm;
0241     sal_uInt32          m_length;
0242     Digest_init_t      *m_init;
0243     Digest_delete_t    *m_delete;
0244     Digest_update_t    *m_update;
0245     Digest_get_t       *m_get;
0246 } Digest_Impl;
0247 
0248 /*
0249  * __rtl_digest_swapLong.
0250  */
0251 static void __rtl_digest_swapLong(sal_uInt32 *pData, sal_uInt32 nDatLen)
0252 {
0253     register sal_uInt32 *X;
0254     register int         i, n;
0255 
0256     X = pData;
0257     n = nDatLen;
0258 
0259     for (i = 0; i < n; ++i)
0260         X[i] = OSL_SWAPDWORD(X[i]);
0261 }
0262 
0263 /*========================================================================
0264  *
0265  * rtlDigest implementation.
0266  *
0267  *======================================================================*/
0268 /*
0269  * rtl_digest_create.
0270 
0271 rtlDigest rtl_digest_create (rtlDigestAlgorithm Algorithm)
0272 {
0273  rtlDigest Digest = (rtlDigest)0;
0274  switch (Algorithm)
0275  {
0276   case rtl_Digest_AlgorithmMD2:
0277    Digest = rtl_digest_createMD2();
0278    break;
0279 
0280   case rtl_Digest_AlgorithmMD5:
0281    Digest = rtl_digest_createMD5();
0282    break;
0283 
0284   case rtl_Digest_AlgorithmSHA:
0285    Digest = rtl_digest_createSHA();
0286    break;
0287 
0288   case rtl_Digest_AlgorithmSHA1:
0289    Digest = rtl_digest_createSHA1();
0290    break;
0291 
0292   case rtl_Digest_AlgorithmHMAC_MD5:
0293    Digest = rtl_digest_createHMAC_MD5();
0294    break;
0295 
0296   case rtl_Digest_AlgorithmHMAC_SHA1:
0297    Digest = rtl_digest_createHMAC_SHA1();
0298    break;
0299 
0300                 default: // rtl_Digest_AlgorithmInvalid
0301    break;
0302  }
0303  return Digest;
0304 }
0305 
0306 
0307 // rtl_digest_queryAlgorithm.
0308 
0309 rtlDigestAlgorithm rtl_digest_queryAlgorithm (rtlDigest Digest)
0310 {
0311  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0312  if (pImpl)
0313   return pImpl->m_algorithm;
0314  else
0315   return rtl_Digest_AlgorithmInvalid;
0316 }
0317 
0318  // rtl_digest_queryLength.
0319 sal_uInt32 rtl_digest_queryLength (rtlDigest Digest)
0320 {
0321  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0322  if (pImpl)
0323   return pImpl->m_length;
0324  else
0325   return 0;
0326 }
0327 
0328 // * rtl_digest_init.
0329 rtlDigestError rtl_digest_init (
0330  rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
0331 {
0332  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0333  if (pImpl)
0334  {
0335   if (pImpl->m_init)
0336    return pImpl->m_init (Digest, pData, nDatLen);
0337   else
0338    return rtl_Digest_E_None;
0339  }
0340  return rtl_Digest_E_Argument;
0341 }
0342 
0343 // * rtl_digest_update.
0344 rtlDigestError rtl_digest_update (
0345  rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
0346 {
0347  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0348  if (pImpl && pImpl->m_update)
0349   return pImpl->m_update (Digest, pData, nDatLen);
0350  else
0351   return rtl_Digest_E_Argument;
0352 }
0353 
0354 // * rtl_digest_get.
0355 rtlDigestError rtl_digest_get (
0356  rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
0357 {
0358  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0359  if (pImpl && pImpl->m_get)
0360   return pImpl->m_get (Digest, pBuffer, nBufLen);
0361  else
0362   return rtl_Digest_E_Argument;
0363 }
0364 
0365 // * rtl_digest_destroy.
0366 void rtl_digest_destroy (rtlDigest Digest)
0367 {
0368  Digest_Impl *pImpl = (Digest_Impl *)Digest;
0369  if (pImpl && pImpl->m_delete)
0370   pImpl->m_delete (Digest);
0371 }
0372 */
0373 
0374 /*========================================================================
0375  *
0376  * rtl_digest_(SHA|SHA1) common internals.
0377  *
0378  *======================================================================*/
0379 #define DIGEST_CBLOCK_SHA 64
0380 #define DIGEST_LBLOCK_SHA 16
0381 
0382 typedef sal_uInt32 DigestSHA_update_t (sal_uInt32 x);
0383 
0384 static sal_uInt32 __rtl_digest_updateSHA_1(sal_uInt32 x);
0385 
0386 typedef struct digestSHA_context_st {
0387     DigestSHA_update_t *m_update;
0388     sal_uInt32          m_nDatLen;
0389     sal_uInt32          m_pData[DIGEST_LBLOCK_SHA];
0390     sal_uInt32          m_nA, m_nB, m_nC, m_nD, m_nE;
0391     sal_uInt32          m_nL, m_nH;
0392 } DigestContextSHA;
0393 
0394 typedef struct digestSHA_impl_st {
0395     Digest_Impl      m_digest;
0396     DigestContextSHA m_context;
0397 } DigestSHA_Impl;
0398 
0399 static void __rtl_digest_initSHA(
0400     DigestContextSHA *ctx, DigestSHA_update_t *fct);
0401 
0402 static void __rtl_digest_updateSHA(DigestContextSHA *ctx);
0403 static void __rtl_digest_endSHA(DigestContextSHA *ctx);
0404 
0405 #define K_00_19 (sal_uInt32)0x5a827999L
0406 #define K_20_39 (sal_uInt32)0x6ed9eba1L
0407 #define K_40_59 (sal_uInt32)0x8f1bbcdcL
0408 #define K_60_79 (sal_uInt32)0xca62c1d6L
0409 
0410 #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
0411 #define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
0412 #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
0413 #define F_60_79(b,c,d) F_20_39(b,c,d)
0414 
0415 #define BODY_X(i) \
0416     (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
0417 
0418 #define BODY_00_15(u,i,a,b,c,d,e,f) \
0419     (f)  = X[i]; \
0420     (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
0421     (b)  = RTL_DIGEST_ROTL((b), 30);
0422 
0423 #define BODY_16_19(u,i,a,b,c,d,e,f) \
0424     (f)  = BODY_X((i)); \
0425     (f)  = X[(i)&0x0f] = (u)((f)); \
0426     (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
0427     (b)  = RTL_DIGEST_ROTL((b), 30);
0428 
0429 #define BODY_20_39(u,i,a,b,c,d,e,f) \
0430     (f)  = BODY_X((i)); \
0431     (f)  = X[(i)&0x0f] = (u)((f)); \
0432     (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
0433     (b)  = RTL_DIGEST_ROTL((b), 30);
0434 
0435 #define BODY_40_59(u,i,a,b,c,d,e,f) \
0436     (f)  = BODY_X((i)); \
0437     (f)  = X[(i)&0x0f] = (u)((f)); \
0438     (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
0439     (b)  = RTL_DIGEST_ROTL((b), 30);
0440 
0441 #define BODY_60_79(u,i,a,b,c,d,e,f) \
0442     (f)  = BODY_X((i)); \
0443     (f)  = X[(i)&0x0f] = (u)((f)); \
0444     (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
0445     (b)  = RTL_DIGEST_ROTL((b), 30);
0446 
0447 /*
0448  * __rtl_digest_initSHA.
0449  */
0450 static void __rtl_digest_initSHA(
0451     DigestContextSHA *ctx, DigestSHA_update_t *fct)
0452 {
0453     rtl_zeroMemory(ctx, sizeof(DigestContextSHA));
0454     ctx->m_update = fct;
0455 
0456     ctx->m_nA = (sal_uInt32)0x67452301L;
0457     ctx->m_nB = (sal_uInt32)0xefcdab89L;
0458     ctx->m_nC = (sal_uInt32)0x98badcfeL;
0459     ctx->m_nD = (sal_uInt32)0x10325476L;
0460     ctx->m_nE = (sal_uInt32)0xc3d2e1f0L;
0461 }
0462 
0463 /*
0464  * __rtl_digest_updateSHA.
0465  */
0466 static void __rtl_digest_updateSHA(DigestContextSHA *ctx)
0467 {
0468     register sal_uInt32  A, B, C, D, E, T;
0469     register sal_uInt32 *X;
0470 
0471     register DigestSHA_update_t *U;
0472     U = ctx->m_update;
0473 
0474     A = ctx->m_nA;
0475     B = ctx->m_nB;
0476     C = ctx->m_nC;
0477     D = ctx->m_nD;
0478     E = ctx->m_nE;
0479     X = ctx->m_pData;
0480 
0481     BODY_00_15(U,  0, A, B, C, D, E, T);
0482     BODY_00_15(U,  1, T, A, B, C, D, E);
0483     BODY_00_15(U,  2, E, T, A, B, C, D);
0484     BODY_00_15(U,  3, D, E, T, A, B, C);
0485     BODY_00_15(U,  4, C, D, E, T, A, B);
0486     BODY_00_15(U,  5, B, C, D, E, T, A);
0487     BODY_00_15(U,  6, A, B, C, D, E, T);
0488     BODY_00_15(U,  7, T, A, B, C, D, E);
0489     BODY_00_15(U,  8, E, T, A, B, C, D);
0490     BODY_00_15(U,  9, D, E, T, A, B, C);
0491     BODY_00_15(U, 10, C, D, E, T, A, B);
0492     BODY_00_15(U, 11, B, C, D, E, T, A);
0493     BODY_00_15(U, 12, A, B, C, D, E, T);
0494     BODY_00_15(U, 13, T, A, B, C, D, E);
0495     BODY_00_15(U, 14, E, T, A, B, C, D);
0496     BODY_00_15(U, 15, D, E, T, A, B, C);
0497     BODY_16_19(U, 16, C, D, E, T, A, B);
0498     BODY_16_19(U, 17, B, C, D, E, T, A);
0499     BODY_16_19(U, 18, A, B, C, D, E, T);
0500     BODY_16_19(U, 19, T, A, B, C, D, E);
0501 
0502     BODY_20_39(U, 20, E, T, A, B, C, D);
0503     BODY_20_39(U, 21, D, E, T, A, B, C);
0504     BODY_20_39(U, 22, C, D, E, T, A, B);
0505     BODY_20_39(U, 23, B, C, D, E, T, A);
0506     BODY_20_39(U, 24, A, B, C, D, E, T);
0507     BODY_20_39(U, 25, T, A, B, C, D, E);
0508     BODY_20_39(U, 26, E, T, A, B, C, D);
0509     BODY_20_39(U, 27, D, E, T, A, B, C);
0510     BODY_20_39(U, 28, C, D, E, T, A, B);
0511     BODY_20_39(U, 29, B, C, D, E, T, A);
0512     BODY_20_39(U, 30, A, B, C, D, E, T);
0513     BODY_20_39(U, 31, T, A, B, C, D, E);
0514     BODY_20_39(U, 32, E, T, A, B, C, D);
0515     BODY_20_39(U, 33, D, E, T, A, B, C);
0516     BODY_20_39(U, 34, C, D, E, T, A, B);
0517     BODY_20_39(U, 35, B, C, D, E, T, A);
0518     BODY_20_39(U, 36, A, B, C, D, E, T);
0519     BODY_20_39(U, 37, T, A, B, C, D, E);
0520     BODY_20_39(U, 38, E, T, A, B, C, D);
0521     BODY_20_39(U, 39, D, E, T, A, B, C);
0522 
0523     BODY_40_59(U, 40, C, D, E, T, A, B);
0524     BODY_40_59(U, 41, B, C, D, E, T, A);
0525     BODY_40_59(U, 42, A, B, C, D, E, T);
0526     BODY_40_59(U, 43, T, A, B, C, D, E);
0527     BODY_40_59(U, 44, E, T, A, B, C, D);
0528     BODY_40_59(U, 45, D, E, T, A, B, C);
0529     BODY_40_59(U, 46, C, D, E, T, A, B);
0530     BODY_40_59(U, 47, B, C, D, E, T, A);
0531     BODY_40_59(U, 48, A, B, C, D, E, T);
0532     BODY_40_59(U, 49, T, A, B, C, D, E);
0533     BODY_40_59(U, 50, E, T, A, B, C, D);
0534     BODY_40_59(U, 51, D, E, T, A, B, C);
0535     BODY_40_59(U, 52, C, D, E, T, A, B);
0536     BODY_40_59(U, 53, B, C, D, E, T, A);
0537     BODY_40_59(U, 54, A, B, C, D, E, T);
0538     BODY_40_59(U, 55, T, A, B, C, D, E);
0539     BODY_40_59(U, 56, E, T, A, B, C, D);
0540     BODY_40_59(U, 57, D, E, T, A, B, C);
0541     BODY_40_59(U, 58, C, D, E, T, A, B);
0542     BODY_40_59(U, 59, B, C, D, E, T, A);
0543 
0544     BODY_60_79(U, 60, A, B, C, D, E, T);
0545     BODY_60_79(U, 61, T, A, B, C, D, E);
0546     BODY_60_79(U, 62, E, T, A, B, C, D);
0547     BODY_60_79(U, 63, D, E, T, A, B, C);
0548     BODY_60_79(U, 64, C, D, E, T, A, B);
0549     BODY_60_79(U, 65, B, C, D, E, T, A);
0550     BODY_60_79(U, 66, A, B, C, D, E, T);
0551     BODY_60_79(U, 67, T, A, B, C, D, E);
0552     BODY_60_79(U, 68, E, T, A, B, C, D);
0553     BODY_60_79(U, 69, D, E, T, A, B, C);
0554     BODY_60_79(U, 70, C, D, E, T, A, B);
0555     BODY_60_79(U, 71, B, C, D, E, T, A);
0556     BODY_60_79(U, 72, A, B, C, D, E, T);
0557     BODY_60_79(U, 73, T, A, B, C, D, E);
0558     BODY_60_79(U, 74, E, T, A, B, C, D);
0559     BODY_60_79(U, 75, D, E, T, A, B, C);
0560     BODY_60_79(U, 76, C, D, E, T, A, B);
0561     BODY_60_79(U, 77, B, C, D, E, T, A);
0562     BODY_60_79(U, 78, A, B, C, D, E, T);
0563     BODY_60_79(U, 79, T, A, B, C, D, E);
0564 
0565     ctx->m_nA += E;
0566     ctx->m_nB += T;
0567     ctx->m_nC += A;
0568     ctx->m_nD += B;
0569     ctx->m_nE += C;
0570 }
0571 
0572 /*
0573  * __rtl_digest_endSHA.
0574  */
0575 static void __rtl_digest_endSHA(DigestContextSHA *ctx)
0576 {
0577     static const sal_uInt8 end[4] = {
0578         0x80, 0x00, 0x00, 0x00
0579     };
0580     register const sal_uInt8 *p = end;
0581 
0582     register sal_uInt32 *X;
0583     register int         i;
0584 
0585     X = ctx->m_pData;
0586     i = (ctx->m_nDatLen >> 2);
0587 
0588 #ifdef WORDS_BIGENDIAN
0589     __rtl_digest_swapLong(X, i + 1);
0590 #endif
0591 
0592     switch (ctx->m_nDatLen & 0x03) {
0593     case 1: X[i] &= 0x000000ff; break;
0594     case 2: X[i] &= 0x0000ffff; break;
0595     case 3: X[i] &= 0x00ffffff; break;
0596     }
0597 
0598     switch (ctx->m_nDatLen & 0x03) {
0599     case 0: X[i]  = ((sal_uInt32)(*(p++))) <<  0L;
0600     case 1: X[i] |= ((sal_uInt32)(*(p++))) <<  8L;
0601     case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L;
0602     case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L;
0603     }
0604 
0605     __rtl_digest_swapLong(X, i + 1);
0606 
0607     i += 1;
0608 
0609     if (i >= (DIGEST_LBLOCK_SHA - 2)) {
0610         for (; i < DIGEST_LBLOCK_SHA; ++i)
0611             X[i] = 0;
0612         __rtl_digest_updateSHA(ctx);
0613         i = 0;
0614     }
0615 
0616     for (; i < (DIGEST_LBLOCK_SHA - 2); ++i)
0617         X[i] = 0;
0618 
0619     X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
0620     X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
0621 
0622     __rtl_digest_updateSHA(ctx);
0623 }
0624 
0625 /*========================================================================
0626  *
0627  * rtl_digest_SHA1 internals.
0628  *
0629  *======================================================================*/
0630 /*
0631  * __rtl_digest_SHA_1.
0632  */
0633 static const Digest_Impl __rtl_digest_SHA_1 = { rtl_Digest_AlgorithmSHA1,
0634         RTL_DIGEST_LENGTH_SHA1,
0635         0,
0636         rtl_digest_destroySHA1,
0637         rtl_digest_updateSHA1,
0638         rtl_digest_getSHA1
0639                                               };
0640 
0641 /*
0642  * __rtl_digest_updateSHA_1.
0643  */
0644 static sal_uInt32 __rtl_digest_updateSHA_1(sal_uInt32 x)
0645 {
0646     return RTL_DIGEST_ROTL(x, 1);
0647 }
0648 
0649 /*========================================================================
0650  *
0651  * rtl_digest_SHA1 implementation.
0652  *
0653  *======================================================================*/
0654 /*
0655  * rtl_digest_SHA1.
0656  */
0657 rtlDigestError rtl_digest_SHA1(
0658     const void *pData,   sal_uInt32 nDatLen,
0659     sal_uInt8  *pBuffer, sal_uInt32 nBufLen)
0660 {
0661     DigestSHA_Impl digest;
0662     rtlDigestError result;
0663 
0664     digest.m_digest = __rtl_digest_SHA_1;
0665     __rtl_digest_initSHA(&(digest.m_context), __rtl_digest_updateSHA_1);
0666 
0667     result = rtl_digest_updateSHA1(&digest, pData, nDatLen);
0668     if (result == rtl_Digest_E_None)
0669         result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen);
0670 
0671     rtl_zeroMemory(&digest, sizeof(digest));
0672     return (result);
0673 }
0674 
0675 /*
0676  * rtl_digest_createSHA1.
0677  */
0678 rtlDigest rtl_digest_createSHA1(void)
0679 {
0680     DigestSHA_Impl *pImpl = (DigestSHA_Impl*)0;
0681     pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
0682     if (pImpl) {
0683         pImpl->m_digest = __rtl_digest_SHA_1;
0684         __rtl_digest_initSHA(&(pImpl->m_context), __rtl_digest_updateSHA_1);
0685     }
0686     return ((rtlDigest)pImpl);
0687 }
0688 
0689 /*
0690  * rtl_digest_updateSHA1.
0691  */
0692 rtlDigestError rtl_digest_updateSHA1(
0693     rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
0694 {
0695     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
0696     const sal_uInt8  *d     = (const sal_uInt8 *)pData;
0697 
0698     DigestContextSHA *ctx;
0699     sal_uInt32        len;
0700 
0701     if ((pImpl == 0) || (pData == 0))
0702         return rtl_Digest_E_Argument;
0703 
0704     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
0705         return rtl_Digest_E_Algorithm;
0706 
0707     if (nDatLen == 0)
0708         return rtl_Digest_E_None;
0709 
0710     ctx = &(pImpl->m_context);
0711 
0712     len = ctx->m_nL + (nDatLen << 3);
0713     if (len < ctx->m_nL) ctx->m_nH += 1;
0714     ctx->m_nH += (nDatLen >> 29);
0715     ctx->m_nL  = len;
0716 
0717     if (ctx->m_nDatLen) {
0718         sal_uInt8  *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
0719         sal_uInt32  n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
0720 
0721         if (nDatLen < n) {
0722             rtl_copyMemory(p, d, nDatLen);
0723             ctx->m_nDatLen += nDatLen;
0724 
0725             return rtl_Digest_E_None;
0726         }
0727 
0728         rtl_copyMemory(p, d, n);
0729         d       += n;
0730         nDatLen -= n;
0731 
0732 #ifndef WORDS_BIGENDIAN
0733         __rtl_digest_swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
0734 #endif
0735 
0736         __rtl_digest_updateSHA(ctx);
0737         ctx->m_nDatLen = 0;
0738     }
0739 
0740     while (nDatLen >= DIGEST_CBLOCK_SHA) {
0741         rtl_copyMemory(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
0742         d       += DIGEST_CBLOCK_SHA;
0743         nDatLen -= DIGEST_CBLOCK_SHA;
0744 
0745 #ifndef WORDS_BIGENDIAN
0746         __rtl_digest_swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
0747 #endif
0748 
0749         __rtl_digest_updateSHA(ctx);
0750     }
0751 
0752     rtl_copyMemory(ctx->m_pData, d, nDatLen);
0753     ctx->m_nDatLen = nDatLen;
0754 
0755     return rtl_Digest_E_None;
0756 }
0757 
0758 /*
0759  * rtl_digest_getSHA1.
0760  */
0761 rtlDigestError rtl_digest_getSHA1(
0762     rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
0763 {
0764     DigestSHA_Impl   *pImpl = (DigestSHA_Impl *)Digest;
0765     sal_uInt8        *p     = pBuffer;
0766 
0767     DigestContextSHA *ctx;
0768 
0769     if ((pImpl == 0) || (pBuffer == 0))
0770         return rtl_Digest_E_Argument;
0771 
0772     if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
0773         return rtl_Digest_E_Algorithm;
0774 
0775     if (!(pImpl->m_digest.m_length <= nBufLen))
0776         return rtl_Digest_E_BufferSize;
0777 
0778     ctx = &(pImpl->m_context);
0779 
0780     __rtl_digest_endSHA(ctx);
0781     RTL_DIGEST_HTONL(ctx->m_nA, p);
0782     RTL_DIGEST_HTONL(ctx->m_nB, p);
0783     RTL_DIGEST_HTONL(ctx->m_nC, p);
0784     RTL_DIGEST_HTONL(ctx->m_nD, p);
0785     RTL_DIGEST_HTONL(ctx->m_nE, p);
0786     __rtl_digest_initSHA(ctx, __rtl_digest_updateSHA_1);
0787 
0788     return rtl_Digest_E_None;
0789 }
0790 
0791 /*
0792  * rtl_digest_destroySHA1.
0793  */
0794 void rtl_digest_destroySHA1(rtlDigest Digest)
0795 {
0796     DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
0797     if (pImpl) {
0798         if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
0799             rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
0800         else
0801             rtl_freeMemory(pImpl);
0802     }
0803 }
0804 
0805 /*========================================================================
0806  *
0807  * The End.
0808  *
0809  *======================================================================*/
0810 
0811 bool SHA1::getHash(QString const & text, QByteArray & hash)
0812 {
0813     rtlDigest aDigest     = rtl_digest_createSHA1();
0814     rtlDigestError aError = rtl_digest_updateSHA1(aDigest, text.unicode(), text.length() * sizeof(QChar));
0815 
0816     if (aError == rtl_Digest_E_None) {
0817         QByteArray digest;
0818         digest.resize(RTL_DIGEST_LENGTH_SHA1 + 1);
0819         digest.fill('\0', RTL_DIGEST_LENGTH_SHA1);
0820 
0821         aError = rtl_digest_getSHA1(aDigest, (unsigned char *) digest.data(), RTL_DIGEST_LENGTH_SHA1);
0822 
0823         if (aError != rtl_Digest_E_None)
0824             return false;
0825 
0826         hash = digest;
0827 
0828         return true;
0829     }
0830 
0831     return false;
0832 }