Coverage Report

Created: 2026-07-25 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/ext/standard/crypt_sha512.c
Line
Count
Source
1
/* SHA512-based Unix crypt implementation.
2
   Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
3
/* Windows VC++ port by Pierre Joye <pierre@php.net> */
4
5
#include "php.h"
6
#include "php_main.h"
7
8
#include <errno.h>
9
#include <limits.h>
10
#ifdef PHP_WIN32
11
# define __alignof__ __alignof
12
#else
13
# ifndef HAVE_ALIGNOF
14
#  include <stddef.h>
15
#  define __alignof__(type) offsetof (struct { char c; type member;}, member)
16
# endif
17
#endif
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
22
#ifdef PHP_WIN32
23
# include <string.h>
24
#else
25
# include <sys/types.h>
26
# include <string.h>
27
#endif
28
29
extern char * __php_stpncpy(char *dst, const char *src, size_t len);
30
31
#ifndef MIN
32
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
33
#endif
34
#ifndef MAX
35
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
36
#endif
37
38
/* See #51582 */
39
#ifndef UINT64_C
40
# define UINT64_C(value) __CONCAT(value, ULL)
41
#endif
42
43
/* Structure to save state of computation between the single steps.  */
44
struct sha512_ctx
45
{
46
  uint64_t H[8];
47
48
  uint64_t total[2];
49
  uint64_t buflen;
50
  char buffer[256]; /* NB: always correctly aligned for uint64_t.  */
51
};
52
53
54
#if defined(PHP_WIN32) || (!defined(WORDS_BIGENDIAN))
55
# define SWAP(n) \
56
0
  (((n) << 56)          \
57
0
   | (((n) & 0xff00) << 40)     \
58
0
   | (((n) & 0xff0000) << 24)     \
59
0
   | (((n) & 0xff000000) << 8)      \
60
0
   | (((n) >> 8) & 0xff000000)      \
61
0
   | (((n) >> 24) & 0xff0000)     \
62
0
   | (((n) >> 40) & 0xff00)     \
63
0
   | ((n) >> 56))
64
#else
65
# define SWAP(n) (n)
66
#endif
67
68
/* This array contains the bytes used to pad the buffer to the next
69
   64-byte boundary.  (FIPS 180-2:5.1.2)  */
70
static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ...  */ };
71
72
/* Constants for SHA512 from FIPS 180-2:4.2.3.  */
73
static const uint64_t K[80] = {
74
  UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
75
  UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
76
  UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
77
  UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
78
  UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
79
  UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
80
  UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
81
  UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
82
  UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
83
  UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
84
  UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
85
  UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
86
  UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
87
  UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
88
  UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
89
  UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
90
  UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
91
  UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
92
  UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
93
  UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
94
  UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
95
  UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
96
  UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
97
  UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
98
  UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
99
  UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
100
  UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
101
  UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
102
  UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
103
  UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
104
  UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
105
  UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
106
  UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
107
  UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
108
  UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
109
  UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
110
  UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
111
  UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
112
  UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
113
  UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
114
  };
115
116
117
/* Process LEN bytes of BUFFER, accumulating context into CTX.
118
   It is assumed that LEN % 128 == 0.  */
