1 /* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD$ 10 * 11 */ 12 13 #if defined(LIBC_SCCS) && !defined(lint) 14 static const char rcsid[] = "$FreeBSD$"; 15 #endif /* LIBC_SCCS and not lint */ 16 17 #include <unistd.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <md5.h> 21 #include "crypt.h" 22 23 /* 24 * UNIX password 25 */ 26 27 char * 28 crypt_md5(pw, salt) 29 const char *pw; 30 const char *salt; 31 { 32 static char *magic = "$1$"; /* 33 * This string is magic for 34 * this algorithm. Having 35 * it this way, we can get 36 * get better later on 37 */ 38 static char passwd[120], *p; 39 static const char *sp,*ep; 40 unsigned char final[MD5_SIZE]; 41 int sl,pl,i; 42 MD5_CTX ctx,ctx1; 43 unsigned long l; 44 45 /* Refine the Salt first */ 46 sp = salt; 47 48 /* If it starts with the magic string, then skip that */ 49 if(!strncmp(sp,magic,strlen(magic))) 50 sp += strlen(magic); 51 52 /* It stops at the first '$', max 8 chars */ 53 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) 54 continue; 55 56 /* get the length of the true salt */ 57 sl = ep - sp; 58 59 MD5Init(&ctx); 60 61 /* The password first, since that is what is most unknown */ 62 MD5Update(&ctx,pw,strlen(pw)); 63 64 /* Then our magic string */ 65 MD5Update(&ctx,magic,strlen(magic)); 66 67 /* Then the raw salt */ 68 MD5Update(&ctx,sp,sl); 69 70 /* Then just as many characters of the MD5(pw,salt,pw) */ 71 MD5Init(&ctx1); 72 MD5Update(&ctx1,pw,strlen(pw)); 73 MD5Update(&ctx1,sp,sl); 74 MD5Update(&ctx1,pw,strlen(pw)); 75 MD5Final(final,&ctx1); 76 for(pl = strlen(pw); pl > 0; pl -= MD5_SIZE) 77 MD5Update(&ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl); 78 79 /* Don't leave anything around in vm they could use. */ 80 memset(final,0,sizeof final); 81 82 /* Then something really weird... */ 83 for (i = strlen(pw); i ; i >>= 1) 84 if(i&1) 85 MD5Update(&ctx, final, 1); 86 else 87 MD5Update(&ctx, pw, 1); 88 89 /* Now make the output string */ 90 strcpy(passwd,magic); 91 strncat(passwd,sp,sl); 92 strcat(passwd,"$"); 93 94 MD5Final(final,&ctx); 95 96 /* 97 * and now, just to make sure things don't run too fast 98 * On a 60 Mhz Pentium this takes 34 msec, so you would 99 * need 30 seconds to build a 1000 entry dictionary... 100 */ 101 for(i=0;i<1000;i++) { 102 MD5Init(&ctx1); 103 if(i & 1) 104 MD5Update(&ctx1,pw,strlen(pw)); 105 else 106 MD5Update(&ctx1,final,MD5_SIZE); 107 108 if(i % 3) 109 MD5Update(&ctx1,sp,sl); 110 111 if(i % 7) 112 MD5Update(&ctx1,pw,strlen(pw)); 113 114 if(i & 1) 115 MD5Update(&ctx1,final,MD5_SIZE); 116 else 117 MD5Update(&ctx1,pw,strlen(pw)); 118 MD5Final(final,&ctx1); 119 } 120 121 p = passwd + strlen(passwd); 122 123 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; 124 _crypt_to64(p,l,4); p += 4; 125 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; 126 _crypt_to64(p,l,4); p += 4; 127 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; 128 _crypt_to64(p,l,4); p += 4; 129 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; 130 _crypt_to64(p,l,4); p += 4; 131 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; 132 _crypt_to64(p,l,4); p += 4; 133 l = final[11] ; 134 _crypt_to64(p,l,2); p += 2; 135 *p = '\0'; 136 137 /* Don't leave anything around in vm they could use. */ 138 memset(final,0,sizeof final); 139 140 return passwd; 141 } 142 143