root/ext/standard/crypt_sha512.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sha512_process_block
  2. sha512_init_ctx
  3. sha512_finish_ctx
  4. sha512_process_bytes
  5. php_sha512_crypt_r
  6. php_sha512_crypt
  7. main

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

/* [<][>][^][v][top][bottom][index][help] */