Coverage Report

Created: 2026-07-25 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/hash/hash_ripemd.c
Line
Count
Source
1
/*
2
  +----------------------------------------------------------------------+
3
  | Copyright © The PHP Group and Contributors.                          |
4
  +----------------------------------------------------------------------+
5
  | This source file is subject to the Modified BSD License that is      |
6
  | bundled with this package in the file LICENSE, and is available      |
7
  | through the World Wide Web at <https://www.php.net/license/>.        |
8
  |                                                                      |
9
  | SPDX-License-Identifier: BSD-3-Clause                                |
10
  +----------------------------------------------------------------------+
11
  | Author: Sara Golemon <pollita@php.net>                               |
12
  +----------------------------------------------------------------------+
13
*/
14
15
/* Heavily borrowed from md5.c & sha1.c of PHP archival fame
16
   Note that ripemd laughs in the face of logic and uses
17
   little endian byte ordering */
18
19
#include "php_hash.h"
20
#include "php_hash_ripemd.h"
21
22
const php_hash_ops php_hash_ripemd128_ops = {
23
  "ripemd128",
24
  (php_hash_init_func_t) PHP_RIPEMD128Init,
25
  (php_hash_update_func_t) PHP_RIPEMD128Update,
26
  (php_hash_final_func_t) PHP_RIPEMD128Final,
27
  php_hash_copy,
28
  php_hash_serialize,
29
  php_hash_unserialize,
30
  PHP_RIPEMD128_SPEC,
31
  16,
32
  64,
33
  sizeof(PHP_RIPEMD128_CTX),
34
  1,
35
  0
36
};
37
38
const php_hash_ops php_hash_ripemd160_ops = {
39
  "ripemd160",
40
  (php_hash_init_func_t) PHP_RIPEMD160Init,
41
  (php_hash_update_func_t) PHP_RIPEMD160Update,
42
  (php_hash_final_func_t) PHP_RIPEMD160Final,
43
  php_hash_copy,
44
  php_hash_serialize,
45
  php_hash_unserialize,
46
  PHP_RIPEMD160_SPEC,
47
  20,
48
  64,
49
  sizeof(PHP_RIPEMD160_CTX),
50
  1,
51
  0
52
};
53
54
const php_hash_ops php_hash_ripemd256_ops = {
55
  "ripemd256",
56
  (php_hash_init_func_t) PHP_RIPEMD256Init,
57
  (php_hash_update_func_t) PHP_RIPEMD256Update,
58
  (php_hash_final_func_t) PHP_RIPEMD256Final,
59
  php_hash_copy,
60
  php_hash_serialize,
61
  php_hash_unserialize,
62
  PHP_RIPEMD256_SPEC,
63
  32,
64
  64,
65
  sizeof(PHP_RIPEMD256_CTX),
66
  1,
67
  0
68
};
69
70
const php_hash_ops php_hash_ripemd320_ops = {
71
  "ripemd320",
72
  (php_hash_init_func_t) PHP_RIPEMD320Init,
73
  (php_hash_update_func_t) PHP_RIPEMD320Update,
74
  (php_hash_final_func_t) PHP_RIPEMD320Final,
75
  php_hash_copy,
76
  php_hash_serialize,
77
  php_hash_unserialize,
78
  PHP_RIPEMD320_SPEC,
79
  40,
80
  64,
81
  sizeof(PHP_RIPEMD320_CTX),
82
  1,
83
  0
84
};
85
86
/* {{{ PHP_RIPEMD128Init
87
 * ripemd128 initialization. Begins a ripemd128 operation, writing a new context.
88
 */
