Add options to enable sharding
[hiphop-php.git] / hphp / zend / crypt-sha512.cpp
blobe0165d459b92377af79e4fc9c28868ad1907d49d
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> */
5 #include "php-crypt_r.h"
7 #include <errno.h>
8 #include <limits.h>
9 #include <memory.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
16 #include <folly/portability/Malloc.h>
17 #include <folly/portability/Windows.h>
19 namespace HPHP {
21 // Defined in crypt-sha256.c
22 extern void * __php_mempcpy(void * dst, const void * src, size_t len);
23 extern char * __php_stpncpy(char *dst, const char *src, size_t len);
25 #ifndef MIN
26 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
27 #endif
28 #ifndef MAX
29 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
30 #endif
32 /* See #51582 */
33 #ifndef UINT64_C
34 # define UINT64_C(value) __CONCAT(value, ULL)
35 #endif
37 /* Structure to save state of computation between the single steps. */
38 struct sha512_ctx
40 uint64_t H[8];
42 uint64_t total[2];
43 uint64_t buflen;
44 char buffer[256]; /* NB: always correctly aligned for uint64_t. */
48 #define SWAP(n) \
49 (((n) << 56) \
50 | (((n) & 0xff00) << 40) \
51 | (((n) & 0xff0000) << 24) \
52 | (((n) & 0xff000000) << 8) \
53 | (((n) >> 8) & 0xff000000) \
54 | (((n) >> 24) & 0xff0000) \
55 | (((n) >> 40) & 0xff00) \
56 | ((n) >> 56))
58 /* This array contains the bytes used to pad the buffer to the next
59 64-byte boundary. (FIPS 180-2:5.1.2) */
60 static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
62 /* Constants for SHA512 from FIPS 180-2:4.2.3. */
63 static const uint64_t K[80] = {
64 UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
65 UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
66 UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
67 UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
68 UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
69 UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
70 UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
71 UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
72 UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
73 UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
74 UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
75 UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
76 UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
77 UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
78 UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
79 UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
80 UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
81 UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
82 UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
83 UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
84 UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
85 UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
86 UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
87 UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
88 UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
89 UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
90 UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
91 UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
92 UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
93 UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
94 UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
95 UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
96 UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
97 UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
98 UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
99 UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
100 UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
101 UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
102 UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
103 UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
107 /* Process LEN bytes of BUFFER, accumulating context into CTX.
108 It is assumed that LEN % 128 == 0. */
109 static void
110 sha512_process_block(const void *buffer, size_t len, struct sha512_ctx *ctx) {
111 const uint64_t *words = (const uint64_t*)buffer;
112 size_t nwords = len / sizeof(uint64_t);
113 uint64_t a = ctx->H[0];
114 uint64_t b = ctx->H[1];
115 uint64_t c = ctx->H[2];
116 uint64_t d = ctx->H[3];
117 uint64_t e = ctx->H[4];
118 uint64_t f = ctx->H[5];
119 uint64_t g = ctx->H[6];
120 uint64_t h = ctx->H[7];
122 /* First increment the byte count. FIPS 180-2 specifies the possible
123 length of the file up to 2^128 bits. Here we only compute the
124 number of bytes. Do a double word increment. */
125 ctx->total[0] += len;
126 if (ctx->total[0] < len) {
127 ++ctx->total[1];
130 /* Process all bytes in the buffer with 128 bytes in each round of
131 the loop. */
132 while (nwords > 0) {
133 uint64_t W[80];
134 uint64_t a_save = a;
135 uint64_t b_save = b;
136 uint64_t c_save = c;
137 uint64_t d_save = d;
138 uint64_t e_save = e;
139 uint64_t f_save = f;
140 uint64_t g_save = g;
141 uint64_t h_save = h;
142 unsigned int t;
144 /* Operators defined in FIPS 180-2:4.1.2. */
145 #define Ch(x, y, z) ((x & y) ^ (~x & z))
146 #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
147 #define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
148 #define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
149 #define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
150 #define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
152 /* It is unfortunate that C does not provide an operator for
153 cyclic rotation. Hope the C compiler is smart enough. */
154 #define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
156 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
157 for (t = 0; t < 16; ++t) {
158 W[t] = SWAP (*words);
159 ++words;
162 for (t = 16; t < 80; ++t) {
163 W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
166 /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
167 for (t = 0; t < 80; ++t) {
168 uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
169 uint64_t T2 = S0 (a) + Maj (a, b, c);
170 h = g;
171 g = f;
172 f = e;
173 e = d + T1;
174 d = c;
175 c = b;
176 b = a;
177 a = T1 + T2;
180 /* Add the starting values of the context according to FIPS 180-2:6.3.2
181 step 4. */
182 a += a_save;
183 b += b_save;
184 c += c_save;
185 d += d_save;
186 e += e_save;
187 f += f_save;
188 g += g_save;
189 h += h_save;
191 /* Prepare for the next round. */
192 nwords -= 16;
195 /* Put checksum in context given as argument. */
196 ctx->H[0] = a;
197 ctx->H[1] = b;
198 ctx->H[2] = c;
199 ctx->H[3] = d;
200 ctx->H[4] = e;
201 ctx->H[5] = f;
202 ctx->H[6] = g;
203 ctx->H[7] = h;
207 /* Initialize structure containing state of computation.
208 (FIPS 180-2:5.3.3) */
209 static void sha512_init_ctx (struct sha512_ctx *ctx) {
210 ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
211 ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
212 ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
213 ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
214 ctx->H[4] = UINT64_C (0x510e527fade682d1);
215 ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
216 ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
217 ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
219 ctx->total[0] = ctx->total[1] = 0;
220 ctx->buflen = 0;
224 /* Process the remaining bytes in the internal buffer and the usual
225 prolog according to the standard and write the result to RESBUF.
227 IMPORTANT: On some systems it is required that RESBUF is correctly
228 aligned for a 32 bits value. */
229 static void * sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) {
230 /* Take yet unprocessed bytes into account. */
231 uint64_t bytes = ctx->buflen;
232 size_t pad;
233 unsigned int i;
235 /* Now count remaining bytes. */
236 ctx->total[0] += bytes;
237 if (ctx->total[0] < bytes) {
238 ++ctx->total[1];
241 pad = bytes >= 112 ? 128 + 112 - (size_t)bytes : 112 - (size_t)bytes;
242 memcpy(&ctx->buffer[bytes], fillbuf, pad);
244 /* Put the 128-bit file length in *bits* at the end of the buffer. */
245 *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP(ctx->total[0] << 3);
246 *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP((ctx->total[1] << 3) |
247 (ctx->total[0] >> 61));
249 /* Process last bytes. */
250 sha512_process_block(ctx->buffer, (size_t)(bytes + pad + 16), ctx);
252 /* Put result from CTX in first 64 bytes following RESBUF. */
253 for (i = 0; i < 8; ++i) {
254 ((uint64_t *) resbuf)[i] = SWAP(ctx->H[i]);
257 return resbuf;
260 static void
261 sha512_process_bytes(const void *buffer, size_t len, struct sha512_ctx *ctx) {
262 /* When we already have some bits in our internal buffer concatenate
263 both inputs first. */
264 if (ctx->buflen != 0) {
265 size_t left_over = (size_t)ctx->buflen;
266 size_t add = (size_t)(256 - left_over > len ? len : 256 - left_over);
268 memcpy(&ctx->buffer[left_over], buffer, add);
269 ctx->buflen += add;
271 if (ctx->buflen > 128) {
272 sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx);
274 ctx->buflen &= 127;
275 /* The regions in the following copy operation cannot overlap. */
276 memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
277 (size_t)ctx->buflen);
280 buffer = (const char *) buffer + add;
281 len -= add;
284 /* Process available complete blocks. */
285 if (len >= 128) {
286 #if !_STRING_ARCH_unaligned
287 #define UNALIGNED_P(p) (((uintptr_t) p) % alignof (uint64_t) != 0)
288 if (UNALIGNED_P(buffer))
289 while (len > 128) {
290 sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx);
291 buffer = (const char *) buffer + 128;
292 len -= 128;
294 else
295 #endif
297 sha512_process_block(buffer, len & ~127, ctx);
298 buffer = (const char *) buffer + (len & ~127);
299 len &= 127;
303 /* Move remaining bytes into internal buffer. */
304 if (len > 0) {
305 size_t left_over = (size_t)ctx->buflen;
307 memcpy(&ctx->buffer[left_over], buffer, len);
308 left_over += len;
309 if (left_over >= 128) {
310 sha512_process_block(ctx->buffer, 128, ctx);
311 left_over -= 128;
312 memcpy(ctx->buffer, &ctx->buffer[128], left_over);
314 ctx->buflen = left_over;
319 /* Define our magic string to mark salt for SHA512 "encryption"
320 replacement. */
321 static const char sha512_salt_prefix[] = "$6$";
323 /* Prefix for optional rounds specification. */
324 static const char sha512_rounds_prefix[] = "rounds=";
326 /* Maximum salt string length. */
327 #define SALT_LEN_MAX 16
328 /* Default number of rounds if not explicitly specified. */
329 #define ROUNDS_DEFAULT 5000
330 /* Minimum number of rounds. */
331 #define ROUNDS_MIN 1000
332 /* Maximum number of rounds. */
333 #define ROUNDS_MAX 999999999
335 /* Table with characters for base64 transformation. */
336 static const char b64t[] =
337 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
340 char *
341 php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) {
342 alignas(64) unsigned char alt_result[64];
343 alignas(64) unsigned char temp_result[64];
344 struct sha512_ctx ctx;
345 struct sha512_ctx alt_ctx;
346 size_t salt_len;
347 size_t key_len;
348 size_t cnt;
349 char *cp;
350 char *copied_key = NULL;
351 char *copied_salt = NULL;
352 char *p_bytes;
353 char *s_bytes;
354 /* Default number of rounds. */
355 size_t rounds = ROUNDS_DEFAULT;
356 char rounds_custom = 0;
358 /* Find beginning of salt string. The prefix should normally always
359 be present. Just in case it is not. */
360 if (strncmp(sha512_salt_prefix, salt, sizeof(sha512_salt_prefix) - 1) == 0) {
361 /* Skip salt prefix. */
362 salt += sizeof(sha512_salt_prefix) - 1;
365 if (strncmp(salt, sha512_rounds_prefix, sizeof(sha512_rounds_prefix) - 1) == 0) {
366 const char *num = salt + sizeof(sha512_rounds_prefix) - 1;
367 char *endp;
368 unsigned long long srounds = STRTOUL(num, &endp, 10);
370 if (*endp == '$') {
371 salt = endp + 1;
372 rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
373 rounds_custom = 1;
377 salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
378 key_len = strlen(key);
380 if ((key - (char *) 0) % alignof (uint64_t) != 0) {
381 char *tmp = (char *) alloca (key_len + alignof (uint64_t));
382 key = copied_key =
383 (char*)memcpy(tmp + alignof(uint64_t) - (tmp - (char *) 0) % alignof(uint64_t), key, key_len);
386 if ((salt - (char *) 0) % alignof (uint64_t) != 0) {
387 char *tmp = (char *) alloca(salt_len + 1 + alignof(uint64_t));
388 salt = copied_salt = (char*)memcpy(tmp + alignof(uint64_t) - (tmp - (char *) 0) % alignof(uint64_t), salt, salt_len);
389 copied_salt[salt_len] = 0;
392 /* Prepare for the real work. */
393 sha512_init_ctx(&ctx);
395 /* Add the key string. */
396 sha512_process_bytes(key, key_len, &ctx);
398 /* The last part is the salt string. This must be at most 16
399 characters and it ends at the first `$' character (for
400 compatibility with existing implementations). */
401 sha512_process_bytes(salt, salt_len, &ctx);
404 /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
405 final result will be added to the first context. */
406 sha512_init_ctx(&alt_ctx);
408 /* Add key. */
409 sha512_process_bytes(key, key_len, &alt_ctx);
411 /* Add salt. */
412 sha512_process_bytes(salt, salt_len, &alt_ctx);
414 /* Add key again. */
415 sha512_process_bytes(key, key_len, &alt_ctx);
417 /* Now get result of this (64 bytes) and add it to the other
418 context. */
419 sha512_finish_ctx(&alt_ctx, alt_result);
421 /* Add for any character in the key one byte of the alternate sum. */
422 for (cnt = key_len; cnt > 64; cnt -= 64) {
423 sha512_process_bytes(alt_result, 64, &ctx);
425 sha512_process_bytes(alt_result, cnt, &ctx);
427 /* Take the binary representation of the length of the key and for every
428 1 add the alternate sum, for every 0 the key. */
429 for (cnt = key_len; cnt > 0; cnt >>= 1) {
430 if ((cnt & 1) != 0) {
431 sha512_process_bytes(alt_result, 64, &ctx);
432 } else {
433 sha512_process_bytes(key, key_len, &ctx);
437 /* Create intermediate result. */
438 sha512_finish_ctx(&ctx, alt_result);
440 /* Start computation of P byte sequence. */
441 sha512_init_ctx(&alt_ctx);
443 /* For every character in the password add the entire password. */
444 for (cnt = 0; cnt < key_len; ++cnt) {
445 sha512_process_bytes(key, key_len, &alt_ctx);
448 /* Finish the digest. */
449 sha512_finish_ctx(&alt_ctx, temp_result);
451 /* Create byte sequence P. */
452 cp = p_bytes = (char*)alloca(key_len);
453 for (cnt = key_len; cnt >= 64; cnt -= 64) {
454 cp = (char*)__php_mempcpy((void *) cp, (const void *)temp_result, 64);
457 memcpy(cp, temp_result, cnt);
459 /* Start computation of S byte sequence. */
460 sha512_init_ctx(&alt_ctx);
462 /* For every character in the password add the entire password. */
463 for (cnt = 0; cnt < (size_t) (16 + alt_result[0]); ++cnt) {
464 sha512_process_bytes(salt, salt_len, &alt_ctx);
467 /* Finish the digest. */
468 sha512_finish_ctx(&alt_ctx, temp_result);
470 /* Create byte sequence S. */
471 cp = s_bytes = (char*)alloca(salt_len);
472 for (cnt = salt_len; cnt >= 64; cnt -= 64) {
473 cp = (char*)__php_mempcpy(cp, temp_result, 64);
475 memcpy(cp, temp_result, cnt);
477 /* Repeatedly run the collected hash value through SHA512 to burn
478 CPU cycles. */
479 for (cnt = 0; cnt < rounds; ++cnt) {
480 /* New context. */
481 sha512_init_ctx(&ctx);
483 /* Add key or last result. */
484 if ((cnt & 1) != 0) {
485 sha512_process_bytes(p_bytes, key_len, &ctx);
486 } else {
487 sha512_process_bytes(alt_result, 64, &ctx);
490 /* Add salt for numbers not divisible by 3. */
491 if (cnt % 3 != 0) {
492 sha512_process_bytes(s_bytes, salt_len, &ctx);
495 /* Add key for numbers not divisible by 7. */
496 if (cnt % 7 != 0) {
497 sha512_process_bytes(p_bytes, key_len, &ctx);
500 /* Add key or last result. */
501 if ((cnt & 1) != 0) {
502 sha512_process_bytes(alt_result, 64, &ctx);
503 } else {
504 sha512_process_bytes(p_bytes, key_len, &ctx);
507 /* Create intermediate result. */
508 sha512_finish_ctx(&ctx, alt_result);
511 /* Now we can construct the result string. It consists of three
512 parts. */
513 cp = __php_stpncpy(buffer, sha512_salt_prefix, MAX(0, buflen));
514 buflen -= sizeof(sha512_salt_prefix) - 1;
516 if (rounds_custom) {
517 int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds);
518 cp += n;
519 buflen -= n;
522 cp = __php_stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len));
523 buflen -= (int) MIN((size_t) MAX(0, buflen), salt_len);
525 if (buflen > 0) {
526 *cp++ = '$';
527 --buflen;
530 #define b64_from_24bit(B2, B1, B0, N) \
531 do { \
532 unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
533 int n = (N); \
534 while (n-- > 0 && buflen > 0) \
536 *cp++ = b64t[w & 0x3f]; \
537 --buflen; \
538 w >>= 6; \
540 } while (0)
542 b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4);
543 b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4);
544 b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4);
545 b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4);
546 b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4);
547 b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4);
548 b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4);
549 b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4);
550 b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4);
551 b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4);
552 b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4);
553 b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4);
554 b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4);
555 b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4);
556 b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4);
557 b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4);
558 b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4);
559 b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4);
560 b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4);
561 b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4);
562 b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4);
563 b64_from_24bit(0, 0, alt_result[63], 2);
565 if (buflen <= 0) {
566 errno = ERANGE;
567 buffer = NULL;
568 } else {
569 *cp = '\0'; /* Terminate the string. */
572 /* Clear the buffer for the intermediate result so that people
573 attaching to processes or reading core dumps cannot get any
574 information. We do it in this way to clear correct_words[]
575 inside the SHA512 implementation as well. */
576 sha512_init_ctx(&ctx);
577 sha512_finish_ctx(&ctx, alt_result);
578 SECURE_ZERO(temp_result, sizeof(temp_result));
579 SECURE_ZERO(p_bytes, key_len);
580 SECURE_ZERO(s_bytes, salt_len);
581 SECURE_ZERO(&ctx, sizeof(ctx));
582 SECURE_ZERO(&alt_ctx, sizeof(alt_ctx));
583 if (copied_key != NULL) {
584 SECURE_ZERO(copied_key, key_len);
586 if (copied_salt != NULL) {
587 SECURE_ZERO(copied_salt, salt_len);
590 return buffer;
594 /* This entry point is equivalent to the `crypt' function in Unix
595 libcs. */
596 char *
597 php_sha512_crypt(const char *key, const char *salt) {
598 /* We don't want to have an arbitrary limit in the size of the
599 password. We can compute an upper bound for the size of the
600 result in advance and so we can prepare the buffer we pass to
601 `sha512_crypt_r'. */
602 static char *buffer;
603 static int buflen;
604 int needed = (int)(sizeof(sha512_salt_prefix) - 1
605 + sizeof(sha512_rounds_prefix) + 9 + 1
606 + strlen(salt) + 1 + 86 + 1);
608 if (buflen < needed) {
609 char *new_buffer = (char *) realloc(buffer, needed);
610 if (new_buffer == NULL) {
611 return NULL;
614 buffer = new_buffer;
615 buflen = needed;
618 return php_sha512_crypt_r (key, salt, buffer, buflen);