-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathMd5.c
206 lines (181 loc) · 5.96 KB
/
Md5.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/* Md5.c -- MD5 Hash
: Igor Pavlov : Public domain
This code is based on Colin Plumb's public domain md5.c code */
#include "Precomp.h"
#include <string.h>
#include "Md5.h"
#include "RotateDefs.h"
#include "CpuArch.h"
#define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks
Z7_NO_INLINE
void Md5_Init(CMd5 *p)
{
p->count = 0;
p->state[0] = 0x67452301;
p->state[1] = 0xefcdab89;
p->state[2] = 0x98badcfe;
p->state[3] = 0x10325476;
}
#if 0 && !defined(MY_CPU_LE_UNALIGN)
// optional optimization for Big-endian processors or processors without unaligned access:
// it is intended to reduce the number of complex LE32 memory reading from 64 to 16.
// But some compilers (sparc, armt) are better without this optimization.
#define Z7_MD5_USE_DATA32_ARRAY
#endif
#define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i))
#ifdef Z7_MD5_USE_DATA32_ARRAY
#define D(i) data32[i]
#else
#define D(i) LOAD_DATA(i)
#endif
#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 R1(i, f, start, step, w, x, y, z, s, k) \
w += D((start + step * (i)) % 16) + k; \
w += f(x, y, z); \
w = rotlFixed(w, s) + x; \
#define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \
R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \
R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \
R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \
R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \
#define R16(f, start, step, s0,s1,s2,s3, k00,k01,k02,k03, k10,k11,k12,k13, k20,k21,k22,k23, k30,k31,k32,k33) \
R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \
R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \
R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \
R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \
static
Z7_NO_INLINE
void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks)
{
UInt32 a, b, c, d;
// if (numBlocks == 0) return;
a = state[0];
b = state[1];
c = state[2];
d = state[3];
do
{
#ifdef Z7_MD5_USE_DATA32_ARRAY
UInt32 data32[MD5_NUM_BLOCK_WORDS];
{
#define LOAD_data32_x4(i) { \
data32[i ] = LOAD_DATA(i ); \
data32[i + 1] = LOAD_DATA(i + 1); \
data32[i + 2] = LOAD_DATA(i + 2); \
data32[i + 3] = LOAD_DATA(i + 3); }
#if 1
LOAD_data32_x4 (0 * 4)
LOAD_data32_x4 (1 * 4)
LOAD_data32_x4 (2 * 4)
LOAD_data32_x4 (3 * 4)
#else
unsigned i;
for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4)
{
LOAD_data32_x4(i)
}
#endif
}
#endif
R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821)
R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a)
R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665)
R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
data += MD5_BLOCK_SIZE;
}
while (--numBlocks);
}
#define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
void Md5_Update(CMd5 *p, const Byte *data, size_t size)
{
if (size == 0)
return;
{
const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
const unsigned num = MD5_BLOCK_SIZE - pos;
p->count += size;
if (num > size)
{
memcpy(p->buffer + pos, data, size);
return;
}
if (pos != 0)
{
size -= num;
memcpy(p->buffer + pos, data, num);
data += num;
Md5_UpdateBlock(p);
}
}
{
const size_t numBlocks = size >> 6;
if (numBlocks)
MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
size &= MD5_BLOCK_SIZE - 1;
if (size == 0)
return;
data += (numBlocks << 6);
memcpy(p->buffer, data, size);
}
}
void Md5_Final(CMd5 *p, Byte *digest)
{
unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
p->buffer[pos++] = 0x80;
if (pos > (MD5_BLOCK_SIZE - 4 * 2))
{
while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; }
// memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos);
Md5_UpdateBlock(p);
pos = 0;
}
memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos);
{
const UInt64 numBits = p->count << 3;
#if defined(MY_CPU_LE_UNALIGN)
SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits)
#else
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits))
SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32))
#endif
}
Md5_UpdateBlock(p);
SetUi32(digest, p->state[0])
SetUi32(digest + 4, p->state[1])
SetUi32(digest + 8, p->state[2])
SetUi32(digest + 12, p->state[3])
Md5_Init(p);
}
#undef R1
#undef R4
#undef R16
#undef D
#undef LOAD_DATA
#undef LOAD_data32_x4
#undef F1
#undef F2
#undef F3
#undef F4