PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - php_crypt_r.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 64
Code covered: 100.0 % Executed lines: 64
Legend: not executed executed

       1                 : /* $Id: php_crypt_r.c 290154 2009-11-02 20:46:52Z pajoye $ */
       2                 : /*
       3                 :    +----------------------------------------------------------------------+
       4                 :    | PHP Version 5                                                        |
       5                 :    +----------------------------------------------------------------------+
       6                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       7                 :    +----------------------------------------------------------------------+
       8                 :    | This source file is subject to version 3.01 of the PHP license,      |
       9                 :    | that is bundled with this package in the file LICENSE, and is        |
      10                 :    | available through the world-wide-web at the following url:           |
      11                 :    | http://www.php.net/license/3_01.txt                                  |
      12                 :    | If you did not receive a copy of the PHP license and are unable to   |
      13                 :    | obtain it through the world-wide-web, please send a note to          |
      14                 :    | license@php.net so we can mail you a copy immediately.               |
      15                 :    +----------------------------------------------------------------------+
      16                 :    | Authors: Pierre Alain Joye  <pajoye@php.net                          |
      17                 :    +----------------------------------------------------------------------+
      18                 :  */
      19                 : 
      20                 : /*
      21                 :  * License for the Unix md5crypt implementation (md5_crypt):
      22                 :  *
      23                 :  * ----------------------------------------------------------------------------
      24                 :  * "THE BEER-WARE LICENSE" (Revision 42):
      25                 :  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
      26                 :  * can do whatever you want with this stuff. If we meet some day, and you think
      27                 :  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
      28                 :  * ----------------------------------------------------------------------------
      29                 :  *
      30                 :  * from FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp
      31                 :  * via OpenBSD: md5crypt.c,v 1.9 1997/07/23 20:58:27 kstailey Exp
      32                 :  * via NetBSD: md5crypt.c,v 1.4.2.1 2002/01/22 19:31:59 he Exp
      33                 :  *
      34                 :  */
      35                 : 
      36                 : #include "php.h"
      37                 : 
      38                 : #include <string.h>
      39                 : 
      40                 : #if PHP_WIN32
      41                 : # include <windows.h>
      42                 : # include <Wincrypt.h>
      43                 : #endif
      44                 : 
      45                 : #include <signal.h>
      46                 : #include "php_crypt_r.h"
      47                 : #include "crypt_freesec.h"
      48                 : 
      49                 : #if !PHP_WIN32
      50                 : #include "ext/standard/md5.h"
      51                 : #endif
      52                 : 
      53                 : #ifdef ZTS
      54                 : MUTEX_T php_crypt_extended_init_lock;
      55                 : #endif
      56                 : 
      57                 : /* TODO: enable it when enabling vista/2k8 mode in tsrm */
      58                 : #if 0
      59                 : CONDITION_VARIABLE initialized;
      60                 : #endif
      61                 :         
      62                 : void php_init_crypt_r()
      63           17633 : {
      64                 : #ifdef ZTS
      65                 :         php_crypt_extended_init_lock = tsrm_mutex_alloc();
      66                 : #endif
      67           17633 : }
      68                 : 
      69                 : void php_shutdown_crypt_r()
      70           17665 : {
      71                 : #ifdef ZTS
      72                 :         tsrm_mutex_free(php_crypt_extended_init_lock);
      73                 : #endif
      74           17665 : }
      75                 : 
      76                 : void _crypt_extended_init_r(void)
      77               2 : {
      78                 :         static volatile sig_atomic_t initialized = 0;
      79                 : 
      80                 : #ifdef ZTS
      81                 :         tsrm_mutex_lock(php_crypt_extended_init_lock);
      82                 : #endif
      83                 : 
      84               2 :         if (initialized) {
      85               1 :                 return;
      86                 :         } else {
      87               1 :                 _crypt_extended_init();
      88               1 :                 initialized = 1;
      89                 :         }
      90                 : #ifdef ZTS
      91                 :         tsrm_mutex_unlock(php_crypt_extended_init_lock);
      92                 : #endif
      93                 : }
      94                 : 
      95                 : /* MD% crypt implementation using the windows CryptoApi */
      96                 : #define MD5_MAGIC "$1$"
      97                 : #define MD5_MAGIC_LEN 3
      98                 : 
      99                 : static unsigned char itoa64[] =         /* 0 ... 63 => ascii - 64 */
     100                 :         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     101                 : 
     102                 : static void
     103                 : to64(char *s, int32_t v, int n)
     104              18 : {
     105             102 :         while (--n >= 0) {
     106              66 :                 *s++ = itoa64[v & 0x3f];
     107              66 :                 v >>= 6;
     108                 :         }
     109              18 : }
     110                 : 
     111                 : #if PHP_WIN32
     112                 : char * php_md5_crypt_r(const char *pw, const char *salt, char *out) {
     113                 :         HCRYPTPROV hCryptProv;
     114                 :         HCRYPTHASH ctx, ctx1;
     115                 :         unsigned int i, pwl, sl;
     116                 :         const BYTE magic_md5[4] = "$1$";
     117                 :         const DWORD magic_md5_len = 3;
     118                 :         DWORD        dwHashLen;
     119                 :         int pl;
     120                 :         __int32 l;
     121                 :         const char *sp = salt;
     122                 :         const char *ep = salt;
     123                 :         char *p = NULL;
     124                 :         char *passwd = out;
     125                 :         unsigned char final[16];
     126                 : 
     127                 :         /* Acquire a cryptographic provider context handle. */
     128                 :         if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
     129                 :                 return NULL;
     130                 :         }
     131                 : 
     132                 :         pwl = (unsigned int) strlen(pw);
     133                 : 
     134                 :         /* Refine the salt first */
     135                 :         sp = salt;
     136                 : 
     137                 :         /* If it starts with the magic string, then skip that */
     138                 :         if (strncmp(sp, MD5_MAGIC, MD5_MAGIC_LEN) == 0) {
     139                 :                 sp += MD5_MAGIC_LEN;
     140                 :         }
     141                 : 
     142                 :         /* It stops at the first '$', max 8 chars */
     143                 :         for (ep = sp; *ep != '\0' && *ep != '$' && ep < (sp + 8); ep++) {
     144                 :                 continue;
     145                 :         }
     146                 : 
     147                 :         /* get the length of the true salt */
     148                 :         sl = ep - sp;
     149                 : 
     150                 :         /* Create an empty hash object. */
     151                 :         if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx)) {
     152                 :                 goto _destroyProv;
     153                 :         }
     154                 : 
     155                 :         /* The password first, since that is what is most unknown */
     156                 :         if(!CryptHashData(ctx, (BYTE *)pw, pwl, 0)) {
     157                 :                 goto _destroyCtx0;
     158                 :         }
     159                 : 
     160                 :         /* Then our magic string */
     161                 :         if(!CryptHashData(ctx, magic_md5, magic_md5_len, 0)) {
     162                 :                 goto _destroyCtx0;
     163                 :         }
     164                 : 
     165                 :         /* Then the raw salt */
     166                 :         if(!CryptHashData( ctx, (BYTE *)sp, sl, 0)) {
     167                 :                 goto _destroyCtx0;
     168                 :         }
     169                 : 
     170                 :         /* MD5(pw,salt,pw), valid. */
     171                 :         /* Then just as many characters of the MD5(pw,salt,pw) */
     172                 :         if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx1)) {
     173                 :                 goto _destroyCtx0;
     174                 :         }
     175                 :         if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
     176                 :                 goto _destroyCtx1;
     177                 :         }
     178                 :         if(!CryptHashData(ctx1, (BYTE *)sp, sl, 0)) {
     179                 :                 goto _destroyCtx1;
     180                 :         }
     181                 :         if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
     182                 :                 goto _destroyCtx1;
     183                 :         }
     184                 : 
     185                 :         dwHashLen = pwl + sl + pwl;
     186                 :         CryptGetHashParam(ctx1, HP_HASHVAL, final, &dwHashLen, 0);
     187                 :         /*  MD5(pw,salt,pw). Valid. */
     188                 : 
     189                 :         for (pl = pwl; pl > 0; pl -= 16) {
     190                 :                 CryptHashData(ctx, final, (DWORD)(pl > 16 ? 16 : pl), 0);
     191                 :         }
     192                 : 
     193                 :         /* Don't leave anything around in vm they could use. */
     194                 :         memset(final, 0, sizeof(final));
     195                 : 
     196                 :         /* Then something really weird... */
     197                 :         for (i = pwl; i != 0; i >>= 1) {
     198                 :                 if ((i & 1) != 0) {
     199                 :                         CryptHashData(ctx, (const BYTE *)final, 1, 0);
     200                 :                 } else {
     201                 :                         CryptHashData(ctx, (const BYTE *)pw, 1, 0);
     202                 :                 }
     203                 :         }
     204                 : 
     205                 :         memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
     206                 : 
     207                 : #if _MSC_VER >= 1500
     208                 :         if (strncpy_s(passwd + MD5_MAGIC_LEN, MD5_HASH_MAX_LEN - MD5_MAGIC_LEN, sp, sl + 1) != 0) {
     209                 :                 goto _destroyCtx1;
     210                 :         }
     211                 :         passwd[MD5_MAGIC_LEN + sl] = '\0';
     212                 :         strcat_s(passwd, MD5_HASH_MAX_LEN, "$");
     213                 : #else
     214                 :         /* VC6 version doesn't have strcat_s or strncpy_s */
     215                 :         if (strncpy(passwd + MD5_MAGIC_LEN, sp, sl + 1) < sl) {
     216                 :                 goto _destroyCtx1;
     217                 :         }
     218                 :         strcat(passwd, "$");
     219                 : #endif
     220                 :         dwHashLen = 16;
     221                 : 
     222                 :         /* Fetch the ctx hash value */
     223                 :         CryptGetHashParam(ctx, HP_HASHVAL, final, &dwHashLen, 0);
     224                 : 
     225                 :         for (i = 0; i < 1000; i++) {
     226                 :                 if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx1)) {
     227                 :                         goto _destroyCtx1;
     228                 :                 }
     229                 : 
     230                 :                 if ((i & 1) != 0) {
     231                 :                         if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
     232                 :                                 goto _destroyCtx1;
     233                 :                         }
     234                 :                 } else {
     235                 :                         if(!CryptHashData(ctx1, (BYTE *)final, 16, 0)) {
     236                 :                                 goto _destroyCtx1;
     237                 :                         }
     238                 :                 }
     239                 : 
     240                 :                 if ((i % 3) != 0) {
     241                 :                         if(!CryptHashData(ctx1, (BYTE *)sp, sl, 0)) {
     242                 :                                 goto _destroyCtx1;
     243                 :                         }
     244                 :                 }
     245                 : 
     246                 :                 if ((i % 7) != 0) {
     247                 :                         if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
     248                 :                                 goto _destroyCtx1;
     249                 :                         }
     250                 :                 }
     251                 : 
     252                 :                 if ((i & 1) != 0) {
     253                 :                         if(!CryptHashData(ctx1, (BYTE *)final, 16, 0)) {
     254                 :                                 goto _destroyCtx1;
     255                 :                         }
     256                 :                 } else {
     257                 :                         if(!CryptHashData(ctx1, (BYTE *)pw, pwl, 0)) {
     258                 :                                 goto _destroyCtx1;
     259                 :                         }
     260                 :                 }
     261                 : 
     262                 :                 /* Fetch the ctx hash value */
     263                 :                 dwHashLen = 16;
     264                 :                 CryptGetHashParam(ctx1, HP_HASHVAL, final, &dwHashLen, 0);
     265                 :                 if(!(CryptDestroyHash(ctx1))) {
     266                 :                         goto _destroyCtx0;
     267                 :                 }
     268                 :         }
     269                 : 
     270                 :         ctx1 = (HCRYPTHASH) NULL;
     271                 : 
     272                 :         p = passwd + sl + MD5_MAGIC_LEN + 1;
     273                 : 
     274                 :         l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
     275                 :         l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
     276                 :         l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
     277                 :         l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
     278                 :         l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
     279                 :         l = final[11]; to64(p,l,2); p += 2;
     280                 : 
     281                 :         *p = '\0';
     282                 : 
     283                 :         memset(final, 0, sizeof(final));
     284                 : 
     285                 : 
     286                 : _destroyCtx1:
     287                 :         if (ctx1) {
     288                 :                 if (!CryptDestroyHash(ctx1)) {
     289                 :                         
     290                 :                 }
     291                 :         }
     292                 : 
     293                 : _destroyCtx0:
     294                 :         CryptDestroyHash(ctx);
     295                 : 
     296                 : _destroyProv:
     297                 :         /* Release the provider handle.*/
     298                 :         if(hCryptProv) {
     299                 :                 if(!(CryptReleaseContext(hCryptProv, 0))) {
     300                 :                         return NULL;
     301                 :                 }
     302                 :         }
     303                 : 
     304                 :         return out;
     305                 : }
     306                 : #else
     307                 : 
     308                 : /*
     309                 :  * MD5 password encryption.
     310                 :  */
     311                 : char * php_md5_crypt_r(const char *pw, const char *salt, char *out)
     312               3 : {
     313                 :         static char passwd[MD5_HASH_MAX_LEN], *p;
     314                 :         const char *sp, *ep;
     315                 :         unsigned char final[16];
     316                 :         unsigned int i, sl, pwl;
     317                 :         PHP_MD5_CTX     ctx, ctx1;
     318                 :         php_uint32 l;
     319                 :         int pl;
     320                 :         
     321               3 :         pwl = strlen(pw);
     322                 :         
     323                 :         /* Refine the salt first */
     324               3 :         sp = salt;
     325                 : 
     326                 :         /* If it starts with the magic string, then skip that */
     327               3 :         if (strncmp(sp, MD5_MAGIC, MD5_MAGIC_LEN) == 0)
     328               3 :                 sp += MD5_MAGIC_LEN;
     329                 : 
     330                 :         /* It stops at the first '$', max 8 chars */
     331               3 :         for (ep = sp; *ep != '\0' && *ep != '$' && ep < (sp + 8); ep++)
     332                 :                 continue;
     333                 : 
     334                 :         /* get the length of the true salt */
     335               3 :         sl = ep - sp;
     336                 : 
     337               3 :         PHP_MD5Init(&ctx);
     338                 : 
     339                 :         /* The password first, since that is what is most unknown */
     340               3 :         PHP_MD5Update(&ctx, (const unsigned char *)pw, pwl);
     341                 : 
     342                 :         /* Then our magic string */
     343               3 :         PHP_MD5Update(&ctx, (const unsigned char *)MD5_MAGIC, MD5_MAGIC_LEN);
     344                 : 
     345                 :         /* Then the raw salt */
     346               3 :         PHP_MD5Update(&ctx, (const unsigned char *)sp, sl);
     347                 : 
     348                 :         /* Then just as many characters of the MD5(pw,salt,pw) */
     349               3 :         PHP_MD5Init(&ctx1);
     350               3 :         PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
     351               3 :         PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl);
     352               3 :         PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
     353               3 :         PHP_MD5Final(final, &ctx1);
     354                 : 
     355               6 :         for (pl = pwl; pl > 0; pl -= 16)
     356               3 :                 PHP_MD5Update(&ctx, final, (unsigned int)(pl > 16 ? 16 : pl));
     357                 : 
     358                 :         /* Don't leave anything around in vm they could use. */
     359               3 :         memset(final, 0, sizeof(final));
     360                 : 
     361                 :         /* Then something really weird... */
     362              14 :         for (i = pwl; i != 0; i >>= 1)
     363              11 :                 if ((i & 1) != 0)
     364               7 :                     PHP_MD5Update(&ctx, final, 1);
     365                 :                 else
     366               4 :                     PHP_MD5Update(&ctx, (const unsigned char *)pw, 1);
     367                 : 
     368                 :         /* Now make the output string */
     369               3 :         memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN);
     370               3 :         strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1);
     371               3 :         strcat(passwd, "$");
     372                 : 
     373               3 :         PHP_MD5Final(final, &ctx);
     374                 : 
     375                 :         /*
     376                 :          * And now, just to make sure things don't run too fast. On a 60 MHz
     377                 :          * Pentium this takes 34 msec, so you would need 30 seconds to build
     378                 :          * a 1000 entry dictionary...
     379                 :          */
     380            3003 :         for (i = 0; i < 1000; i++) {
     381            3000 :                 PHP_MD5Init(&ctx1);
     382                 : 
     383            3000 :                 if ((i & 1) != 0)
     384            1500 :                         PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
     385                 :                 else
     386            1500 :                         PHP_MD5Update(&ctx1, final, 16);
     387                 : 
     388            3000 :                 if ((i % 3) != 0)
     389            1998 :                         PHP_MD5Update(&ctx1, (const unsigned char *)sp, sl);
     390                 : 
     391            3000 :                 if ((i % 7) != 0)
     392            2571 :                         PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
     393                 : 
     394            3000 :                 if ((i & 1) != 0)
     395            1500 :                         PHP_MD5Update(&ctx1, final, 16);
     396                 :                 else
     397            1500 :                         PHP_MD5Update(&ctx1, (const unsigned char *)pw, pwl);
     398                 : 
     399            3000 :                 PHP_MD5Final(final, &ctx1);
     400                 :         }
     401                 : 
     402               3 :         p = passwd + sl + MD5_MAGIC_LEN + 1;
     403                 : 
     404               3 :         l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
     405               3 :         l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
     406               3 :         l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
     407               3 :         l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
     408               3 :         l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
     409               3 :         l =                    final[11]                ; to64(p,l,2); p += 2;
     410               3 :         *p = '\0';
     411                 : 
     412                 :         /* Don't leave anything around in vm they could use. */
     413               3 :         memset(final, 0, sizeof(final));
     414               3 :         return (passwd);
     415                 : }
     416                 : 
     417                 : #undef MD5_MAGIC
     418                 : #undef MD5_MAGIC_LEN
     419                 : #endif
     420                 : 

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:11 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.