89
PHP_HASH_API void PHP_RIPEMD128Init(PHP_RIPEMD128_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
90
88
{
91
88
  context->count[0] = context->count[1] = 0;
92
  /* Load magic initialization constants.
93
   */
94
88
  context->state[0] = 0x67452301;
95
88
  context->state[1] = 0xEFCDAB89;
96
88
  context->state[2] = 0x98BADCFE;
97
88
  context->state[3] = 0x10325476;
98
88
}
99
/* }}} */
100
101
/* {{{ PHP_RIPEMD256Init
102
 * ripemd256 initialization. Begins a ripemd256 operation, writing a new context.
103
 */
104
PHP_HASH_API void PHP_RIPEMD256Init(PHP_RIPEMD256_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
105
104
{
106
104
  context->count[0] = context->count[1] = 0;
107
  /* Load magic initialization constants.
108
   */
109
104
  context->state[0] = 0x67452301;
110
104
  context->state[1] = 0xEFCDAB89;
111
104
  context->state[2] = 0x98BADCFE;
112
104
  context->state[3] = 0x10325476;
113
104
  context->state[4] = 0x76543210;
114
104
  context->state[5] = 0xFEDCBA98;
115
104
  context->state[6] = 0x89ABCDEF;
116
104
  context->state[7] = 0x01234567;
117
104
}
118
/* }}} */
119
120
/* {{{ PHP_RIPEMD160Init
121
 * ripemd160 initialization. Begins a ripemd160 operation, writing a new context.
122
 */
123
PHP_HASH_API void PHP_RIPEMD160Init(PHP_RIPEMD160_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
124
129
{
125
129
  context->count[0] = context->count[1] = 0;
126
  /* Load magic initialization constants.
127
   */
128
129
  context->state[0] = 0x67452301;
129
129
  context->state[1] = 0xEFCDAB89;
130
129
  context->state[2] = 0x98BADCFE;
131
129
  context->state[3] = 0x10325476;
132
129
  context->state[4] = 0xC3D2E1F0;
133
129
}
134
/* }}} */
135
136
/* {{{ PHP_RIPEMD320Init
137
 * ripemd320 initialization. Begins a ripemd320 operation, writing a new context.
138
 */
139
PHP_HASH_API void PHP_RIPEMD320Init(PHP_RIPEMD320_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
140
101
{
141
101
  context->count[0] = context->count[1] = 0;
142
  /* Load magic initialization constants.
143
   */
144
101
  context->state[0] = 0x67452301;
145
101
  context->state[1] = 0xEFCDAB89;
146
101
  context->state[2] = 0x98BADCFE;
147
101
  context->state[3] = 0x10325476;
148
101
  context->state[4] = 0xC3D2E1F0;
149
101
  context->state[5] = 0x76543210;
150
101
  context->state[6] = 0xFEDCBA98;
151
101
  context->state[7] = 0x89ABCDEF;
152
101
  context->state[8] = 0x01234567;
153
101
  context->state[9] = 0x3C2D1E0F;
154
101
}
155
/* }}} */
156
157
/* Basic ripemd function */
158
#define F0(x,y,z)   ((x) ^ (y) ^ (z))
159
#define F1(x,y,z)   (((x) & (y)) | ((~(x)) & (z)))
160
#define F2(x,y,z)   (((x) | (~(y))) ^ (z))
161
#define F3(x,y,z)   (((x) & (z)) | ((y) & (~(z))))
162
#define F4(x,y,z)   ((x) ^ ((y) | (~(z))))
163
164
static const uint32_t K_values[5]  = { 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E };    /* 128, 256, 160, 320 */
165
static const uint32_t KK_values[4] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000 };                /* 128 & 256 */
166
static const uint32_t KK160_values[5] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000 }; /* 160 & 320 */
167
168
#define K(n)  K_values[ (n) >> 4]
169
#define KK(n) KK_values[(n) >> 4]
170
#define KK160(n) KK160_values[(n) >> 4]
171
172
static const unsigned char R[80] = {
173
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
174
   7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
175
   3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
176
   1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
177
   4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13 };
178
179
static const unsigned char RR[80] = {
180
   5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
181
   6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
182
  15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
183
   8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
184
  12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11 };
185
186
static const unsigned char S[80] = {
187
  11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
188
   7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
189
  11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
190
  11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
191
   9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6 };
192
193
static const unsigned char SS[80] = {
194
   8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
195
   9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
196
   9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
197
  15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
198
   8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11 };
199
200
8.10M
#define ROLS(j, x)  (((x) << S[j])  | ((x) >> (32 - S[j])))
201
8.10M
#define ROLSS(j, x) (((x) << SS[j]) | ((x) >> (32 - SS[j])))
202
8.25M
#define ROL(n, x) (((x) << n) | ((x) >> (32 - n)))
203
204
/* {{{ RIPEMDDecode
205
   Decodes input (unsigned char) into output (uint32_t). Assumes len is
206
   a multiple of 4.
207
 */
208
static void RIPEMDDecode(uint32_t *output, const unsigned char *input, unsigned int len)
209
113k
{
210
113k
  unsigned int i, j;
211
212
1.93M
  for (i = 0, j = 0; j < len; i++, j += 4)
213
1.82M
    output[i] = ((uint32_t) input[j + 0]) | (((uint32_t) input[j + 1]) << 8) |
214
1.82M
      (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
215
113k
}
216
/* }}} */
217
218
/* {{{ RIPEMD128Transform
219
 * ripemd128 basic transformation. Transforms state based on block.
220
 */
221
static void RIPEMD128Transform(uint32_t state[4], const unsigned char block[64])
222
35.4k
{
223
35.4k
  uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3];
224
35.4k
  uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3];
225
35.4k
  uint32_t tmp, x[16];
226
35.4k
  int j;
227
228
35.4k
  RIPEMDDecode(x, block, 64);
229
230
602k
  for(j = 0; j < 16; j++) {
231
566k
    tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j));
232
566k
    a = d; d = c; c = b; b = tmp;
233
566k
    tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j));
