This library implements some hash and cryptographic algorithms.

Dependents:   mBuinoBlinky PB_Emma_Ethernet SLOTrashHTTP Garagem ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MD5.cpp Source File

MD5.cpp

00001 /**
00002     Implementation of MD5 as described here:
00003     http://tools.ietf.org/html/rfc1321
00004 */
00005 
00006 #include "MD5.h"
00007 #include <string.h>
00008 
00009 static const uint32_t A = 0x67452301;
00010 static const uint32_t B = 0xefcdab89;
00011 static const uint32_t C = 0x98badcfe;
00012 static const uint32_t D = 0x10325476;
00013 
00014 
00015 #define F(X,Y,Z) (((X) & (Y)) | ((~(X)) & (Z)))
00016 #define G(X,Y,Z) (((X) & (Z)) | ((Y) & (~(Z))))
00017 #define H(X,Y,Z) ((X) ^ (Y) ^ (Z))
00018 #define I(X,Y,Z) ((Y) ^ ((X) | (~(Z))))
00019 
00020 #define ROTL(W,N) (((W) << N) | ((W) >> (32-N)))
00021 
00022 #define ROUND1(a,b,c,d,x,s,t) \
00023     a = ROTL(a + F(b,c,d) + x + t,s) + b; 
00024 
00025 #define ROUND2(a,b,c,d,x,s,t) \
00026     a = ROTL(a + G(b,c,d) + x + t,s) + b; 
00027 
00028 #define ROUND3(a,b,c,d,x,s,t) \
00029     a = ROTL(a + H(b,c,d) + x + t,s) + b; 
00030 
00031 #define ROUND4(a,b,c,d,x,s,t) \
00032     a = ROTL(a + I(b,c,d) + x + t,s) + b; 
00033 
00034 
00035     
00036 MD5::MD5():
00037 HashAlgorithm(),
00038 a(A),
00039 b(B),
00040 c(C),
00041 d(D),
00042 totalBufferLength(0),
00043 buffer(),
00044 bufferLength(0)
00045 {
00046 }
00047 
00048 uint8_t MD5::outputSize() const
00049 {
00050     return 16;
00051 }
00052 
00053 void MD5::update(uint8_t *data, uint32_t length)
00054 {
00055     if((int)length < 64-bufferLength)
00056     {
00057         memcpy(&buffer[bufferLength], data, length);
00058         bufferLength += length;
00059         totalBufferLength += length;
00060         return;
00061     }
00062     int offset = 64-bufferLength;
00063     memcpy(&buffer[bufferLength], data, offset);
00064     computeRounds(&a, &b, &c, &d, buffer);
00065     while(length-offset > 64)
00066     {
00067         memcpy(buffer, &data[offset], 64);
00068         computeRounds(&a, &b, &c, &d, buffer);
00069         offset += 64;
00070     }
00071     if(offset > (int)length)
00072         offset -= 64;
00073     bufferLength = length - offset;
00074     memcpy(buffer, &data[offset], bufferLength);
00075     totalBufferLength += length;
00076 }
00077 
00078 void MD5::finalize(uint8_t *hash)
00079 {
00080     uint32_t *hash2 = (uint32_t*)hash;
00081     uint16_t padding;
00082     if(totalBufferLength % 64 < 56)
00083         padding = 56 - (totalBufferLength % 64);
00084     else
00085         padding = 56 + (64 - (totalBufferLength % 64));
00086     buffer[bufferLength++] = 0x80;
00087     padding--;
00088     if(padding+bufferLength == 56)
00089         memset(&buffer[bufferLength], 0, padding);
00090     else
00091     {
00092         memset(&buffer[bufferLength], 0, 64-bufferLength);
00093         computeRounds(&a, &b, &c, &d, buffer);
00094         memset(buffer, 0, 56);
00095     }
00096     uint64_t lengthBit = totalBufferLength << 3;
00097     uint32_t lengthBitLow = lengthBit;
00098     uint32_t lengthBitHigh = lengthBit >> 32;
00099     memcpy(&buffer[56], &lengthBitLow, 4);
00100     memcpy(&buffer[60], &lengthBitHigh, 4);
00101     computeRounds(&a, &b, &c, &d, buffer);
00102 
00103     hash2[0] = a;
00104     hash2[1] = b;
00105     hash2[2] = c;
00106     hash2[3] = d;
00107     // reset state
00108     a = A;
00109     b = B;
00110     c = C;
00111     d = D;
00112     totalBufferLength = 0;
00113     bufferLength = 0;
00114 }
00115 
00116 
00117 void MD5::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
00118 {
00119     uint32_t *hash2 = (uint32_t*)hash;
00120     uint64_t lengthBit = length << 3;
00121     uint32_t padding;
00122     if(length % 64 < 56)
00123         padding = 56 - (length % 64);
00124     else
00125         padding = 56 + (64 - (length % 64));
00126         
00127     uint32_t a = A, b = B, c = C, d = D;
00128     while(length >= 64)
00129     {
00130         computeRounds(&a, &b, &c, &d, data);
00131         data += 64;
00132         length -= 64;
00133     }
00134     uint8_t buffer[64];
00135     memcpy(buffer, data, length);
00136     buffer[length++] = 0x80;
00137     padding--;
00138     if(padding+length == 56)
00139         memset(&buffer[length], 0, padding);
00140     else
00141     {
00142         memset(&buffer[length], 0, 64-length);
00143         computeRounds(&a, &b, &c, &d, data);
00144         memset(buffer, 0, 56);
00145     }
00146 
00147     uint32_t lengthBitLow = lengthBit;
00148     uint32_t lengthBitHigh = lengthBit >> 32;
00149     memcpy(&buffer[56], &lengthBitLow, 4);
00150     memcpy(&buffer[60], &lengthBitHigh, 4);
00151     
00152     computeRounds(&a, &b, &c, &d, buffer);
00153     
00154     hash2[0] = a;
00155     hash2[1] = b;
00156     hash2[2] = c;
00157     hash2[3] = d;
00158 }
00159 
00160 
00161 
00162 #ifdef __CC_ARM
00163 __forceinline 
00164 #endif
00165 void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
00166 {
00167     uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
00168     uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
00169 
00170     uint32_t *x = (uint32_t*)buffer;
00171        
00172     // Round 1
00173     ROUND1(a,b,c,d,x[0],7,0xd76aa478);     ROUND1(d,a,b,c,x[1],12,0xe8c7b756);    ROUND1(c,d,a,b,x[2],17,0x242070db);    ROUND1(b,c,d,a,x[3],22,0xc1bdceee);
00174     ROUND1(a,b,c,d,x[4],7,0xf57c0faf);     ROUND1(d,a,b,c,x[5],12,0x4787c62a);    ROUND1(c,d,a,b,x[6],17,0xa8304613);    ROUND1(b,c,d,a,x[7],22,0xfd469501);
00175     ROUND1(a,b,c,d,x[8],7,0x698098d8);     ROUND1(d,a,b,c,x[9],12,0x8b44f7af);    ROUND1(c,d,a,b,x[10],17,0xffff5bb1);   ROUND1(b,c,d,a,x[11],22,0x895cd7be);
00176     ROUND1(a,b,c,d,x[12],7,0x6b901122);    ROUND1(d,a,b,c,x[13],12,0xfd987193);   ROUND1(c,d,a,b,x[14],17,0xa679438e);   ROUND1(b,c,d,a,x[15],22,0x49b40821);
00177 
00178 
00179     // Round 2      
00180     ROUND2(a,b,c,d,x[1],5,0xf61e2562);     ROUND2(d,a,b,c,x[6],9,0xc040b340);     ROUND2(c,d,a,b,x[11],14,0x265e5a51);   ROUND2(b,c,d,a,x[0],20,0xe9b6c7aa);
00181     ROUND2(a,b,c,d,x[5],5,0xd62f105d);     ROUND2(d,a,b,c,x[10],9,0x02441453);    ROUND2(c,d,a,b,x[15],14,0xd8a1e681);   ROUND2(b,c,d,a,x[4],20,0xe7d3fbc8);
00182     ROUND2(a,b,c,d,x[9],5,0x21e1cde6);     ROUND2(d,a,b,c,x[14],9,0xc33707d6);    ROUND2(c,d,a,b,x[3],14,0xf4d50d87);    ROUND2(b,c,d,a,x[8],20,0x455a14ed);
00183     ROUND2(a,b,c,d,x[13],5,0xa9e3e905);    ROUND2(d,a,b,c,x[2],9,0xfcefa3f8);     ROUND2(c,d,a,b,x[7],14,0x676f02d9);    ROUND2(b,c,d,a,x[12],20,0x8d2a4c8a);
00184     
00185 
00186     // Round 3      
00187     ROUND3(a,b,c,d,x[5],4,0xfffa3942);     ROUND3(d,a,b,c,x[8],11,0x8771f681);    ROUND3(c,d,a,b,x[11],16,0x6d9d6122);   ROUND3(b,c,d,a,x[14],23,0xfde5380c);
00188     ROUND3(a,b,c,d,x[1],4,0xa4beea44);     ROUND3(d,a,b,c,x[4],11,0x4bdecfa9);    ROUND3(c,d,a,b,x[7],16,0xf6bb4b60);    ROUND3(b,c,d,a,x[10],23,0xbebfbc70);
00189     ROUND3(a,b,c,d,x[13],4,0x289b7ec6);    ROUND3(d,a,b,c,x[0],11,0xeaa127fa);    ROUND3(c,d,a,b,x[3],16,0xd4ef3085);    ROUND3(b,c,d,a,x[6],23,0x04881d05);
00190     ROUND3(a,b,c,d,x[9],4,0xd9d4d039);     ROUND3(d,a,b,c,x[12],11,0xe6db99e5);   ROUND3(c,d,a,b,x[15],16,0x1fa27cf8);   ROUND3(b,c,d,a,x[2],23,0xc4ac5665);
00191  
00192  
00193     // Round 4
00194     ROUND4(a,b,c,d,x[0],6,0xf4292244);     ROUND4(d,a,b,c,x[7],10,0x432aff97);    ROUND4(c,d,a,b,x[14],15,0xab9423a7);   ROUND4(b,c,d,a,x[5],21,0xfc93a039);
00195     ROUND4(a,b,c,d,x[12],6,0x655b59c3);    ROUND4(d,a,b,c,x[3],10,0x8f0ccc92);    ROUND4(c,d,a,b,x[10],15,0xffeff47d);   ROUND4(b,c,d,a,x[1],21,0x85845dd1);
00196     ROUND4(a,b,c,d,x[8],6,0x6fa87e4f);     ROUND4(d,a,b,c,x[15],10,0xfe2ce6e0);   ROUND4(c,d,a,b,x[6],15,0xa3014314);    ROUND4(b,c,d,a,x[13],21,0x4e0811a1);
00197     ROUND4(a,b,c,d,x[4],6,0xf7537e82);     ROUND4(d,a,b,c,x[11],10,0xbd3af235);   ROUND4(c,d,a,b,x[2],15,0x2ad7d2bb);    ROUND4(b,c,d,a,x[9],21,0xeb86d391);
00198     
00199     *a2 = a + tmpA;
00200     *b2 = b + tmpB;
00201     *c2 = c + tmpC;
00202     *d2 = d + tmpD;
00203 }