119
static void
120
0
sha512_process_block(const void *buffer, size_t len, struct sha512_ctx *ctx) {
121
0
  const uint64_t *words = buffer;
122
0
  size_t nwords = len / sizeof(uint64_t);
123
0
  uint64_t a = ctx->H[0];
124
0
  uint64_t b = ctx->H[1];
125
0
  uint64_t c = ctx->H[2];
126
0
  uint64_t d = ctx->H[3];
127
0
  uint64_t e = ctx->H[4];
128
0
  uint64_t f = ctx->H[5];
129
0
  uint64_t g = ctx->H[6];
130
0
  uint64_t h = ctx->H[7];
131
132
  /* First increment the byte count.  FIPS 180-2 specifies the possible
133
   length of the file up to 2^128 bits.  Here we only compute the
134
   number of bytes.  Do a double word increment.  */
135
0
  ctx->total[0] += len;
136
0
  if (ctx->total[0] < len) {
137
0
    ++ctx->total[1];
138
0
  }
139
140
  /* Process all bytes in the buffer with 128 bytes in each round of
141
   the loop.  */
142
0
  while (nwords > 0) {
143
0
    uint64_t W[80];
144
0
    uint64_t a_save = a;
145
0
    uint64_t b_save = b;
146
0
    uint64_t c_save = c;
147
0
    uint64_t d_save = d;
148
0
    uint64_t e_save = e;
149
0
    uint64_t f_save = f;
150
0
    uint64_t g_save = g;
151
0
    uint64_t h_save = h;
152
0
    unsigned int t;
153
154
/* Operators defined in FIPS 180-2:4.1.2.  */
155
0
#define Ch(x, y, z) ((x & y) ^ (~x & z))
156
0
#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
157
0
#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
158
0
#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
159
0
#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
160
0
#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
161
162
    /* It is unfortunate that C does not provide an operator for
163
       cyclic rotation.  Hope the C compiler is smart enough.  */
164
0
#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
165
166
    /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
167
0
    for (t = 0; t < 16; ++t) {
168
0
      W[t] = SWAP (*words);
169
0
      ++words;
170
0
    }
171
172
0
    for (t = 16; t < 80; ++t) {
173
0
      W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
174
0
    }
175
176
    /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
177
0
    for (t = 0; t < 80; ++t) {
178
0
      uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
179
0
      uint64_t T2 = S0 (a) + Maj (a, b, c);
180
0
      h = g;
181
0
      g = f;
182
0
      f = e;
183
0
      e = d + T1;
184
0
      d = c;
185
0
      c = b;
186
0
      b = a;
187
0
      a = T1 + T2;
188
0
    }
189
190
    /* Add the starting values of the context according to FIPS 180-2:6.3.2
191
    step 4.  */
192
0
    a += a_save;
193
0
    b += b_save;
194
0
    c += c_save;
195
0
    d += d_save;
196
0
    e += e_save;
197
0
    f += f_save;
198
0
    g += g_save;
199
0
    h += h_save;
200
201
    /* Prepare for the next round.  */
202
0
    nwords -= 16;
203
0
  }
204
205
  /* Put checksum in context given as argument.  */
206
0
  ctx->H[0] = a;
207
0
  ctx->H[1] = b;
208
0
  ctx->H[2] = c;
209
0
  ctx->H[3] = d;
210
0
  ctx->H[4] = e;
211
0
  ctx->H[5] = f;
212
0
  ctx->H[6] = g;
213
0
  ctx->H[7] = h;
214
0
}
215
216
217
/* Initialize structure containing state of computation.
218
   (FIPS 180-2:5.3.3)  */
219
0
static void sha512_init_ctx (struct sha512_ctx *ctx) {
220
0
  ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
221
0
  ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
222
0
  ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
223
0
  ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
224
0
  ctx->H[4] = UINT64_C (0x510e527fade682d1);
225
0
  ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
226
0
  ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
227
0
  ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
228
229
0
  ctx->total[0] = ctx->total[1] = 0;
230
0
  ctx->buflen = 0;
231
0
}
232
233
234
/* Process the remaining bytes in the internal buffer and the usual
235
  prolog according to the standard and write the result to RESBUF.
236
237
  IMPORTANT: On some systems it is required that RESBUF is correctly
238
  aligned for a 32 bits value. */
239
0
static void * sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) {
240
  /* Take yet unprocessed bytes into account.  */
241
0
  uint64_t bytes = ctx->buflen;
242
0
  size_t pad;
243
0
  unsigned int i;
244
245
  /* Now count remaining bytes.  */
246
0
  ctx->total[0] += bytes;
247
0
  if (ctx->total[0] < bytes) {
248
0
    ++ctx->total[1];
249
0
  }
250
251
0
  pad = bytes >= 112 ? 128 + 112 - (size_t)bytes : 112 - (size_t)bytes;
252
0
  memcpy(&ctx->buffer[bytes], fillbuf, pad);
253
254
  /* Put the 128-bit file length in *bits* at the end of the buffer.  */
255
0
  *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP(ctx->total[0] << 3);
256
0
  *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP((ctx->total[1] << 3) |
257
0
            (ctx->total[0] >> 61));
258
259
  /* Process last bytes.  */
260
0
  sha512_process_block(ctx->buffer, (size_t)(bytes + pad + 16), ctx);
261
262
  /* Put result from CTX in first 64 bytes following RESBUF.  */
263
0
  for (i = 0; i < 8; ++i) {
264
0
    ((uint64_t *) resbuf)[i] = SWAP(ctx->H[i]);
265
0
  }
266
267
0
  return resbuf;
268
0
}
269
270
static void
271
0
sha512_process_bytes(const void *buffer, size_t len, struct sha512_ctx *ctx) {
272
  /* When we already have some bits in our internal buffer concatenate
273
   both inputs first.  */
274
0
  if (ctx->buflen != 0) {
275
0
    size_t left_over = (size_t)ctx->buflen;
276
0
    size_t add = (size_t)(256 - left_over > len ? len : 256 - left_over);
277
278
0
    memcpy(&ctx->buffer[left_over], buffer, add);
279
0
    ctx->buflen += add;
280
281
0
    if (ctx->buflen > 128) {
282
0
      sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx);
283
284
0
      ctx->buflen &= 127;
285
      /* The regions in the following copy operation cannot overlap.  */
286
0
      memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
287
0
          (size_t)ctx->buflen);
288
0
    }