234
566k
    aa = dd; dd = cc; cc = bb; bb = tmp;
235
566k
  }
236
237
602k
  for(j = 16; j < 32; j++) {
238
566k
    tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j));
239
566k
    a = d; d = c; c = b; b = tmp;
240
566k
    tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j));
241
566k
    aa = dd; dd = cc; cc = bb; bb = tmp;
242
566k
  }
243
244
602k
  for(j = 32; j < 48; j++) {
245
566k
    tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j));
246
566k
    a = d; d = c; c = b; b = tmp;
247
566k
    tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j));
248
566k
    aa = dd; dd = cc; cc = bb; bb = tmp;
249
566k
  }
250
251
602k
  for(j = 48; j < 64; j++) {
252
566k
    tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j));
253
566k
    a = d; d = c; c = b; b = tmp;
254
566k
    tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j));
255
566k
    aa = dd; dd = cc; cc = bb; bb = tmp;
256
566k
  }
257
258
35.4k
  tmp = state[1] + c + dd;
259
35.4k
  state[1] = state[2] + d + aa;
260
35.4k
  state[2] = state[3] + a + bb;
261
35.4k
  state[3] = state[0] + b + cc;
262
35.4k
  state[0] = tmp;
263
264
35.4k
  tmp = 0;
265
35.4k
  ZEND_SECURE_ZERO(x, sizeof(x));
266
35.4k
}
267
/* }}} */
268
269
/* {{{ PHP_RIPEMD128Update
270
   ripemd128 block update operation. Continues a ripemd128 message-digest
271
   operation, processing another message block, and updating the
272
   context.
273
 */
274
PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context, const unsigned char *input, size_t inputLen)
275
264
{
276
264
  unsigned int index, partLen;
277
264
  size_t i;
278
279
  /* Compute number of bytes mod 64 */
280
264
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
281
282
  /* Update number of bits */
283
264
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
284
17
    context->count[1]++;
285
17
  }
286
264
  context->count[1] += (uint32_t) (inputLen >> 29);
287
288
264
  partLen = 64 - index;
289
290
  /* Transform as many times as possible.
291
   */
292
264
  if (inputLen >= partLen) {
293
173
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
294
173
    RIPEMD128Transform(context->state, context->buffer);
295
296
35.4k
    for (i = partLen; i + 63 < inputLen; i += 64) {
297
35.2k
      RIPEMD128Transform(context->state, &input[i]);
298
35.2k
    }
299
300
173
    index = 0;
301
173
  } else {
302
91
    i = 0;
303
91
  }
304
305
  /* Buffer remaining input */
306
264
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
307
264
}
308
/* }}} */
309
310
/* {{{ RIPEMD256Transform
311
 * ripemd256 basic transformation. Transforms state based on block.
312
 */
313
static void RIPEMD256Transform(uint32_t state[8], const unsigned char block[64])
314
26.7k
{
315
26.7k
  uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3];
316
26.7k
  uint32_t aa = state[4], bb = state[5], cc = state[6], dd = state[7];
317
26.7k
  uint32_t tmp, x[16];
318
26.7k
  int j;
319
320
26.7k
  RIPEMDDecode(x, block, 64);
321
322
455k
  for(j = 0; j < 16; j++) {
323
428k
    tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j));
