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> */
11 # include "win32/php_stdint.h"
12 # define __alignof__ __alignof
13 # define alloca _alloca
16 # include <inttypes.h>
22 # define __alignof__(type) offsetof (struct { char c; type member;}, member)
24 # if HAVE_ATTRIBUTE_ALIGNED
25 # define ALIGNED(size) __attribute__ ((__aligned__ (size)))
27 # define ALIGNED(size)
37 # include <sys/param.h>
38 # include <sys/types.h>
46 extern void * __php_mempcpy(void * dst
, const void * src
, size_t len
);
47 extern char * __php_stpncpy(char *dst
, const char *src
, size_t len
);
50 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
53 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
58 # define UINT64_C(value) __CONCAT(value, ULL)
61 /* Structure to save state of computation between the single steps. */
68 char buffer
[256]; /* NB: always correctly aligned for uint64_t. */
72 #if PHP_WIN32 || (!defined(WORDS_BIGENDIAN))
75 | (((n) & 0xff00) << 40) \
76 | (((n) & 0xff0000) << 24) \
77 | (((n) & 0xff000000) << 8) \
78 | (((n) >> 8) & 0xff000000) \
79 | (((n) >> 24) & 0xff0000) \
80 | (((n) >> 40) & 0xff00) \
86 /* This array contains the bytes used to pad the buffer to the next
87 64-byte boundary. (FIPS 180-2:5.1.2) */
88 static const unsigned char fillbuf
[128] = { 0x80, 0 /* , 0, 0, ... */ };
90 /* Constants for SHA512 from FIPS 180-2:4.2.3. */
91 static const uint64_t K
[80] = {
92 UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
93 UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
94 UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
95 UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
96 UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
97 UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
98 UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
99 UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
100 UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
101 UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
102 UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
103 UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
104 UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
105 UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
106 UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
107 UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
108 UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
109 UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
110 UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
111 UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
112 UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
113 UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
114 UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
115 UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
116 UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
117 UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
118 UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
119 UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
120 UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
121 UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
122 UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
123 UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
124 UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
125 UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
126 UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
127 UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
128 UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
129 UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
130 UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
131 UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
135 /* Process LEN bytes of BUFFER, accumulating context into CTX.
136 It is assumed that LEN % 128 == 0. */
138 sha512_process_block(const void *buffer
, size_t len
, struct sha512_ctx
*ctx
) {
139 const uint64_t *words
= buffer
;
140 size_t nwords
= len
/ sizeof(uint64_t);
141 uint64_t a
= ctx
->H
[0];
142 uint64_t b
= ctx
->H
[1];
143 uint64_t c
= ctx
->H
[2];
144 uint64_t d
= ctx
->H
[3];
145 uint64_t e
= ctx
->H
[4];
146 uint64_t f
= ctx
->H
[5];
147 uint64_t g
= ctx
->H
[6];
148 uint64_t h
= ctx
->H
[7];
150 /* First increment the byte count. FIPS 180-2 specifies the possible
151 length of the file up to 2^128 bits. Here we only compute the
152 number of bytes. Do a double word increment. */
153 ctx
->total
[0] += len
;
154 if (ctx
->total
[0] < len
) {
158 /* Process all bytes in the buffer with 128 bytes in each round of
172 /* Operators defined in FIPS 180-2:4.1.2. */
173 #define Ch(x, y, z) ((x & y) ^ (~x & z))
174 #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
175 #define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
176 #define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
177 #define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
178 #define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
180 /* It is unfortunate that C does not provide an operator for
181 cyclic rotation. Hope the C compiler is smart enough. */
182 #define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
184 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
185 for (t
= 0; t
< 16; ++t
) {
186 W
[t
] = SWAP (*words
);
190 for (t
= 16; t
< 80; ++t
) {
191 W
[t
] = R1 (W
[t
- 2]) + W
[t
- 7] + R0 (W
[t
- 15]) + W
[t
- 16];
194 /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
195 for (t
= 0; t
< 80; ++t
) {
196 uint64_t T1
= h
+ S1 (e
) + Ch (e
, f
, g
) + K
[t
] + W
[t
];
197 uint64_t T2
= S0 (a
) + Maj (a
, b
, c
);
208 /* Add the starting values of the context according to FIPS 180-2:6.3.2
219 /* Prepare for the next round. */
223 /* Put checksum in context given as argument. */
235 /* Initialize structure containing state of computation.
236 (FIPS 180-2:5.3.3) */
237 static void sha512_init_ctx (struct sha512_ctx
*ctx
) {
238 ctx
->H
[0] = UINT64_C (0x6a09e667f3bcc908);
239 ctx
->H
[1] = UINT64_C (0xbb67ae8584caa73b);
240 ctx
->H
[2] = UINT64_C (0x3c6ef372fe94f82b);
241 ctx
->H
[3] = UINT64_C (0xa54ff53a5f1d36f1);
242 ctx
->H
[4] = UINT64_C (0x510e527fade682d1);
243 ctx
->H
[5] = UINT64_C (0x9b05688c2b3e6c1f);
244 ctx
->H
[6] = UINT64_C (0x1f83d9abfb41bd6b);
245 ctx
->H
[7] = UINT64_C (0x5be0cd19137e2179);
247 ctx
->total
[0] = ctx
->total
[1] = 0;
252 /* Process the remaining bytes in the internal buffer and the usual
253 prolog according to the standard and write the result to RESBUF.
255 IMPORTANT: On some systems it is required that RESBUF is correctly
256 aligned for a 32 bits value. */
257 static void * sha512_finish_ctx (struct sha512_ctx
*ctx
, void *resbuf
) {
258 /* Take yet unprocessed bytes into account. */
259 uint64_t bytes
= ctx
->buflen
;
263 /* Now count remaining bytes. */
264 ctx
->total
[0] += bytes
;
265 if (ctx
->total
[0] < bytes
) {
269 pad
= bytes
>= 112 ? 128 + 112 - (size_t)bytes
: 112 - (size_t)bytes
;
270 memcpy(&ctx
->buffer
[bytes
], fillbuf
, pad
);
272 /* Put the 128-bit file length in *bits* at the end of the buffer. */
273 *(uint64_t *) &ctx
->buffer
[bytes
+ pad
+ 8] = SWAP(ctx
->total
[0] << 3);
274 *(uint64_t *) &ctx
->buffer
[bytes
+ pad
] = SWAP((ctx
->total
[1] << 3) |
275 (ctx
->total
[0] >> 61));
277 /* Process last bytes. */
278 sha512_process_block(ctx
->buffer
, (size_t)(bytes
+ pad
+ 16), ctx
);
280 /* Put result from CTX in first 64 bytes following RESBUF. */
281 for (i
= 0; i
< 8; ++i
) {
282 ((uint64_t *) resbuf
)[i
] = SWAP(ctx
->H
[i
]);
289 sha512_process_bytes(const void *buffer
, size_t len
, struct sha512_ctx
*ctx
) {
290 /* When we already have some bits in our internal buffer concatenate
291 both inputs first. */
292 if (ctx
->buflen
!= 0) {
293 size_t left_over
= (size_t)ctx
->buflen
;
294 size_t add
= (size_t)(256 - left_over
> len
? len
: 256 - left_over
);
296 memcpy(&ctx
->buffer
[left_over
], buffer
, add
);
299 if (ctx
->buflen
> 128) {
300 sha512_process_block(ctx
->buffer
, ctx
->buflen
& ~127, ctx
);
303 /* The regions in the following copy operation cannot overlap. */
304 memcpy(ctx
->buffer
, &ctx
->buffer
[(left_over
+ add
) & ~127],
305 (size_t)ctx
->buflen
);
308 buffer
= (const char *) buffer
+ add
;
312 /* Process available complete blocks. */
314 #if !_STRING_ARCH_unaligned
315 /* To check alignment gcc has an appropriate operator. Other
318 # define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
320 # define UNALIGNED_P(p) (((uintptr_t) p) % sizeof(uint64_t) != 0)
322 if (UNALIGNED_P(buffer
))
324 sha512_process_block(memcpy(ctx
->buffer
, buffer
, 128), 128, ctx
);
325 buffer
= (const char *) buffer
+ 128;
331 sha512_process_block(buffer
, len
& ~127, ctx
);
332 buffer
= (const char *) buffer
+ (len
& ~127);
337 /* Move remaining bytes into internal buffer. */
339 size_t left_over
= (size_t)ctx
->buflen
;
341 memcpy(&ctx
->buffer
[left_over
], buffer
, len
);
343 if (left_over
>= 128) {
344 sha512_process_block(ctx
->buffer
, 128, ctx
);
346 memcpy(ctx
->buffer
, &ctx
->buffer
[128], left_over
);
348 ctx
->buflen
= left_over
;
353 /* Define our magic string to mark salt for SHA512 "encryption"
355 static const char sha512_salt_prefix
[] = "$6$";
357 /* Prefix for optional rounds specification. */
358 static const char sha512_rounds_prefix
[] = "rounds=";
360 /* Maximum salt string length. */
361 #define SALT_LEN_MAX 16
362 /* Default number of rounds if not explicitly specified. */
363 #define ROUNDS_DEFAULT 5000
364 /* Minimum number of rounds. */
365 #define ROUNDS_MIN 1000
366 /* Maximum number of rounds. */
367 #define ROUNDS_MAX 999999999
369 /* Table with characters for base64 transformation. */
370 static const char b64t
[64] =
371 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
375 php_sha512_crypt_r(const char *key
, const char *salt
, char *buffer
, int buflen
) {
378 # pragma pack(push, 16)
379 unsigned char alt_result
[64];
380 unsigned char temp_result
[64];
383 __declspec(align(64)) unsigned char alt_result
[64];
384 __declspec(align(64)) unsigned char temp_result
[64];
387 unsigned char alt_result
[64] ALIGNED(__alignof__ (uint64_t));
388 unsigned char temp_result
[64] ALIGNED(__alignof__ (uint64_t));
390 struct sha512_ctx ctx
;
391 struct sha512_ctx alt_ctx
;
396 char *copied_key
= NULL
;
397 char *copied_salt
= NULL
;
400 /* Default number of rounds. */
401 size_t rounds
= ROUNDS_DEFAULT
;
402 zend_bool rounds_custom
= 0;
404 /* Find beginning of salt string. The prefix should normally always
405 be present. Just in case it is not. */
406 if (strncmp(sha512_salt_prefix
, salt
, sizeof(sha512_salt_prefix
) - 1) == 0) {
407 /* Skip salt prefix. */
408 salt
+= sizeof(sha512_salt_prefix
) - 1;
411 if (strncmp(salt
, sha512_rounds_prefix
, sizeof(sha512_rounds_prefix
) - 1) == 0) {
412 const char *num
= salt
+ sizeof(sha512_rounds_prefix
) - 1;
414 unsigned long int srounds
= strtoul(num
, &endp
, 10);
418 rounds
= MAX(ROUNDS_MIN
, MIN(srounds
, ROUNDS_MAX
));
423 salt_len
= MIN(strcspn(salt
, "$"), SALT_LEN_MAX
);
424 key_len
= strlen(key
);
426 if ((key
- (char *) 0) % __alignof__ (uint64_t) != 0) {
427 char *tmp
= (char *) alloca (key_len
+ __alignof__ (uint64_t));
429 memcpy(tmp
+ __alignof__(uint64_t) - (tmp
- (char *) 0) % __alignof__(uint64_t), key
, key_len
);
432 if ((salt
- (char *) 0) % __alignof__ (uint64_t) != 0) {
433 char *tmp
= (char *) alloca(salt_len
+ 1 + __alignof__(uint64_t));
434 salt
= copied_salt
= memcpy(tmp
+ __alignof__(uint64_t) - (tmp
- (char *) 0) % __alignof__(uint64_t), salt
, salt_len
);
435 copied_salt
[salt_len
] = 0;
438 /* Prepare for the real work. */
439 sha512_init_ctx(&ctx
);
441 /* Add the key string. */
442 sha512_process_bytes(key
, key_len
, &ctx
);
444 /* The last part is the salt string. This must be at most 16
445 characters and it ends at the first `$' character (for
446 compatibility with existing implementations). */
447 sha512_process_bytes(salt
, salt_len
, &ctx
);
450 /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
451 final result will be added to the first context. */
452 sha512_init_ctx(&alt_ctx
);
455 sha512_process_bytes(key
, key_len
, &alt_ctx
);
458 sha512_process_bytes(salt
, salt_len
, &alt_ctx
);
461 sha512_process_bytes(key
, key_len
, &alt_ctx
);
463 /* Now get result of this (64 bytes) and add it to the other
465 sha512_finish_ctx(&alt_ctx
, alt_result
);
467 /* Add for any character in the key one byte of the alternate sum. */
468 for (cnt
= key_len
; cnt
> 64; cnt
-= 64) {
469 sha512_process_bytes(alt_result
, 64, &ctx
);
471 sha512_process_bytes(alt_result
, cnt
, &ctx
);
473 /* Take the binary representation of the length of the key and for every
474 1 add the alternate sum, for every 0 the key. */
475 for (cnt
= key_len
; cnt
> 0; cnt
>>= 1) {
476 if ((cnt
& 1) != 0) {
477 sha512_process_bytes(alt_result
, 64, &ctx
);
479 sha512_process_bytes(key
, key_len
, &ctx
);
483 /* Create intermediate result. */
484 sha512_finish_ctx(&ctx
, alt_result
);
486 /* Start computation of P byte sequence. */
487 sha512_init_ctx(&alt_ctx
);
489 /* For every character in the password add the entire password. */
490 for (cnt
= 0; cnt
< key_len
; ++cnt
) {
491 sha512_process_bytes(key
, key_len
, &alt_ctx
);
494 /* Finish the digest. */
495 sha512_finish_ctx(&alt_ctx
, temp_result
);
497 /* Create byte sequence P. */
498 cp
= p_bytes
= alloca(key_len
);
499 for (cnt
= key_len
; cnt
>= 64; cnt
-= 64) {
500 cp
= __php_mempcpy((void *) cp
, (const void *)temp_result
, 64);
503 memcpy(cp
, temp_result
, cnt
);
505 /* Start computation of S byte sequence. */
506 sha512_init_ctx(&alt_ctx
);
508 /* For every character in the password add the entire password. */
509 for (cnt
= 0; cnt
< (size_t) (16 + alt_result
[0]); ++cnt
) {
510 sha512_process_bytes(salt
, salt_len
, &alt_ctx
);
513 /* Finish the digest. */
514 sha512_finish_ctx(&alt_ctx
, temp_result
);
516 /* Create byte sequence S. */
517 cp
= s_bytes
= alloca(salt_len
);
518 for (cnt
= salt_len
; cnt
>= 64; cnt
-= 64) {
519 cp
= __php_mempcpy(cp
, temp_result
, 64);
521 memcpy(cp
, temp_result
, cnt
);
523 /* Repeatedly run the collected hash value through SHA512 to burn
525 for (cnt
= 0; cnt
< rounds
; ++cnt
) {
527 sha512_init_ctx(&ctx
);
529 /* Add key or last result. */
530 if ((cnt
& 1) != 0) {
531 sha512_process_bytes(p_bytes
, key_len
, &ctx
);
533 sha512_process_bytes(alt_result
, 64, &ctx
);
536 /* Add salt for numbers not divisible by 3. */
538 sha512_process_bytes(s_bytes
, salt_len
, &ctx
);
541 /* Add key for numbers not divisible by 7. */
543 sha512_process_bytes(p_bytes
, key_len
, &ctx
);
546 /* Add key or last result. */
547 if ((cnt
& 1) != 0) {
548 sha512_process_bytes(alt_result
, 64, &ctx
);
550 sha512_process_bytes(p_bytes
, key_len
, &ctx
);
553 /* Create intermediate result. */
554 sha512_finish_ctx(&ctx
, alt_result
);
557 /* Now we can construct the result string. It consists of three
559 cp
= __php_stpncpy(buffer
, sha512_salt_prefix
, MAX(0, buflen
));
560 buflen
-= sizeof(sha512_salt_prefix
) - 1;
564 int n
= _snprintf(cp
, MAX(0, buflen
), "%s%u$", sha512_rounds_prefix
, rounds
);
566 int n
= snprintf(cp
, MAX(0, buflen
), "%s%zu$", sha512_rounds_prefix
, rounds
);
572 cp
= __php_stpncpy(cp
, salt
, MIN((size_t) MAX(0, buflen
), salt_len
));
573 buflen
-= (int) MIN((size_t) MAX(0, buflen
), salt_len
);
580 #define b64_from_24bit(B2, B1, B0, N) \
582 unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
584 while (n-- > 0 && buflen > 0) \
586 *cp++ = b64t[w & 0x3f]; \
592 b64_from_24bit(alt_result
[0], alt_result
[21], alt_result
[42], 4);
593 b64_from_24bit(alt_result
[22], alt_result
[43], alt_result
[1], 4);
594 b64_from_24bit(alt_result
[44], alt_result
[2], alt_result
[23], 4);
595 b64_from_24bit(alt_result
[3], alt_result
[24], alt_result
[45], 4);
596 b64_from_24bit(alt_result
[25], alt_result
[46], alt_result
[4], 4);
597 b64_from_24bit(alt_result
[47], alt_result
[5], alt_result
[26], 4);
598 b64_from_24bit(alt_result
[6], alt_result
[27], alt_result
[48], 4);
599 b64_from_24bit(alt_result
[28], alt_result
[49], alt_result
[7], 4);
600 b64_from_24bit(alt_result
[50], alt_result
[8], alt_result
[29], 4);
601 b64_from_24bit(alt_result
[9], alt_result
[30], alt_result
[51], 4);
602 b64_from_24bit(alt_result
[31], alt_result
[52], alt_result
[10], 4);
603 b64_from_24bit(alt_result
[53], alt_result
[11], alt_result
[32], 4);
604 b64_from_24bit(alt_result
[12], alt_result
[33], alt_result
[54], 4);
605 b64_from_24bit(alt_result
[34], alt_result
[55], alt_result
[13], 4);
606 b64_from_24bit(alt_result
[56], alt_result
[14], alt_result
[35], 4);
607 b64_from_24bit(alt_result
[15], alt_result
[36], alt_result
[57], 4);
608 b64_from_24bit(alt_result
[37], alt_result
[58], alt_result
[16], 4);
609 b64_from_24bit(alt_result
[59], alt_result
[17], alt_result
[38], 4);
610 b64_from_24bit(alt_result
[18], alt_result
[39], alt_result
[60], 4);
611 b64_from_24bit(alt_result
[40], alt_result
[61], alt_result
[19], 4);
612 b64_from_24bit(alt_result
[62], alt_result
[20], alt_result
[41], 4);
613 b64_from_24bit(0, 0, alt_result
[63], 2);
619 *cp
= '\0'; /* Terminate the string. */
622 /* Clear the buffer for the intermediate result so that people
623 attaching to processes or reading core dumps cannot get any
624 information. We do it in this way to clear correct_words[]
625 inside the SHA512 implementation as well. */
626 sha512_init_ctx(&ctx
);
627 sha512_finish_ctx(&ctx
, alt_result
);
628 memset(temp_result
, '\0', sizeof(temp_result
));
629 memset(p_bytes
, '\0', key_len
);
630 memset(s_bytes
, '\0', salt_len
);
631 memset(&ctx
, '\0', sizeof(ctx
));
632 memset(&alt_ctx
, '\0', sizeof(alt_ctx
));
633 if (copied_key
!= NULL
) {
634 memset(copied_key
, '\0', key_len
);
636 if (copied_salt
!= NULL
) {
637 memset(copied_salt
, '\0', salt_len
);
644 /* This entry point is equivalent to the `crypt' function in Unix
647 php_sha512_crypt(const char *key
, const char *salt
) {
648 /* We don't want to have an arbitrary limit in the size of the
649 password. We can compute an upper bound for the size of the
650 result in advance and so we can prepare the buffer we pass to
654 int needed
= (int)(sizeof(sha512_salt_prefix
) - 1
655 + sizeof(sha512_rounds_prefix
) + 9 + 1
656 + strlen(salt
) + 1 + 86 + 1);
658 if (buflen
< needed
) {
659 char *new_buffer
= (char *) realloc(buffer
, needed
);
660 if (new_buffer
== NULL
) {
668 return php_sha512_crypt_r (key
, salt
, buffer
, buflen
);
672 static const struct {
674 const char result
[64];
677 /* Test vectors from FIPS 180-2: appendix C.1. */
679 "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
680 "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
681 "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
682 "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
683 /* Test vectors from FIPS 180-2: appendix C.2. */
684 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
685 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
686 "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
687 "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
688 "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
689 "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
690 /* Test vectors from the NESSIE project. */
692 "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
693 "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
694 "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
695 "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
697 "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
698 "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
699 "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
700 "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
702 "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
703 "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
704 "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
705 "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
706 { "abcdefghijklmnopqrstuvwxyz",
707 "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
708 "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
709 "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
710 "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
711 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
712 "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
713 "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
714 "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
715 "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
716 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
717 "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
718 "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
719 "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
720 "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
721 { "123456789012345678901234567890123456789012345678901234567890"
722 "12345678901234567890",
723 "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
724 "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
725 "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
726 "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
728 #define ntests (sizeof (tests) / sizeof (tests[0]))
735 const char *expected
;
737 { "$6$saltstring", "Hello world!",
738 "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
739 "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1"},
740 { "$6$rounds=10000$saltstringsaltstring", "Hello world!",
741 "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
742 "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
743 { "$6$rounds=5000$toolongsaltstring", "This is just a test",
744 "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
745 "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
746 { "$6$rounds=1400$anotherlongsaltstring",
747 "a very much longer text to encrypt. This one even stretches over more"
749 "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
750 "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
751 { "$6$rounds=77777$short",
752 "we have a short salt string but not a short password",
753 "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
754 "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
755 { "$6$rounds=123456$asaltof16chars..", "a short string",
756 "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
757 "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
758 { "$6$rounds=10$roundstoolow", "the minimum number is still observed",
759 "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
760 "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
762 #define ntests2 (sizeof (tests2) / sizeof (tests2[0]))
766 struct sha512_ctx ctx
;
772 static const char expected
[64] =
773 "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
774 "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
775 "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
776 "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
778 for (cnt
= 0; cnt
< (int) ntests
; ++cnt
) {
779 sha512_init_ctx (&ctx
);
780 sha512_process_bytes (tests
[cnt
].input
, strlen (tests
[cnt
].input
), &ctx
);
781 sha512_finish_ctx (&ctx
, sum
);
782 if (memcmp (tests
[cnt
].result
, sum
, 64) != 0) {
783 printf ("test %d run %d failed\n", cnt
, 1);
787 sha512_init_ctx (&ctx
);
788 for (i
= 0; tests
[cnt
].input
[i
] != '\0'; ++i
) {
789 sha512_process_bytes (&tests
[cnt
].input
[i
], 1, &ctx
);
791 sha512_finish_ctx (&ctx
, sum
);
792 if (memcmp (tests
[cnt
].result
, sum
, 64) != 0) {
793 printf ("test %d run %d failed\n", cnt
, 2);
798 /* Test vector from FIPS 180-2: appendix C.3. */
800 memset (buf
, 'a', sizeof (buf
));
801 sha512_init_ctx (&ctx
);
802 for (i
= 0; i
< 1000; ++i
) {
803 sha512_process_bytes (buf
, sizeof (buf
), &ctx
);
806 sha512_finish_ctx (&ctx
, sum
);
807 if (memcmp (expected
, sum
, 64) != 0) {
808 printf ("test %d failed\n", cnt
);
812 for (cnt
= 0; cnt
< ntests2
; ++cnt
) {
813 char *cp
= php_sha512_crypt(tests2
[cnt
].input
, tests2
[cnt
].salt
);
815 if (strcmp (cp
, tests2
[cnt
].expected
) != 0) {
816 printf ("test %d: expected \"%s\", got \"%s\"\n",
817 cnt
, tests2
[cnt
].expected
, cp
);
823 puts ("all tests OK");