php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Alexander Peslyak (Solar Designer) <solar at openwall.com> |
14 | Lachlan Roche |
15 | Alessandro Astarita <aleast@capri.it> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "php.h"
20#include "md5.h"
21
22PHPAPI void make_digest(char *md5str, const unsigned char *digest) /* {{{ */
23{
24 make_digest_ex(md5str, digest, 16);
25}
26/* }}} */
27
28PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len) /* {{{ */
29{
30 static const char hexits[17] = "0123456789abcdef";
31 int i;
32
33 for (i = 0; i < len; i++) {
34 md5str[i * 2] = hexits[digest[i] >> 4];
35 md5str[(i * 2) + 1] = hexits[digest[i] & 0x0F];
36 }
37 md5str[len * 2] = '\0';
38}
39/* }}} */
40
41/* {{{ Calculate the md5 hash of a string */
43{
45 bool raw_output = 0;
47 unsigned char digest[16];
48
52 Z_PARAM_BOOL(raw_output)
54
57 PHP_MD5Final(digest, &context);
58 if (raw_output) {
59 RETURN_STRINGL((char *) digest, 16);
60 } else {
61 RETVAL_NEW_STR(zend_string_alloc(32, 0));
63 }
64
65}
66/* }}} */
67
68/* {{{ Calculate the md5 hash of given filename */
70{
71 char *arg;
72 size_t arg_len;
73 bool raw_output = 0;
74 unsigned char buf[1024];
75 unsigned char digest[16];
77 ssize_t n;
78 php_stream *stream;
79
81 Z_PARAM_PATH(arg, arg_len)
83 Z_PARAM_BOOL(raw_output)
85
87 if (!stream) {
89 }
90
92
93 while ((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
95 }
96
97 /* XXX this probably can be improved with some number of retries */
98 if (!php_stream_eof(stream)) {
99 php_stream_close(stream);
100 PHP_MD5Final(digest, &context);
101
103 }
104
105 php_stream_close(stream);
106
107 PHP_MD5Final(digest, &context);
108
109 if (raw_output) {
110 RETURN_STRINGL((char *) digest, 16);
111 } else {
112 RETVAL_NEW_STR(zend_string_alloc(32, 0));
114 }
115}
116/* }}} */
117
118/*
119 * This is an OpenSSL-compatible implementation of the RSA Data Security,
120 * Inc. MD5 Message-Digest Algorithm (RFC 1321).
121 *
122 * Written by Solar Designer <solar at openwall.com> in 2001, and placed
123 * in the public domain. There's absolutely no warranty.
124 *
125 * This differs from Colin Plumb's older public domain implementation in
126 * that no 32-bit integer data type is required, there's no compile-time
127 * endianness configuration, and the function prototypes match OpenSSL's.
128 * The primary goals are portability and ease of use.
129 *
130 * This implementation is meant to be fast, but not as fast as possible.
131 * Some known optimizations are not included to reduce source code size
132 * and avoid compile-time configuration.
133 */
134
135#include <string.h>
136
137/*
138 * The basic MD5 functions.
139 *
140 * F and G are optimized compared to their RFC 1321 definitions for
141 * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
142 * implementation.
143 */
144#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
145#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
146#define H(x, y, z) ((x) ^ (y) ^ (z))
147#define I(x, y, z) ((y) ^ ((x) | ~(z)))
148
149/*
150 * The MD5 transformation for all four rounds.
151 */
152#define STEP(f, a, b, c, d, x, t, s) \
153 (a) += f((b), (c), (d)) + (x) + (t); \
154 (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
155 (a) += (b);
156
157/*
158 * SET reads 4 input bytes in little-endian byte order and stores them
159 * in a properly aligned word in host byte order.
160 *
161 * The check for little-endian architectures that tolerate unaligned
162 * memory accesses is just an optimization. Nothing will break if it
163 * doesn't work.
164 */
165#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
166typedef ZEND_SET_ALIGNED(1, uint32_t unaligned_uint32_t);
167# define SET(n) \
168 (*(unaligned_uint32_t *)&ptr[(n) * 4])
169# define GET(n) \
170 SET(n)
171#else
172# define SET(n) \
173 (ctx->block[(n)] = \
174 (uint32_t)ptr[(n) * 4] | \
175 ((uint32_t)ptr[(n) * 4 + 1] << 8) | \
176 ((uint32_t)ptr[(n) * 4 + 2] << 16) | \
177 ((uint32_t)ptr[(n) * 4 + 3] << 24))
178# define GET(n) \
179 (ctx->block[(n)])
180#endif
181
182/*
183 * This processes one or more 64-byte data blocks, but does NOT update
184 * the bit counters. There are no alignment requirements.
185 */
186static const void *body(PHP_MD5_CTX *ctx, const void *data, size_t size)
187{
188 const unsigned char *ptr;
189 uint32_t a, b, c, d;
190 uint32_t saved_a, saved_b, saved_c, saved_d;
191
192 ptr = data;
193
194 a = ctx->a;
195 b = ctx->b;
196 c = ctx->c;
197 d = ctx->d;
198
199 do {
200 saved_a = a;
201 saved_b = b;
202 saved_c = c;
203 saved_d = d;
204
205/* Round 1 */
206 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
207 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
208 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
209 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
210 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
211 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
212 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
213 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
214 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
215 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
216 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
217 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
218 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
219 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
220 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
221 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
222
223/* Round 2 */
224 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
225 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
226 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
227 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
228 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
229 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
230 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
231 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
232 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
233 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
234 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
235 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
236 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
237 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
238 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
239 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
240
241/* Round 3 */
242 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
243 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
244 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
245 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
246 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
247 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
248 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
249 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
250 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
251 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
252 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
253 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
254 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
255 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
256 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
257 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
258
259/* Round 4 */
260 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
261 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
262 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
263 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
264 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
265 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
266 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
267 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
268 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
269 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
270 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
271 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
272 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
273 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
274 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
275 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
276
277 a += saved_a;
278 b += saved_b;
279 c += saved_c;
280 d += saved_d;
281
282 ptr += 64;
283 } while (size -= 64);
284
285 ctx->a = a;
286 ctx->b = b;
287 ctx->c = c;
288 ctx->d = d;
289
290 return ptr;
291}
292
294{
295 ctx->a = 0x67452301;
296 ctx->b = 0xefcdab89;
297 ctx->c = 0x98badcfe;
298 ctx->d = 0x10325476;
299
300 ctx->lo = 0;
301 ctx->hi = 0;
302}
303
304PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
305{
306 uint32_t saved_lo;
307 uint32_t used, free;
308
309 saved_lo = ctx->lo;
310 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
311 ctx->hi++;
312 }
313 ctx->hi += size >> 29;
314
315 used = saved_lo & 0x3f;
316
317 if (used) {
318 free = 64 - used;
319
320 if (size < free) {
321 memcpy(&ctx->buffer[used], data, size);
322 return;
323 }
324
325 memcpy(&ctx->buffer[used], data, free);
326 data = (unsigned char *)data + free;
327 size -= free;
328 body(ctx, ctx->buffer, 64);
329 }
330
331 if (size >= 64) {
332 data = body(ctx, data, size & ~(size_t)0x3f);
333 size &= 0x3f;
334 }
335
336 memcpy(ctx->buffer, data, size);
337}
338
339PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
340{
341 uint32_t used, free;
342
343 used = ctx->lo & 0x3f;
344
345 ctx->buffer[used++] = 0x80;
346
347 free = 64 - used;
348
349 if (free < 8) {
350 memset(&ctx->buffer[used], 0, free);
351 body(ctx, ctx->buffer, 64);
352 used = 0;
353 free = 64;
354 }
355
356 memset(&ctx->buffer[used], 0, free - 8);
357
358 ctx->lo <<= 3;
359 ctx->buffer[56] = ctx->lo;
360 ctx->buffer[57] = ctx->lo >> 8;
361 ctx->buffer[58] = ctx->lo >> 16;
362 ctx->buffer[59] = ctx->lo >> 24;
363 ctx->buffer[60] = ctx->hi;
364 ctx->buffer[61] = ctx->hi >> 8;
365 ctx->buffer[62] = ctx->hi >> 16;
366 ctx->buffer[63] = ctx->hi >> 24;
367
368 body(ctx, ctx->buffer, 64);
369
370 result[0] = ctx->a;
371 result[1] = ctx->a >> 8;
372 result[2] = ctx->a >> 16;
373 result[3] = ctx->a >> 24;
374 result[4] = ctx->b;
375 result[5] = ctx->b >> 8;
376 result[6] = ctx->b >> 16;
377 result[7] = ctx->b >> 24;
378 result[8] = ctx->c;
379 result[9] = ctx->c >> 8;
380 result[10] = ctx->c >> 16;
381 result[11] = ctx->c >> 24;
382 result[12] = ctx->d;
383 result[13] = ctx->d >> 8;
384 result[14] = ctx->d >> 16;
385 result[15] = ctx->d >> 24;
386
387 ZEND_SECURE_ZERO(ctx, sizeof(*ctx));
388}
size_t len
Definition apprentice.c:174
md5(string $string, bool $binary=false)
md5_file(string $filename, bool $binary=false)
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
void * ptr
Definition ffi.c:3814
memcpy(ptr1, ptr2, size)
zval * arg
Definition ffi.c:3975
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define F
Definition encoding.c:235
#define I
Definition encoding.c:237
#define NULL
Definition gdcache.h:45
PHPAPI void make_digest(char *md5str, const unsigned char *digest)
Definition md5.c:22
#define GET(n)
Definition md5.c:178
PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len)
Definition md5.c:28
PHPAPI void PHP_MD5InitArgs(PHP_MD5_CTX *ctx, ZEND_ATTRIBUTE_UNUSED HashTable *args)
Definition md5.c:293
#define STEP(f, a, b, c, d, x, t, s)
Definition md5.c:152
#define SET(n)
Definition md5.c:172
PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
Definition md5.c:339
#define H(x, y, z)
Definition md5.c:146
PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
Definition md5.c:304
#define PHP_MD5Init(ctx)
Definition md5.h:43
#define G(L)
Definition minilua.c:489
#define PHP_FUNCTION
Definition php.h:364
#define PHPAPI
Definition php.h:71
struct _php_stream php_stream
Definition php_streams.h:96
#define REPORT_ERRORS
#define php_stream_read(stream, buf, count)
#define php_stream_eof(stream)
#define php_stream_close(stream)
#define php_stream_open_wrapper(path, mode, options, opened)
zend_constant * data
@ body
uint32_t d
Definition md5.h:37
uint32_t b
Definition md5.h:37
uint32_t hi
Definition md5.h:36
unsigned char buffer[64]
Definition md5.h:38
uint32_t lo
Definition md5.h:36
uint32_t c
Definition md5.h:37
uint32_t a
Definition md5.h:37
Definition dce.c:49
$obj a
Definition test.php:84
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_NEW_STR(s)
Definition zend_API.h:1015
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_BOOL(dest)
Definition zend_API.h:1726
#define Z_PARAM_PATH(dest, dest_len)
Definition zend_API.h:2026
zval * args
struct _zend_string zend_string
#define ZEND_ATTRIBUTE_UNUSED
#define ZEND_SECURE_ZERO(var, size)
#define ZEND_SET_ALIGNED(alignment, decl)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
struct _zend_array HashTable
Definition zend_types.h:386
zval * return_value
bool result