289
290
0
    buffer = (const char *) buffer + add;
291
0
    len -= add;
292
0
  }
293
294
  /* Process available complete blocks.  */
295
0
  if (len >= 128) {
296
0
#ifndef _STRING_ARCH_unaligned
297
/* To check alignment gcc has an appropriate operator.  Other
298
   compilers don't.  */
299
0
# if __GNUC__ >= 2
300
0
#  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
301
# else
302
#  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof(uint64_t) != 0)
303
# endif
304
0
    if (UNALIGNED_P(buffer))
305
0
      while (len > 128) {
306
0
        sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx);
307
0
        buffer = (const char *) buffer + 128;
308
0
        len -= 128;
309
0
      }
310
0
    else
311
0
#endif
312
0
    {
313
0
      sha512_process_block(buffer, len & ~127, ctx);
314
0
      buffer = (const char *) buffer + (len & ~127);
315
0
      len &= 127;
316
0
    }
317
0
  }
318
319
  /* Move remaining bytes into internal buffer.  */
320
0
  if (len > 0) {
321
0
    size_t left_over = (size_t)ctx->buflen;
322
323
0
    memcpy(&ctx->buffer[left_over], buffer, len);
324
0
    left_over += len;
325
0
    if (left_over >= 128) {
326
0
      sha512_process_block(ctx->buffer, 128, ctx);
327
0
      left_over -= 128;
328
0
      memcpy(ctx->buffer, &ctx->buffer[128], left_over);
329
0
    }
330
0
    ctx->buflen = left_over;
331
0
  }
332
0
}
333
334
335
/* Define our magic string to mark salt for SHA512 "encryption"
336
   replacement.  */
