Back to index

php5  5.3.10
Defines | Functions
php_crypt_r.h File Reference
#include "crypt_freesec.h"
#include "crypt_blowfish.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define __CONST
#define MD5_HASH_MAX_LEN   120

Functions

void php_init_crypt_r ()
void php_shutdown_crypt_r ()
void _crypt_extended_init_r (void)
PHPAPI char * php_crypt_r (const char *__key, const char *__salt, struct php_crypt_extended_data *__data)
char * php_md5_crypt_r (const char *pw, const char *salt, char *out)
char * php_sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
char * php_sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen)

Define Documentation

#define __CONST

Definition at line 33 of file php_crypt_r.h.

#define MD5_HASH_MAX_LEN   120

Definition at line 47 of file php_crypt_r.h.


Function Documentation

void _crypt_extended_init_r ( void  )

Definition at line 80 of file php_crypt_r.c.

{
#ifdef PHP_WIN32
       LONG volatile initialized = 0;
#elif defined(HAVE_ATOMIC_H) /* Solaris 10 defines atomic API within */
       volatile unsigned int initialized = 0;
#else
       static volatile sig_atomic_t initialized = 0;
#endif

#ifdef ZTS
       tsrm_mutex_lock(php_crypt_extended_init_lock);
#endif

       if (!initialized) {
#ifdef PHP_WIN32
              InterlockedIncrement(&initialized);
#elif defined(HAVE_SYNC_FETCH_AND_ADD)
              __sync_fetch_and_add(&initialized, 1);
#elif defined(HAVE_ATOMIC_H) /* Solaris 10 defines atomic API within */
              membar_producer();
              atomic_add_int(&initialized, 1);
#endif
              _crypt_extended_init();
       }
#ifdef ZTS
       tsrm_mutex_unlock(php_crypt_extended_init_lock);
#endif
}

Here is the call graph for this function:

PHPAPI char* php_crypt_r ( const char *  __key,
const char *  __salt,
struct php_crypt_extended_data __data 
)
void php_init_crypt_r ( )

Definition at line 66 of file php_crypt_r.c.

{
#ifdef ZTS
       php_crypt_extended_init_lock = tsrm_mutex_alloc();
#endif
}
char* php_md5_crypt_r ( const char *  pw,
const char *  salt,
char *  out 
)

Definition at line 324 of file php_crypt_r.c.

{
       static char passwd[MD5_HASH_MAX_LEN], *p;
       const char *sp, *ep;
       unsigned char final[16];
       unsigned int i, sl, pwl;
       PHP_MD5_CTX   ctx, ctx1;
       php_uint32 l;
       int pl;
       
       pwl = strlen(pw);
       
       /* Refine the salt first */
       sp = salt;

       /* If it starts with the magic string, then skip that */
       if (strncmp(sp, MD5_MAGIC, MD5_MAGIC_LEN) == 0)
              sp += MD5_MAGIC_LEN;

       /* It stops at the first '$', max 8 chars */
       for (ep = sp; *ep != '\0' && *ep != '$' && ep < (sp + 8); ep++)
              continue;

       /* get the length of the true salt */
       sl = ep - sp;

       PHP_MD5Init(&ctx);

       /* The password first, since that is what is most unknown */
       PHP_MD5Update(&ctx, (const unsigned char *)pw, pwl);

       /* Then our magic string */
       PHP_MD5Update(&ctx, (const unsigned char *)MD5_MAGIC, MD5_MAGIC_LEN);

       /* Then the raw salt */
       PHP_MD5Update(&ctx, (const unsigned char *)sp, sl);

       /* Then just as many characters of the MD5(pw,salt,pw) */
       PHP_MD5Init(&ctx1);
       PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
       PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl);
       PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
       PHP_MD5Final(final, &ctx1);

       for (pl = pwl; pl > 0; pl -= 16)
              PHP_MD5Update(&ctx, final, (unsigned int)(pl > 16 ? 16 : pl));

       /* Don't leave anything around in vm they could use. */
       memset(final, 0, sizeof(final));

       /* Then something really weird... */
       for (i = pwl; i != 0; i >>= 1)
              if ((i & 1) != 0)
                  PHP_MD5Update(&ctx, final, 1);
              else
                  PHP_MD5Update(&ctx, (const unsigned char *)pw, 1);

       /* Now make the output string */
       memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
       strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1);
       strcat(passwd, "$");

       PHP_MD5Final(final, &ctx);

       /*
        * And now, just to make sure things don't run too fast. On a 60 MHz
        * Pentium this takes 34 msec, so you would need 30 seconds to build
        * a 1000 entry dictionary...
        */
       for (i = 0; i < 1000; i++) {
              PHP_MD5Init(&ctx1);

              if ((i & 1) != 0)
                     PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
              else
                     PHP_MD5Update(&ctx1, final, 16);

              if ((i % 3) != 0)
                     PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl);

              if ((i % 7) != 0)
                     PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);

              if ((i & 1) != 0)
                     PHP_MD5Update(&ctx1, final, 16);
              else
                     PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);

              PHP_MD5Final(final, &ctx1);
       }

       p = passwd + sl + MD5_MAGIC_LEN + 1;

       l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
       l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
       l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
       l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
       l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
       l =                  final[11]            ; to64(p,l,2); p += 2;
       *p = '\0';

       /* Don't leave anything around in vm they could use. */
       memset(final, 0, sizeof(final));
       return (passwd);
}

