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