337
static const char sha512_salt_prefix[] = "$6$";
338
339
/* Prefix for optional rounds specification.  */
340
static const char sha512_rounds_prefix[] = "rounds=";
341
342
/* Maximum salt string length.  */
343
#define SALT_LEN_MAX 16
344
/* Default number of rounds if not explicitly specified.  */
345
0
#define ROUNDS_DEFAULT 5000
346
/* Minimum number of rounds.  */
347
0
#define ROUNDS_MIN 1000
348
/* Maximum number of rounds.  */
349
0
#define ROUNDS_MAX 999999999
350
351
/* Table with characters for base64 transformation.  */
352
static const char b64t[64] ZEND_NONSTRING =
353
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
354
355
356
char *
357
0
php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) {
358
#ifdef PHP_WIN32
359
  ZEND_SET_ALIGNED(64, unsigned char alt_result[64]);
360
  ZEND_SET_ALIGNED(64, unsigned char temp_result[64]);
361
#else
362
0
  ZEND_SET_ALIGNED(__alignof__ (uint64_t), unsigned char alt_result[64]);
363
0
  ZEND_SET_ALIGNED(__alignof__ (uint64_t), unsigned char temp_result[64]);
364
0
#endif
365
0
  struct sha512_ctx ctx;
366
0
  struct sha512_ctx alt_ctx;
367
0
  size_t salt_len;
368
0
  size_t key_len;
369
0
  size_t cnt;
370
0
  char *cp;
371
0
  char *copied_key = NULL;
372
0
  char *copied_salt = NULL;
373
0
  char *p_bytes;
374
0
  char *s_bytes;
375
  /* Default number of rounds.  */
376
0
  size_t rounds = ROUNDS_DEFAULT;
377
0
  bool rounds_custom = false;
378
379
  /* Find beginning of salt string.  The prefix should normally always
380
   be present.  Just in case it is not.  */
381
0
  if (strncmp(sha512_salt_prefix, salt, sizeof(sha512_salt_prefix) - 1) == 0) {
382
    /* Skip salt prefix.  */
383
0
    salt += sizeof(sha512_salt_prefix) - 1;
384
0
  }
385
386
0
  if (strncmp(salt, sha512_rounds_prefix, sizeof(sha512_rounds_prefix) - 1) == 0) {
387
0
    const char *num = salt + sizeof(sha512_rounds_prefix) - 1;
388
0
    char *endp;
389
0
    zend_ulong srounds = ZEND_STRTOUL(num, &endp, 10);
390
391
0
    if (*endp == '$') {
392
0
      salt = endp + 1;
393
0
      if (srounds < ROUNDS_MIN || srounds > ROUNDS_MAX) {
394
0
        return NULL;
395
0
      }
396
397
0
      rounds = srounds;
398
0
      rounds_custom = true;
399
0
    }
400
0
  }
401
402
0
  salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
403
0
  key_len = strlen(key);
404
0
  char *tmp_key = NULL;
405
0
  ALLOCA_FLAG(use_heap_key);
406
0
  char *tmp_salt = NULL;
407
0
  ALLOCA_FLAG(use_heap_salt);
408
409
0
  SET_ALLOCA_FLAG(use_heap_key);
410
0
  SET_ALLOCA_FLAG(use_heap_salt);
411
412
0
  if ((uintptr_t)key % __alignof__ (uint64_t) != 0) {
413
0
    tmp_key = (char *) do_alloca(key_len + __alignof__ (uint64_t), use_heap_key);
414
0
    key = copied_key =
415
0
    memcpy(tmp_key + __alignof__(uint64_t) - (uintptr_t)tmp_key % __alignof__(uint64_t), key, key_len);
416
0
  }
417
418
0
  if ((uintptr_t)salt % __alignof__ (uint64_t) != 0) {
419
0
    tmp_salt = (char *) do_alloca(salt_len + 1 + __alignof__(uint64_t), use_heap_salt);
420
0
    salt = copied_salt = memcpy(tmp_salt + __alignof__(uint64_t) - (uintptr_t)tmp_salt % __alignof__(uint64_t), salt, salt_len);
421
0
    copied_salt[salt_len] = 0;
422
0
  }
423
424
  /* Prepare for the real work.  */
425
0
  sha512_init_ctx(&ctx);
426
427
  /* Add the key string.  */
428
0
  sha512_process_bytes(key, key_len, &ctx);
429
430
  /* The last part is the salt string.  This must be at most 16
431
   characters and it ends at the first `$' character (for
432
   compatibility with existing implementations).  */
433
0
  sha512_process_bytes(salt, salt_len, &ctx);
434
435
436
  /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
437
   final result will be added to the first context.  */
438
0
  sha512_init_ctx(&alt_ctx);
439
440
  /* Add key.  */
441
0
  sha512_process_bytes(key, key_len, &alt_ctx);
442
443
  /* Add salt.  */
444
0
  sha512_process_bytes(salt, salt_len, &alt_ctx);
445
446
  /* Add key again.  */
447
0
  sha512_process_bytes(key, key_len, &alt_ctx);
448
449
  /* Now get result of this (64 bytes) and add it to the other
450
   context.  */
451
0
  sha512_finish_ctx(&alt_ctx, alt_result);
452
453
  /* Add for any character in the key one byte of the alternate sum.  */
454
0
  for (cnt = key_len; cnt > 64; cnt -= 64) {
455
0
    sha512_process_bytes(alt_result, 64, &ctx);
456
0
  }
457
0
  sha512_process_bytes(alt_result, cnt, &ctx);
458
459
  /* Take the binary representation of the length of the key and for every
460
   1 add the alternate sum, for every 0 the key.  */
461
0
  for (cnt = key_len; cnt > 0; cnt >>= 1) {
462
0
    if ((cnt & 1) != 0) {
463
0
      sha512_process_bytes(alt_result, 64, &ctx);
464
0
    } else {
465
0
      sha512_process_bytes(key, key_len, &ctx);
466
0
    }
467
0
  }
468
469
  /* Create intermediate result.  */
470
0
  sha512_finish_ctx(&ctx, alt_result);
471
472
  /* Start computation of P byte sequence.  */
473
0
  sha512_init_ctx(&alt_ctx);
474
475
  /* For every character in the password add the entire password.  */
476
0
  for (cnt = 0; cnt < key_len; ++cnt) {
477
0
    sha512_process_bytes(key, key_len, &alt_ctx);
478
0
  }
479
480
  /* Finish the digest.  */
481
0
  sha512_finish_ctx(&alt_ctx, temp_result);
482
483
  /* Create byte sequence P.  */
484
0
  ALLOCA_FLAG(use_heap_p_bytes);
485
0
  cp = p_bytes = do_alloca(key_len, use_heap_p_bytes);
486
0
  for (cnt = key_len; cnt >= 64; cnt -= 64) {
487
0
    cp = zend_mempcpy((void *) cp, (const void *)temp_result, 64);
488
0
  }
489
490
0
  memcpy(cp, temp_result, cnt);
491
492
  /* Start computation of S byte sequence.  */
493
0
  sha512_init_ctx(&alt_ctx);
494
495
  /* For every character in the password add the entire password.  */
496
0
  for (cnt = 0; cnt < (size_t) (16 + alt_result[0]); ++cnt) {
497
0
    sha512_process_bytes(salt, salt_len, &alt_ctx);
498
0
  }
499
500
  /* Finish the digest.  */
501
0
  sha512_finish_ctx(&alt_ctx, temp_result);
502
503
  /* Create byte sequence S.  */
504
0
  ALLOCA_FLAG(use_heap_s_bytes);
505
0
  cp = s_bytes = do_alloca(salt_len, use_heap_s_bytes);
506
0
  for (cnt = salt_len; cnt >= 64; cnt -= 64) {
507
0
    cp = zend_mempcpy(cp, temp_result, 64);
508
0
  }
509
0
  memcpy(cp, temp_result, cnt);
510
511
  /* Repeatedly run the collected hash value through SHA512 to burn
512
   CPU cycles.  */
513
0
  for (cnt = 0; cnt < rounds; ++cnt) {
514
    /* New context.  */
515
0
    sha512_init_ctx(&ctx);
516
517
    /* Add key or last result.  */
518
0
    if ((cnt & 1) != 0) {
519
0
      sha512_process_bytes(p_bytes, key_len, &ctx);
520
0
    } else {
521
0
      sha512_process_bytes(alt_result, 64, &ctx);
522
0
    }
523
524
    /* Add salt for numbers not divisible by 3.  */
525
0
    if (cnt % 3 != 0) {
526
0
      sha512_process_bytes(s_bytes, salt_len, &ctx);
527
0
    }
528
529
    /* Add key for numbers not divisible by 7.  */
530
0
    if (cnt % 7 != 0) {
531
0
      sha512_process_bytes(p_bytes, key_len, &ctx);
532
0
    }
533
534
    /* Add key or last result.  */
535
0
    if ((cnt & 1) != 0) {
536
0
      sha512_process_bytes(alt_result, 64, &ctx);
537
0
    } else {
538
0
      sha512_process_bytes(p_bytes, key_len, &ctx);
539
0
    }
540
541
    /* Create intermediate result.  */
542
0
    sha512_finish_ctx(&ctx, alt_result);
543
0
  }
544
545
  /* Now we can construct the result string.  It consists of three
546
   parts.  */
547
0
  cp = __php_stpncpy(buffer, sha512_salt_prefix, MAX(0, buflen));
548
0
  buflen -= sizeof(sha512_salt_prefix) - 1;
549
550
0
  if (rounds_custom) {
551
#ifdef PHP_WIN32
552
    int n = _snprintf(cp, MAX(0, buflen), "%s" ZEND_ULONG_FMT "$", sha512_rounds_prefix, rounds);
553
#else
554
0
    int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds);
555
0
#endif
556
0
    cp += n;
557
0
    buflen -= n;
558
0
  }
