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