Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HMD5.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/pig/Humble/HMD5.h 4     2/04/05 10:45a Neusel $
00004 **
00005 ****************************************************************************/
00040 #ifndef HMD5_H
00041     #define HMD5_H
00042 
00077 class HMD5 : public HObj
00078     {
00079     typedef HObj        base_class;
00080     static StringPtr    ClassName(void) { return "HMD5"; }
00081 public:
00082     enum    { 
00083             kInputLen = 64,
00084             kDigestLen = 16,
00085             } bogus;
00086 
00087     typedef uint8       Digest[kDigestLen];
00088 /*  -----------------------------------------------------------------------
00089     VARIABLES
00090     ----------------------------------------------------------------------- */
00091 protected:
00092     Digest              m_digest;           
00093     uint32              m_uBits[2],         
00094                         m_uBuffer[4];       
00095     uint8               m_cInput[kInputLen];
00096 /*  -----------------------------------------------------------------------
00097     CTOR / DTOR
00098     ----------------------------------------------------------------------- */
00099 public:
00100     HMD5(void)
00101         { (void) Start(); }
00102     ~HMD5(void)
00103         { /* EMPTY DTOR */ }
00104 /*  -----------------------------------------------------------------------
00105     METHODS
00106     ----------------------------------------------------------------------- */
00107 public:
00116     static ErrCode
00117     Compute(PtrConst pData, uint32 uBytes, HMD5::Digest & digest)
00118         { 
00119         ErrCode     ec = HError::NoError();
00120         HMD5        md5;
00121             
00122         MEM_ZERO(&digest, sizeof(HMD5::Digest));
00123         
00124         if (md5.Start() == NO_ERROR &&
00125             md5.Update(pData, uBytes) == NO_ERROR &&
00126             md5.Stop() == NO_ERROR)
00127             {
00128             md5.GetDigest(digest);
00129             }
00130         else
00131             ec = ErrCode(HError::GetLastError());
00132         
00133         return ec;
00134         }
00142     static ErrCode
00143     ConvertToDigest(StringPtr pstr, HMD5::Digest & digest)
00144         {
00145         const int32 kDigestStrLen = kDigestLen * 2;
00146         ErrCode     ec = HError::NoError();
00147 
00148         if (STR_LEN(pstr) != kDigestStrLen)
00149             ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00150         else
00151             {       
00152             int32       nByte;
00153             
00154             #define HEX2VAL(c)      int8(((c)>='0'&&(c)<='9')?((c)-'0'):((toupper(c)-'A')+ 10))
00155             
00156             for (nByte = 0; nByte < kDigestLen; ++nByte)
00157                 {
00158                 if (!(isxdigit(pstr[0]) && isxdigit(pstr[1])))
00159                     break;
00160                 
00161                 digest[nByte] = (HEX2VAL(pstr[0]) << 4) + HEX2VAL(pstr[1]);
00162                 pstr += 2;
00163                 }
00164             
00165             if (nByte != kDigestLen)
00166                 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00167 
00168             #undef  HEX2VAL
00169             }
00170 
00171         return ec;
00172         }
00184     static StringPtr
00185     ConvertToString(const HMD5::Digest & digest, const bool bAllCaps = true)
00186         {
00187         const int32 kDigestStrLen = kDigestLen * 2;
00188         static Text szDigest[kDigestStrLen+1];
00189         
00190         int32           nLen = 0;
00191         StringPtr       pstrFormat = (bAllCaps) ? "%02lX" : "%02lx";
00192 
00193         MEM_ZERO(szDigest, sizeof(szDigest));
00194         
00195         for (uint32 ndx = 0; ndx < kDigestLen; ++ndx)
00196             {
00197             ASSERT(nLen < kDigestStrLen);
00198             nLen += STR_SPRINTF(&szDigest[nLen], kDigestStrLen - nLen, 
00199                                 pstrFormat,
00200                                 digest[ndx]);
00201             }
00202         
00203         return szDigest;
00204         }
00210     ErrCode
00211     Start(void)
00212         {
00213         MEM_ZERO(m_digest, sizeof(Digest));
00214 
00215         m_uBits[0] = m_uBits[1] = 0L;
00216         //  Load magic initialization constants.
00217         m_uBuffer[0] = 0x67452301L;
00218         m_uBuffer[1] = 0xEFCDAB89L;
00219         m_uBuffer[2] = 0x98BADCFEL;
00220         m_uBuffer[3] = 0x10325476L;
00221         
00222         return HError::NoError();
00223         }
00232     ErrCode
00233     Stop(void)
00234         {
00235         const uint8 cPadding[] =    {
00236                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00237                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00238                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00239                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00240                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00241                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00242                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00243                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00244                                     };
00245 
00246         ErrCode     ec = HError::NoError();
00247         uint32      uBits,
00248                     uPadding,
00249                     uScratch[16];
00250         
00251         ASSERT( ARRAY_DIM(cPadding) == kInputLen );
00252         
00253         uScratch[14] = m_uBits[0];  // save number of bits
00254         uScratch[15] = m_uBits[1];
00255         uBits = (m_uBits[0] >> 3) & 0x3F;
00256         uPadding = ((uBits < 56) ? 56 : 120) - uBits;   // pad to 56 mod 64
00257         
00258         if ((ec = Update(cPadding, uPadding)) == NO_ERROR)
00259             {
00260             int32       ndx1,
00261                         ndx2;
00262             //
00263             //  Append length in bits and transform
00264             //
00265             for (ndx1 = ndx2 = 0; ndx1 < 14; ndx1++, ndx2 += 4)
00266                 {
00267                 uScratch[ndx1] =    (uint32(m_cInput[ndx2 + 3]) << 24) |
00268                                     (uint32(m_cInput[ndx2 + 2]) << 16) |
00269                                     (uint32(m_cInput[ndx2 + 1]) << 8) |
00270                                      uint32(m_cInput[ndx2]);
00271                 }
00272             
00273             transform(uScratch);
00274             //
00275             //  Now copy the buffer to our digest
00276             //
00277             for (ndx1 = ndx2 = 0; ndx1 < 4; ndx1++, ndx2 += 4)
00278                 {
00279                 m_digest[ndx2]     = uint8(m_uBuffer[ndx1] & 0xFF);
00280                 m_digest[ndx2 + 1] = uint8((m_uBuffer[ndx1] >> 8) & 0xFF);
00281                 m_digest[ndx2 + 2] = uint8((m_uBuffer[ndx1] >> 16) & 0xFF);
00282                 m_digest[ndx2 + 3] = uint8((m_uBuffer[ndx1] >> 24) & 0xFF);
00283                 }
00284             }
00285 
00286         return ec;
00287         }
00299     ErrCode
00300     Update(PtrConst pData, uint32 uBytes)
00301         {
00302         ErrCode         ec = HError::NoError();
00303         PtrDataConst    pc = reinterpret_cast<PtrDataConst>( pData );
00304         
00305         if (GOOD_PTR(pc) && uBytes > 0)
00306             {
00307             int32   ndx1,
00308                     ndx2,
00309                     nBits;
00310             uint32  uScratch[16];
00311             //
00312             //  Compute number of bytes mod 64
00313             //
00314             nBits = int32((m_uBits[0] >> 3) & 0x3F);
00315             if ((m_uBits[0] + (uBytes << 3)) < m_uBits[0])
00316                 m_uBits[1] += 1;    //  update number of bits
00317             
00318             m_uBits[0] += uBytes << 3;
00319             m_uBits[1] += uBytes >> 29;
00320             //
00321             //  Now traverse the data one byte at a time, adding it to the input buffer
00322             //  and transforming it when necessary.
00323             //
00324             while (uBytes--)
00325                 {
00326                 m_cInput[nBits++] = *pc++;
00327                 if (nBits >= kInputLen)
00328                     {
00329                     for (ndx1 = ndx2 = 0; ndx1 < 16; ndx1++, ndx2 += 4)
00330                         {
00331                         uScratch[ndx1] =    (uint32(m_cInput[ndx2 + 3]) << 24) |
00332                                             (uint32(m_cInput[ndx2 + 2]) << 16) |
00333                                             (uint32(m_cInput[ndx2 + 1]) << 8)  |
00334                                              uint32(m_cInput[ndx2]);
00335                         }
00336             
00337                     transform(uScratch);
00338                     nBits = 0;
00339                     }
00340                 }
00341             }
00342         else if (uBytes > 0 && NULL_PTR(pData))
00343             ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00344 
00345         return ec;
00346         }
00347 protected:
00353     void
00354     transform(const uint32 uScratch[])
00355         {
00356         uint32  a = m_uBuffer[0],
00357                 b = m_uBuffer[1],
00358                 c = m_uBuffer[2],
00359                 d = m_uBuffer[3];
00360 
00361         //
00362         //  Rotate the 32-bit value (x) left by (n) bits
00363         //
00364         #define ROTATE_LEFT(x,n)    (((x) << (n)) | ((x) >> (32 - (n))))
00365         /*
00366         **  Round #1
00367         */
00368         #define S11     7
00369         #define S12     12
00370         #define S13     17
00371         #define S14     22
00372 
00373         #define F(x,y,z)        (((x) & (y)) | ((~x) & (z)))
00374         #define FF(a, b, c, d, x, s, ac)    { \
00375             (a) += F((b), (c), (d)) + (x) + uint32(ac); \
00376             (a) = ROTATE_LEFT((a), (s)); \
00377             (a) += (b); }
00378 
00379         FF( a, b, c, d, uScratch[ 0], S11, 0xD76AA478L);    /* 1 */
00380         FF( d, a, b, c, uScratch[ 1], S12, 0xE8C7B756L);    /* 2 */
00381         FF( c, d, a, b, uScratch[ 2], S13, 0x242070DBL);    /* 3 */
00382         FF( b, c, d, a, uScratch[ 3], S14, 0xC1BDCEEEL);    /* 4 */
00383         FF( a, b, c, d, uScratch[ 4], S11, 0xF57C0FAFL);    /* 5 */
00384         FF( d, a, b, c, uScratch[ 5], S12, 0x4787C62AL);    /* 6 */
00385         FF( c, d, a, b, uScratch[ 6], S13, 0xA8304613L);    /* 7 */
00386         FF( b, c, d, a, uScratch[ 7], S14, 0xFD469501L);    /* 8 */
00387         FF( a, b, c, d, uScratch[ 8], S11, 0x698098D8L);    /* 9 */
00388         FF( d, a, b, c, uScratch[ 9], S12, 0x8B44F7AFL);    /* 10 */
00389         FF( c, d, a, b, uScratch[10], S13, 0xFFFF5BB1L);    /* 11 */
00390         FF( b, c, d, a, uScratch[11], S14, 0x895CD7BEL);    /* 12 */
00391         FF( a, b, c, d, uScratch[12], S11, 0x6B901122L);    /* 13 */
00392         FF( d, a, b, c, uScratch[13], S12, 0xFD987193L);    /* 14 */
00393         FF( c, d, a, b, uScratch[14], S13, 0xA679438EL);    /* 15 */
00394         FF( b, c, d, a, uScratch[15], S14, 0x49B40821L);    /* 16 */
00395         /*
00396         **  Round #2
00397         */
00398         #define S21     5
00399         #define S22     9
00400         #define S23     14
00401         #define S24     20
00402 
00403         #define G(x,y,z)        (((x) & (z)) | ((y) & (~z)))
00404         #define GG(a, b, c, d, x, s, ac)    { \
00405             (a) += G((b), (c), (d)) + (x) + uint32(ac); \
00406             (a) = ROTATE_LEFT((a), (s)); \
00407             (a) += (b); }
00408 
00409         GG( a, b, c, d, uScratch[ 1], S21, 0xF61E2562L);    /* 17 */
00410         GG( d, a, b, c, uScratch[ 6], S22, 0xC040B340L);    /* 18 */
00411         GG( c, d, a, b, uScratch[11], S23, 0x265E5A51L);    /* 19 */
00412         GG( b, c, d, a, uScratch[ 0], S24, 0xE9B6C7AAL);    /* 20 */
00413         GG( a, b, c, d, uScratch[ 5], S21, 0xD62F105DL);    /* 21 */
00414         GG( d, a, b, c, uScratch[10], S22, 0x02441453L);    /* 22 */
00415         GG( c, d, a, b, uScratch[15], S23, 0xD8A1E681L);    /* 23 */
00416         GG( b, c, d, a, uScratch[ 4], S24, 0xE7D3FBC8L);    /* 24 */
00417         GG( a, b, c, d, uScratch[ 9], S21, 0x21E1CDE6L);    /* 25 */
00418         GG( d, a, b, c, uScratch[14], S22, 0xC33707D6L);    /* 26 */
00419         GG( c, d, a, b, uScratch[ 3], S23, 0xF4D50D87L);    /* 27 */
00420         GG( b, c, d, a, uScratch[ 8], S24, 0x455A14EDL);    /* 28 */
00421         GG( a, b, c, d, uScratch[13], S21, 0xA9E3E905L);    /* 29 */
00422         GG( d, a, b, c, uScratch[ 2], S22, 0xFCEFA3F8L);    /* 30 */
00423         GG( c, d, a, b, uScratch[ 7], S23, 0x676F02D9L);    /* 31 */
00424         GG( b, c, d, a, uScratch[12], S24, 0x8D2A4C8AL);    /* 32 */
00425         /*
00426         **  Round #3
00427         */
00428         #define S31     4
00429         #define S32     11
00430         #define S33     16
00431         #define S34     23
00432 
00433         #define H(x,y,z)    ((x) ^ (y) ^ (z))
00434         #define HH(a, b, c, d, x, s, ac)    { \
00435             (a) += H((b), (c), (d)) + (x) + uint32(ac); \
00436             (a) = ROTATE_LEFT((a), (s)); \
00437             (a) += (b); }
00438     
00439         HH( a, b, c, d, uScratch[ 5], S31, 0xFFFA3942L);    /* 33 */
00440         HH( d, a, b, c, uScratch[ 8], S32, 0x8771F681L);    /* 34 */
00441         HH( c, d, a, b, uScratch[11], S33, 0x6D9D6122L);    /* 35 */
00442         HH( b, c, d, a, uScratch[14], S34, 0xFDE5380CL);    /* 36 */
00443         HH( a, b, c, d, uScratch[ 1], S31, 0xA4BEEA44L);    /* 37 */
00444         HH( d, a, b, c, uScratch[ 4], S32, 0x4BDECFA9L);    /* 38 */
00445         HH( c, d, a, b, uScratch[ 7], S33, 0xF6BB4B60L);    /* 39 */
00446         HH( b, c, d, a, uScratch[10], S34, 0xBEBFBC70L);    /* 40 */
00447         HH( a, b, c, d, uScratch[13], S31, 0x289B7EC6L);    /* 41 */
00448         HH( d, a, b, c, uScratch[ 0], S32, 0xEAA127FAL);    /* 42 */
00449         HH( c, d, a, b, uScratch[ 3], S33, 0xD4EF3085L);    /* 43 */
00450         HH( b, c, d, a, uScratch[ 6], S34, 0x04881D05L);    /* 44 */
00451         HH( a, b, c, d, uScratch[ 9], S31, 0xD9D4D039L);    /* 45 */
00452         HH( d, a, b, c, uScratch[12], S32, 0xE6DB99E5L);    /* 46 */
00453         HH( c, d, a, b, uScratch[15], S33, 0x1FA27CF8L);    /* 47 */
00454         HH( b, c, d, a, uScratch[ 2], S34, 0xC4AC5665L);    /* 48 */
00455         /*
00456         **  Round #4
00457         */
00458         #define S41     6
00459         #define S42     10
00460         #define S43     15
00461         #define S44     21
00462         #define I(x,y,z)        ((y) ^ ((x) | (~z)))
00463 
00464         #define II(a, b, c, d, x, s, ac)    { \
00465             (a) += I((b), (c), (d)) + (x) + uint32(ac); \
00466             (a) = ROTATE_LEFT((a), (s)); \
00467             (a) += (b); }
00468 
00469             II( a, b, c, d, uScratch[ 0], S41, 0xF4292244L);    /* 49 */
00470         II( d, a, b, c, uScratch[ 7], S42, 0x432AFF97L);    /* 50 */
00471         II( c, d, a, b, uScratch[14], S43, 0xAB9423A7L);    /* 51 */
00472         II( b, c, d, a, uScratch[ 5], S44, 0xFC93A039L);    /* 52 */
00473         II( a, b, c, d, uScratch[12], S41, 0x655B59C3L);    /* 53 */
00474         II( d, a, b, c, uScratch[ 3], S42, 0x8F0CCC92L);    /* 54 */
00475         II( c, d, a, b, uScratch[10], S43, 0xFFEFF47DL);    /* 55 */
00476         II( b, c, d, a, uScratch[ 1], S44, 0x85845DD1L);    /* 56 */
00477         II( a, b, c, d, uScratch[ 8], S41, 0x6FA87E4FL);    /* 57 */
00478         II( d, a, b, c, uScratch[15], S42, 0xFE2CE6E0L);    /* 58 */
00479         II( c, d, a, b, uScratch[ 6], S43, 0xA3014314L);    /* 59 */
00480         II( b, c, d, a, uScratch[13], S44, 0x4E0811A1L);    /* 60 */
00481         II( a, b, c, d, uScratch[ 4], S41, 0xF7537E82L);    /* 61 */
00482         II( d, a, b, c, uScratch[11], S42, 0xBD3AF235L);    /* 62 */
00483         II( c, d, a, b, uScratch[ 2], S43, 0x2AD7D2BBL);    /* 63 */
00484         II( b, c, d, a, uScratch[ 9], S44, 0xEB86D391L);    /* 64 */
00485         
00486         m_uBuffer[0] += a;
00487         m_uBuffer[1] += b;
00488         m_uBuffer[2] += c;
00489         m_uBuffer[3] += d;
00490         }
00491 /*  -----------------------------------------------------------------------
00492     GETTERS & SETTERS
00493     ----------------------------------------------------------------------- */
00494 public:
00499     void                GetDigest(HMD5::Digest & digest) const
00500                             { MEM_COPY(&digest, &m_digest, sizeof(Digest)); }
00511     StringPtr           GetDigestStr(const bool bUppercase = true) const
00512                             { return ConvertToString(m_digest, bUppercase); }
00513 /*  -----------------------------------------------------------------------
00514     INLINES
00515     ----------------------------------------------------------------------- */
00516 public:
00522     inline static int32 Compare(const HMD5::Digest & lhs, const HMD5::Digest & rhs)
00523                             { return MEM_CMP(lhs, rhs, sizeof(Digest)); }
00529     inline static int32 Compare(const HMD5::Digest & digest, StringPtr pstrDigest)
00530                             { return STR_ICMP(pstrDigest, ConvertToString(digest)); }
00531 /*  -----------------------------------------------------------------------
00532     OPERATORS
00533     ----------------------------------------------------------------------- */
00534     bool                operator == (const HMD5 & rhs) const
00535                             { return (Compare(m_digest, rhs.m_digest) == 0); }
00536 
00537     bool                operator != (const HMD5 & rhs) const
00538                             { return (Compare(m_digest, rhs.m_digest) != 0); }
00539     };
00540 
00541 #endif  // HMD5_H
00542 /****************************************************************************
00543 **
00544 **  $History: HMD5.h $
00545  * 
00546  * *****************  Version 4  *****************
00547  * User: Neusel       Date: 2/04/05    Time: 10:45a
00548  * Updated in $/SkyOS.root/pig/Humble
00549  * 
00550  * *****************  Version 3  *****************
00551  * User: Neusel       Date: 12/23/04   Time: 3:50p
00552  * Updated in $/SkyOS.root/pig/Humble
00553  * 
00554  * *****************  Version 2  *****************
00555  * User: Neusel       Date: 12/08/04   Time: 5:06p
00556  * Updated in $/SkyOS.root/pig/Humble
00557  * 20041208
00558  * 
00559  * *****************  Version 1  *****************
00560  * User: Neusel       Date: 11/23/04   Time: 8:24a
00561  * Created in $/SkyOS.root/pig/Humble
00562 **
00563 **  -------------------------------------------------------------------------
00564 **
00565 **  End of HMD5.h
00566 **
00567 ****************************************************************************/