1 /* $NetBSD: md5crypt.c,v 1.9 2007/01/17 23:24:22 hubertf Exp $ */
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 * ----------------------------------------------------------------------------
11 * from FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp
12 * via OpenBSD: md5crypt.c,v 1.9 1997/07/23 20:58:27 kstailey Exp
16 #include <sys/cdefs.h>
18 __RCSID("$NetBSD: md5crypt.c,v 1.9 2007/01/17 23:24:22 hubertf Exp $");
22 * NOTE: We are also built for inclusion in libcrypto; when built for that
23 * environment, use the libcrypto versions of the MD5 routines, so save
24 * having to pull two versions into the same program.
31 #include <openssl/md5.h>
38 #define MD5_MAGIC "$1$"
39 #define MD5_MAGIC_LEN 3
42 #define INIT(x) MD5_Init((x))
43 #define UPDATE(x, b, l) MD5_Update((x), (b), (l))
44 #define FINAL(v, x) MD5_Final((v), (x))
46 #define INIT(x) MD5Init((x))
47 #define UPDATE(x, b, l) MD5Update((x), (b), (l))
48 #define FINAL(v, x) MD5Final((v), (x))
53 * MD5 password encryption.
56 __md5crypt(const char *pw
, const char *salt
)
58 static char passwd
[120], *p
;
60 unsigned char final
[16];
61 unsigned int i
, sl
, pwl
;
68 /* Refine the salt first */
71 /* If it starts with the magic string, then skip that */
72 if (strncmp(sp
, MD5_MAGIC
, MD5_MAGIC_LEN
) == 0)
75 /* It stops at the first '$', max 8 chars */
76 for (ep
= sp
; *ep
!= '\0' && *ep
!= '$' && ep
< (sp
+ 8); ep
++)
79 /* get the length of the true salt */
84 /* The password first, since that is what is most unknown */
85 UPDATE(&ctx
, (const unsigned char *)pw
, pwl
);
87 /* Then our magic string */
88 UPDATE(&ctx
, (const unsigned char *)MD5_MAGIC
, MD5_MAGIC_LEN
);
90 /* Then the raw salt */
91 UPDATE(&ctx
, (const unsigned char *)sp
, sl
);
93 /* Then just as many characters of the MD5(pw,salt,pw) */
95 UPDATE(&ctx1
, (const unsigned char *)pw
, pwl
);
96 UPDATE(&ctx1
, (const unsigned char *)sp
, sl
);
97 UPDATE(&ctx1
, (const unsigned char *)pw
, pwl
);
100 for (pl
= pwl
; pl
> 0; pl
-= 16)
101 UPDATE(&ctx
, final
, (unsigned int)(pl
> 16 ? 16 : pl
));
103 /* Don't leave anything around in vm they could use. */
104 memset(final
, 0, sizeof(final
));
106 /* Then something really weird... */
107 for (i
= pwl
; i
!= 0; i
>>= 1)
109 UPDATE(&ctx
, final
, 1);
111 UPDATE(&ctx
, (const unsigned char *)pw
, 1);
113 /* Now make the output string */
114 memcpy(passwd
, MD5_MAGIC
, MD5_MAGIC_LEN
);
115 strlcpy(passwd
+ MD5_MAGIC_LEN
, sp
, sl
+ 1);
116 strlcat(passwd
, "$", sizeof(passwd
));
121 * And now, just to make sure things don't run too fast. On a 60 MHz
122 * Pentium this takes 34 msec, so you would need 30 seconds to build
123 * a 1000 entry dictionary...
125 for (i
= 0; i
< 1000; i
++) {
129 UPDATE(&ctx1
, (const unsigned char *)pw
, pwl
);
131 UPDATE(&ctx1
, final
, 16);
134 UPDATE(&ctx1
, (const unsigned char *)sp
, sl
);
137 UPDATE(&ctx1
, (const unsigned char *)pw
, pwl
);
140 UPDATE(&ctx1
, final
, 16);
142 UPDATE(&ctx1
, (const unsigned char *)pw
, pwl
);
147 p
= passwd
+ sl
+ MD5_MAGIC_LEN
+ 1;
149 l
= (final
[ 0]<<16) | (final
[ 6]<<8) | final
[12]; __crypt_to64(p
,l
,4); p
+= 4;
150 l
= (final
[ 1]<<16) | (final
[ 7]<<8) | final
[13]; __crypt_to64(p
,l
,4); p
+= 4;
151 l
= (final
[ 2]<<16) | (final
[ 8]<<8) | final
[14]; __crypt_to64(p
,l
,4); p
+= 4;
152 l
= (final
[ 3]<<16) | (final
[ 9]<<8) | final
[15]; __crypt_to64(p
,l
,4); p
+= 4;
153 l
= (final
[ 4]<<16) | (final
[10]<<8) | final
[ 5]; __crypt_to64(p
,l
,4); p
+= 4;
154 l
= final
[11] ; __crypt_to64(p
,l
,2); p
+= 2;
157 /* Don't leave anything around in vm they could use. */
158 memset(final
, 0, sizeof(final
));