#if 0
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libcrypt/crypt-md5.c,v 1.13 2003/06/02 21:43:14 markm Exp $");
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <openssl/md5.h>
#include "crypt-md5.h"
static char itoa64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
void
_crypt_to64(char *s, u_long v, int n)
{
while (--n >= 0) {
*s++ = itoa64[v&0x3f];
v >>= 6;
}
}
char *
crypt_md5(const char *pw, const char *salt)
{
MD5_CTX ctx,ctx1;
unsigned long l;
int sl, pl;
u_int i;
u_char final[MD5_DIGEST_LENGTH];
static const char *sp, *ep;
static char passwd[120], *p;
static const char *magic = "$1$";
sp = salt;
if(!strncmp(sp, magic, strlen(magic)))
sp += strlen(magic);
for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
continue;
sl = ep - sp;
MD5_Init(&ctx);
MD5_Update(&ctx, (const u_char *)pw, strlen(pw));
MD5_Update(&ctx, (const u_char *)magic, strlen(magic));
MD5_Update(&ctx, (const u_char *)sp, (u_int)sl);
MD5_Init(&ctx1);
MD5_Update(&ctx1, (const u_char *)pw, strlen(pw));
MD5_Update(&ctx1, (const u_char *)sp, (u_int)sl);
MD5_Update(&ctx1, (const u_char *)pw, strlen(pw));
MD5_Final(final, &ctx1);
for(pl = (int)strlen(pw); pl > 0; pl -= MD5_DIGEST_LENGTH)
MD5_Update(&ctx, (const u_char *)final,
(u_int)(pl > MD5_DIGEST_LENGTH ? MD5_DIGEST_LENGTH : pl));
memset(final, 0, sizeof(final));
for (i = strlen(pw); i; i >>= 1)
if(i & 1)
MD5_Update(&ctx, (const u_char *)final, 1);
else
MD5_Update(&ctx, (const u_char *)pw, 1);
strcpy(passwd, magic);
strncat(passwd, sp, (u_int)sl);
strcat(passwd, "$");
MD5_Final(final, &ctx);
for(i = 0; i < 1000; i++) {
MD5_Init(&ctx1);
if(i & 1)
MD5_Update(&ctx1, (const u_char *)pw, strlen(pw));
else
MD5_Update(&ctx1, (const u_char *)final, MD5_DIGEST_LENGTH);
if(i % 3)
MD5_Update(&ctx1, (const u_char *)sp, (u_int)sl);
if(i % 7)
MD5_Update(&ctx1, (const u_char *)pw, strlen(pw));
if(i & 1)
MD5_Update(&ctx1, (const u_char *)final, MD5_DIGEST_LENGTH);
else
MD5_Update(&ctx1, (const u_char *)pw, strlen(pw));
MD5_Final(final, &ctx1);
}
p = passwd + strlen(passwd);
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
_crypt_to64(p, l, 4); p += 4;
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
_crypt_to64(p, l, 4); p += 4;
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
_crypt_to64(p, l, 4); p += 4;
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
_crypt_to64(p, l, 4); p += 4;
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
_crypt_to64(p, l, 4); p += 4;
l = final[11];
_crypt_to64(p, l, 2); p += 2;
*p = '\0';
memset(final, 0, sizeof(final));
return (passwd);
}