Here is the call graph for this function:

char* php_sha256_crypt_r ( const char *  key,
const char *  salt,
char *  buffer,
int  buflen 
)

Definition at line 340 of file crypt_sha256.c.

{
#ifdef PHP_WIN32
# if _MSC <= 1300
#  pragma pack(push, 16)
       unsigned char alt_result[32];
       unsigned char temp_result[32];
#  pragma pack(pop)
# else
       __declspec(align(32)) unsigned char alt_result[32];
       __declspec(align(32)) unsigned char temp_result[32];
# endif
#else
       unsigned char alt_result[32] ALIGNED(__alignof__ (uint32_t));
       unsigned char temp_result[32] ALIGNED(__alignof__ (uint32_t));
#endif

       struct sha256_ctx ctx;
       struct sha256_ctx alt_ctx;
       size_t salt_len;
       size_t key_len;
       size_t cnt;
       char *cp;
       char *copied_key = NULL;
       char *copied_salt = NULL;
       char *p_bytes;
       char *s_bytes;
       /* Default number of rounds.  */
       size_t rounds = ROUNDS_DEFAULT;
       zend_bool rounds_custom = 0;

       /* Find beginning of salt string.  The prefix should normally always
       be present.  Just in case it is not.  */
       if (strncmp(sha256_salt_prefix, salt, sizeof(sha256_salt_prefix) - 1) == 0) {
              /* Skip salt prefix.  */
              salt += sizeof(sha256_salt_prefix) - 1;
       }

       if (strncmp(salt, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1) == 0) {
              const char *num = salt + sizeof(sha256_rounds_prefix) - 1;
              char *endp;
              unsigned long int srounds = strtoul(num, &endp, 10);
              if (*endp == '$') {
                     salt = endp + 1;
                     rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
                     rounds_custom = 1;
              }
       }

       salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
       key_len = strlen(key);

       if ((key - (char *) 0) % __alignof__ (uint32_t) != 0) {
              char *tmp = (char *) alloca(key_len + __alignof__(uint32_t));
              key = copied_key = memcpy(tmp + __alignof__(uint32_t) - (tmp - (char *) 0) % __alignof__(uint32_t), key, key_len);
       }

       if ((salt - (char *) 0) % __alignof__(uint32_t) != 0) {
              char *tmp = (char *) alloca(salt_len + 1 + __alignof__(uint32_t));
              salt = copied_salt =
              memcpy(tmp + __alignof__(uint32_t) - (tmp - (char *) 0) % __alignof__ (uint32_t), salt, salt_len);
              copied_salt[salt_len] = 0;
       }

       /* Prepare for the real work.  */
       sha256_init_ctx(&ctx);

       /* Add the key string.  */
       sha256_process_bytes(key, key_len, &ctx);

       /* The last part is the salt string.  This must be at most 16
        characters and it ends at the first `$' character (for
        compatibility with existing implementations).  */
       sha256_process_bytes(salt, salt_len, &ctx);


       /* Compute alternate SHA256 sum with input KEY, SALT, and KEY.  The
        final result will be added to the first context.  */
       sha256_init_ctx(&alt_ctx);

       /* Add key.  */
       sha256_process_bytes(key, key_len, &alt_ctx);

       /* Add salt.  */
       sha256_process_bytes(salt, salt_len, &alt_ctx);

       /* Add key again.  */
       sha256_process_bytes(key, key_len, &alt_ctx);

       /* Now get result of this (32 bytes) and add it to the other
        context.  */
       sha256_finish_ctx(&alt_ctx, alt_result);

       /* Add for any character in the key one byte of the alternate sum.  */
       for (cnt = key_len; cnt > 32; cnt -= 32) {
              sha256_process_bytes(alt_result, 32, &ctx);
       }
       sha256_process_bytes(alt_result, cnt, &ctx);

       /* Take the binary representation of the length of the key and for every
       1 add the alternate sum, for every 0 the key.  */
       for (cnt = key_len; cnt > 0; cnt >>= 1) {
              if ((cnt & 1) != 0) {
                     sha256_process_bytes(alt_result, 32, &ctx);
              } else {
                     sha256_process_bytes(key, key_len, &ctx);
              }
       }

       /* Create intermediate result.  */
       sha256_finish_ctx(&ctx, alt_result);

       /* Start computation of P byte sequence.  */
       sha256_init_ctx(&alt_ctx);

       /* For every character in the password add the entire password.  */
       for (cnt = 0; cnt < key_len; ++cnt) {
              sha256_process_bytes(key, key_len, &alt_ctx);
       }

       /* Finish the digest.  */
       sha256_finish_ctx(&alt_ctx, temp_result);

       /* Create byte sequence P.  */
       cp = p_bytes = alloca(key_len);
       for (cnt = key_len; cnt >= 32; cnt -= 32) {
              cp = __php_mempcpy((void *)cp, (const void *)temp_result, 32);
       }
       memcpy(cp, temp_result, cnt);

       /* Start computation of S byte sequence.  */
       sha256_init_ctx(&alt_ctx);

       /* For every character in the password add the entire password.  */
       for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
              sha256_process_bytes(salt, salt_len, &alt_ctx);
       }

       /* Finish the digest.  */
       sha256_finish_ctx(&alt_ctx, temp_result);

       /* Create byte sequence S.  */
       cp = s_bytes = alloca(salt_len);
       for (cnt = salt_len; cnt >= 32; cnt -= 32) {
              cp = __php_mempcpy(cp, temp_result, 32);
       }
       memcpy(cp, temp_result, cnt);

       /* Repeatedly run the collected hash value through SHA256 to burn
       CPU cycles.  */
       for (cnt = 0; cnt < rounds; ++cnt) {
              /* New context.  */
              sha256_init_ctx(&ctx);

              /* Add key or last result.  */
              if ((cnt & 1) != 0) {
                     sha256_process_bytes(p_bytes, key_len, &ctx);
              } else {
                     sha256_process_bytes(alt_result, 32, &ctx);
              }

              /* Add salt for numbers not divisible by 3.  */
              if (cnt % 3 != 0) {
                     sha256_process_bytes(s_bytes, salt_len, &ctx);
              }

              /* Add key for numbers not divisible by 7.  */
              if (cnt % 7 != 0) {
                     sha256_process_bytes(p_bytes, key_len, &ctx);
              }

              /* Add key or last result.  */
              if ((cnt & 1) != 0) {
                     sha256_process_bytes(alt_result, 32, &ctx);
              } else {
                     sha256_process_bytes(p_bytes, key_len, &ctx);
              }

              /* Create intermediate result.  */
              sha256_finish_ctx(&ctx, alt_result);
       }

       /* Now we can construct the result string.  It consists of three
       parts.  */
       cp = __php_stpncpy(buffer, sha256_salt_prefix, MAX(0, buflen));
       buflen -= sizeof(sha256_salt_prefix) - 1;

       if (rounds_custom) {
#ifdef PHP_WIN32
              int n = _snprintf(cp, MAX(0, buflen), "%s%u$", sha256_rounds_prefix, rounds);
#else
              int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha256_rounds_prefix, rounds);
