Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/standard/sha1.c
Line
Count
Source
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: Stefan Esser <sesser@php.net>                                |
14
   +----------------------------------------------------------------------+
15
*/
16
17
#include "php.h"
18
19
/* This code is heavily based on the PHP md5 implementation */
20
21
#include "sha1.h"
22
#include "md5.h"
23
24
PHPAPI void make_sha1_digest(char *sha1str, const unsigned char *digest)
25
0
{
26
0
  make_digest_ex(sha1str, digest, 20);
27
0
}
28
29
/* {{{ Calculate the sha1 hash of a string */
30
PHP_FUNCTION(sha1)
31
0
{
32
0
  zend_string *arg;
33
0
  bool raw_output = 0;
34
0
  PHP_SHA1_CTX context;
35
0
  unsigned char digest[20];
36
37
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
38
0
    Z_PARAM_STR(arg)
39
0
    Z_PARAM_OPTIONAL
40
0
    Z_PARAM_BOOL(raw_output)
41
0
  ZEND_PARSE_PARAMETERS_END();
42
43
0
  PHP_SHA1Init(&context);
44
0
  PHP_SHA1Update(&context, (unsigned char *) ZSTR_VAL(arg), ZSTR_LEN(arg));
45
0
  PHP_SHA1Final(digest, &context);
46
0
  if (raw_output) {
47
0
    RETURN_STRINGL((char *) digest, 20);
48
0
  } else {
49
0
    RETVAL_NEW_STR(zend_string_alloc(40, 0));
50
0
    make_digest_ex(Z_STRVAL_P(return_value), digest, 20);
51
0
  }
52
53
0
}
54
55
/* }}} */
56
57
58
/* {{{ Calculate the sha1 hash of given filename */
59
PHP_FUNCTION(sha1_file)
60
0
{
61
0
  char          *arg;
62
0
  size_t           arg_len;
63
0
  bool raw_output = 0;
64
0
  unsigned char buf[1024];
65
0
  unsigned char digest[20];
66
0
  PHP_SHA1_CTX   context;
67
0
  ssize_t        n;
68
0
  php_stream    *stream;
69
70
0
  ZEND_PARSE_PARAMETERS_START(1, 2)
71
0
    Z_PARAM_PATH(arg, arg_len)
72
0
    Z_PARAM_OPTIONAL
73
0
    Z_PARAM_BOOL(raw_output)
74
0
  ZEND_PARSE_PARAMETERS_END();
75
76
0
  stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
77
0
  if (!stream) {
78
0
    RETURN_FALSE;
79
0
  }
80
81
0
  PHP_SHA1Init(&context);
82
83
0
  while ((n = php_stream_read(stream, (char *) buf, sizeof(buf))) > 0) {
84
0
    PHP_SHA1Update(&context, buf, n);
85
0
  }
86
87
0
  PHP_SHA1Final(digest, &context);
88
89
0
  php_stream_close(stream);
90
91
0
  if (raw_output) {
92
0
    RETURN_STRINGL((char *) digest, 20);
93
0
  } else {
94
0
    RETVAL_NEW_STR(zend_string_alloc(40, 0));
95
0
    make_digest_ex(Z_STRVAL_P(return_value), digest, 20);
96
0
  }
97
0
}
98
/* }}} */
99
100
101
static void SHA1Transform(uint32_t[5], const unsigned char[64]);
102
static void SHA1Encode(unsigned char *, uint32_t *, unsigned int);
103
static void SHA1Decode(uint32_t *, const unsigned char *, unsigned int);
104
105
static const unsigned char PADDING[64] =
106
{
107
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
110
};
111
112
/* F, G, H and I are basic SHA1 functions.
113
 */
114
455k
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
115
455k
#define G(x, y, z) ((x) ^ (y) ^ (z))
116
455k
#define H(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
117
455k
#define I(x, y, z) ((x) ^ (y) ^ (z))
118
119
/* ROTATE_LEFT rotates x left n bits.
120
 */
121
3.64M
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
122
123
/* W[i]
124
 */
125
#define W(i) ( tmp=x[(i-3)&15]^x[(i-8)&15]^x[(i-14)&15]^x[i&15], \
126
  (x[i&15]=ROTATE_LEFT(tmp, 1)) )
127
128
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
129
 */
130
455k
#define FF(a, b, c, d, e, w) { \
131
455k
 (e) += F ((b), (c), (d)) + (w) + (uint32_t)(0x5A827999); \
132
455k
 (e) += ROTATE_LEFT ((a), 5); \
