Embedded systems coursework 2.
Fork of Crypto_light by
hash/MD5.cpp@13:ac8e23b98dae, 2014-05-11 (annotated)
- Committer:
- feb11
- Date:
- Sun May 11 11:14:51 2014 +0000
- Revision:
- 13:ac8e23b98dae
- Parent:
- 10:bc9c23aa3870
fixed warnings + fixed errors if compiling with gcc arm compiler
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
feb11 | 4:0da19393bd57 | 1 | /** |
feb11 | 4:0da19393bd57 | 2 | Implementation of MD5 as described here: |
feb11 | 4:0da19393bd57 | 3 | http://tools.ietf.org/html/rfc1321 |
feb11 | 4:0da19393bd57 | 4 | */ |
feb11 | 4:0da19393bd57 | 5 | |
feb11 | 0:7a1237bd2d13 | 6 | #include "MD5.h" |
feb11 | 0:7a1237bd2d13 | 7 | #include <string.h> |
feb11 | 0:7a1237bd2d13 | 8 | |
feb11 | 0:7a1237bd2d13 | 9 | static const uint32_t A = 0x67452301; |
feb11 | 0:7a1237bd2d13 | 10 | static const uint32_t B = 0xefcdab89; |
feb11 | 0:7a1237bd2d13 | 11 | static const uint32_t C = 0x98badcfe; |
feb11 | 0:7a1237bd2d13 | 12 | static const uint32_t D = 0x10325476; |
feb11 | 0:7a1237bd2d13 | 13 | |
feb11 | 0:7a1237bd2d13 | 14 | |
feb11 | 3:85c6ee25cf3e | 15 | #define F(X,Y,Z) (((X) & (Y)) | ((~(X)) & (Z))) |
feb11 | 3:85c6ee25cf3e | 16 | #define G(X,Y,Z) (((X) & (Z)) | ((Y) & (~(Z)))) |
feb11 | 3:85c6ee25cf3e | 17 | #define H(X,Y,Z) ((X) ^ (Y) ^ (Z)) |
feb11 | 3:85c6ee25cf3e | 18 | #define I(X,Y,Z) ((Y) ^ ((X) | (~(Z)))) |
feb11 | 0:7a1237bd2d13 | 19 | |
feb11 | 3:85c6ee25cf3e | 20 | #define ROTL(W,N) (((W) << N) | ((W) >> (32-N))) |
feb11 | 0:7a1237bd2d13 | 21 | |
feb11 | 3:85c6ee25cf3e | 22 | #define ROUND1(a,b,c,d,x,s,t) \ |
feb11 | 3:85c6ee25cf3e | 23 | a = ROTL(a + F(b,c,d) + x + t,s) + b; |
feb11 | 3:85c6ee25cf3e | 24 | |
feb11 | 3:85c6ee25cf3e | 25 | #define ROUND2(a,b,c,d,x,s,t) \ |
feb11 | 3:85c6ee25cf3e | 26 | a = ROTL(a + G(b,c,d) + x + t,s) + b; |
feb11 | 0:7a1237bd2d13 | 27 | |
feb11 | 3:85c6ee25cf3e | 28 | #define ROUND3(a,b,c,d,x,s,t) \ |
feb11 | 3:85c6ee25cf3e | 29 | a = ROTL(a + H(b,c,d) + x + t,s) + b; |
feb11 | 3:85c6ee25cf3e | 30 | |
feb11 | 3:85c6ee25cf3e | 31 | #define ROUND4(a,b,c,d,x,s,t) \ |
feb11 | 3:85c6ee25cf3e | 32 | a = ROTL(a + I(b,c,d) + x + t,s) + b; |
feb11 | 3:85c6ee25cf3e | 33 | |
feb11 | 0:7a1237bd2d13 | 34 | |
feb11 | 0:7a1237bd2d13 | 35 | |
feb11 | 0:7a1237bd2d13 | 36 | MD5::MD5(): |
feb11 | 0:7a1237bd2d13 | 37 | HashAlgorithm(), |
feb11 | 0:7a1237bd2d13 | 38 | a(A), |
feb11 | 0:7a1237bd2d13 | 39 | b(B), |
feb11 | 0:7a1237bd2d13 | 40 | c(C), |
feb11 | 0:7a1237bd2d13 | 41 | d(D), |
feb11 | 0:7a1237bd2d13 | 42 | totalBufferLength(0), |
feb11 | 0:7a1237bd2d13 | 43 | buffer(), |
feb11 | 0:7a1237bd2d13 | 44 | bufferLength(0) |
feb11 | 0:7a1237bd2d13 | 45 | { |
feb11 | 0:7a1237bd2d13 | 46 | } |
feb11 | 0:7a1237bd2d13 | 47 | |
feb11 | 0:7a1237bd2d13 | 48 | uint8_t MD5::outputSize() const |
feb11 | 0:7a1237bd2d13 | 49 | { |
feb11 | 0:7a1237bd2d13 | 50 | return 16; |
feb11 | 0:7a1237bd2d13 | 51 | } |
feb11 | 0:7a1237bd2d13 | 52 | |
feb11 | 6:19aa835f2bbb | 53 | void MD5::update(uint8_t *data, uint32_t length) |
feb11 | 0:7a1237bd2d13 | 54 | { |
feb11 | 13:ac8e23b98dae | 55 | if((int)length < 64-bufferLength) |
feb11 | 0:7a1237bd2d13 | 56 | { |
feb11 | 6:19aa835f2bbb | 57 | memcpy(&buffer[bufferLength], data, length); |
feb11 | 0:7a1237bd2d13 | 58 | bufferLength += length; |
feb11 | 0:7a1237bd2d13 | 59 | totalBufferLength += length; |
feb11 | 0:7a1237bd2d13 | 60 | return; |
feb11 | 0:7a1237bd2d13 | 61 | } |
feb11 | 0:7a1237bd2d13 | 62 | int offset = 64-bufferLength; |
feb11 | 6:19aa835f2bbb | 63 | memcpy(&buffer[bufferLength], data, offset); |
feb11 | 0:7a1237bd2d13 | 64 | computeRounds(&a, &b, &c, &d, buffer); |
feb11 | 0:7a1237bd2d13 | 65 | while(length-offset > 64) |
feb11 | 0:7a1237bd2d13 | 66 | { |
feb11 | 6:19aa835f2bbb | 67 | memcpy(buffer, &data[offset], 64); |
feb11 | 0:7a1237bd2d13 | 68 | computeRounds(&a, &b, &c, &d, buffer); |
feb11 | 0:7a1237bd2d13 | 69 | offset += 64; |
feb11 | 0:7a1237bd2d13 | 70 | } |
feb11 | 13:ac8e23b98dae | 71 | if(offset > (int)length) |
feb11 | 0:7a1237bd2d13 | 72 | offset -= 64; |
feb11 | 0:7a1237bd2d13 | 73 | bufferLength = length - offset; |
feb11 | 6:19aa835f2bbb | 74 | memcpy(buffer, &data[offset], bufferLength); |
feb11 | 0:7a1237bd2d13 | 75 | totalBufferLength += length; |
feb11 | 0:7a1237bd2d13 | 76 | } |
feb11 | 0:7a1237bd2d13 | 77 | |
feb11 | 6:19aa835f2bbb | 78 | void MD5::finalize(uint8_t *hash) |
feb11 | 0:7a1237bd2d13 | 79 | { |
feb11 | 6:19aa835f2bbb | 80 | uint32_t *hash2 = (uint32_t*)hash; |
feb11 | 0:7a1237bd2d13 | 81 | uint16_t padding; |
feb11 | 0:7a1237bd2d13 | 82 | if(totalBufferLength % 64 < 56) |
feb11 | 0:7a1237bd2d13 | 83 | padding = 56 - (totalBufferLength % 64); |
feb11 | 0:7a1237bd2d13 | 84 | else |
feb11 | 0:7a1237bd2d13 | 85 | padding = 56 + (64 - (totalBufferLength % 64)); |
feb11 | 3:85c6ee25cf3e | 86 | buffer[bufferLength++] = 0x80; |
feb11 | 3:85c6ee25cf3e | 87 | padding--; |
feb11 | 3:85c6ee25cf3e | 88 | if(padding+bufferLength == 56) |
feb11 | 3:85c6ee25cf3e | 89 | memset(&buffer[bufferLength], 0, padding); |
feb11 | 3:85c6ee25cf3e | 90 | else |
feb11 | 3:85c6ee25cf3e | 91 | { |
feb11 | 3:85c6ee25cf3e | 92 | memset(&buffer[bufferLength], 0, 64-bufferLength); |
feb11 | 3:85c6ee25cf3e | 93 | computeRounds(&a, &b, &c, &d, buffer); |
feb11 | 5:06cd9c8afa0b | 94 | memset(buffer, 0, 56); |
feb11 | 3:85c6ee25cf3e | 95 | } |
feb11 | 3:85c6ee25cf3e | 96 | uint64_t lengthBit = totalBufferLength << 3; |
feb11 | 0:7a1237bd2d13 | 97 | uint32_t lengthBitLow = lengthBit; |
feb11 | 0:7a1237bd2d13 | 98 | uint32_t lengthBitHigh = lengthBit >> 32; |
feb11 | 3:85c6ee25cf3e | 99 | memcpy(&buffer[56], &lengthBitLow, 4); |
feb11 | 3:85c6ee25cf3e | 100 | memcpy(&buffer[60], &lengthBitHigh, 4); |
feb11 | 3:85c6ee25cf3e | 101 | computeRounds(&a, &b, &c, &d, buffer); |
feb11 | 0:7a1237bd2d13 | 102 | |
feb11 | 6:19aa835f2bbb | 103 | hash2[0] = a; |
feb11 | 6:19aa835f2bbb | 104 | hash2[1] = b; |
feb11 | 6:19aa835f2bbb | 105 | hash2[2] = c; |
feb11 | 6:19aa835f2bbb | 106 | hash2[3] = d; |
feb11 | 0:7a1237bd2d13 | 107 | // reset state |
feb11 | 0:7a1237bd2d13 | 108 | a = A; |
feb11 | 0:7a1237bd2d13 | 109 | b = B; |
feb11 | 0:7a1237bd2d13 | 110 | c = C; |
feb11 | 0:7a1237bd2d13 | 111 | d = D; |
feb11 | 0:7a1237bd2d13 | 112 | totalBufferLength = 0; |
feb11 | 0:7a1237bd2d13 | 113 | bufferLength = 0; |
feb11 | 0:7a1237bd2d13 | 114 | } |
feb11 | 0:7a1237bd2d13 | 115 | |
feb11 | 6:19aa835f2bbb | 116 | |
feb11 | 6:19aa835f2bbb | 117 | void MD5::computeHash(uint8_t *hash, uint8_t *data, uint32_t length) |
feb11 | 6:19aa835f2bbb | 118 | { |
feb11 | 6:19aa835f2bbb | 119 | uint32_t *hash2 = (uint32_t*)hash; |
feb11 | 6:19aa835f2bbb | 120 | uint64_t lengthBit = length << 3; |
feb11 | 10:bc9c23aa3870 | 121 | uint32_t padding; |
feb11 | 6:19aa835f2bbb | 122 | if(length % 64 < 56) |
feb11 | 6:19aa835f2bbb | 123 | padding = 56 - (length % 64); |
feb11 | 6:19aa835f2bbb | 124 | else |
feb11 | 6:19aa835f2bbb | 125 | padding = 56 + (64 - (length % 64)); |
feb11 | 6:19aa835f2bbb | 126 | |
feb11 | 6:19aa835f2bbb | 127 | uint32_t a = A, b = B, c = C, d = D; |
feb11 | 6:19aa835f2bbb | 128 | while(length >= 64) |
feb11 | 6:19aa835f2bbb | 129 | { |
feb11 | 6:19aa835f2bbb | 130 | computeRounds(&a, &b, &c, &d, data); |
feb11 | 6:19aa835f2bbb | 131 | data += 64; |
feb11 | 6:19aa835f2bbb | 132 | length -= 64; |
feb11 | 6:19aa835f2bbb | 133 | } |
feb11 | 6:19aa835f2bbb | 134 | uint8_t buffer[64]; |
feb11 | 6:19aa835f2bbb | 135 | memcpy(buffer, data, length); |
feb11 | 6:19aa835f2bbb | 136 | buffer[length++] = 0x80; |
feb11 | 6:19aa835f2bbb | 137 | padding--; |
feb11 | 6:19aa835f2bbb | 138 | if(padding+length == 56) |
feb11 | 6:19aa835f2bbb | 139 | memset(&buffer[length], 0, padding); |
feb11 | 6:19aa835f2bbb | 140 | else |
feb11 | 6:19aa835f2bbb | 141 | { |
feb11 | 6:19aa835f2bbb | 142 | memset(&buffer[length], 0, 64-length); |
feb11 | 6:19aa835f2bbb | 143 | computeRounds(&a, &b, &c, &d, data); |
feb11 | 6:19aa835f2bbb | 144 | memset(buffer, 0, 56); |
feb11 | 6:19aa835f2bbb | 145 | } |
feb11 | 6:19aa835f2bbb | 146 | |
feb11 | 6:19aa835f2bbb | 147 | uint32_t lengthBitLow = lengthBit; |
feb11 | 6:19aa835f2bbb | 148 | uint32_t lengthBitHigh = lengthBit >> 32; |
feb11 | 6:19aa835f2bbb | 149 | memcpy(&buffer[56], &lengthBitLow, 4); |
feb11 | 6:19aa835f2bbb | 150 | memcpy(&buffer[60], &lengthBitHigh, 4); |
feb11 | 6:19aa835f2bbb | 151 | |
feb11 | 6:19aa835f2bbb | 152 | computeRounds(&a, &b, &c, &d, buffer); |
feb11 | 6:19aa835f2bbb | 153 | |
feb11 | 6:19aa835f2bbb | 154 | hash2[0] = a; |
feb11 | 6:19aa835f2bbb | 155 | hash2[1] = b; |
feb11 | 6:19aa835f2bbb | 156 | hash2[2] = c; |
feb11 | 6:19aa835f2bbb | 157 | hash2[3] = d; |
feb11 | 6:19aa835f2bbb | 158 | } |
feb11 | 6:19aa835f2bbb | 159 | |
feb11 | 13:ac8e23b98dae | 160 | |
feb11 | 13:ac8e23b98dae | 161 | |
feb11 | 13:ac8e23b98dae | 162 | #ifdef __CC_ARM |
feb11 | 13:ac8e23b98dae | 163 | __forceinline |
feb11 | 13:ac8e23b98dae | 164 | #endif |
feb11 | 13:ac8e23b98dae | 165 | void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer) |
feb11 | 0:7a1237bd2d13 | 166 | { |
feb11 | 0:7a1237bd2d13 | 167 | uint32_t a = *a2, b = *b2, c = *c2, d = *d2; |
feb11 | 1:14a7cea431aa | 168 | uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d; |
feb11 | 1:14a7cea431aa | 169 | |
feb11 | 3:85c6ee25cf3e | 170 | uint32_t *x = (uint32_t*)buffer; |
feb11 | 3:85c6ee25cf3e | 171 | |
feb11 | 0:7a1237bd2d13 | 172 | // Round 1 |
feb11 | 3:85c6ee25cf3e | 173 | 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); |
feb11 | 3:85c6ee25cf3e | 174 | 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); |
feb11 | 3:85c6ee25cf3e | 175 | 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); |
feb11 | 3:85c6ee25cf3e | 176 | 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); |
feb11 | 3:85c6ee25cf3e | 177 | |
feb11 | 3:85c6ee25cf3e | 178 | |
feb11 | 0:7a1237bd2d13 | 179 | // Round 2 |
feb11 | 3:85c6ee25cf3e | 180 | 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); |
feb11 | 3:85c6ee25cf3e | 181 | 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); |
feb11 | 3:85c6ee25cf3e | 182 | 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); |
feb11 | 3:85c6ee25cf3e | 183 | 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); |
feb11 | 0:7a1237bd2d13 | 184 | |
feb11 | 3:85c6ee25cf3e | 185 | |
feb11 | 0:7a1237bd2d13 | 186 | // Round 3 |
feb11 | 3:85c6ee25cf3e | 187 | 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); |
feb11 | 3:85c6ee25cf3e | 188 | 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); |
feb11 | 3:85c6ee25cf3e | 189 | 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); |
feb11 | 3:85c6ee25cf3e | 190 | 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); |
feb11 | 3:85c6ee25cf3e | 191 | |
feb11 | 3:85c6ee25cf3e | 192 | |
feb11 | 0:7a1237bd2d13 | 193 | // Round 4 |
feb11 | 3:85c6ee25cf3e | 194 | 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); |
feb11 | 3:85c6ee25cf3e | 195 | 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); |
feb11 | 3:85c6ee25cf3e | 196 | 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); |
feb11 | 3:85c6ee25cf3e | 197 | 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); |
feb11 | 3:85c6ee25cf3e | 198 | |
feb11 | 3:85c6ee25cf3e | 199 | *a2 = a + tmpA; |
feb11 | 3:85c6ee25cf3e | 200 | *b2 = b + tmpB; |
feb11 | 3:85c6ee25cf3e | 201 | *c2 = c + tmpC; |
feb11 | 3:85c6ee25cf3e | 202 | *d2 = d + tmpD; |
feb11 | 13:ac8e23b98dae | 203 | } |