Coverage Report

Created: 2026-06-02 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/hash/hash_sha.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
  | Authors: Steffan Esser <sesser@php.net>                              |
12
  |          Sara Golemon <pollita@php.net>                              |
13
  +----------------------------------------------------------------------+
14
*/
15
16
#include "php_hash.h"
17
#include "php_hash_sha.h"
18
#include "Zend/zend_cpuinfo.h"
19
20
static const unsigned char PADDING[128] =
21
{
22
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
30
};
31
32
/* {{{ SHAEncode32
33
   Encodes input (uint32_t) into output (unsigned char). Assumes len is
34
   a multiple of 4.
35
 */
36
static void SHAEncode32(unsigned char *output, uint32_t *input, unsigned int len)
37
54
{
38
54
  unsigned int i, j;
39
40
468
  for (i = 0, j = 0; j < len; i++, j += 4) {
41
414
    output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
42
414
    output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
43
414
    output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
44
414
    output[j + 3] = (unsigned char) (input[i] & 0xff);
45
414
  }
46
54
}
47
/* }}} */
48
49
50
/* {{{ SHADecode32
51
   Decodes input (unsigned char) into output (uint32_t). Assumes len is
52
   a multiple of 4.
53
 */
54
static void SHADecode32(uint32_t *output, const unsigned char *input, unsigned int len)
55
0
{
56
0
  unsigned int i, j;
57
0
58
0
  for (i = 0, j = 0; j < len; i++, j += 4)
59
0
    output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) |
60
0
      (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24);
