aboutsummaryrefslogtreecommitdiff
path: root/C/Md5.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Md5.c')
-rw-r--r--C/Md5.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/C/Md5.c b/C/Md5.c
new file mode 100644
index 0000000..1b745d7
--- /dev/null
+++ b/C/Md5.c
@@ -0,0 +1,206 @@
1/* Md5.c -- MD5 Hash
2: Igor Pavlov : Public domain
3This code is based on Colin Plumb's public domain md5.c code */
4
5#include "Precomp.h"
6
7#include <string.h>
8
9#include "Md5.h"
10#include "RotateDefs.h"
11#include "CpuArch.h"
12
13#define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks
14
15Z7_NO_INLINE
16void Md5_Init(CMd5 *p)
17{
18 p->count = 0;
19 p->state[0] = 0x67452301;
20 p->state[1] = 0xefcdab89;
21 p->state[2] = 0x98badcfe;
22 p->state[3] = 0x10325476;
23}
24
25#if 0 && !defined(MY_CPU_LE_UNALIGN)
26// optional optimization for Big-endian processors or processors without unaligned access:
27// it is intended to reduce the number of complex LE32 memory reading from 64 to 16.
28// But some compilers (sparc, armt) are better without this optimization.
29#define Z7_MD5_USE_DATA32_ARRAY
30#endif
31
32#define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i))
33
34#ifdef Z7_MD5_USE_DATA32_ARRAY
35#define D(i) data32[i]
36#else
37#define D(i) LOAD_DATA(i)
38#endif
39
40#define F1(x, y, z) (z ^ (x & (y ^ z)))
41#define F2(x, y, z) F1(z, x, y)
42#define F3(x, y, z) (x ^ y ^ z)
43#define F4(x, y, z) (y ^ (x | ~z))
44
45#define R1(i, f, start, step, w, x, y, z, s, k) \
46 w += D((start + step * (i)) % 16) + k; \
47 w += f(x, y, z); \
48 w = rotlFixed(w, s) + x; \
49
50#define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \
51 R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \
52 R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \
53 R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \
54 R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \
55
56#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) \
57 R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \
58 R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \
59 R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \
60 R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \
61
62static
63Z7_NO_INLINE
64void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks)
65{
66 UInt32 a, b, c, d;
67 // if (numBlocks == 0) return;
68 a = state[0];
69 b = state[1];
70 c = state[2];
71 d = state[3];
72 do
73 {
74#ifdef Z7_MD5_USE_DATA32_ARRAY
75 UInt32 data32[MD5_NUM_BLOCK_WORDS];
76 {
77#define LOAD_data32_x4(i) { \
78 data32[i ] = LOAD_DATA(i ); \
79 data32[i + 1] = LOAD_DATA(i + 1); \
80 data32[i + 2] = LOAD_DATA(i + 2); \
81 data32[i + 3] = LOAD_DATA(i + 3); }
82#if 1
83 LOAD_data32_x4 (0 * 4)
84 LOAD_data32_x4 (1 * 4)
85 LOAD_data32_x4 (2 * 4)
86 LOAD_data32_x4 (3 * 4)
87#else
88 unsigned i;
89 for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4)
90 {
91 LOAD_data32_x4(i)
92 }
93#endif
94 }
95#endif
96
97 R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
98 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
99 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
100 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821)
101 R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
102 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
103 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
104 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a)
105 R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
106 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
107 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
108 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665)
109 R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
110 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
111 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
112 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
113
114 a += state[0];
115 b += state[1];
116 c += state[2];
117 d += state[3];
118
119 state[0] = a;
120 state[1] = b;
121 state[2] = c;
122 state[3] = d;
123
124 data += MD5_BLOCK_SIZE;
125 }
126 while (--numBlocks);
127}
128
129
130#define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1)
131
132void Md5_Update(CMd5 *p, const Byte *data, size_t size)
133{
134 if (size == 0)
135 return;
136 {
137 const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
138 const unsigned num = MD5_BLOCK_SIZE - pos;
139 p->count += size;
140 if (num > size)
141 {
142 memcpy(p->buffer + pos, data, size);
143 return;
144 }
145 if (pos != 0)
146 {
147 size -= num;
148 memcpy(p->buffer + pos, data, num);
149 data += num;
150 Md5_UpdateBlock(p);
151 }
152 }
153 {
154 const size_t numBlocks = size >> 6;
155 if (numBlocks)
156 MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks);
157 size &= MD5_BLOCK_SIZE - 1;
158 if (size == 0)
159 return;
160 data += (numBlocks << 6);
161 memcpy(p->buffer, data, size);
162 }
163}
164
165
166void Md5_Final(CMd5 *p, Byte *digest)
167{
168 unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1);
169 p->buffer[pos++] = 0x80;
170 if (pos > (MD5_BLOCK_SIZE - 4 * 2))
171 {
172 while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; }
173 // memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos);
174 Md5_UpdateBlock(p);
175 pos = 0;
176 }
177 memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos);
178 {
179 const UInt64 numBits = p->count << 3;
180#if defined(MY_CPU_LE_UNALIGN)
181 SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits)
182#else
183 SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits))
184 SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32))
185#endif
186 }
187 Md5_UpdateBlock(p);
188
189 SetUi32(digest, p->state[0])
190 SetUi32(digest + 4, p->state[1])
191 SetUi32(digest + 8, p->state[2])
192 SetUi32(digest + 12, p->state[3])
193
194 Md5_Init(p);
195}
196
197#undef R1
198#undef R4
199#undef R16
200#undef D
201#undef LOAD_DATA
202#undef LOAD_data32_x4
203#undef F1
204#undef F2
205#undef F3
206#undef F4