#endif
              cp += n;
              buflen -= n;
       }

       cp = __php_stpncpy(cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
       buflen -= MIN((size_t) MAX (0, buflen), salt_len);

       if (buflen > 0) {
              *cp++ = '$';
              --buflen;
       }

#define b64_from_24bit(B2, B1, B0, N)                                       \
  do {                                                               \
    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);                     \
    int n = (N);                                                     \
    while (n-- > 0 && buflen > 0)                                    \
      {                                                                     \
       *cp++ = b64t[w & 0x3f];                                              \
       --buflen;                                                     \
       w >>= 6;                                                      \
      }                                                                     \
  } while (0)

       b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4);
       b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4);
       b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4);
       b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4);
       b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4);
       b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4);
       b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4);
       b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4);
       b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4);
       b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4);
       b64_from_24bit(0, alt_result[31], alt_result[30], 3);
       if (buflen <= 0) {
              errno = ERANGE;
              buffer = NULL;
       } else
              *cp = '\0';          /* Terminate the string.  */

       /* Clear the buffer for the intermediate result so that people
     attaching to processes or reading core dumps cannot get any
     information.  We do it in this way to clear correct_words[]
     inside the SHA256 implementation as well.  */
       sha256_init_ctx(&ctx);
       sha256_finish_ctx(&ctx, alt_result);
       memset(temp_result, '\0', sizeof(temp_result));
       memset(p_bytes, '\0', key_len);
       memset(s_bytes, '\0', salt_len);
       memset(&ctx, '\0', sizeof(ctx));
       memset(&alt_ctx, '\0', sizeof(alt_ctx));

       if (copied_key != NULL) {
              memset(copied_key, '\0', key_len);

       }
       if (copied_salt != NULL) {
              memset(copied_salt, '\0', salt_len);
       }

       return buffer;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* php_sha512_crypt_r ( const char *  key,
const char *  salt,
char *  buffer,
int  buflen 
)