324
428k
    a = d; d = c; c = b; b = tmp;
325
428k
    tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK(j));
326
428k
    aa = dd; dd = cc; cc = bb; bb = tmp;
327
428k
  }
328
26.7k
  tmp = a; a = aa; aa = tmp;
329
330
455k
  for(j = 16; j < 32; j++) {
331
428k
    tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j));
332
428k
    a = d; d = c; c = b; b = tmp;
333
428k
    tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK(j));
334
428k
    aa = dd; dd = cc; cc = bb; bb = tmp;
335
428k
  }
336
26.7k
  tmp = b; b = bb; bb = tmp;
337
338
455k
  for(j = 32; j < 48; j++) {
339
428k
    tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j));
340
428k
    a = d; d = c; c = b; b = tmp;
341
428k
    tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK(j));
342
428k
    aa = dd; dd = cc; cc = bb; bb = tmp;
343
428k
  }
344
26.7k
  tmp = c; c = cc; cc = tmp;
345
346
455k
  for(j = 48; j < 64; j++) {
347
428k
    tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j));
348
428k
    a = d; d = c; c = b; b = tmp;
349
428k
    tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK(j));
350
428k
    aa = dd; dd = cc; cc = bb; bb = tmp;
351
428k
  }
352
26.7k
  tmp = d; d = dd; dd = tmp;
353
354
26.7k
  state[0] += a;
355
26.7k
  state[1] += b;
356
26.7k
  state[2] += c;
357
26.7k
  state[3] += d;
358
26.7k
  state[4] += aa;
359
26.7k
  state[5] += bb;
360
26.7k
  state[6] += cc;
361
26.7k
  state[7] += dd;
362
363
26.7k
  tmp = 0;
364
26.7k
  ZEND_SECURE_ZERO(x, sizeof(x));
365
26.7k
}
366
/* }}} */
367
368
/* {{{ PHP_RIPEMD256Update
369
   ripemd256 block update operation. Continues a ripemd256 message-digest
370
   operation, processing another message block, and updating the
371
   context.
372
 */
373
PHP_HASH_API void PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context, const unsigned char *input, size_t inputLen)
374
312
{
375
312
  unsigned int index, partLen;
376
312
  size_t i;
377
378
  /* Compute number of bytes mod 64 */
379
312
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
380
381
  /* Update number of bits */
382
312
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
383
33
    context->count[1]++;
384
33
  }
385
312
  context->count[1] += (uint32_t) (inputLen >> 29);
386
387
312
  partLen = 64 - index;
388
389
  /* Transform as many times as possible.
390
   */
391
312
  if (inputLen >= partLen) {
392
205
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
393
205
    RIPEMD256Transform(context->state, context->buffer);
394
395
26.7k
    for (i = partLen; i + 63 < inputLen; i += 64) {
396
26.5k
      RIPEMD256Transform(context->state, &input[i]);
397
26.5k
    }
398
399
205
    index = 0;
400
205
  } else {
401
107
    i = 0;
402
107
  }
403
404
  /* Buffer remaining input */
405
312
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
406
312
}
407
/* }}} */
408
409
/* {{{ RIPEMD160Transform
410
 * ripemd160 basic transformation. Transforms state based on block.
411
 */
412
static void RIPEMD160Transform(uint32_t state[5], const unsigned char block[64])
413
1.44k
{
414
1.44k
  uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3], e  = state[4];
415
1.44k
  uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4];
416
1.44k
  uint32_t tmp, x[16];
417
1.44k
  int j;
418
419
1.44k
  RIPEMDDecode(x, block, 64);
420
421
24.5k
  for(j = 0; j < 16; j++) {
422
23.1k
    tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j)) + e;
423
23.1k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
424
23.1k
    tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
425
23.1k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
426
23.1k
  }
427
428
24.5k
  for(j = 16; j < 32; j++) {
429
23.1k
    tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j)) + e;
430
23.1k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
431
23.1k
    tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
432
23.1k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
433
23.1k
  }
434
435
24.5k
  for(j = 32; j < 48; j++) {
436
23.1k
    tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j)) + e;
437
23.1k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
438
23.1k
    tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
439
23.1k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
440
23.1k
  }
441
442
24.5k
  for(j = 48; j < 64; j++) {
443
23.1k
    tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j)) + e;
444
23.1k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
445
23.1k
    tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
