crypt-md5.c revision 91795
151462Smarkm/* 251462Smarkm * ---------------------------------------------------------------------------- 351462Smarkm * "THE BEER-WARE LICENSE" (Revision 42): 451462Smarkm * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 551462Smarkm * can do whatever you want with this stuff. If we meet some day, and you think 651462Smarkm * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 751462Smarkm * ---------------------------------------------------------------------------- 851462Smarkm */ 951462Smarkm 1083551Sdillon#include <sys/cdefs.h> 1183551Sdillon__FBSDID("$FreeBSD: head/lib/libcrypt/crypt-md5.c 91795 2002-03-07 10:41:11Z markm $"); 1251462Smarkm 1351462Smarkm#include <unistd.h> 1451462Smarkm#include <stdio.h> 1551462Smarkm#include <string.h> 1651462Smarkm#include <md5.h> 1754751Speter#include <err.h> 1851462Smarkm#include "crypt.h" 1951462Smarkm 2051462Smarkm/* 2151462Smarkm * UNIX password 2251462Smarkm */ 2351462Smarkm 2451462Smarkmchar * 2591754Smarkmcrypt_md5(const char *pw, const char *salt) 2651462Smarkm{ 2751462Smarkm MD5_CTX ctx,ctx1; 2851462Smarkm unsigned long l; 2991795Smarkm int sl, pl; 3091795Smarkm u_int i; 3191754Smarkm u_char final[MD5_SIZE]; 3291754Smarkm static const char *sp, *ep; 3391754Smarkm static char passwd[120], *p; 3491754Smarkm static const char *magic = "$1$"; /* 3591754Smarkm * This string is magic for 3691754Smarkm * this algorithm. Having 3791754Smarkm * it this way, we can get 3891754Smarkm * get better later on 3991754Smarkm */ 4051462Smarkm 4151462Smarkm /* Refine the Salt first */ 4251462Smarkm sp = salt; 4351462Smarkm 4451462Smarkm /* If it starts with the magic string, then skip that */ 4591754Smarkm if(!strncmp(sp, magic, strlen(magic))) 4651462Smarkm sp += strlen(magic); 4751462Smarkm 4851462Smarkm /* It stops at the first '$', max 8 chars */ 4991754Smarkm for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) 5051462Smarkm continue; 5151462Smarkm 5251462Smarkm /* get the length of the true salt */ 5351462Smarkm sl = ep - sp; 5451462Smarkm 5551462Smarkm MD5Init(&ctx); 5651462Smarkm 5751462Smarkm /* The password first, since that is what is most unknown */ 5891754Smarkm MD5Update(&ctx, (const u_char *)pw, strlen(pw)); 5951462Smarkm 6051462Smarkm /* Then our magic string */ 6191754Smarkm MD5Update(&ctx, (const u_char *)magic, strlen(magic)); 6251462Smarkm 6351462Smarkm /* Then the raw salt */ 6491754Smarkm MD5Update(&ctx, (const u_char *)sp, (u_int)sl); 6551462Smarkm 6651462Smarkm /* Then just as many characters of the MD5(pw,salt,pw) */ 6751462Smarkm MD5Init(&ctx1); 6891754Smarkm MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); 6991754Smarkm MD5Update(&ctx1, (const u_char *)sp, (u_int)sl); 7091754Smarkm MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); 7191754Smarkm MD5Final(final, &ctx1); 7291795Smarkm for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE) 7391754Smarkm MD5Update(&ctx, (const u_char *)final, 7491795Smarkm (u_int)(pl > MD5_SIZE ? MD5_SIZE : pl)); 7551462Smarkm 7651462Smarkm /* Don't leave anything around in vm they could use. */ 7791754Smarkm memset(final, 0, sizeof(final)); 7851462Smarkm 7951462Smarkm /* Then something really weird... */ 8091754Smarkm for (i = strlen(pw); i; i >>= 1) 8191754Smarkm if(i & 1) 8291754Smarkm MD5Update(&ctx, (const u_char *)final, 1); 8351462Smarkm else 8491754Smarkm MD5Update(&ctx, (const u_char *)pw, 1); 8551462Smarkm 8651462Smarkm /* Now make the output string */ 8791754Smarkm strcpy(passwd, magic); 8891754Smarkm strncat(passwd, sp, (u_int)sl); 8991754Smarkm strcat(passwd, "$"); 9051462Smarkm 9191754Smarkm MD5Final(final, &ctx); 9251462Smarkm 9351462Smarkm /* 9451462Smarkm * and now, just to make sure things don't run too fast 9551462Smarkm * On a 60 Mhz Pentium this takes 34 msec, so you would 9651462Smarkm * need 30 seconds to build a 1000 entry dictionary... 9751462Smarkm */ 9891754Smarkm for(i = 0; i < 1000; i++) { 9951462Smarkm MD5Init(&ctx1); 10051462Smarkm if(i & 1) 10191754Smarkm MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); 10251462Smarkm else 10391754Smarkm MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); 10451462Smarkm 10551462Smarkm if(i % 3) 10691754Smarkm MD5Update(&ctx1, (const u_char *)sp, (u_int)sl); 10751462Smarkm 10851462Smarkm if(i % 7) 10991754Smarkm MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); 11051462Smarkm 11151462Smarkm if(i & 1) 11291754Smarkm MD5Update(&ctx1, (const u_char *)final, MD5_SIZE); 11351462Smarkm else 11491754Smarkm MD5Update(&ctx1, (const u_char *)pw, strlen(pw)); 11591754Smarkm MD5Final(final, &ctx1); 11651462Smarkm } 11751462Smarkm 11851462Smarkm p = passwd + strlen(passwd); 11951462Smarkm 12051462Smarkm l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; 12191754Smarkm _crypt_to64(p, l, 4); p += 4; 12251462Smarkm l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; 12391754Smarkm _crypt_to64(p, l, 4); p += 4; 12451462Smarkm l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; 12591754Smarkm _crypt_to64(p, l, 4); p += 4; 12651462Smarkm l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; 12791754Smarkm _crypt_to64(p, l, 4); p += 4; 12851462Smarkm l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; 12991754Smarkm _crypt_to64(p, l, 4); p += 4; 13051462Smarkm l = final[11] ; 13191754Smarkm _crypt_to64(p, l, 2); p += 2; 13251462Smarkm *p = '\0'; 13351462Smarkm 13451462Smarkm /* Don't leave anything around in vm they could use. */ 13591754Smarkm memset(final, 0, sizeof(final)); 13651462Smarkm 13751462Smarkm return passwd; 13851462Smarkm} 13951462Smarkm 140