php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
hash_md.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 | Taken from: ext/standard/md5.c |
14 +----------------------------------------------------------------------+
15*/
16
17#include "php_hash.h"
18#include "php_hash_md.h"
19
34
49
50static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv);
51
66
67/* MD common stuff */
68
69static const unsigned char PADDING[64] =
70{
71 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
74};
75
76/* {{{ Encode
77 Encodes input (uint32_t) into output (unsigned char). Assumes len is
78 a multiple of 4.
79 */
80static void Encode(unsigned char *output, uint32_t *input, unsigned int len)
81{
82 unsigned int i, j;
83
84 for (i = 0, j = 0; j < len; i++, j += 4) {
85 output[j] = (unsigned char) (input[i] & 0xff);
86 output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
87 output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
88 output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
89 }
90}
91/* }}} */
92
93/* {{{ Decode
94 Decodes input (unsigned char) into output (uint32_t). Assumes len is
95 a multiple of 4.
96 */
97static void Decode(uint32_t *output, const unsigned char *input, unsigned int len)
98{
99 unsigned int i, j;
100
101 for (i = 0, j = 0; j < len; i++, j += 4)
102 output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) |
103 (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
104}
105/* }}} */
106
107/* MD4 */
108
109#define MD4_F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
110#define MD4_G(x,y,z) (((x) & ((y) | (z))) | ((y) & (z)))
111#define MD4_H(x,y,z) ((x) ^ (y) ^ (z))
112
113#define ROTL32(s,v) (((v) << (s)) | ((v) >> (32 - (s))))
114
115#define MD4_R1(a,b,c,d,k,s) a = ROTL32(s, a + MD4_F(b,c,d) + x[k])
116#define MD4_R2(a,b,c,d,k,s) a = ROTL32(s, a + MD4_G(b,c,d) + x[k] + 0x5A827999)
117#define MD4_R3(a,b,c,d,k,s) a = ROTL32(s, a + MD4_H(b,c,d) + x[k] + 0x6ED9EBA1)
118
119static void MD4Transform(uint32_t state[4], const unsigned char block[64])
120{
121 uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
122
123 Decode(x, block, 64);
124
125 /* Round 1 */
126 MD4_R1(a,b,c,d, 0, 3);
127 MD4_R1(d,a,b,c, 1, 7);
128 MD4_R1(c,d,a,b, 2,11);
129 MD4_R1(b,c,d,a, 3,19);
130 MD4_R1(a,b,c,d, 4, 3);
131 MD4_R1(d,a,b,c, 5, 7);
132 MD4_R1(c,d,a,b, 6,11);
133 MD4_R1(b,c,d,a, 7,19);
134 MD4_R1(a,b,c,d, 8, 3);
135 MD4_R1(d,a,b,c, 9, 7);
136 MD4_R1(c,d,a,b,10,11);
137 MD4_R1(b,c,d,a,11,19);
138 MD4_R1(a,b,c,d,12, 3);
139 MD4_R1(d,a,b,c,13, 7);
140 MD4_R1(c,d,a,b,14,11);
141 MD4_R1(b,c,d,a,15,19);
142
143 /* Round 2 */
144 MD4_R2(a,b,c,d, 0, 3);
145 MD4_R2(d,a,b,c, 4, 5);
146 MD4_R2(c,d,a,b, 8, 9);
147 MD4_R2(b,c,d,a,12,13);
148 MD4_R2(a,b,c,d, 1, 3);
149 MD4_R2(d,a,b,c, 5, 5);
150 MD4_R2(c,d,a,b, 9, 9);
151 MD4_R2(b,c,d,a,13,13);
152 MD4_R2(a,b,c,d, 2, 3);
153 MD4_R2(d,a,b,c, 6, 5);
154 MD4_R2(c,d,a,b,10, 9);
155 MD4_R2(b,c,d,a,14,13);
156 MD4_R2(a,b,c,d, 3, 3);
157 MD4_R2(d,a,b,c, 7, 5);
158 MD4_R2(c,d,a,b,11, 9);
159 MD4_R2(b,c,d,a,15,13);
160
161 /* Round 3 */
162 MD4_R3(a,b,c,d, 0, 3);
163 MD4_R3(d,a,b,c, 8, 9);
164 MD4_R3(c,d,a,b, 4,11);
165 MD4_R3(b,c,d,a,12,15);
166 MD4_R3(a,b,c,d, 2, 3);
167 MD4_R3(d,a,b,c,10, 9);
168 MD4_R3(c,d,a,b, 6,11);
169 MD4_R3(b,c,d,a,14,15);
170 MD4_R3(a,b,c,d, 1, 3);
171 MD4_R3(d,a,b,c, 9, 9);
172 MD4_R3(c,d,a,b, 5,11);
173 MD4_R3(b,c,d,a,13,15);
174 MD4_R3(a,b,c,d, 3, 3);
175 MD4_R3(d,a,b,c,11, 9);
176 MD4_R3(c,d,a,b, 7,11);
177 MD4_R3(b,c,d,a,15,15);
178
179 state[0] += a;
180 state[1] += b;
181 state[2] += c;
182 state[3] += d;
183}
184
185/* {{{ PHP_MD4InitArgs
186 * MD4 initialization. Begins an MD4 operation, writing a new context.
187 */
189{
190 context->count[0] = context->count[1] = 0;
191 /* Load magic initialization constants.
192 */
193 context->state[0] = 0x67452301;
194 context->state[1] = 0xefcdab89;
195 context->state[2] = 0x98badcfe;
196 context->state[3] = 0x10325476;
197}
198/* }}} */
199
200/* {{{ PHP_MD4Update
201 MD4 block update operation. Continues an MD4 message-digest
202 operation, processing another message block, and updating the
203 context.
204 */
205PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX * context, const unsigned char *input, size_t inputLen)
206{
207 unsigned int index, partLen;
208 size_t i;
209
210 /* Compute number of bytes mod 64 */
211 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
212
213 /* Update number of bits */
214 if ((context->count[0] += ((uint32_t) inputLen << 3))
215 < ((uint32_t) inputLen << 3))
216 context->count[1]++;
217 context->count[1] += (uint32_t) (inputLen >> 29);
218
219 partLen = 64 - index;
220
221 /* Transform as many times as possible.
222 */
223 if (inputLen >= partLen) {
224 memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
225 MD4Transform(context->state, context->buffer);
226
227 for (i = partLen; i + 63 < inputLen; i += 64) {
228 MD4Transform(context->state, &input[i]);
229 }
230
231 index = 0;
232 } else {
233 i = 0;
234 }
235
236 /* Buffer remaining input */
237 memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
238}
239/* }}} */
240
241/* {{{ PHP_MD4Final
242 MD4 finalization. Ends an MD4 message-digest operation, writing
243 the message digest and zeroizing the context.
244 */
245PHP_HASH_API void PHP_MD4Final(unsigned char digest[16], PHP_MD4_CTX * context)
246{
247 unsigned char bits[8];
248 unsigned int index, padLen;
249
250 /* Save number of bits */
251 Encode(bits, context->count, 8);
252
253 /* Pad out to 56 mod 64.
254 */
255 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
256 padLen = (index < 56) ? (56 - index) : (120 - index);
257 PHP_MD4Update(context, PADDING, padLen);
258
259 /* Append length (before padding) */
260 PHP_MD4Update(context, bits, 8);
261
262 /* Store state in digest */
263 Encode(digest, context->state, 16);
264
265 /* Zeroize sensitive information.
266 */
267 ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
268}
269/* }}} */
270
271/* MD2 */
272
273static const unsigned char MD2_S[256] = {
274 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
275 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
276 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
277 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
278 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
279 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
280 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
281 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
282 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
283 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
284 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
285 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
286 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
287 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
288 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
289 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 };
290
295
296static void MD2_Transform(PHP_MD2_CTX *context, const unsigned char *block)
297{
298 unsigned char i,j,t = 0;
299
300 for(i = 0; i < 16; i++) {
301 context->state[16+i] = block[i];
302 context->state[32+i] = (context->state[16+i] ^ context->state[i]);
303 }
304
305 for(i = 0; i < 18; i++) {
306 for(j = 0; j < 48; j++) {
307 t = context->state[j] = context->state[j] ^ MD2_S[t];
308 }
309 t += i;
310 }
311
312 /* Update checksum -- must be after transform to avoid fouling up last message block */
313 t = context->checksum[15];
314 for(i = 0; i < 16; i++) {
315 t = context->checksum[i] ^= MD2_S[block[i] ^ t];
316 }
317}
318
319PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *buf, size_t len)
320{
321 const unsigned char *p = buf, *e = buf + len;
322
323 if (context->in_buffer) {
324 if (context->in_buffer + len < 16) {
325 /* Not enough for block, just pass into buffer */
326 memcpy(context->buffer + context->in_buffer, p, len);
327 context->in_buffer += (char) len;
328 return;
329 }
330 /* Put buffered data together with inbound for a single block */
331 memcpy(context->buffer + context->in_buffer, p, 16 - context->in_buffer);
332 MD2_Transform(context, context->buffer);
333 p += 16 - context->in_buffer;
334 context->in_buffer = 0;
335 }
336
337 /* Process as many whole blocks as remain */
338 while ((p + 16) <= e) {
339 MD2_Transform(context, p);
340 p += 16;
341 }
342
343 /* Copy remaining data to buffer */
344 if (p < e) {
345 memcpy(context->buffer, p, e - p);
346 context->in_buffer = (char) (e - p);
347 }
348}
349
350PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context)
351{
352 memset(context->buffer + context->in_buffer, 16 - context->in_buffer, 16 - context->in_buffer);
353 MD2_Transform(context, context->buffer);
354 MD2_Transform(context, context->checksum);
355
356 memcpy(output, context->state, 16);
357}
358
359static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv)
360{
361 PHP_MD2_CTX *ctx = (PHP_MD2_CTX *) hash->context;
362 int r = FAILURE;
365 && (unsigned char) ctx->in_buffer < sizeof(ctx->buffer)) {
366 return SUCCESS;
367 } else {
368 return r != SUCCESS ? r : -2000;
369 }
370}
size_t len
Definition apprentice.c:174
zval * zv
Definition ffi.c:3975
memcpy(ptr1, ptr2, size)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
PHP_HASH_API zend_result php_hash_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv)
Definition hash.c:334
PHP_HASH_API zend_result php_hash_copy(const void *ops, const void *orig_context, void *dest_context)
Definition hash.c:124
PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec)
Definition hash.c:280
PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv)
Definition hash.c:345
hash(string $algo, string $data, bool $binary=false, array $options=[])
Definition hash.stub.php:12
#define MD4_R2(a, b, c, d, k, s)
Definition hash_md.c:116
const php_hash_ops php_hash_md2_ops
Definition hash_md.c:52
PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX *context, const unsigned char *input, size_t inputLen)
Definition hash_md.c:205
PHP_HASH_API void PHP_MD2InitArgs(PHP_MD2_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
Definition hash_md.c:291
#define MD4_R3(a, b, c, d, k, s)
Definition hash_md.c:117
PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *buf, size_t len)
Definition hash_md.c:319
#define MD4_R1(a, b, c, d, k, s)
Definition hash_md.c:115
PHP_HASH_API void PHP_MD4InitArgs(PHP_MD4_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
Definition hash_md.c:188
const php_hash_ops php_hash_md4_ops
Definition hash_md.c:35
PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context)
Definition hash_md.c:350
const php_hash_ops php_hash_md5_ops
Definition hash_md.c:20
PHP_HASH_API void PHP_MD4Final(unsigned char digest[16], PHP_MD4_CTX *context)
Definition hash_md.c:245
#define SUCCESS
Definition hash_sha3.c:261
again j
PHPAPI void PHP_MD5InitArgs(PHP_MD5_CTX *ctx, ZEND_ATTRIBUTE_UNUSED HashTable *args)
Definition md5.c:293
PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
Definition md5.c:339
PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
Definition md5.c:304
#define PHP_MD5_SPEC
Definition md5.h:41
void(* php_hash_final_func_t)(unsigned char *digest, void *context)
Definition php_hash.h:36
struct _php_hashcontext_object php_hashcontext_object
Definition php_hash.h:32
void(* php_hash_init_func_t)(void *context, HashTable *args)
Definition php_hash.h:34
void(* php_hash_update_func_t)(void *context, const unsigned char *buf, size_t count)
Definition php_hash.h:35
#define PHP_HASH_API
Definition php_hash.h:144
struct _php_hash_ops php_hash_ops
#define PHP_HASH_SERIALIZE_MAGIC_SPEC
Definition php_hash.h:28
#define PHP_MD2_SPEC
Definition php_hash_md.h:43
#define PHP_MD4_SPEC
Definition php_hash_md.h:29
p
Definition session.c:1105
Definition dce.c:49
Definition file.h:202
$obj a
Definition test.php:84
struct _zval_struct zval
zval * args
int32_t zend_long
Definition zend_long.h:42
#define ZEND_ATTRIBUTE_UNUSED
#define ZEND_SECURE_ZERO(var, size)
struct _zend_array HashTable
Definition zend_types.h:386
@ FAILURE
Definition zend_types.h:61