133
455k
 (b) = ROTATE_LEFT((b), 30); \
134
455k
  }
135
455k
#define GG(a, b, c, d, e, w) { \
136
455k
 (e) += G ((b), (c), (d)) + (w) + (uint32_t)(0x6ED9EBA1); \
137
455k
 (e) += ROTATE_LEFT ((a), 5); \
138
455k
 (b) = ROTATE_LEFT((b), 30); \
139
455k
  }
140
455k
#define HH(a, b, c, d, e, w) { \
141
455k
 (e) += H ((b), (c), (d)) + (w) + (uint32_t)(0x8F1BBCDC); \
142
455k
 (e) += ROTATE_LEFT ((a), 5); \
143
455k
 (b) = ROTATE_LEFT((b), 30); \
144
455k
  }
145
455k
#define II(a, b, c, d, e, w) { \
146
455k
 (e) += I ((b), (c), (d)) + (w) + (uint32_t)(0xCA62C1D6); \
147
455k
 (e) += ROTATE_LEFT ((a), 5); \
148
455k
 (b) = ROTATE_LEFT((b), 30); \
149
455k
  }
150
151
152
/* {{{ PHP_SHA1Init
153
 * SHA1 initialization. Begins an SHA1 operation, writing a new context.
154
 */
155
PHPAPI void PHP_SHA1InitArgs(PHP_SHA1_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
156
64
{
157
64
  context->count[0] = context->count[1] = 0;
158
  /* Load magic initialization constants.
159
   */
160
64
  context->state[0] = 0x67452301;
161
64
  context->state[1] = 0xefcdab89;
162
64
  context->state[2] = 0x98badcfe;
163
64
  context->state[3] = 0x10325476;
164
64
  context->state[4] = 0xc3d2e1f0;
165
64
}
166
/* }}} */
167
168
/* {{{ PHP_SHA1Update
169
   SHA1 block update operation. Continues an SHA1 message-digest
170
   operation, processing another message block, and updating the
171
   context.
172
 */
173
PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *input,
174
         size_t inputLen)
175
192
{
176
192
  unsigned int index, partLen;
177
192
  size_t i;
178
179
  /* Compute number of bytes mod 64 */
180
192
  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
181
182
  /* Update number of bits */
183
192
  if ((context->count[0] += ((uint32_t) inputLen << 3))
184
192
    < ((uint32_t) inputLen << 3))
185
10
    context->count[1]++;
186
192
  context->count[1] += (uint32_t) (inputLen >> 29);
187
188
192
  partLen = 64 - index;
189
190
  /* Transform as many times as possible.
191
   */
192
192
  if (inputLen >= partLen) {
193
124
    memcpy
194
124
      ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
195
124
    SHA1Transform(context->state, context->buffer);
196
197
22.7k
    for (i = partLen; i + 63 < inputLen; i += 64)
198
22.6k
      SHA1Transform(context->state, &input[i]);
199
200
124
    index = 0;
201
124
  } else
202
68
    i = 0;
203
204
  /* Buffer remaining input */
205
192
  memcpy
206
192
    ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
207
192
     inputLen - i);
208
192
}
209
/* }}} */
210
211
/* {{{ PHP_SHA1Final
212
   SHA1 finalization. Ends an SHA1 message-digest operation, writing the
213
   the message digest and zeroizing the context.
214
 */
215
PHPAPI void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX * context)
216
64
{
217
64
  unsigned char bits[8];
218
64
  unsigned int index, padLen;
219
220
  /* Save number of bits */
221
64
  bits[7] = context->count[0] & 0xFF;
222
64
  bits[6] = (context->count[0] >> 8) & 0xFF;
223
64
  bits[5] = (context->count[0] >> 16) & 0xFF;
224
64
  bits[4] = (context->count[0] >> 24) & 0xFF;
225
64
  bits[3] = context->count[1] & 0xFF;
226
64
  bits[2] = (context->count[1] >> 8) & 0xFF;
227
64
  bits[1] = (context->count[1] >> 16) & 0xFF;
228
64
  bits[0] = (context->count[1] >> 24) & 0xFF;
229
230
  /* Pad out to 56 mod 64.
231
   */
232
64
  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
233
64
  padLen = (index < 56) ? (56 - index) : (120 - index);
234
64
  PHP_SHA1Update(context, PADDING, padLen);
235
236
  /* Append length (before padding) */
237
64
  PHP_SHA1Update(context, bits, 8);
238
239
  /* Store state in digest */
240
64
  SHA1Encode(digest, context->state, 20);
241
242
  /* Zeroize sensitive information.
243
   */
244
64
  ZEND_SECURE_ZERO((unsigned char*) context, sizeof(*context));
245
64
}
246
/* }}} */
247
248
/* {{{ SHA1Transform
249
 * SHA1 basic transformation. Transforms state based on block.
250
 */