61
0
}
62
/* }}} */
63
64
const php_hash_ops php_hash_sha1_ops = {
65
  "sha1",
66
  (php_hash_init_func_t) PHP_SHA1InitArgs,
67
  (php_hash_update_func_t) PHP_SHA1Update,
68
  (php_hash_final_func_t) PHP_SHA1Final,
69
  php_hash_copy,
70
  php_hash_serialize,
71
  php_hash_unserialize,
72
  PHP_SHA1_SPEC,
73
  20,
74
  64,
75
  sizeof(PHP_SHA1_CTX),
76
  1
77
};
78
79
/* sha224/sha256 */
80
81
const php_hash_ops php_hash_sha256_ops = {
82
  "sha256",
83
  (php_hash_init_func_t) PHP_SHA256InitArgs,
84
  (php_hash_update_func_t) PHP_SHA256Update,
85
  (php_hash_final_func_t) PHP_SHA256Final,
86
  php_hash_copy,
87
  php_hash_serialize,
88
  php_hash_unserialize,
89
  PHP_SHA256_SPEC,
90
  32,
91
  64,
92
  sizeof(PHP_SHA256_CTX),
93
  1
94
};
95
96
const php_hash_ops php_hash_sha224_ops = {
97
  "sha224",
98
  (php_hash_init_func_t) PHP_SHA224InitArgs,
99
  (php_hash_update_func_t) PHP_SHA224Update,
100
  (php_hash_final_func_t) PHP_SHA224Final,
101
  php_hash_copy,
102
  php_hash_serialize,
103
  php_hash_unserialize,
104
  PHP_SHA224_SPEC,
105
  28,
106
  64,
107
  sizeof(PHP_SHA224_CTX),
108
  1
109
};
110
111
0
#define ROTR32(b,x)   ((x >> b) | (x << (32 - b)))
112
38.8M
#define ROTR64(b,x)   ((x >> b) | (x << (64 - b)))
113
6.76M
#define SHR(b, x)   (x >> b)
114
115
/* Ch */
116
0
#define SHA256_F0(x,y,z)  (((x) & (y)) ^ ((~(x)) & (z)))
117
/* Maj */
118
0
#define SHA256_F1(x,y,z)  (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
119
/* SUM0 */
120
0
#define SHA256_F2(x)    (ROTR32( 2,(x)) ^ ROTR32(13,(x)) ^ ROTR32(22,(x)))
121
/* SUM1 */
122
0
#define SHA256_F3(x)    (ROTR32( 6,(x)) ^ ROTR32(11,(x)) ^ ROTR32(25,(x)))
123
/* OM0 */
124
0
#define SHA256_F4(x)    (ROTR32( 7,(x)) ^ ROTR32(18,(x)) ^ SHR( 3,(x)))
125
/* OM1 */
126
0
#define SHA256_F5(x)    (ROTR32(17,(x)) ^ ROTR32(19,(x)) ^ SHR(10,(x)))
127
128
static const uint32_t SHA256_K[64] = {
129
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
130
  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
131
  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
132
  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
133
  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
134
  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
135
  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
136
  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
137
138
/* {{{ PHP_SHA256InitArgs
139
 * SHA256 initialization. Begins an SHA256 operation, writing a new context.
140
 */
141
PHP_HASH_API void PHP_SHA256InitArgs(PHP_SHA256_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
142
40
{
143
40
  context->count[0] = context->count[1] = 0;
144
  /* Load magic initialization constants.
145
   */
146
40
  context->state[0] = 0x6a09e667;
147
40
  context->state[1] = 0xbb67ae85;
148
40
  context->state[2] = 0x3c6ef372;
149
40
  context->state[3] = 0xa54ff53a;
150
40
  context->state[4] = 0x510e527f;
151
40
  context->state[5] = 0x9b05688c;
152
40
  context->state[6] = 0x1f83d9ab;
153
40
  context->state[7] = 0x5be0cd19;
154
40
}
155
/* }}} */
156
157
/* {{{ SHA256Transform
158
 * SHA256 basic transformation. Transforms state based on block.
159
 */
160
static void SHA256Transform(uint32_t state[8], const unsigned char block[64])
161
18.4k
{
162
#if defined(PHP_HASH_INTRIN_SHA_NATIVE)
163
  SHA256_Transform_shani(state, block);
164
  return;
165
#elif defined(PHP_HASH_INTRIN_SHA_RESOLVER)
166
18.4k
  if (zend_cpu_supports(ZEND_CPU_FEATURE_SSSE3) && zend_cpu_supports(ZEND_CPU_FEATURE_SHA)) {
167
18.4k
    SHA256_Transform_shani(state, block);
168
18.4k
    return;
169
18.4k
  }
170
0
#endif
171
172
0
#if defined(__SSE2__)
173
0
  uint32_t tmp32[72];
174
175
0
  SHA256_Transform_sse2(state, block, &tmp32[0], &tmp32[64]);
176
0
  ZEND_SECURE_ZERO((unsigned char*) tmp32, sizeof(tmp32));
177
0
  return;
178
0
#endif
179
180
0
  uint32_t a = state[0], b = state[1], c = state[2], d = state[3];
181
0
  uint32_t e = state[4], f = state[5], g = state[6], h = state[7];
182
0
  uint32_t x[16], T1, T2, W[64];
183
0
  int i;
184
185
0
  SHADecode32(x, block, 64);
186
187
  /* Schedule */
188
0
  for(i = 0; i < 16; i++) {
189
0
    W[i] = x[i];
190
0
  }
191
0
  for(i = 16; i < 64; i++) {
192
0
    W[i] = SHA256_F5(W[i-2]) + W[i-7] + SHA256_F4(W[i-15]) + W[i-16];
193
0
  }
194
195
0
  for (i = 0; i < 64; i++) {
196
0
    T1 = h + SHA256_F3(e) + SHA256_F0(e,f,g) + SHA256_K[i] + W[i];
197
0
    T2 = SHA256_F2(a) + SHA256_F1(a,b,c);
198
0
    h = g; g = f; f = e; e = d + T1;
199
0
    d = c; c = b; b = a; a = T1 + T2;
200
0
  }
201
202
0
  state[0] += a;
203
0
  state[1] += b;
204
0
  state[2] += c;
205
0
  state[3] += d;
206
0
  state[4] += e;
207
0
  state[5] += f;
208
0
  state[6] += g;
209
0
  state[7] += h;
210
211
  /* Zeroize sensitive information. */
212
0
  ZEND_SECURE_ZERO((unsigned char*) x, sizeof(x));
213
0
}
214
/* }}} */
215
216
/* {{{ PHP_SHA224InitArgs
217
 * SHA224 initialization. Begins an SHA224 operation, writing a new context.
218
 */
219
PHP_HASH_API void PHP_SHA224InitArgs(PHP_SHA224_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
220
18
{
221
18
  context->count[0] = context->count[1] = 0;
222
  /* Load magic initialization constants.
223
   */
224
18
  context->state[0] = 0xc1059ed8;
225
18
  context->state[1] = 0x367cd507;
226
18
  context->state[2] = 0x3070dd17;
227
18
  context->state[3] = 0xf70e5939;
228
18
  context->state[4] = 0xffc00b31;
229
18
  context->state[5] = 0x68581511;
230
18
  context->state[6] = 0x64f98fa7;
231
18
  context->state[7] = 0xbefa4fa4;
232
18
}
233
/* }}} */
234
235
/* {{{ PHP_SHA224Update
236
   SHA224 block update operation. Continues an SHA224 message-digest
237
   operation, processing another message block, and updating the
238
   context.
239
 */
240
PHP_HASH_API void PHP_SHA224Update(PHP_SHA224_CTX * context, const unsigned char *input, size_t inputLen)
241
54
{
242
54
  unsigned int index, partLen;
243
54
  size_t i;
244
245
  /* Compute number of bytes mod 64 */
246
54
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
247
248
  /* Update number of bits */
249
54
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
250
16
    context->count[1]++;
251
16
  }
252
54
  context->count[1] += (uint32_t) (inputLen >> 29);
253
254
54
  partLen = 64 - index;
255
256
  /* Transform as many times as possible.
257
   */
258
54
  if (inputLen >= partLen) {
259
39
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
260
39
    SHA256Transform(context->state, context->buffer);
261
262
654
    for (i = partLen; i + 63 < inputLen; i += 64) {
263
615
      SHA256Transform(context->state, &input[i]);
264
615
    }
265
266
39
    index = 0;
267
39
  } else {
268
15
    i = 0;
269
15
  }
270
271
  /* Buffer remaining input */
272
54
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
273
54
}
274
/* }}} */
275
276
/* {{{ PHP_SHA224Final
277
   SHA224 finalization. Ends an SHA224 message-digest operation, writing the
278
   the message digest and zeroizing the context.
279
 */
280
PHP_HASH_API void PHP_SHA224Final(unsigned char digest[28], PHP_SHA224_CTX * context)
281
18
{
282
18
  unsigned char bits[8];
283
18
  unsigned int index, padLen;
284
285
  /* Save number of bits */
286
18
  bits[7] = (unsigned char) (context->count[0] & 0xFF);
287
18
  bits[6] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
288
18
  bits[5] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
289
18
  bits[4] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
290
18
  bits[3] = (unsigned char) (context->count[1] & 0xFF);
291
18
  bits[2] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
292
18
  bits[1] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
293
18
  bits[0] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
294
295
  /* Pad out to 56 mod 64.
296
   */
297
18
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
298
18
  padLen = (index < 56) ? (56 - index) : (120 - index);
299
18
  PHP_SHA224Update(context, PADDING, padLen);
300
301
  /* Append length (before padding) */
302
18
  PHP_SHA224Update(context, bits, 8);
303
304
  /* Store state in digest */
305
18
  SHAEncode32(digest, context->state, 28);
306
307
  /* Zeroize sensitive information.
308
   */
309
18
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
310
18
}
311
/* }}} */
312
313
/* {{{ PHP_SHA256Update
314
   SHA256 block update operation. Continues an SHA256 message-digest
315
   operation, processing another message block, and updating the
316
   context.
317
 */
318
PHP_HASH_API void PHP_SHA256Update(PHP_SHA256_CTX * context, const unsigned char *input, size_t inputLen)
319
108
{
320
108
  unsigned int index, partLen;
321
108
  size_t i;
322
323
  /* Compute number of bytes mod 64 */
324
108
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
325
326
  /* Update number of bits */
327
108
  if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
328
33
    context->count[1]++;
329
33
  }
330
108
  context->count[1] += (uint32_t) (inputLen >> 29);
331
332
108
  partLen = 64 - index;
333
334
  /* Transform as many times as possible.
335
   */
336
108
  if (inputLen >= partLen) {
337
82
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
338
82
    SHA256Transform(context->state, context->buffer);
339
340
17.7k
    for (i = partLen; i + 63 < inputLen; i += 64) {
341
17.6k
      SHA256Transform(context->state, &input[i]);
342
17.6k
    }
343
344
82
    index = 0;
345
82
  } else {
346
26
    i = 0;
347
26
  }
348
349
  /* Buffer remaining input */
350
108
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
351
108
}
352
/* }}} */
353
354
/* {{{ PHP_SHA256Final
355
   SHA256 finalization. Ends an SHA256 message-digest operation, writing the
356
   the message digest and zeroizing the context.
357
 */
358
PHP_HASH_API void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * context)
359
36
{
360
36
  unsigned char bits[8];
361
36
  unsigned int index, padLen;
362
363
  /* Save number of bits */
364
36
  bits[7] = (unsigned char) (context->count[0] & 0xFF);
365
36
  bits[6] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
366
36
  bits[5] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
367
36
  bits[4] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
368
36
  bits[3] = (unsigned char) (context->count[1] & 0xFF);
369
36
  bits[2] = (unsigned char) ((context->count[1] >> 8) & 0xFF);
370
36
  bits[1] = (unsigned char) ((context->count[1] >> 16) & 0xFF);
371
36
  bits[0] = (unsigned char) ((context->count[1] >> 24) & 0xFF);
372
373
  /* Pad out to 56 mod 64.
374
   */
375
36
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
376
36
  padLen = (index < 56) ? (56 - index) : (120 - index);
377
36
  PHP_SHA256Update(context, PADDING, padLen);
378
379
  /* Append length (before padding) */
380
36
  PHP_SHA256Update(context, bits, 8);
381
382
  /* Store state in digest */
383
36
  SHAEncode32(digest, context->state, 32);
384
385
  /* Zeroize sensitive information.
386
   */
387
36
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
388
36
}
389
/* }}} */
390
391
/* sha384/sha512 */
392
393
/* Ch */
394
4.22M
#define SHA512_F0(x,y,z)    (((x) & (y)) ^ ((~(x)) & (z)))
395
/* Maj */
396
4.22M
#define SHA512_F1(x,y,z)    (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
397
/* SUM0 */
398
4.22M
#define SHA512_F2(x)      (ROTR64(28, x) ^ ROTR64(34, x) ^ ROTR64(39, x))
399
/* SUM1 */
400
4.22M
#define SHA512_F3(x)      (ROTR64(14, x) ^ ROTR64(18, x) ^ ROTR64(41, x))
401
/* OM0 */
402
3.38M
#define SHA512_F4(x)      (ROTR64( 1, x) ^ ROTR64( 8, x) ^ SHR(7, x))
403
/* OM1 */
404
3.38M
#define SHA512_F5(x)      (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR(6, x))
405
406
static const uint64_t SHA512_K[128] = {
407
  L64(0x428a2f98d728ae22), L64(0x7137449123ef65cd), L64(0xb5c0fbcfec4d3b2f), L64(0xe9b5dba58189dbbc),
408
  L64(0x3956c25bf348b538), L64(0x59f111f1b605d019), L64(0x923f82a4af194f9b), L64(0xab1c5ed5da6d8118),
409
  L64(0xd807aa98a3030242), L64(0x12835b0145706fbe), L64(0x243185be4ee4b28c), L64(0x550c7dc3d5ffb4e2),
410
  L64(0x72be5d74f27b896f), L64(0x80deb1fe3b1696b1), L64(0x9bdc06a725c71235), L64(0xc19bf174cf692694),
411
  L64(0xe49b69c19ef14ad2), L64(0xefbe4786384f25e3), L64(0x0fc19dc68b8cd5b5), L64(0x240ca1cc77ac9c65),
412
  L64(0x2de92c6f592b0275), L64(0x4a7484aa6ea6e483), L64(0x5cb0a9dcbd41fbd4), L64(0x76f988da831153b5),
413
  L64(0x983e5152ee66dfab), L64(0xa831c66d2db43210), L64(0xb00327c898fb213f), L64(0xbf597fc7beef0ee4),
414
  L64(0xc6e00bf33da88fc2), L64(0xd5a79147930aa725), L64(0x06ca6351e003826f), L64(0x142929670a0e6e70),
415
  L64(0x27b70a8546d22ffc), L64(0x2e1b21385c26c926), L64(0x4d2c6dfc5ac42aed), L64(0x53380d139d95b3df),
416
  L64(0x650a73548baf63de), L64(0x766a0abb3c77b2a8), L64(0x81c2c92e47edaee6), L64(0x92722c851482353b),
417
  L64(0xa2bfe8a14cf10364), L64(0xa81a664bbc423001), L64(0xc24b8b70d0f89791), L64(0xc76c51a30654be30),
418
  L64(0xd192e819d6ef5218), L64(0xd69906245565a910), L64(0xf40e35855771202a), L64(0x106aa07032bbd1b8),
419
  L64(0x19a4c116b8d2d0c8), L64(0x1e376c085141ab53), L64(0x2748774cdf8eeb99), L64(0x34b0bcb5e19b48a8),
420
  L64(0x391c0cb3c5c95a63), L64(0x4ed8aa4ae3418acb), L64(0x5b9cca4f7763e373), L64(0x682e6ff3d6b2b8a3),
421
  L64(0x748f82ee5defb2fc), L64(0x78a5636f43172f60), L64(0x84c87814a1f0ab72), L64(0x8cc702081a6439ec),
422
  L64(0x90befffa23631e28), L64(0xa4506cebde82bde9), L64(0xbef9a3f7b2c67915), L64(0xc67178f2e372532b),
423
  L64(0xca273eceea26619c), L64(0xd186b8c721c0c207), L64(0xeada7dd6cde0eb1e), L64(0xf57d4f7fee6ed178),
424
  L64(0x06f067aa72176fba), L64(0x0a637dc5a2c898a6), L64(0x113f9804bef90dae), L64(0x1b710b35131c471b),
425
  L64(0x28db77f523047d84), L64(0x32caab7b40c72493), L64(0x3c9ebe0a15c9bebc), L64(0x431d67c49c100d4c),
426
  L64(0x4cc5d4becb3e42b6), L64(0x597f299cfc657e2a), L64(0x5fcb6fab3ad6faec), L64(0x6c44198c4a475817) };
