#include "php_crypt_r.h"
#include "crypt_freesec.h"
-
-#if !PHP_WIN32
#include "ext/standard/md5.h"
-#endif
#ifdef ZTS
MUTEX_T php_crypt_extended_init_lock;
#endif
-/* TODO: enable it when enabling vista/2k8 mode in tsrm */
-#if 0
-CONDITION_VARIABLE initialized;
-#endif
-
void php_init_crypt_r()
{
#ifdef ZTS
#endif
}
-/* MD% crypt implementation using the windows CryptoApi */
+/* MD5 crypt implementation using the windows CryptoApi */
#define MD5_MAGIC "$1$"
#define MD5_MAGIC_LEN 3
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-static void
-to64(char *s, int32_t v, int n)
+/* Convert a 16/32 bit integer to Base64 string representation */
+static void to64(char *s, int32_t v, int n)
{
while (--n >= 0) {
*s++ = itoa64[v & 0x3f];
}
}
-#ifdef PHP_WIN32
-char * php_md5_crypt_r(const char *pw, const char *salt, char *out) {
- HCRYPTPROV hCryptProv;
- HCRYPTHASH ctx, ctx1;
- DWORD i, pwl, sl;
- const BYTE magic_md5[4] = "$1$";
- const DWORD magic_md5_len = 3;
- DWORD dwHashLen;
- int pl;
- __int32 l;
- const char *sp = salt;
- const char *ep = salt;
- char *p = NULL;
- char *passwd = out;
- unsigned char final[16];
-
- /* Acquire a cryptographic provider context handle. */
- if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
- return NULL;
- }
-
- pwl = (DWORD) 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++);
-
- /* get the length of the true salt */
- sl = (DWORD)(ep - sp);
-
- /* Create an empty hash object. */
- if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx)) {
- goto _destroyProv;
- }
-
- /* The password first, since that is what is most unknown */
- if(!CryptHashData(ctx, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx0;
- }
-
- /* Then our magic string */
- if(!CryptHashData(ctx, magic_md5, magic_md5_len, 0)) {
- goto _destroyCtx0;
- }
-
- /* Then the raw salt */
- if(!CryptHashData( ctx, (BYTE *)sp, sl, 0)) {
- goto _destroyCtx0;
- }
-
- /* MD5(pw,salt,pw), valid. */
- /* Then just as many characters of the MD5(pw,salt,pw) */
- if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx1)) {
- goto _destroyCtx0;
- }
- if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx1;
- }
- if(!CryptHashData(ctx1, (BYTE *)sp, sl, 0)) {
- goto _destroyCtx1;
- }
- if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx1;
- }
-
- dwHashLen = 16;
- CryptGetHashParam(ctx1, HP_HASHVAL, final, &dwHashLen, 0);
- /* MD5(pw,salt,pw). Valid. */
-
- for (pl = pwl; pl > 0; pl -= 16) {
- CryptHashData(ctx, final, (DWORD)(pl > 16 ? 16 : pl), 0);
- }
-
- /* Don't leave anything around in vm they could use. */
- ZEND_SECURE_ZERO(final, sizeof(final));
-
- /* Then something really weird... */
- for (i = pwl; i != 0; i >>= 1) {
- if ((i & 1) != 0) {
- CryptHashData(ctx, (const BYTE *)final, 1, 0);
- } else {
- CryptHashData(ctx, (const BYTE *)pw, 1, 0);
- }
- }
-
- memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
-
- if (strncpy_s(passwd + MD5_MAGIC_LEN, MD5_HASH_MAX_LEN - MD5_MAGIC_LEN, sp, sl + 1) != 0) {
- goto _destroyCtx1;
- }
- passwd[MD5_MAGIC_LEN + sl] = '\0';
- strcat_s(passwd, MD5_HASH_MAX_LEN, "$");
-
- dwHashLen = 16;
-
- /* Fetch the ctx hash value */
- CryptGetHashParam(ctx, HP_HASHVAL, final, &dwHashLen, 0);
-
- for (i = 0; i < 1000; i++) {
- if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx1)) {
- goto _destroyCtx1;
- }
-
- if ((i & 1) != 0) {
- if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx1;
- }
- } else {
- if(!CryptHashData(ctx1, (BYTE *)final, 16, 0)) {
- goto _destroyCtx1;
- }
- }
-
- if ((i % 3) != 0) {
- if(!CryptHashData(ctx1, (BYTE *)sp, sl, 0)) {
- goto _destroyCtx1;
- }
- }
-
- if ((i % 7) != 0) {
- if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx1;
- }
- }
-
- if ((i & 1) != 0) {
- if(!CryptHashData(ctx1, (BYTE *)final, 16, 0)) {
- goto _destroyCtx1;
- }
- } else {
- if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
- goto _destroyCtx1;
- }
- }
-
- /* Fetch the ctx hash value */
- dwHashLen = 16;
- CryptGetHashParam(ctx1, HP_HASHVAL, final, &dwHashLen, 0);
- if(!(CryptDestroyHash(ctx1))) {
- goto _destroyCtx0;
- }
- }
-
- ctx1 = (HCRYPTHASH) NULL;
-
- 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';
-
- ZEND_SECURE_ZERO(final, sizeof(final));
-
-
-_destroyCtx1:
- if (ctx1) {
- if (!CryptDestroyHash(ctx1)) {
-
- }
- }
-
-_destroyCtx0:
- CryptDestroyHash(ctx);
-
-_destroyProv:
- /* Release the provider handle.*/
- if(hCryptProv) {
- if(!(CryptReleaseContext(hCryptProv, 0))) {
- return NULL;
- }
- }
-
- return out;
-}
-#else
-
/*
* MD5 password encryption.
*/
ZEND_SECURE_ZERO(final, sizeof(final));
return (passwd);
}
-
-#undef MD5_MAGIC
-#undef MD5_MAGIC_LEN
-#endif