559
560
0
  cp = __php_stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len));
561
0
  buflen -= (int) MIN((size_t) MAX(0, buflen), salt_len);
562
563
0
  if (buflen > 0) {
564
0
    *cp++ = '$';
565
0
    --buflen;
566
0
  }
567
568
0
#define b64_from_24bit(B2, B1, B0, N)                    \
569
0
  do {                                  \
570
0
  unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);  \
571
0
  int n = (N);                           \
572
0
  while (n-- > 0 && buflen > 0)              \
573
0
    {                                  \
574
0
  *cp++ = b64t[w & 0x3f];                    \
575
0
  --buflen;                              \
576
0
  w >>= 6;                               \
577
0
    }                                   \
578
0
  } while (0)
579
580
0
  b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4);
581
0
  b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4);
582
0
  b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4);
583
0
  b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4);
584
0
  b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4);
585
0
  b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4);
586
0
  b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4);
587
0
  b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4);
588
0
  b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4);
589
0
  b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4);
590
0
  b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4);
591
0
  b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4);
592
0
  b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4);
593
0
  b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4);
594
0
  b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4);
595
0
  b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4);
596
0
  b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4);
597
0
  b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4);
598
0
  b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4);
599
0
  b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4);
600
0
  b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4);
601
0
  b64_from_24bit(0, 0, alt_result[63], 2);
