This source file includes following definitions.
- make_digest
- make_digest_ex
- PHP_NAMED_FUNCTION
- PHP_NAMED_FUNCTION
- body
- PHP_MD5Init
- PHP_MD5Update
- PHP_MD5Final
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "php.h"
24 #include "md5.h"
25
26 PHPAPI void make_digest(char *md5str, const unsigned char *digest)
27 {
28 make_digest_ex(md5str, digest, 16);
29 }
30
31
32 PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len)
33 {
34 static const char hexits[17] = "0123456789abcdef";
35 int i;
36
37 for (i = 0; i < len; i++) {
38 md5str[i * 2] = hexits[digest[i] >> 4];
39 md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F];
40 }
41 md5str[len * 2] = '\0';
42 }
43
44
45
46
47 PHP_NAMED_FUNCTION(php_if_md5)
48 {
49 zend_string *arg;
50 zend_bool raw_output = 0;
51 char md5str[33];
52 PHP_MD5_CTX context;
53 unsigned char digest[16];
54
55 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &arg, &raw_output) == FAILURE) {
56 return;
57 }
58
59 md5str[0] = '\0';
60 PHP_MD5Init(&context);
61 PHP_MD5Update(&context, ZSTR_VAL(arg), ZSTR_LEN(arg));
62 PHP_MD5Final(digest, &context);
63 if (raw_output) {
64 RETURN_STRINGL((char *) digest, 16);
65 } else {
66 make_digest_ex(md5str, digest, 16);
67 RETVAL_STRING(md5str);
68 }
69
70 }
71
72
73
74
75 PHP_NAMED_FUNCTION(php_if_md5_file)
76 {
77 char *arg;
78 size_t arg_len;
79 zend_bool raw_output = 0;
80 char md5str[33];
81 unsigned char buf[1024];
82 unsigned char digest[16];
83 PHP_MD5_CTX context;
84 size_t n;
85 php_stream *stream;
86
87 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
88 return;
89 }
90
91 stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
92 if (!stream) {
93 RETURN_FALSE;
94 }
95
96 PHP_MD5Init(&context);
97
98 while ((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
99 PHP_MD5Update(&context, buf, n);
100 }
101
102
103 if (!php_stream_eof(stream)) {
104 php_stream_close(stream);
105 PHP_MD5Final(digest, &context);
106
107 RETURN_FALSE;
108 }
109
110 php_stream_close(stream);
111
112 PHP_MD5Final(digest, &context);
113
114 if (raw_output) {
115 RETURN_STRINGL((char *) digest, 16);
116 } else {
117 make_digest_ex(md5str, digest, 16);
118 RETVAL_STRING(md5str);
119 }
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 #include <string.h>
141
142
143
144
145
146
147
148
149 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
150 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
151 #define H(x, y, z) ((x) ^ (y) ^ (z))
152 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
153
154
155
156
157 #define STEP(f, a, b, c, d, x, t, s) \
158 (a) += f((b), (c), (d)) + (x) + (t); \
159 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
160 (a) += (b);
161
162
163
164
165
166
167
168
169
170 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
171 # define SET(n) \
172 (*(php_uint32 *)&ptr[(n) * 4])
173 # define GET(n) \
174 SET(n)
175 #else
176 # define SET(n) \
177 (ctx->block[(n)] = \
178 (php_uint32)ptr[(n) * 4] | \
179 ((php_uint32)ptr[(n) * 4 + 1] << 8) | \
180 ((php_uint32)ptr[(n) * 4 + 2] << 16) | \
181 ((php_uint32)ptr[(n) * 4 + 3] << 24))
182 # define GET(n) \
183 (ctx->block[(n)])
184 #endif
185
186
187
188
189
190 static const void *body(PHP_MD5_CTX *ctx, const void *data, size_t size)
191 {
192 const unsigned char *ptr;
193 php_uint32 a, b, c, d;
194 php_uint32 saved_a, saved_b, saved_c, saved_d;
195
196 ptr = data;
197
198 a = ctx->a;
199 b = ctx->b;
200 c = ctx->c;
201 d = ctx->d;
202
203 do {
204 saved_a = a;
205 saved_b = b;
206 saved_c = c;
207 saved_d = d;
208
209
210 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
211 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
212 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
213 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
214 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
215 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
216 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
217 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
218 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
219 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
220 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
221 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
222 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
223 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
224 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
225 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
226
227
228 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
229 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
230 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
231 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
232 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
233 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
234 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
235 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
236 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
237 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
238 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
239 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
240 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
241 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
242 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
243 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
244
245
246 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
247 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
248 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
249 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
250 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
251 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
252 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
253 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
254 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
255 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
256 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
257 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
258 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
259 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
260 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
261 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
262
263
264 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
265 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
266 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
267 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
268 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
269 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
270 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
271 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
272 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
273 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
274 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
275 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
276 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
277 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
278 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
279 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
280
281 a += saved_a;
282 b += saved_b;
283 c += saved_c;
284 d += saved_d;
285
286 ptr += 64;
287 } while (size -= 64);
288
289 ctx->a = a;
290 ctx->b = b;
291 ctx->c = c;
292 ctx->d = d;
293
294 return ptr;
295 }
296
297 PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx)
298 {
299 ctx->a = 0x67452301;
300 ctx->b = 0xefcdab89;
301 ctx->c = 0x98badcfe;
302 ctx->d = 0x10325476;
303
304 ctx->lo = 0;
305 ctx->hi = 0;
306 }
307
308 PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
309 {
310 php_uint32 saved_lo;
311 php_uint32 used, free;
312
313 saved_lo = ctx->lo;
314 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
315 ctx->hi++;
316 }
317 ctx->hi += size >> 29;
318
319 used = saved_lo & 0x3f;
320
321 if (used) {
322 free = 64 - used;
323
324 if (size < free) {
325 memcpy(&ctx->buffer[used], data, size);
326 return;
327 }
328
329 memcpy(&ctx->buffer[used], data, free);
330 data = (unsigned char *)data + free;
331 size -= free;
332 body(ctx, ctx->buffer, 64);
333 }
334
335 if (size >= 64) {
336 data = body(ctx, data, size & ~(size_t)0x3f);
337 size &= 0x3f;
338 }
339
340 memcpy(ctx->buffer, data, size);
341 }
342
343 PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
344 {
345 php_uint32 used, free;
346
347 used = ctx->lo & 0x3f;
348
349 ctx->buffer[used++] = 0x80;
350
351 free = 64 - used;
352
353 if (free < 8) {
354 memset(&ctx->buffer[used], 0, free);
355 body(ctx, ctx->buffer, 64);
356 used = 0;
357 free = 64;
358 }
359
360 memset(&ctx->buffer[used], 0, free - 8);
361
362 ctx->lo <<= 3;
363 ctx->buffer[56] = ctx->lo;
364 ctx->buffer[57] = ctx->lo >> 8;
365 ctx->buffer[58] = ctx->lo >> 16;
366 ctx->buffer[59] = ctx->lo >> 24;
367 ctx->buffer[60] = ctx->hi;
368 ctx->buffer[61] = ctx->hi >> 8;
369 ctx->buffer[62] = ctx->hi >> 16;
370 ctx->buffer[63] = ctx->hi >> 24;
371
372 body(ctx, ctx->buffer, 64);
373
374 result[0] = ctx->a;
375 result[1] = ctx->a >> 8;
376 result[2] = ctx->a >> 16;
377 result[3] = ctx->a >> 24;
378 result[4] = ctx->b;
379 result[5] = ctx->b >> 8;
380 result[6] = ctx->b >> 16;
381 result[7] = ctx->b >> 24;
382 result[8] = ctx->c;
383 result[9] = ctx->c >> 8;
384 result[10] = ctx->c >> 16;
385 result[11] = ctx->c >> 24;
386 result[12] = ctx->d;
387 result[13] = ctx->d >> 8;
388 result[14] = ctx->d >> 16;
389 result[15] = ctx->d >> 24;
390
391 ZEND_SECURE_ZERO(ctx, sizeof(*ctx));
392 }