Back to index

php5  5.3.10
crypt_sha512.c
Go to the documentation of this file.
00001 /* SHA512-based Unix crypt implementation.
00002    Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
00003 /* Windows VC++ port by Pierre Joye <pierre@php.net> */
00004 
00005 #include "php.h"
00006 #include "php_main.h"
00007 
00008 #include <errno.h>
00009 #include <limits.h>
00010 #ifdef PHP_WIN32
00011 # include "win32/php_stdint.h"
00012 # define __alignof__ __alignof
00013 # define alloca _alloca
00014 #else
00015 # if HAVE_INTTYPES_H
00016 #  include <inttypes.h>
00017 # elif HAVE_STDINT_H
00018 #  include <stdint.h>
00019 # endif
00020 # ifndef HAVE_ALIGNOF
00021 #  include <stddef.h>
00022 #  define __alignof__(type) offsetof (struct { char c; type member;}, member)
00023 # endif
00024 # if HAVE_ATTRIBUTE_ALIGNED
00025 #  define ALIGNED(size) __attribute__ ((__aligned__ (size)))
00026 # else
00027 #  define ALIGNED(size)
00028 # endif
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 
00034 #ifdef PHP_WIN32
00035 # include <string.h>
00036 #else
00037 # include <sys/param.h>
00038 # include <sys/types.h>
00039 # if HAVE_STRING_H
00040 #  include <string.h>
00041 # else
00042 #  include <strings.h>
00043 # endif
00044 #endif
00045 
00046 extern void * __php_mempcpy(void * dst, const void * src, size_t len);
00047 extern char * __php_stpncpy(char *dst, const char *src, size_t len);
00048 
00049 #ifndef MIN
00050 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
00051 #endif
00052 #ifndef MAX
00053 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
00054 #endif
00055 
00056 /* See #51582 */
00057 #ifndef UINT64_C
00058 # define UINT64_C(value) __CONCAT(value, ULL)
00059 #endif
00060 
00061 /* Structure to save state of computation between the single steps.  */
00062 struct sha512_ctx
00063 {
00064        uint64_t H[8];
00065 
00066        uint64_t total[2];
00067        uint64_t buflen;
00068        char buffer[256];    /* NB: always correctly aligned for uint64_t.  */
00069 };
00070 
00071 
00072 #if PHP_WIN32 || (!defined(WORDS_BIGENDIAN))
00073 # define SWAP(n) \
00074   (((n) << 56)                                   \
00075    | (((n) & 0xff00) << 40)               \
00076    | (((n) & 0xff0000) << 24)                    \
00077    | (((n) & 0xff000000) << 8)                   \
00078    | (((n) >> 8) & 0xff000000)                   \
00079    | (((n) >> 24) & 0xff0000)                    \
00080    | (((n) >> 40) & 0xff00)               \
00081    | ((n) >> 56))
00082 #else
00083 # define SWAP(n) (n)
00084 #endif
00085 
00086 /* This array contains the bytes used to pad the buffer to the next
00087    64-byte boundary.  (FIPS 180-2:5.1.2)  */
00088 static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ...  */ };
00089 
00090 /* Constants for SHA512 from FIPS 180-2:4.2.3.  */
00091 static const uint64_t K[80] = {
00092        UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
00093        UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
00094        UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
00095        UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
00096        UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
00097        UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
00098        UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
00099        UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
00100        UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
00101        UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
00102        UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
00103        UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
00104        UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
00105        UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
00106        UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
00107        UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
00108        UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
00109        UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
00110        UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
00111        UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
00112        UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
00113        UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
00114        UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
00115        UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
00116        UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
00117        UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
00118        UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
00119        UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
00120        UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
00121        UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
00122        UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
00123        UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
00124        UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
00125        UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
00126        UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
00127        UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
00128        UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
00129        UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
00130        UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
00131        UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
00132   };
00133 
00134 
00135 /* Process LEN bytes of BUFFER, accumulating context into CTX.
00136    It is assumed that LEN % 128 == 0.  */
00137 static void
00138 sha512_process_block(const void *buffer, size_t len, struct sha512_ctx *ctx) {
00139        const uint64_t *words = buffer;
00140        size_t nwords = len / sizeof(uint64_t);
00141        uint64_t a = ctx->H[0];
00142        uint64_t b = ctx->H[1];
00143        uint64_t c = ctx->H[2];
00144        uint64_t d = ctx->H[3];
00145        uint64_t e = ctx->H[4];
00146        uint64_t f = ctx->H[5];
00147        uint64_t g = ctx->H[6];
00148        uint64_t h = ctx->H[7];
00149 
00150   /* First increment the byte count.  FIPS 180-2 specifies the possible
00151         length of the file up to 2^128 bits.  Here we only compute the
00152         number of bytes.  Do a double word increment.  */
00153        ctx->total[0] += len;
00154        if (ctx->total[0] < len) {
00155               ++ctx->total[1];
00156        }
00157 
00158        /* Process all bytes in the buffer with 128 bytes in each round of
00159         the loop.  */
00160        while (nwords > 0) {
00161               uint64_t W[80];
00162               uint64_t a_save = a;
00163               uint64_t b_save = b;
00164               uint64_t c_save = c;
00165               uint64_t d_save = d;
00166               uint64_t e_save = e;
00167               uint64_t f_save = f;
00168               uint64_t g_save = g;
00169               uint64_t h_save = h;
00170               unsigned int t;
00171 
00172 /* Operators defined in FIPS 180-2:4.1.2.  */
00173 #define Ch(x, y, z) ((x & y) ^ (~x & z))
00174 #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
00175 #define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
00176 #define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
00177 #define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
00178 #define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
00179 
00180               /* It is unfortunate that C does not provide an operator for
00181                  cyclic rotation.  Hope the C compiler is smart enough.  */
00182 #define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
00183 
00184               /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
00185               for (t = 0; t < 16; ++t) {
00186                      W[t] = SWAP (*words);
00187                      ++words;
00188               }
00189 
00190               for (t = 16; t < 80; ++t) {
00191                      W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
00192               }
00193 
00194               /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
00195               for (t = 0; t < 80; ++t) {
00196                      uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
00197                      uint64_t T2 = S0 (a) + Maj (a, b, c);
00198                      h = g;
00199                      g = f;
00200                      f = e;
00201                      e = d + T1;
00202                      d = c;
00203                      c = b;
00204                      b = a;
00205                      a = T1 + T2;
00206               }
00207 
00208               /* Add the starting values of the context according to FIPS 180-2:6.3.2
00209               step 4.  */
00210               a += a_save;
00211               b += b_save;
00212               c += c_save;
00213               d += d_save;
00214               e += e_save;
00215               f += f_save;
00216               g += g_save;
00217               h += h_save;
00218 
00219               /* Prepare for the next round.  */
00220               nwords -= 16;
00221        }
00222 
00223        /* Put checksum in context given as argument.  */
00224        ctx->H[0] = a;
00225        ctx->H[1] = b;
00226        ctx->H[2] = c;
00227        ctx->H[3] = d;
00228        ctx->H[4] = e;
00229        ctx->H[5] = f;
00230        ctx->H[6] = g;
00231        ctx->H[7] = h;
00232 }
00233 
00234 
00235 /* Initialize structure containing state of computation.
00236    (FIPS 180-2:5.3.3)  */
00237 static void sha512_init_ctx (struct sha512_ctx *ctx) {
00238        ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
00239        ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
00240        ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
00241        ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
00242        ctx->H[4] = UINT64_C (0x510e527fade682d1);
00243        ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
00244        ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
00245        ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
00246 
00247        ctx->total[0] = ctx->total[1] = 0;
00248        ctx->buflen = 0;
00249 }
00250 
00251 
00252 /* Process the remaining bytes in the internal buffer and the usual
00253        prolog according to the standard and write the result to RESBUF.
00254 
00255        IMPORTANT: On some systems it is required that RESBUF is correctly
00256        aligned for a 32 bits value. */
00257 static void * sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) {
00258        /* Take yet unprocessed bytes into account.  */
00259        uint64_t bytes = ctx->buflen;
00260        size_t pad;
00261        unsigned int i;
00262 
00263        /* Now count remaining bytes.  */
00264        ctx->total[0] += bytes;
00265        if (ctx->total[0] < bytes) {
00266               ++ctx->total[1];
00267        }
00268 
00269        pad = bytes >= 112 ? 128 + 112 - (size_t)bytes : 112 - (size_t)bytes;
00270        memcpy(&ctx->buffer[bytes], fillbuf, pad);
00271 
00272        /* Put the 128-bit file length in *bits* at the end of the buffer.  */
00273        *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP(ctx->total[0] << 3);
00274        *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP((ctx->total[1] << 3) |
00275                                           (ctx->total[0] >> 61));
00276 
00277        /* Process last bytes.  */
00278        sha512_process_block(ctx->buffer, (size_t)(bytes + pad + 16), ctx);
00279 
00280        /* Put result from CTX in first 64 bytes following RESBUF.  */
00281        for (i = 0; i < 8; ++i) {
00282               ((uint64_t *) resbuf)[i] = SWAP(ctx->H[i]);
00283        }
00284 
00285        return resbuf;
00286 }
00287 
00288 static void
00289 sha512_process_bytes(const void *buffer, size_t len, struct sha512_ctx *ctx) {
00290        /* When we already have some bits in our internal buffer concatenate
00291         both inputs first.  */
00292        if (ctx->buflen != 0) {
00293               size_t left_over = (size_t)ctx->buflen;
00294               size_t add = (size_t)(256 - left_over > len ? len : 256 - left_over);
00295 
00296               memcpy(&ctx->buffer[left_over], buffer, add);
00297               ctx->buflen += add;
00298 
00299               if (ctx->buflen > 128) {
00300                      sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx);
00301 
00302                      ctx->buflen &= 127;
00303                      /* The regions in the following copy operation cannot overlap.  */
00304                      memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
00305                                    (size_t)ctx->buflen);
00306               }
00307 
00308               buffer = (const char *) buffer + add;
00309               len -= add;
00310        }
00311 
00312        /* Process available complete blocks.  */
00313        if (len >= 128) {
00314 #if !_STRING_ARCH_unaligned
00315 /* To check alignment gcc has an appropriate operator.  Other
00316    compilers don't.  */
00317 # if __GNUC__ >= 2
00318 #  define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
00319 # else
00320 #  define UNALIGNED_P(p) (((uintptr_t) p) % sizeof(uint64_t) != 0)
00321 # endif
00322               if (UNALIGNED_P(buffer))
00323                      while (len > 128) {
00324                             sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx);
00325                             buffer = (const char *) buffer + 128;
00326                             len -= 128;
00327                      }
00328               else
00329 #endif
00330               {
00331                 sha512_process_block(buffer, len & ~127, ctx);
00332                 buffer = (const char *) buffer + (len & ~127);
00333                 len &= 127;
00334               }
00335        }
00336 
00337   /* Move remaining bytes into internal buffer.  */
00338        if (len > 0) {
00339               size_t left_over = (size_t)ctx->buflen;
00340 
00341               memcpy(&ctx->buffer[left_over], buffer, len);
00342               left_over += len;
00343               if (left_over >= 128) {
00344                      sha512_process_block(ctx->buffer, 128, ctx);
00345                      left_over -= 128;
00346                      memcpy(ctx->buffer, &ctx->buffer[128], left_over);
00347               }
00348               ctx->buflen = left_over;
00349        }
00350 }
00351 
00352 
00353 /* Define our magic string to mark salt for SHA512 "encryption"
00354    replacement.  */
00355 static const char sha512_salt_prefix[] = "$6$";
00356 
00357 /* Prefix for optional rounds specification.  */
00358 static const char sha512_rounds_prefix[] = "rounds=";
00359 
00360 /* Maximum salt string length.  */
00361 #define SALT_LEN_MAX 16
00362 /* Default number of rounds if not explicitly specified.  */
00363 #define ROUNDS_DEFAULT 5000
00364 /* Minimum number of rounds.  */
00365 #define ROUNDS_MIN 1000
00366 /* Maximum number of rounds.  */
00367 #define ROUNDS_MAX 999999999
00368 
00369 /* Table with characters for base64 transformation.  */
00370 static const char b64t[64] =
00371 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00372 
00373 
00374 char *
00375 php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) {
00376 #ifdef PHP_WIN32
00377 # if _MSC <= 1300
00378 #  pragma pack(push, 16)
00379        unsigned char alt_result[64];
00380        unsigned char temp_result[64];
00381 #  pragma pack(pop)
00382 # else
00383        __declspec(align(64)) unsigned char alt_result[64];
00384        __declspec(align(64)) unsigned char temp_result[64];
00385 # endif
00386 #else
00387        unsigned char alt_result[64] ALIGNED(__alignof__ (uint64_t));
00388        unsigned char temp_result[64] ALIGNED(__alignof__ (uint64_t));
00389 #endif
00390        struct sha512_ctx ctx;
00391        struct sha512_ctx alt_ctx;
00392        size_t salt_len;
00393        size_t key_len;
00394        size_t cnt;
00395        char *cp;
00396        char *copied_key = NULL;
00397        char *copied_salt = NULL;
00398        char *p_bytes;
00399        char *s_bytes;
00400        /* Default number of rounds.  */
00401        size_t rounds = ROUNDS_DEFAULT;
00402        zend_bool rounds_custom = 0;
00403 
00404        /* Find beginning of salt string.  The prefix should normally always
00405         be present.  Just in case it is not.  */
00406        if (strncmp(sha512_salt_prefix, salt, sizeof(sha512_salt_prefix) - 1) == 0) {
00407               /* Skip salt prefix.  */
00408               salt += sizeof(sha512_salt_prefix) - 1;
00409        }
00410 
00411        if (strncmp(salt, sha512_rounds_prefix, sizeof(sha512_rounds_prefix) - 1) == 0) {
00412               const char *num = salt + sizeof(sha512_rounds_prefix) - 1;
00413               char *endp;
00414               unsigned long int srounds = strtoul(num, &endp, 10);
00415 
00416               if (*endp == '$') {
00417                      salt = endp + 1;
00418                      rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
00419                      rounds_custom = 1;
00420               }
00421        }
00422 
00423        salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
00424        key_len = strlen(key);
00425 
00426        if ((key - (char *) 0) % __alignof__ (uint64_t) != 0) {
00427               char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
00428               key = copied_key =
00429               memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), key, key_len);
00430        }
00431 
00432        if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0) {
00433               char *tmp = (char *) alloca(salt_len + 1 + __alignof__(uint64_t));
00434               salt = copied_salt = memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), salt, salt_len);
00435               copied_salt[salt_len] = 0;
00436        }
00437 
00438        /* Prepare for the real work.  */
00439        sha512_init_ctx(&ctx);
00440 
00441        /* Add the key string.  */
00442        sha512_process_bytes(key, key_len, &ctx);
00443 
00444        /* The last part is the salt string.  This must be at most 16
00445         characters and it ends at the first `$' character (for
00446         compatibility with existing implementations).  */
00447        sha512_process_bytes(salt, salt_len, &ctx);
00448 
00449 
00450        /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
00451         final result will be added to the first context.  */
00452        sha512_init_ctx(&alt_ctx);
00453 
00454        /* Add key.  */
00455        sha512_process_bytes(key, key_len, &alt_ctx);
00456 
00457        /* Add salt.  */
00458        sha512_process_bytes(salt, salt_len, &alt_ctx);
00459 
00460        /* Add key again.  */
00461        sha512_process_bytes(key, key_len, &alt_ctx);
00462 
00463        /* Now get result of this (64 bytes) and add it to the other
00464         context.  */
00465        sha512_finish_ctx(&alt_ctx, alt_result);
00466 
00467        /* Add for any character in the key one byte of the alternate sum.  */
00468        for (cnt = key_len; cnt > 64; cnt -= 64) {
00469               sha512_process_bytes(alt_result, 64, &ctx);
00470        }
00471        sha512_process_bytes(alt_result, cnt, &ctx);
00472 
00473        /* Take the binary representation of the length of the key and for every
00474         1 add the alternate sum, for every 0 the key.  */
00475        for (cnt = key_len; cnt > 0; cnt >>= 1) {
00476               if ((cnt & 1) != 0) {
00477                      sha512_process_bytes(alt_result, 64, &ctx);
00478               } else {
00479                      sha512_process_bytes(key, key_len, &ctx);
00480               }
00481        }
00482 
00483        /* Create intermediate result.  */
00484        sha512_finish_ctx(&ctx, alt_result);
00485 
00486        /* Start computation of P byte sequence.  */
00487        sha512_init_ctx(&alt_ctx);
00488 
00489        /* For every character in the password add the entire password.  */
00490        for (cnt = 0; cnt < key_len; ++cnt) {
00491               sha512_process_bytes(key, key_len, &alt_ctx);
00492        }
00493 
00494        /* Finish the digest.  */
00495        sha512_finish_ctx(&alt_ctx, temp_result);
00496 
00497        /* Create byte sequence P.  */
00498        cp = p_bytes = alloca(key_len);
00499        for (cnt = key_len; cnt >= 64; cnt -= 64) {
00500               cp = __php_mempcpy((void *) cp, (const void *)temp_result, 64);
00501        }
00502 
00503        memcpy(cp, temp_result, cnt);
00504 
00505        /* Start computation of S byte sequence.  */
00506        sha512_init_ctx(&alt_ctx);
00507 
00508        /* For every character in the password add the entire password.  */
00509        for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
00510               sha512_process_bytes(salt, salt_len, &alt_ctx);
00511        }
00512 
00513        /* Finish the digest.  */
00514        sha512_finish_ctx(&alt_ctx, temp_result);
00515 
00516        /* Create byte sequence S.  */
00517        cp = s_bytes = alloca(salt_len);
00518        for (cnt = salt_len; cnt >= 64; cnt -= 64) {
00519               cp = __php_mempcpy(cp, temp_result, 64);
00520        }
00521        memcpy(cp, temp_result, cnt);
00522 
00523        /* Repeatedly run the collected hash value through SHA512 to burn
00524         CPU cycles.  */
00525        for (cnt = 0; cnt < rounds; ++cnt) {
00526               /* New context.  */
00527               sha512_init_ctx(&ctx);
00528 
00529               /* Add key or last result.  */
00530               if ((cnt & 1) != 0) {
00531                      sha512_process_bytes(p_bytes, key_len, &ctx);
00532               } else {
00533                      sha512_process_bytes(alt_result, 64, &ctx);
00534               }
00535 
00536               /* Add salt for numbers not divisible by 3.  */
00537               if (cnt % 3 != 0) {
00538                      sha512_process_bytes(s_bytes, salt_len, &ctx);
00539               }
00540 
00541               /* Add key for numbers not divisible by 7.  */
00542               if (cnt % 7 != 0) {
00543                      sha512_process_bytes(p_bytes, key_len, &ctx);
00544               }
00545 
00546               /* Add key or last result.  */
00547               if ((cnt & 1) != 0) {
00548                      sha512_process_bytes(alt_result, 64, &ctx);
00549               } else {
00550                      sha512_process_bytes(p_bytes, key_len, &ctx);
00551               }
00552 
00553               /* Create intermediate result.  */
00554               sha512_finish_ctx(&ctx, alt_result);
00555        }
00556 
00557        /* Now we can construct the result string.  It consists of three
00558         parts.  */
00559        cp = __php_stpncpy(buffer, sha512_salt_prefix, MAX(0, buflen));
00560        buflen -= sizeof(sha512_salt_prefix) - 1;
00561 
00562        if (rounds_custom) {
00563 #ifdef PHP_WIN32
00564          int n = _snprintf(cp, MAX(0, buflen), "%s%u$", sha512_rounds_prefix, rounds);
00565 #else
00566          int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds);
00567 #endif
00568          cp += n;
00569          buflen -= n;
00570        }
00571 
00572        cp = __php_stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len));
00573        buflen -= (int) MIN((size_t) MAX(0, buflen), salt_len);
00574 
00575        if (buflen > 0) {
00576               *cp++ = '$';
00577               --buflen;
00578        }
00579 
00580 #define b64_from_24bit(B2, B1, B0, N)                    \
00581   do {                                                                          \
00582        unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);      \
00583        int n = (N);                                                         \
00584        while (n-- > 0 && buflen > 0)                                       \
00585          {                                                                             \
00586        *cp++ = b64t[w & 0x3f];                                                 \
00587        --buflen;                                                                \
00588        w >>= 6;                                                                 \
00589          }                                                                             \
00590   } while (0)
00591 
00592        b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4);
00593        b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4);
00594        b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4);
00595        b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4);
00596        b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4);
00597        b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4);
00598        b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4);
00599        b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4);
00600        b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4);
00601        b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4);
00602        b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4);
00603        b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4);
00604        b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4);
00605        b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4);
00606        b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4);
00607        b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4);
00608        b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4);
00609        b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4);
00610        b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4);
00611        b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4);
00612        b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4);
00613        b64_from_24bit(0, 0, alt_result[63], 2);
00614 
00615        if (buflen <= 0) {
00616               errno = ERANGE;
00617               buffer = NULL;
00618        } else {
00619               *cp = '\0';          /* Terminate the string.  */
00620        }
00621 
00622        /* Clear the buffer for the intermediate result so that people
00623         attaching to processes or reading core dumps cannot get any
00624         information.  We do it in this way to clear correct_words[]
00625         inside the SHA512 implementation as well.  */
00626        sha512_init_ctx(&ctx);
00627        sha512_finish_ctx(&ctx, alt_result);
00628        memset(temp_result, '\0', sizeof(temp_result));
00629        memset(p_bytes, '\0', key_len);
00630        memset(s_bytes, '\0', salt_len);
00631        memset(&ctx, '\0', sizeof(ctx));
00632        memset(&alt_ctx, '\0', sizeof(alt_ctx));
00633        if (copied_key != NULL) {
00634               memset(copied_key, '\0', key_len);
00635        }
00636        if (copied_salt != NULL) {
00637               memset(copied_salt, '\0', salt_len);
00638        }
00639 
00640        return buffer;
00641 }
00642 
00643 
00644 /* This entry point is equivalent to the `crypt' function in Unix
00645    libcs.  */
00646 char *
00647 php_sha512_crypt(const char *key, const char *salt) {
00648        /* We don't want to have an arbitrary limit in the size of the
00649         password.  We can compute an upper bound for the size of the
00650         result in advance and so we can prepare the buffer we pass to
00651         `sha512_crypt_r'.  */
00652        static char *buffer;
00653        static int buflen;
00654        int needed = (int)(sizeof(sha512_salt_prefix) - 1
00655               + sizeof(sha512_rounds_prefix) + 9 + 1
00656               + strlen(salt) + 1 + 86 + 1);
00657 
00658        if (buflen < needed) {
00659               char *new_buffer = (char *) realloc(buffer, needed);
00660               if (new_buffer == NULL) {
00661                      return NULL;
00662               }
00663 
00664               buffer = new_buffer;
00665               buflen = needed;
00666        }
00667 
00668        return php_sha512_crypt_r (key, salt, buffer, buflen);
00669 }
00670 
00671 #ifdef TEST
00672 static const struct {
00673        const char *input;
00674        const char result[64];
00675 } tests[] =
00676        {
00677        /* Test vectors from FIPS 180-2: appendix C.1.  */
00678        { "abc",
00679          "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
00680          "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
00681          "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
00682          "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
00683        /* Test vectors from FIPS 180-2: appendix C.2.  */
00684        { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
00685          "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
00686          "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
00687          "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
00688          "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
00689          "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
00690        /* Test vectors from the NESSIE project.  */
00691        { "",
00692          "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
00693          "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
00694          "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
00695          "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
00696        { "a",
00697          "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
00698          "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
00699          "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
00700          "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
00701        { "message digest",
00702          "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
00703          "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
00704          "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
00705          "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
00706        { "abcdefghijklmnopqrstuvwxyz",
00707          "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
00708          "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
00709          "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
00710          "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
00711        { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
00712          "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
00713          "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
00714          "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
00715          "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
00716        { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00717          "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
00718          "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
00719          "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
00720          "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
00721        { "123456789012345678901234567890123456789012345678901234567890"
00722          "12345678901234567890",
00723          "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
00724          "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
00725          "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
00726          "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
00727   };
00728 #define ntests (sizeof (tests) / sizeof (tests[0]))
00729 
00730 
00731 static const struct
00732 {
00733        const char *salt;
00734        const char *input;
00735        const char *expected;
00736 } tests2[] = {
00737        { "$6$saltstring", "Hello world!",
00738        "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
00739        "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1"},
00740        { "$6$rounds=10000$saltstringsaltstring", "Hello world!",
00741        "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
00742        "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
00743        { "$6$rounds=5000$toolongsaltstring", "This is just a test",
00744        "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
00745        "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
00746        { "$6$rounds=1400$anotherlongsaltstring",
00747        "a very much longer text to encrypt.  This one even stretches over more"
00748        "than one line.",
00749        "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
00750        "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
00751        { "$6$rounds=77777$short",
00752        "we have a short salt string but not a short password",
00753        "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
00754        "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
00755        { "$6$rounds=123456$asaltof16chars..", "a short string",
00756        "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
00757        "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
00758        { "$6$rounds=10$roundstoolow", "the minimum number is still observed",
00759        "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
00760        "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
00761 };
00762 #define ntests2 (sizeof (tests2) / sizeof (tests2[0]))
00763 
00764 
00765 int main (void) {
00766        struct sha512_ctx ctx;
00767        char sum[64];
00768        int result = 0;
00769        int cnt;
00770        int i;
00771        char buf[1000];
00772        static const char expected[64] =
00773               "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
00774               "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
00775               "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
00776               "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
00777 
00778        for (cnt = 0; cnt < (int) ntests; ++cnt) {
00779               sha512_init_ctx (&ctx);
00780               sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
00781               sha512_finish_ctx (&ctx, sum);
00782               if (memcmp (tests[cnt].result, sum, 64) != 0) {
00783                      printf ("test %d run %d failed\n", cnt, 1);
00784                      result = 1;
00785               }
00786 
00787               sha512_init_ctx (&ctx);
00788               for (i = 0; tests[cnt].input[i] != '\0'; ++i) {
00789                      sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
00790               }
00791               sha512_finish_ctx (&ctx, sum);
00792               if (memcmp (tests[cnt].result, sum, 64) != 0) {
00793                      printf ("test %d run %d failed\n", cnt, 2);
00794                      result = 1;
00795               }
00796        }
00797 
00798        /* Test vector from FIPS 180-2: appendix C.3.  */
00799 
00800        memset (buf, 'a', sizeof (buf));
00801        sha512_init_ctx (&ctx);
00802        for (i = 0; i < 1000; ++i) {
00803               sha512_process_bytes (buf, sizeof (buf), &ctx);
00804        }
00805 
00806        sha512_finish_ctx (&ctx, sum);
00807        if (memcmp (expected, sum, 64) != 0) {
00808               printf ("test %d failed\n", cnt);
00809               result = 1;
00810        }
00811 
00812        for (cnt = 0; cnt < ntests2; ++cnt) {
00813               char *cp = php_sha512_crypt(tests2[cnt].input, tests2[cnt].salt);
00814 
00815               if (strcmp (cp, tests2[cnt].expected) != 0) {
00816                      printf ("test %d: expected \"%s\", got \"%s\"\n",
00817                                    cnt, tests2[cnt].expected, cp);
00818                      result = 1;
00819               }
00820        }
00821 
00822        if (result == 0) {
00823               puts ("all tests OK");
00824        }
00825 
00826        return result;
00827 }
00828 #endif