602
603
0
  if (buflen <= 0) {
604
0
    errno = ERANGE;
605
0
    buffer = NULL;
606
0
  } else {
607
0
    *cp = '\0';   /* Terminate the string.  */
608
0
  }
609
610
  /* Clear the buffer for the intermediate result so that people
611
   attaching to processes or reading core dumps cannot get any
612
   information.  We do it in this way to clear correct_words[]
613
   inside the SHA512 implementation as well.  */
614
0
  sha512_init_ctx(&ctx);
615
0
  sha512_finish_ctx(&ctx, alt_result);
616
0
  ZEND_SECURE_ZERO(temp_result, sizeof(temp_result));
617
0
  ZEND_SECURE_ZERO(p_bytes, key_len);
618
0
  ZEND_SECURE_ZERO(s_bytes, salt_len);
619
0
  ZEND_SECURE_ZERO(&ctx, sizeof(ctx));
620
0
  ZEND_SECURE_ZERO(&alt_ctx, sizeof(alt_ctx));
621
0
  if (copied_key != NULL) {
622
0
    ZEND_SECURE_ZERO(copied_key, key_len);
623
0
  }
624
0
  if (copied_salt != NULL) {
625
0
    ZEND_SECURE_ZERO(copied_salt, salt_len);
626
0
  }
627
0
  if (tmp_key != NULL) {
628
0
    free_alloca(tmp_key, use_heap_key);
629
0
  }
630
0
  if (tmp_salt != NULL) {
631
0
    free_alloca(tmp_salt, use_heap_salt);
632
0
  }
633
0
  free_alloca(p_bytes, use_heap_p_bytes);
634
0
  free_alloca(s_bytes, use_heap_s_bytes);
635
636
0
  return buffer;
637
0
}
638
639
640
/* This entry point is equivalent to the `crypt' function in Unix
641
   libcs.  */