Definition at line 375 of file crypt_sha512.c.

                                                                                {
#ifdef PHP_WIN32
# if _MSC <= 1300
#  pragma pack(push, 16)
       unsigned char alt_result[64];
       unsigned char temp_result[64];
#  pragma pack(pop)
# else
       __declspec(align(64)) unsigned char alt_result[64];
       __declspec(align(64)) unsigned char temp_result[64];
# endif
#else
       unsigned char alt_result[64] ALIGNED(__alignof__ (uint64_t));
       unsigned char temp_result[64] ALIGNED(__alignof__ (uint64_t));
#endif
       struct sha512_ctx ctx;
       struct sha512_ctx alt_ctx;
       size_t salt_len;
       size_t key_len;
       size_t cnt;
       char *cp;
       char *copied_key = NULL;
       char *copied_salt = NULL;
       char *p_bytes;
       char *s_bytes;
       /* Default number of rounds.  */
       size_t rounds = ROUNDS_DEFAULT;
       zend_bool rounds_custom = 0;

       /* Find beginning of salt string.  The prefix should normally always
        be present.  Just in case it is not.  */
       if (strncmp(sha512_salt_prefix, salt, sizeof(sha512_salt_prefix) - 1) == 0) {
              /* Skip salt prefix.  */
              salt += sizeof(sha512_salt_prefix) - 1;
       }

       if (strncmp(salt, sha512_rounds_prefix, sizeof(sha512_rounds_prefix) - 1) == 0) {
              const char *num = salt + sizeof(sha512_rounds_prefix) - 1;
              char *endp;
              unsigned long int srounds = strtoul(num, &endp, 10);

              if (*endp == '$') {
                     salt = endp + 1;
                     rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
                     rounds_custom = 1;
              }
       }

       salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
       key_len = strlen(key);

       if ((key - (char *) 0) % __alignof__ (uint64_t) != 0) {
              char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
              key = copied_key =
              memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), key, key_len);
       }

       if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0) {
              char *tmp = (char *) alloca(salt_len + 1 + __alignof__(uint64_t));
              salt = copied_salt = memcpy(tmp + __alignof__(uint64_t) - (tmp - (char *) 0) % __alignof__(uint64_t), salt, salt_len);
              copied_salt[salt_len] = 0;
       }

       /* Prepare for the real work.  */
       sha512_init_ctx(&ctx);

       /* Add the key string.  */
       sha512_process_bytes(key, key_len, &ctx);

       /* The last part is the salt string.  This must be at most 16
        characters and it ends at the first `$' character (for
        compatibility with existing implementations).  */
       sha512_process_bytes(salt, salt_len, &ctx);


       /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
        final result will be added to the first context.  */
       sha512_init_ctx(&alt_ctx);

       /* Add key.  */
       sha512_process_bytes(key, key_len, &alt_ctx);

       /* Add salt.  */
       sha512_process_bytes(salt, salt_len, &alt_ctx);

       /* Add key again.  */
       sha512_process_bytes(key, key_len, &alt_ctx);

       /* Now get result of this (64 bytes) and add it to the other
        context.  */
       sha512_finish_ctx(&alt_ctx, alt_result);

       /* Add for any character in the key one byte of the alternate sum.  */
       for (cnt = key_len; cnt > 64; cnt -= 64) {
              sha512_process_bytes(alt_result, 64, &ctx);
       }
       sha512_process_bytes(alt_result, cnt, &ctx);

       /* Take the binary representation of the length of the key and for every
        1 add the alternate sum, for every 0 the key.  */
       for (cnt = key_len; cnt > 0; cnt >>= 1) {
              if ((cnt & 1) != 0) {
                     sha512_process_bytes(alt_result, 64, &ctx);
              } else {
                     sha512_process_bytes(key, key_len, &ctx);
              }
       }

       /* Create intermediate result.  */
       sha512_finish_ctx(&ctx, alt_result);

       /* Start computation of P byte sequence.  */
       sha512_init_ctx(&alt_ctx);

       /* For every character in the password add the entire password.  */
       for (cnt = 0; cnt < key_len; ++cnt) {
              sha512_process_bytes(key, key_len, &alt_ctx);
       }

       /* Finish the digest.  */
       sha512_finish_ctx(&alt_ctx, temp_result);

       /* Create byte sequence P.  */
       cp = p_bytes = alloca(key_len);
       for (cnt = key_len; cnt >= 64; cnt -= 64) {
              cp = __php_mempcpy((void *) cp, (const void *)temp_result, 64);
       }

       memcpy(cp, temp_result, cnt);

       /* Start computation of S byte sequence.  */
       sha512_init_ctx(&alt_ctx);

       /* For every character in the password add the entire password.  */
       for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
              sha512_process_bytes(salt, salt_len, &alt_ctx);
       }

       /* Finish the digest.  */
       sha512_finish_ctx(&alt_ctx, temp_result);

       /* Create byte sequence S.  */
       cp = s_bytes = alloca(salt_len);
       for (cnt = salt_len; cnt >= 64; cnt -= 64) {
              cp = __php_mempcpy(cp, temp_result, 64);
       }
       memcpy(cp, temp_result, cnt);

       /* Repeatedly run the collected hash value through SHA512 to burn
        CPU cycles.  */
       for (cnt = 0; cnt < rounds; ++cnt) {
              /* New context.  */
              sha512_init_ctx(&ctx);

              /* Add key or last result.  */
              if ((cnt & 1) != 0) {
                     sha512_process_bytes(p_bytes, key_len, &ctx);
              } else {
                     sha512_process_bytes(alt_result, 64, &ctx);
              }

              /* Add salt for numbers not divisible by 3.  */
              if (cnt % 3 != 0) {
                     sha512_process_bytes(s_bytes, salt_len, &ctx);
              }

              /* Add key for numbers not divisible by 7.  */
              if (cnt % 7 != 0) {
                     sha512_process_bytes(p_bytes, key_len, &ctx);
              }

              /* Add key or last result.  */
              if ((cnt & 1) != 0) {
                     sha512_process_bytes(alt_result, 64, &ctx);
              } else {
                     sha512_process_bytes(p_bytes, key_len, &ctx);
              }

              /* Create intermediate result.  */
              sha512_finish_ctx(&ctx, alt_result);
       }

       /* Now we can construct the result string.  It consists of three
        parts.  */
       cp = __php_stpncpy(buffer, sha512_salt_prefix, MAX(0, buflen));
       buflen -= sizeof(sha512_salt_prefix) - 1;

       if (rounds_custom) {
#ifdef PHP_WIN32
         int n = _snprintf(cp, MAX(0, buflen), "%s%u$", sha512_rounds_prefix, rounds);
#else
         int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds);