427
428
/* {{{ SHAEncode64
429
   Encodes input (uint64_t) into output (unsigned char). Assumes len is
430
   a multiple of 8.
431
 */
432
static void SHAEncode64(unsigned char *output, uint64_t *input, unsigned int len)
433
280
{
434
280
  unsigned int i, j;
435
436
2.27k
  for (i = 0, j = 0; j < len; i++, j += 8) {
437
1.99k
    output[j] = (unsigned char) ((input[i] >> 56) & 0xff);
438
1.99k
    output[j + 1] = (unsigned char) ((input[i] >> 48) & 0xff);
439
1.99k
    output[j + 2] = (unsigned char) ((input[i] >> 40) & 0xff);
440
1.99k
    output[j + 3] = (unsigned char) ((input[i] >> 32) & 0xff);
441
1.99k
    output[j + 4] = (unsigned char) ((input[i] >> 24) & 0xff);
442
1.99k
    output[j + 5] = (unsigned char) ((input[i] >> 16) & 0xff);
443
1.99k
    output[j + 6] = (unsigned char) ((input[i] >> 8) & 0xff);
444
1.99k
    output[j + 7] = (unsigned char) (input[i] & 0xff);
445
1.99k
  }
446
280
}
447
/* }}} */
448
449
450
/* {{{ SHADecode64
451
   Decodes input (unsigned char) into output (uint64_t). Assumes len is
452
   a multiple of 8.
453
 */