446
23.1k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
447
23.1k
  }
448
449
24.5k
  for(j = 64; j < 80; j++) {
450
23.1k
    tmp = ROLS( j, a  + F4(b,  c,  d)  + x[R[j]]  + K(j)) + e;
451
23.1k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
452
23.1k
    tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
453
23.1k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
454
23.1k
  }
455
456
1.44k
  tmp = state[1] + c + dd;
457
1.44k
  state[1] = state[2] + d + ee;
458
1.44k
  state[2] = state[3] + e + aa;
459
1.44k
  state[3] = state[4] + a + bb;
460
1.44k
  state[4] = state[0] + b + cc;
461
1.44k
  state[0] = tmp;
462
463
1.44k
  tmp = 0;
464
1.44k
  ZEND_SECURE_ZERO(x, sizeof(x));
465
1.44k
}
466
/* }}} */
467
468
/* {{{ PHP_RIPEMD160Update
469
   ripemd160 block update operation. Continues a ripemd160 message-digest
470
   operation, processing another message block, and updating the
471
   context.
472
 */
473
PHP_HASH_API void PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context, const unsigned char *input, size_t inputLen)
474
237
{
475
237
  unsigned int index, partLen;
476
237
  size_t i;
477
478
  /* Compute number of bytes mod 64 */
479
237
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
480
481
  /* Update number of bits */
482
237
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
483
28
    context->count[1]++;
484
28
  }
485
237
  context->count[1] += (uint32_t) (inputLen >> 29);
486
487
237
  partLen = 64 - index;
488
489
  /* Transform as many times as possible.
490
   */
491
237
  if (inputLen >= partLen) {
492
146
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
493
146
    RIPEMD160Transform(context->state, context->buffer);
494
495
1.44k
    for (i = partLen; i + 63 < inputLen; i += 64) {
496
1.29k
      RIPEMD160Transform(context->state, &input[i]);
497
1.29k
    }
498
499
146
    index = 0;
500
146
  } else {
501
91
    i = 0;
502
91
  }
503
504
  /* Buffer remaining input */
505
237
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
506
237
}
507
/* }}} */
508
509
/* {{{ RIPEMD320Transform
510
 * ripemd320 basic transformation. Transforms state based on block.
511
 */
