18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
|
#include <string.h>
#import "OFMD5Hash.h"
#import "OFHashAlreadyCalculatedException.h"
/* The four MD5 core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define F(a, b, c) (((a) & (b)) | (~(a) & (c)))
#define G(a, b, c) (((a) & (c)) | ((b) & ~(c)))
#define H(a, b, c) ((a) ^ (b) ^ (c))
#define I(a, b, c) ((b) ^ ((a) | ~(c)))
static const uint32_t sinTable[] = {
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
};
static const uint8_t wordOrder[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
};
static const uint8_t rotateBits[] = {
7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21
};
#ifdef OF_BIG_ENDIAN
static OF_INLINE void
BSWAP32_VEC_IF_BE(uint32_t *buffer, size_t length)
static void
byteSwapVectorIfBE(uint32_t *vector, uint_fast8_t length)
{
while (length--) {
*buffer = OF_BSWAP32(*buffer);
buffer++;
}
uint_fast8_t i;
for (i = 0; i < length; i++)
vector[i] = OF_BSWAP32_IF_BE(vector[i]);
}
#else
# define BSWAP32_VEC_IF_BE(buffer, length)
#endif
static void
md5_transform(uint32_t buffer[4], const uint32_t in[16])
processBlock(uint32_t *state, uint32_t *buffer)
{
register uint32_t a, b, c, d;
uint32_t new[4];
uint_fast8_t i = 0;
a = buffer[0];
b = buffer[1];
c = buffer[2];
d = buffer[3];
new[0] = state[0];
new[1] = state[1];
new[2] = state[2];
new[3] = state[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xD76AA478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xE8C7B756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070DB, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xC1BDCEEE, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xF57C0FAF, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787C62A, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xA8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xFD469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098D8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8B44F7AF, 12);
byteSwapVectorIfBE(buffer, 16);
#define LOOP_BODY(f) \
{ \
const uint_fast8_t a = (4 - (i & 3)) & 3; \
const uint_fast8_t b = (a + 1) & 3; \
const uint_fast8_t c = (a + 2) & 3; \
const uint_fast8_t d = (a + 3) & 3; \
const uint_fast8_t r = rotateBits[(i % 4) + (i / 16) * 4]; \
MD5STEP(F1, c, d, a, b, in[10] + 0xFFFF5BB1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895CD7Be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6B901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xFD987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xA679438e, 17);
\
new[a] += f(new[b], new[c], new[d]) + \
buffer[wordOrder[i]] + sinTable[i]; \
new[a] = OF_ROL(new[a], r); \
new[a] += new[b]; \
MD5STEP(F1, b, c, d, a, in[15] + 0x49B40821, 22);
}
MD5STEP(F2, a, b, c, d, in[1] + 0xF61E2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xC040B340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265E5A51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xE9B6C7AA, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xD62F105D, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xD8A1E681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xE7D3FBC8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21E1CDE6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xC33707D6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xF4D50D87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455A14ED, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xA9E3E905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xFCEFA3F8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676F02D9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8D2A4C8a, 20);
for (; i < 16; i++)
LOOP_BODY(F)
MD5STEP(F3, a, b, c, d, in[5] + 0xFFFA3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771F681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6D9D6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xFDE5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xA4BEEA44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4BDECFA9, 11);
for (; i < 32; i++)
LOOP_BODY(G)
for (; i < 48; i++)
LOOP_BODY(H)
for (; i < 64; i++)
LOOP_BODY(I)
MD5STEP(F3, c, d, a, b, in[7] + 0xF6BB4B60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xBEBFBC70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289B7EC6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xEAA127FA, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xD4EF3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881D05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xD9D4D039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xE6DB99E5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1FA27CF8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xC4AC5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xF4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432AFF97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xAB9423A7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xFC93A039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655B59C3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8F0CCC92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xFFEFF47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845DD1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6FA87E4F, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xFE2CE6E0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xA3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4E0811A1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xF7537E82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xBD3AF235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2AD7D2BB, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xEB86D391, 21);
#undef LOOP_BODY
buffer[0] += a;
buffer[1] += b;
buffer[2] += c;
buffer[3] += d;
state[0] += new[0];
state[1] += new[1];
state[2] += new[2];
state[3] += new[3];
}
@implementation OFMD5Hash
+ (size_t)digestSize
{
return 16;
}
|