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