Coverage Report

Created: 2025-06-13 06:43

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