454
static void SHADecode64(uint64_t *output, const unsigned char *input, unsigned int len)
455
52.8k
{
456
52.8k
  unsigned int i, j;
457
458
897k
  for (i = 0, j = 0; j < len; i++, j += 8)
459
845k
    output[i] =
460
845k
      ((uint64_t) input[j + 7]) | (((uint64_t) input[j + 6]) << 8) |
461
845k
      (((uint64_t) input[j + 5]) << 16) | (((uint64_t) input[j + 4]) << 24) |
462
845k
      (((uint64_t) input[j + 3]) << 32) | (((uint64_t) input[j + 2]) << 40) |
463
845k
      (((uint64_t) input[j + 1]) << 48) | (((uint64_t) input[j]) << 56);
464
52.8k
}
465
/* }}} */
466
467
/* {{{ PHP_SHA384InitArgs
468
 * SHA384 initialization. Begins an SHA384 operation, writing a new context.
469
 */
470
PHP_HASH_API void PHP_SHA384InitArgs(PHP_SHA384_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
471
126
{
472
126
  context->count[0] = context->count[1] = 0;
473
  /* Load magic initialization constants.
474
   */
475
126
  context->state[0] = L64(0xcbbb9d5dc1059ed8);
476
126
  context->state[1] = L64(0x629a292a367cd507);
477
126
  context->state[2] = L64(0x9159015a3070dd17);
478
126
  context->state[3] = L64(0x152fecd8f70e5939);
479
126
  context->state[4] = L64(0x67332667ffc00b31);
480
126
  context->state[5] = L64(0x8eb44a8768581511);
481
126
  context->state[6] = L64(0xdb0c2e0d64f98fa7);
482
126
  context->state[7] = L64(0x47b5481dbefa4fa4);
483
126
}
484
/* }}} */
485
486
/* {{{ SHA512Transform
487
 * SHA512 basic transformation. Transforms state based on block.
488
 * SHA384 uses the exact same algorithm
489
 */
490
static void SHA512Transform(uint64_t state[8], const unsigned char block[128])
491
52.8k
{
492
52.8k
  uint64_t a = state[0], b = state[1], c = state[2], d = state[3];
493
52.8k
  uint64_t e = state[4], f = state[5], g = state[6], h = state[7];
494
52.8k
  uint64_t x[16], T1, T2, W[80];
495
52.8k
  int i;
496
497
52.8k
  SHADecode64(x, block, 128);
498
499
  /* Schedule */
500
897k
  for(i = 0; i < 16; i++) {
501
845k
    W[i] = x[i];
502
845k
  }
503
3.43M
  for(i = 16; i < 80; i++) {
504
3.38M
    W[i] = SHA512_F5(W[i-2]) + W[i-7] + SHA512_F4(W[i-15]) + W[i-16];
505
3.38M
  }
506
507
4.27M
  for (i = 0; i < 80; i++) {
508
4.22M
    T1 = h + SHA512_F3(e) + SHA512_F0(e,f,g) + SHA512_K[i] + W[i];
509
4.22M
    T2 = SHA512_F2(a) + SHA512_F1(a,b,c);
510
4.22M
    h = g; g = f; f = e; e = d + T1;
511
4.22M
    d = c; c = b; b = a; a = T1 + T2;
512
4.22M
  }
513
514
52.8k
  state[0] += a;
515
52.8k
  state[1] += b;
516
52.8k
  state[2] += c;
517
52.8k
  state[3] += d;
518
52.8k
  state[4] += e;
519
52.8k
  state[5] += f;
520
52.8k
  state[6] += g;
521
52.8k
  state[7] += h;
522
523
  /* Zeroize sensitive information. */
524
52.8k
  ZEND_SECURE_ZERO((unsigned char*) x, sizeof(x));
525
52.8k
}
526
/* }}} */
527
528
/* {{{ PHP_SHA384Update
529
   SHA384 block update operation. Continues an SHA384 message-digest
530
   operation, processing another message block, and updating the
531
   context.
532
 */
533
PHP_HASH_API void PHP_SHA384Update(PHP_SHA384_CTX * context, const unsigned char *input, size_t inputLen)
534
375
{
535
375
  unsigned int index, partLen;
536
375
  size_t i = 0;
537
538
  /* Compute number of bytes mod 128 */
539
375
  index = (unsigned int) ((context->count[0] >> 3) & 0x7F);
540
541
  /* Update number of bits */
542
375
  if ((context->count[0] += ((uint64_t) inputLen << 3)) < ((uint64_t) inputLen << 3)) {
543
31
    context->count[1]++;
544
31
  }
545
  /* The cast may seem unnecessary, but on 32-bit this makes sure the result is 0 without invoking undefined behaviour. */
546
375
  context->count[1] += (uint64_t) inputLen >> 61;
547
548
375
  partLen = 128 - index;
549
550
  /* Transform as many times as possible.
551
   */
552
375
  if (inputLen >= partLen) {
553
228
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
554
228
    SHA512Transform(context->state, context->buffer);
555
556
22.8k
    for (i = partLen; i + 127 < inputLen; i += 128) {
557
22.6k
      SHA512Transform(context->state, &input[i]);
558
22.6k
    }
559
560
228
    index = 0;
561
228
  }
562
563
  /* Buffer remaining input */
564
375
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
565
375
}
566
/* }}} */
567
568
/* {{{ PHP_SHA384Final
569
   SHA384 finalization. Ends an SHA384 message-digest operation, writing the
570
   the message digest and zeroizing the context.
571
 */
572
PHP_HASH_API void PHP_SHA384Final(unsigned char digest[48], PHP_SHA384_CTX * context)
573
125
{
574
125
  unsigned char bits[16];
575
125
  unsigned int index, padLen;
576
577
  /* Save number of bits */
578
125
  bits[15] = (unsigned char) (context->count[0] & 0xFF);
579
125
  bits[14] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
580
125
  bits[13] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
581
125
  bits[12] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
582
125
  bits[11] = (unsigned char) ((context->count[0] >> 32) & 0xFF);
583
125
  bits[10] = (unsigned char) ((context->count[0] >> 40) & 0xFF);
584
125
  bits[9]  = (unsigned char) ((context->count[0] >> 48) & 0xFF);
585
125
  bits[8]  = (unsigned char) ((context->count[0] >> 56) & 0xFF);
586
125
  bits[7]  = (unsigned char) (context->count[1] & 0xFF);
587
125
  bits[6]  = (unsigned char) ((context->count[1] >> 8) & 0xFF);
588
125
  bits[5]  = (unsigned char) ((context->count[1] >> 16) & 0xFF);
589
125
  bits[4]  = (unsigned char) ((context->count[1] >> 24) & 0xFF);
590
125
  bits[3]  = (unsigned char) ((context->count[1] >> 32) & 0xFF);
591
125
  bits[2]  = (unsigned char) ((context->count[1] >> 40) & 0xFF);
592
125
  bits[1]  = (unsigned char) ((context->count[1] >> 48) & 0xFF);
593
125
  bits[0]  = (unsigned char) ((context->count[1] >> 56) & 0xFF);
594
595
  /* Pad out to 112 mod 128.
596
   */
597
125
  index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
598
125
  padLen = (index < 112) ? (112 - index) : (240 - index);
599
125
  PHP_SHA384Update(context, PADDING, padLen);
600
601
  /* Append length (before padding) */
602
125
  PHP_SHA384Update(context, bits, 16);
603
604
  /* Store state in digest */
605
125
  SHAEncode64(digest, context->state, 48);
606
607
  /* Zeroize sensitive information.
608
   */
609
125
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
610
125
}
611
/* }}} */
612
613
const php_hash_ops php_hash_sha384_ops = {
614
  "sha384",
615
  (php_hash_init_func_t) PHP_SHA384InitArgs,
616
  (php_hash_update_func_t) PHP_SHA384Update,
617
  (php_hash_final_func_t) PHP_SHA384Final,
618
  php_hash_copy,
619
  php_hash_serialize,
620
  php_hash_unserialize,
621
  PHP_SHA384_SPEC,
622
  48,
623
  128,
624
  sizeof(PHP_SHA384_CTX),
625
  1
626
};
627
628
/* {{{ PHP_SHA512InitArgs
629
 * SHA512 initialization. Begins an SHA512 operation, writing a new context.
630
 */
631
PHP_HASH_API void PHP_SHA512InitArgs(PHP_SHA512_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
632
154
{
633
154
  context->count[0] = context->count[1] = 0;
634
  /* Load magic initialization constants.
635
   */
636
154
  context->state[0] = L64(0x6a09e667f3bcc908);
637
154
  context->state[1] = L64(0xbb67ae8584caa73b);
638
154
  context->state[2] = L64(0x3c6ef372fe94f82b);
639
154
  context->state[3] = L64(0xa54ff53a5f1d36f1);
640
154
  context->state[4] = L64(0x510e527fade682d1);
641
154
  context->state[5] = L64(0x9b05688c2b3e6c1f);
642
154
  context->state[6] = L64(0x1f83d9abfb41bd6b);
643
154
  context->state[7] = L64(0x5be0cd19137e2179);
644
154
}
645
/* }}} */
646
647
/* {{{ PHP_SHA512_256InitArgs
648
 * SHA512/245 initialization. Identical algorithm to SHA512, using alternate initval and truncation
649
 */
650
PHP_HASH_API void PHP_SHA512_256InitArgs(PHP_SHA512_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
651
1
{
652
1
  context->count[0] = context->count[1] = 0;
653
654
1
  context->state[0] = L64(0x22312194FC2BF72C);
655
1
  context->state[1] = L64(0x9F555FA3C84C64C2);
656
1
  context->state[2] = L64(0x2393B86B6F53B151);
657
1
  context->state[3] = L64(0x963877195940EABD);
658
1
  context->state[4] = L64(0x96283EE2A88EFFE3);
659
1
  context->state[5] = L64(0xBE5E1E2553863992);
660
1
  context->state[6] = L64(0x2B0199FC2C85B8AA);
661
1
  context->state[7] = L64(0x0EB72DDC81C52CA2);
662
1
}
663
/* }}} */
664
665
/* {{{ PHP_SHA512_224InitArgs
666
 * SHA512/224 initialization. Identical algorithm to SHA512, using alternate initval and truncation
667
 */
668
PHP_HASH_API void PHP_SHA512_224InitArgs(PHP_SHA512_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
669
1
{
670
1
        context->count[0] = context->count[1] = 0;
671
672
1
  context->state[0] = L64(0x8C3D37C819544DA2);
673
1
  context->state[1] = L64(0x73E1996689DCD4D6);
674
1
  context->state[2] = L64(0x1DFAB7AE32FF9C82);
675
1
  context->state[3] = L64(0x679DD514582F9FCF);
676
1
  context->state[4] = L64(0x0F6D2B697BD44DA8);
677
1
  context->state[5] = L64(0x77E36F7304C48942);
678
1
  context->state[6] = L64(0x3F9D85A86A1D36C8);
679
1
  context->state[7] = L64(0x1112E6AD91D692A1);
680
1
}
681
/* }}} */
682
683
/* {{{ PHP_SHA512Update
684
   SHA512 block update operation. Continues an SHA512 message-digest
685
   operation, processing another message block, and updating the
686
   context.
687
 */
688
PHP_HASH_API void PHP_SHA512Update(PHP_SHA512_CTX * context, const unsigned char *input, size_t inputLen)
689
465
{
690
465
  unsigned int index, partLen;
691
465
  size_t i;
692
693
  /* Compute number of bytes mod 128 */
694
465
  index = (unsigned int) ((context->count[0] >> 3) & 0x7F);
695
696
  /* Update number of bits */
697
465
  if ((context->count[0] += ((uint64_t) inputLen << 3)) < ((uint64_t) inputLen << 3)) {
698
29
    context->count[1]++;
699
29
  }
700
  /* The cast may seem unnecessary, but on 32-bit this makes sure the result is 0 without invoking undefined behaviour. */
701
465
  context->count[1] += (uint64_t) inputLen >> 61;
702
703
465
  partLen = 128 - index;
704
705
  /* Transform as many times as possible.
706
   */
707
465
  if (inputLen >= partLen) {
708
312
    memcpy((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
709
312
    SHA512Transform(context->state, context->buffer);
710
711
29.9k
    for (i = partLen; i + 127 < inputLen; i += 128) {
712
29.6k
      SHA512Transform(context->state, &input[i]);
713
29.6k
    }
714
715
312
    index = 0;
716
312
  } else {
717
153
    i = 0;
718
153
  }
719
720
  /* Buffer remaining input */
721
465
  memcpy((unsigned char*) & context->buffer[index], (unsigned char*) & input[i], inputLen - i);
722
465
}
723
/* }}} */
724
725
/* {{{ PHP_SHA512Final
726
   SHA512 finalization. Ends an SHA512 message-digest operation, writing the
727
   the message digest and zeroizing the context.
728
 */
729
PHP_HASH_API void PHP_SHA512Final(unsigned char digest[64], PHP_SHA512_CTX * context)
730
155
{
731
155
  unsigned char bits[16];
732
155
  unsigned int index, padLen;
733
734
  /* Save number of bits */
735
155
  bits[15] = (unsigned char) (context->count[0] & 0xFF);
736
155
  bits[14] = (unsigned char) ((context->count[0] >> 8) & 0xFF);
737
155
  bits[13] = (unsigned char) ((context->count[0] >> 16) & 0xFF);
738
155
  bits[12] = (unsigned char) ((context->count[0] >> 24) & 0xFF);
739
155
  bits[11] = (unsigned char) ((context->count[0] >> 32) & 0xFF);
740
155
  bits[10] = (unsigned char) ((context->count[0] >> 40) & 0xFF);
741
155
  bits[9]  = (unsigned char) ((context->count[0] >> 48) & 0xFF);
742
155
  bits[8]  = (unsigned char) ((context->count[0] >> 56) & 0xFF);
743
155
  bits[7]  = (unsigned char) (context->count[1] & 0xFF);
744
155
  bits[6]  = (unsigned char) ((context->count[1] >> 8) & 0xFF);
745
155
  bits[5]  = (unsigned char) ((context->count[1] >> 16) & 0xFF);
746
155
  bits[4]  = (unsigned char) ((context->count[1] >> 24) & 0xFF);
747
155
  bits[3]  = (unsigned char) ((context->count[1] >> 32) & 0xFF);
748
155
  bits[2]  = (unsigned char) ((context->count[1] >> 40) & 0xFF);
749
155
  bits[1]  = (unsigned char) ((context->count[1] >> 48) & 0xFF);
750
155
  bits[0]  = (unsigned char) ((context->count[1] >> 56) & 0xFF);
751
752
  /* Pad out to 112 mod 128.
753
   */
754
155
  index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
755
155
  padLen = (index < 112) ? (112 - index) : (240 - index);
756
155
  PHP_SHA512Update(context, PADDING, padLen);
757
758
  /* Append length (before padding) */
759
155
  PHP_SHA512Update(context, bits, 16);
760
761
  /* Store state in digest */
762
155
  SHAEncode64(digest, context->state, 64);
763
764
  /* Zeroize sensitive information.
765
   */
766
155
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
767
155
}
768
/* }}} */
769
770
/* {{{ PHP_SHA512_256Final
771
   SHA512/256 finalization. Identical to SHA512Final, but with truncation
772
 */
773
PHP_HASH_API void PHP_SHA512_256Final(unsigned char digest[32], PHP_SHA512_CTX * context)
774
1
{
775
1
  unsigned char full_digest[64];
776
1
  PHP_SHA512Final(full_digest, context);
777
1
  memcpy(digest, full_digest, 32);
778
1
}
779
/* }}} */
780
781
/* {{{ PHP_SHA512_224Final
782
   SHA512/224 finalization. Identical to SHA512Final, but with truncation
783
 */
784
PHP_HASH_API void PHP_SHA512_224Final(unsigned char digest[28], PHP_SHA512_CTX * context)
785
1
{
786
1
  unsigned char full_digest[64];
787
1
  PHP_SHA512Final(full_digest, context);
788
1
  memcpy(digest, full_digest, 28);
789
1
}
790
/* }}} */
791
792
const php_hash_ops php_hash_sha512_ops = {
793
  "sha512",
794
  (php_hash_init_func_t) PHP_SHA512InitArgs,
795
  (php_hash_update_func_t) PHP_SHA512Update,
796
  (php_hash_final_func_t) PHP_SHA512Final,
797
  php_hash_copy,
798
  php_hash_serialize,
799
  php_hash_unserialize,
800
  PHP_SHA512_SPEC,
801
  64,
802
  128,
803
  sizeof(PHP_SHA512_CTX),
804
  1
805
};
806
807
const php_hash_ops php_hash_sha512_256_ops = {
808
  "sha512/256",
809
  (php_hash_init_func_t) PHP_SHA512_256InitArgs,
810
  (php_hash_update_func_t) PHP_SHA512_256Update,
811
  (php_hash_final_func_t) PHP_SHA512_256Final,
812
  php_hash_copy,
813
  php_hash_serialize,
814
  php_hash_unserialize,
815
  PHP_SHA512_SPEC,
816
  32,
817
  128,
818
  sizeof(PHP_SHA512_CTX),
819
  1
820
};
821
822
const php_hash_ops php_hash_sha512_224_ops = {
823
  "sha512/224",
824
  (php_hash_init_func_t) PHP_SHA512_224InitArgs,
825
  (php_hash_update_func_t) PHP_SHA512_224Update,
826
  (php_hash_final_func_t) PHP_SHA512_224Final,
827
  php_hash_copy,
828
  php_hash_serialize,
829
  php_hash_unserialize,
830
  PHP_SHA512_SPEC,
831
  28,
832
  128,
833
  sizeof(PHP_SHA512_CTX),
834
  1
835
};