251
static void SHA1Transform(uint32_t state[5], const unsigned char block[64])
252
22.7k
{
253
22.7k
  uint32_t a = state[0], b = state[1], c = state[2];
254
22.7k
  uint32_t d = state[3], e = state[4], x[16], tmp;
255
256
22.7k
  SHA1Decode(x, block, 64);
257
258
  /* Round 1 */
259
22.7k
  FF(a, b, c, d, e, x[0]);   /* 1 */
260
22.7k
  FF(e, a, b, c, d, x[1]);   /* 2 */
261
22.7k
  FF(d, e, a, b, c, x[2]);   /* 3 */
262
22.7k
  FF(c, d, e, a, b, x[3]);   /* 4 */
263
22.7k
  FF(b, c, d, e, a, x[4]);   /* 5 */
264
22.7k
  FF(a, b, c, d, e, x[5]);   /* 6 */
265
22.7k
  FF(e, a, b, c, d, x[6]);   /* 7 */
266
22.7k
  FF(d, e, a, b, c, x[7]);   /* 8 */
267
22.7k
  FF(c, d, e, a, b, x[8]);   /* 9 */
268
22.7k
  FF(b, c, d, e, a, x[9]);   /* 10 */
269
22.7k
  FF(a, b, c, d, e, x[10]);  /* 11 */
270
22.7k
  FF(e, a, b, c, d, x[11]);  /* 12 */
271
22.7k
  FF(d, e, a, b, c, x[12]);  /* 13 */
272
22.7k
  FF(c, d, e, a, b, x[13]);  /* 14 */
273
22.7k
  FF(b, c, d, e, a, x[14]);  /* 15 */
274
22.7k
  FF(a, b, c, d, e, x[15]);  /* 16 */
275
22.7k
  FF(e, a, b, c, d, W(16));  /* 17 */
276
22.7k
  FF(d, e, a, b, c, W(17));  /* 18 */
277
22.7k
  FF(c, d, e, a, b, W(18));  /* 19 */
278
22.7k
  FF(b, c, d, e, a, W(19));  /* 20 */
279
280
  /* Round 2 */
281
22.7k
  GG(a, b, c, d, e, W(20));  /* 21 */
282
22.7k
  GG(e, a, b, c, d, W(21));  /* 22 */
283
22.7k
  GG(d, e, a, b, c, W(22));  /* 23 */
284
22.7k
  GG(c, d, e, a, b, W(23));  /* 24 */
285
22.7k
  GG(b, c, d, e, a, W(24));  /* 25 */
286
22.7k
  GG(a, b, c, d, e, W(25));  /* 26 */
287
22.7k
  GG(e, a, b, c, d, W(26));  /* 27 */
288
22.7k
  GG(d, e, a, b, c, W(27));  /* 28 */
289
22.7k
  GG(c, d, e, a, b, W(28));  /* 29 */
290
22.7k
  GG(b, c, d, e, a, W(29));  /* 30 */
291
22.7k
  GG(a, b, c, d, e, W(30));  /* 31 */
292
22.7k
  GG(e, a, b, c, d, W(31));  /* 32 */
293
22.7k
  GG(d, e, a, b, c, W(32));  /* 33 */
294
22.7k
  GG(c, d, e, a, b, W(33));  /* 34 */
295
22.7k
  GG(b, c, d, e, a, W(34));  /* 35 */
296
22.7k
  GG(a, b, c, d, e, W(35));  /* 36 */
297
22.7k
  GG(e, a, b, c, d, W(36));  /* 37 */
298
22.7k
  GG(d, e, a, b, c, W(37));  /* 38 */
299
22.7k
  GG(c, d, e, a, b, W(38));  /* 39 */
300
22.7k
  GG(b, c, d, e, a, W(39));  /* 40 */
301
302
  /* Round 3 */
303
22.7k
  HH(a, b, c, d, e, W(40));  /* 41 */
304
22.7k
  HH(e, a, b, c, d, W(41));  /* 42 */
305
22.7k
  HH(d, e, a, b, c, W(42));  /* 43 */
306
22.7k
  HH(c, d, e, a, b, W(43));  /* 44 */
307
22.7k
  HH(b, c, d, e, a, W(44));  /* 45 */
308
22.7k
  HH(a, b, c, d, e, W(45));  /* 46 */
309
22.7k
  HH(e, a, b, c, d, W(46));  /* 47 */
310
22.7k
  HH(d, e, a, b, c, W(47));  /* 48 */
311
22.7k
  HH(c, d, e, a, b, W(48));  /* 49 */
312
22.7k
  HH(b, c, d, e, a, W(49));  /* 50 */
313
22.7k
  HH(a, b, c, d, e, W(50));  /* 51 */
314
22.7k
  HH(e, a, b, c, d, W(51));  /* 52 */
315
22.7k
  HH(d, e, a, b, c, W(52));  /* 53 */
316
22.7k
  HH(c, d, e, a, b, W(53));  /* 54 */
317
22.7k
  HH(b, c, d, e, a, W(54));  /* 55 */
318
22.7k
  HH(a, b, c, d, e, W(55));  /* 56 */
319
22.7k
  HH(e, a, b, c, d, W(56));  /* 57 */
320
22.7k
  HH(d, e, a, b, c, W(57));  /* 58 */
321
22.7k
  HH(c, d, e, a, b, W(58));  /* 59 */
322
22.7k
  HH(b, c, d, e, a, W(59));  /* 60 */
323
324
  /* Round 4 */
325
22.7k
  II(a, b, c, d, e, W(60));  /* 61 */
326
22.7k
  II(e, a, b, c, d, W(61));  /* 62 */
327
22.7k
  II(d, e, a, b, c, W(62));  /* 63 */
328
22.7k
  II(c, d, e, a, b, W(63));  /* 64 */
329
22.7k
  II(b, c, d, e, a, W(64));  /* 65 */
330
22.7k
  II(a, b, c, d, e, W(65));  /* 66 */
331
22.7k
  II(e, a, b, c, d, W(66));  /* 67 */
332
22.7k
  II(d, e, a, b, c, W(67));  /* 68 */
333
22.7k
  II(c, d, e, a, b, W(68));  /* 69 */
334
22.7k
  II(b, c, d, e, a, W(69));  /* 70 */
335
22.7k
  II(a, b, c, d, e, W(70));  /* 71 */
336
22.7k
  II(e, a, b, c, d, W(71));  /* 72 */
337
22.7k
  II(d, e, a, b, c, W(72));  /* 73 */
338
22.7k
  II(c, d, e, a, b, W(73));  /* 74 */
339
22.7k
  II(b, c, d, e, a, W(74));  /* 75 */
340
22.7k
  II(a, b, c, d, e, W(75));  /* 76 */
341
22.7k
  II(e, a, b, c, d, W(76));  /* 77 */
342
22.7k
  II(d, e, a, b, c, W(77));  /* 78 */
343
22.7k
  II(c, d, e, a, b, W(78));  /* 79 */
344
22.7k
  II(b, c, d, e, a, W(79));  /* 80 */
345
346
22.7k
  state[0] += a;
347
22.7k
  state[1] += b;
348
22.7k
  state[2] += c;
349
22.7k
  state[3] += d;
350
22.7k
  state[4] += e;
351
352
  /* Zeroize sensitive information. */
353
22.7k
  ZEND_SECURE_ZERO((unsigned char*) x, sizeof(x));
354
22.7k
}
355
/* }}} */
356
357
/* {{{ SHA1Encode
358
   Encodes input (uint32_t) into output (unsigned char). Assumes len is
359
   a multiple of 4.
360
 */
361
static void SHA1Encode(unsigned char *output, uint32_t *input, unsigned int len)
362
64
{
363
64
  unsigned int i, j;
364
365
384
  for (i = 0, j = 0; j < len; i++, j += 4) {
366
320
    output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
367
320
    output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
368
320
    output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
369
320
    output[j + 3] = (unsigned char) (input[i] & 0xff);
370
320
  }
371
64
}
372
/* }}} */
373
374
/* {{{ SHA1Decode
375
   Decodes input (unsigned char) into output (uint32_t). Assumes len is
376
   a multiple of 4.
377
 */
378
static void SHA1Decode(uint32_t *output, const unsigned char *input, unsigned int len)
379
22.7k
{
380
22.7k
  unsigned int i, j;
381
382
387k
  for (i = 0, j = 0; j < len; i++, j += 4)
383
364k
    output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) |
384
364k
      (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24);
385
22.7k
}
386
/* }}} */