512
static void RIPEMD320Transform(uint32_t state[10], const unsigned char block[64])
513
50.1k
{
514
50.1k
  uint32_t a  = state[0], b  = state[1], c  = state[2], d  = state[3], e  = state[4];
515
50.1k
  uint32_t aa = state[5], bb = state[6], cc = state[7], dd = state[8], ee = state[9];
516
50.1k
  uint32_t tmp, x[16];
517
50.1k
  int j;
518
519
50.1k
  RIPEMDDecode(x, block, 64);
520
521
852k
  for(j = 0; j < 16; j++) {
522
802k
    tmp = ROLS( j, a  + F0(b,  c,  d)  + x[R[j]]  + K(j)) + e;
523
802k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
524
802k
    tmp = ROLSS(j, aa + F4(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
525
802k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
526
802k
  }
527
50.1k
  tmp = b; b = bb; bb = tmp;
528
529
852k
  for(j = 16; j < 32; j++) {
530
802k
    tmp = ROLS( j, a  + F1(b,  c,  d)  + x[R[j]]  + K(j)) + e;
531
802k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
532
802k
    tmp = ROLSS(j, aa + F3(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
533
802k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
534
802k
  }
535
50.1k
  tmp = d; d = dd; dd = tmp;
536
537
852k
  for(j = 32; j < 48; j++) {
538
802k
    tmp = ROLS( j, a  + F2(b,  c,  d)  + x[R[j]]  + K(j)) + e;
539
802k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
540
802k
    tmp = ROLSS(j, aa + F2(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
541
802k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
542
802k
  }
543
50.1k
  tmp = a; a = aa; aa = tmp;
544
545
852k
  for(j = 48; j < 64; j++) {
546
802k
    tmp = ROLS( j, a  + F3(b,  c,  d)  + x[R[j]]  + K(j)) + e;
547
802k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
548
802k
    tmp = ROLSS(j, aa + F1(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
549
802k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
550
802k
  }
551
50.1k
  tmp = c; c = cc; cc = tmp;
552
553
852k
  for(j = 64; j < 80; j++) {
554
802k
    tmp = ROLS( j, a  + F4(b,  c,  d)  + x[R[j]]  + K(j)) + e;
555
802k
    a = e; e = d; d = ROL(10, c); c = b; b = tmp;
556
802k
    tmp = ROLSS(j, aa + F0(bb, cc, dd) + x[RR[j]] + KK160(j)) + ee;
557
802k
    aa = ee; ee = dd; dd = ROL(10, cc); cc = bb; bb = tmp;
558
802k
  }
559
50.1k
  tmp = e; e = ee; ee = tmp;
560
561
50.1k
  state[0] += a;
562
50.1k
  state[1] += b;
563
50.1k
  state[2] += c;
564
50.1k
  state[3] += d;
565
50.1k
  state[4] += e;
566
50.1k
  state[5] += aa;
567
50.1k
  state[6] += bb;
568
50.1k
  state[7] += cc;
569
50.1k
  state[8] += dd;
570
50.1k
  state[9] += ee;
571
572
50.1k
  tmp = 0;
573
50.1k
  ZEND_SECURE_ZERO(x, sizeof(x));
574
50.1k
}
575
/* }}} */
576
577
/* {{{ PHP_RIPEMD320Update
578
   ripemd320 block update operation. Continues a ripemd320 message-digest
579
   operation, processing another message block, and updating the
580
   context.
581
 */
582
PHP_HASH_API void PHP_RIPEMD320Update(PHP_RIPEMD320_CTX * context, const unsigned char *input, size_t inputLen)
583
300
{
584
300
  unsigned int index, partLen;
585
300
  size_t i;
586
587
  /* Compute number of bytes mod 64 */
588
300
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
589
590
  /* Update number of bits */
591
300
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
592
48
    context->count[1]++;
593
48
  }
594
300
  context->count[1] += (uint32_t) (inputLen >> 29);
595
596
300
  partLen = 64 - index;
597
598
  /* Transform as many times as possible.
599
   */
600
300
  if (inputLen >= partLen) {
601
196
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
602
196
    RIPEMD320Transform(context->state, context->buffer);
603
604
50.1k
    for (i = partLen; i + 63 < inputLen; i += 64) {
605
49.9k
      RIPEMD320Transform(context->state, &input[i]);
606
49.9k
    }
607
608
196
    index = 0;
609
196
  } else {
610
104
    i = 0;
611
104
  }
612
613
  /* Buffer remaining input */
614
300
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
615
300
}
616
/* }}} */
617
618
static const unsigned char PADDING[64] =
619
{
620
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
621
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
622
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
623
};
624
625
/* {{{ RIPEMDEncode
626
   Encodes input (uint32_t) into output (unsigned char). Assumes len is
627
   a multiple of 4.
628
 */
629
static void RIPEMDEncode(unsigned char *output, uint32_t *input, unsigned int len)
630
371
{
631
371
  unsigned int i, j;
632
633
2.95k
  for (i = 0, j = 0; j < len; i++, j += 4) {
634
2.57k
    output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
635
2.57k
    output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
636
2.57k
    output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
637
2.57k
    output[j + 0] = (unsigned char) (input[i] & 0xff);
638
2.57k
  }
639
371
}
640
/* }}} */
641
642
/* {{{ PHP_RIPEMD128Final
643
   ripemd128 finalization. Ends a ripemd128 message-digest operation, writing the
644
   the message digest and zeroizing the context.
645
 */
646
PHP_HASH_API void PHP_RIPEMD128Final(unsigned char digest[16], PHP_RIPEMD128_CTX * context)
647
88
{
648
88
  unsigned char bits[8];
649
88
  unsigned int index, padLen;
650
651
  /* Save number of bits */
652
88
  bits[0] = (unsigned char) (context->count[0] & 0xFF);
653
88
  bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
654
88
  bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
655
88
  bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
656
88
  bits[4] = (unsigned char) (context->count[1] & 0xFF);
657
88
  bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
658
88
  bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
659
88
  bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
660
661
  /* Pad out to 56 mod 64.
662
   */
663
88
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
664
88
  padLen = (index < 56) ? (56 - index) : (120 - index);
665
88
  PHP_RIPEMD128Update(context, PADDING, padLen);
666
667
  /* Append length (before padding) */
668
88
  PHP_RIPEMD128Update(context, bits, 8);
669
670
  /* Store state in digest */
671
88
  RIPEMDEncode(digest, context->state, 16);
672
673
  /* Zeroize sensitive information.
674
   */
675
88
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
676
88
}
677
/* }}} */
678
679
/* {{{ PHP_RIPEMD256Final
680
   ripemd256 finalization. Ends a ripemd256 message-digest operation, writing the
681
   the message digest and zeroizing the context.
682
 */
683
PHP_HASH_API void PHP_RIPEMD256Final(unsigned char digest[32], PHP_RIPEMD256_CTX * context)
684
104
{
685
104
  unsigned char bits[8];
686
104
  unsigned int index, padLen;
687
688
  /* Save number of bits */
689
104
  bits[0] = (unsigned char) (context->count[0] & 0xFF);
690
104
  bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
691
104
  bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
692
104
  bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
693
104
  bits[4] = (unsigned char) (context->count[1] & 0xFF);
694
104
  bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
695
104
  bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
696
104
  bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
697
698
  /* Pad out to 56 mod 64.
699
   */
700
104
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
701
104
  padLen = (index < 56) ? (56 - index) : (120 - index);
702
104
  PHP_RIPEMD256Update(context, PADDING, padLen);
703
704
  /* Append length (before padding) */
705
104
  PHP_RIPEMD256Update(context, bits, 8);
706
707
  /* Store state in digest */
708
104
  RIPEMDEncode(digest, context->state, 32);
709
710
  /* Zeroize sensitive information.
711
   */
712
104
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
713
104
}
714
/* }}} */
715
716
/* {{{ PHP_RIPEMD160Final
717
   ripemd160 finalization. Ends a ripemd160 message-digest operation, writing the
718
   the message digest and zeroizing the context.
719
 */
720
PHP_HASH_API void PHP_RIPEMD160Final(unsigned char digest[20], PHP_RIPEMD160_CTX * context)
721
79
{
722
79
  unsigned char bits[8];
723
79
  unsigned int index, padLen;
724
725
  /* Save number of bits */
726
79
  bits[0] = (unsigned char) (context->count[0] & 0xFF);
727
79
  bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
728
79
  bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
729
79
  bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
730
79
  bits[4] = (unsigned char) (context->count[1] & 0xFF);
731
79
  bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
732
79
  bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
733
79
  bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
734
735
  /* Pad out to 56 mod 64.
736
   */
737
79
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
738
79
  padLen = (index < 56) ? (56 - index) : (120 - index);
739
79
  PHP_RIPEMD160Update(context, PADDING, padLen);
740
741
  /* Append length (before padding) */
742
79
  PHP_RIPEMD160Update(context, bits, 8);
743
744
  /* Store state in digest */
745
79
  RIPEMDEncode(digest, context->state, 20);
746
747
  /* Zeroize sensitive information.
748
   */
749
79
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
750
79
}
751
/* }}} */
752
753
/* {{{ PHP_RIPEMD320Final
754
   ripemd320 finalization. Ends a ripemd320 message-digest operation, writing the
755
   the message digest and zeroizing the context.
756
 */
757
PHP_HASH_API void PHP_RIPEMD320Final(unsigned char digest[40], PHP_RIPEMD320_CTX * context)
758
100
{
759
100
  unsigned char bits[8];
760
100
  unsigned int index, padLen;
761
762
  /* Save number of bits */
763
100
  bits[0] = (unsigned char) (context->count[0] & 0xFF);
764
100
  bits[1] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
765
100
  bits[2] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
766
100
  bits[3] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
767
100
  bits[4] = (unsigned char) (context->count[1] & 0xFF);
768
100
  bits[5] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
769
100
  bits[6] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
770
100
  bits[7] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
771
772
  /* Pad out to 56 mod 64.
773
   */
774
100
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
775
100
  padLen = (index < 56) ? (56 - index) : (120 - index);
776
100
  PHP_RIPEMD320Update(context, PADDING, padLen);
777
778
  /* Append length (before padding) */
779
100
  PHP_RIPEMD320Update(context, bits, 8);
780
781
  /* Store state in digest */
782
100
  RIPEMDEncode(digest, context->state, 40);
783
784
  /* Zeroize sensitive information.
785
   */
786
100
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
787
100
}
788
/* }}} */