642
char *
643
0
php_sha512_crypt(const char *key, const char *salt) {
644
  /* We don't want to have an arbitrary limit in the size of the
645
   password.  We can compute an upper bound for the size of the
646
   result in advance and so we can prepare the buffer we pass to
647
   `sha512_crypt_r'.  */
648
0
  ZEND_TLS char *buffer;
649
0
  ZEND_TLS int buflen = 0;
650
0
  int needed = (int)(sizeof(sha512_salt_prefix) - 1
651
0
    + sizeof(sha512_rounds_prefix) + 9 + 1
652
0
    + strlen(salt) + 1 + 86 + 1);
653
654
0
  if (buflen < needed) {
655
0
    char *new_buffer = (char *) realloc(buffer, needed);
656
0
    if (new_buffer == NULL) {
657
0
      return NULL;
658
0
    }
659
660
0
    buffer = new_buffer;
661
0
    buflen = needed;
662
0
  }
663
664
0
  return php_sha512_crypt_r (key, salt, buffer, buflen);
665
0
}
666
667
#ifdef TEST
668
static const struct {
669
  const char *input;
670
  const char result[64];
671
} tests[] =
672
  {
673
  /* Test vectors from FIPS 180-2: appendix C.1.  */
674
  { "abc",
675
    "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
676
    "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
677
    "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
678
    "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
679
  /* Test vectors from FIPS 180-2: appendix C.2.  */
680
  { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
681
    "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
682
    "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
683
    "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
684
    "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
685
    "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
686
  /* Test vectors from the NESSIE project.  */
687
  { "",
688
    "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
689
    "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
690
    "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
691
    "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
692
  { "a",
693
    "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
694
    "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
695
    "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
696
    "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
697
  { "message digest",
698
    "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
699
    "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
700
    "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
701
    "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
702
  { "abcdefghijklmnopqrstuvwxyz",
703
    "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
704
    "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
705
    "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
706
    "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
707
  { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
708
    "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
709
    "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
710
    "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
711
    "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
712
  { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
713
    "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
714
    "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
715
    "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
716
    "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
717
  { "123456789012345678901234567890123456789012345678901234567890"
718
    "12345678901234567890",
719
    "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
720
    "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
721
    "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
722
    "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
723
  };
724
#define ntests (sizeof (tests) / sizeof (tests[0]))
725
726
727
static const struct
728
{
729
  const char *salt;
730
  const char *input;
731
  const char *expected;
732
} tests2[] = {
733
  { "$6$saltstring", "Hello world!",
734
  "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
735
  "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1"},
736
  { "$6$rounds=10000$saltstringsaltstring", "Hello world!",
737
  "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
738
  "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
739
  { "$6$rounds=5000$toolongsaltstring", "This is just a test",
740
  "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
741
  "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
742
  { "$6$rounds=1400$anotherlongsaltstring",
743
  "a very much longer text to encrypt.  This one even stretches over more"
744
  "than one line.",
745
  "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
746
  "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
747
  { "$6$rounds=77777$short",
748
  "we have a short salt string but not a short password",
749
  "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
750
  "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
751
  { "$6$rounds=123456$asaltof16chars..", "a short string",
752
  "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
753
  "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
754
  { "$6$rounds=10$roundstoolow", "the minimum number is still observed",
755
  "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
756
  "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
757
};
758
#define ntests2 (sizeof (tests2) / sizeof (tests2[0]))
759
760
761
int main (void) {
762
  struct sha512_ctx ctx;
763
  char sum[64];
764
  int result = 0;
765
  int cnt;
766
  int i;
767
  char buf[1000];
768
  static const char expected[64] =
769
    "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
770
    "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
771
    "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
772
    "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
773
774
  for (cnt = 0; cnt < (int) ntests; ++cnt) {
775
    sha512_init_ctx (&ctx);
776
    sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
777
    sha512_finish_ctx (&ctx, sum);
778
    if (memcmp (tests[cnt].result, sum, 64) != 0) {
779
      printf ("test %d run %d failed\n", cnt, 1);
780
      result = 1;
781
    }
782
783
    sha512_init_ctx (&ctx);
784
    for (i = 0; tests[cnt].input[i] != '\0'; ++i) {
785
      sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
786
    }
787
    sha512_finish_ctx (&ctx, sum);
788
    if (memcmp (tests[cnt].result, sum, 64) != 0) {
789
      printf ("test %d run %d failed\n", cnt, 2);
790
      result = 1;
791
    }
792
  }
793
794
  /* Test vector from FIPS 180-2: appendix C.3.  */
795
796
  memset (buf, 'a', sizeof (buf));
797
  sha512_init_ctx (&ctx);
798
  for (i = 0; i < 1000; ++i) {
799
    sha512_process_bytes (buf, sizeof (buf), &ctx);
800
  }
801
802
  sha512_finish_ctx (&ctx, sum);
803
  if (memcmp (expected, sum, 64) != 0) {
804
    printf ("test %d failed\n", cnt);
805
    result = 1;
806
  }
807
808
  for (cnt = 0; cnt < ntests2; ++cnt) {
809
    char *cp = php_sha512_crypt(tests2[cnt].input, tests2[cnt].salt);
810
811
    if (strcmp (cp, tests2[cnt].expected) != 0) {
812
      printf ("test %d: expected \"%s\", got \"%s\"\n",
813
          cnt, tests2[cnt].expected, cp);
814
      result = 1;
815
    }
816
  }
817
818
  if (result == 0) {
819
    puts ("all tests OK");
820
  }
821
822
  return result;
823
}
824
#endif