#endif
         cp += n;
         buflen -= n;
       }

       cp = __php_stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len));
       buflen -= (int) MIN((size_t) MAX(0, buflen), salt_len);

       if (buflen > 0) {
              *cp++ = '$';
              --buflen;
       }

#define b64_from_24bit(B2, B1, B0, N)                    \
  do {                                                                          \
       unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);      \
       int n = (N);                                                         \
       while (n-- > 0 && buflen > 0)                                       \
         {                                                                             \
       *cp++ = b64t[w & 0x3f];                                                 \
       --buflen;                                                                \
       w >>= 6;                                                                 \
         }                                                                             \
  } while (0)

       b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4);
       b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4);
       b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4);
       b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4);
       b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4);
       b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4);
       b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4);
       b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4);
       b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4);
       b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4);
       b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4);
       b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4);
       b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4);
       b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4);
       b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4);
       b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4);
       b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4);
       b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4);
       b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4);
       b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4);
       b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4);
       b64_from_24bit(0, 0, alt_result[63], 2);

       if (buflen <= 0) {
              errno = ERANGE;
              buffer = NULL;
       } else {
              *cp = '\0';          /* Terminate the string.  */
       }

       /* Clear the buffer for the intermediate result so that people
        attaching to processes or reading core dumps cannot get any
        information.  We do it in this way to clear correct_words[]
        inside the SHA512 implementation as well.  */
       sha512_init_ctx(&ctx);
       sha512_finish_ctx(&ctx, alt_result);
       memset(temp_result, '\0', sizeof(temp_result));
       memset(p_bytes, '\0', key_len);
       memset(s_bytes, '\0', salt_len);
       memset(&ctx, '\0', sizeof(ctx));
       memset(&alt_ctx, '\0', sizeof(alt_ctx));
       if (copied_key != NULL) {
              memset(copied_key, '\0', key_len);
       }
       if (copied_salt != NULL) {
              memset(copied_salt, '\0', salt_len);
       }

       return buffer;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 73 of file php_crypt_r.c.

{
#ifdef ZTS
       tsrm_mutex_free(php_crypt_extended_init_lock);
#endif
}