source: trunk/sys/dietlibc/md5crypt.c @ 402

Last change on this file since 402 was 1, checked in by alain, 7 years ago

First import

File size: 4.0 KB
Line 
1/*      $OpenBSD: md5crypt.c,v 1.9 1997/07/23 20:58:27 kstailey 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.9 1997/07/23 20:58:27 kstailey 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
24static unsigned char itoa64[] =         /* 0 ... 63 => ascii - 64 */
25        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
26
27static void to64 (char *, uint32_t, int);
28
29static void
30to64(s, v, n)
31        char *s;
32        uint32_t v;
33        int n;
34{
35        while (--n >= 0) {
36                *s++ = itoa64[v&0x3f];
37                v >>= 6;
38        }
39}
40
41/*
42 * UNIX password
43 *
44 * Use MD5 for what it is best at...
45 */
46
47char *
48md5crypt(pw, salt)
49        register const char *pw;
50        register const char *salt;
51{
52        /*
53         * This string is magic for this algorithm.  Having
54         * it this way, we can get get better later on
55         */
56        static unsigned char    *magic = (unsigned char *)"$1$";
57
58        static char     passwd[120], *p;
59        static const unsigned char *sp,*ep;
60        unsigned char   final[16];
61        int sl,pl,i;
62        MD5_CTX ctx,ctx1;
63        uint32_t l;
64
65        /* Refine the Salt first */
66        sp = (const unsigned char *)salt;
67
68        /* If it starts with the magic string, then skip that */
69        if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
70                sp += strlen((const char *)magic);
71
72        /* It stops at the first '$', max 8 chars */
73        for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
74                continue;
75
76        /* get the length of the true salt */
77        sl = ep - sp;
78
79        MD5Init(&ctx);
80
81        /* The password first, since that is what is most unknown */
82        MD5Update(&ctx,(const unsigned char *)pw,strlen(pw));
83
84        /* Then our magic string */
85        MD5Update(&ctx,magic,strlen((const char *)magic));
86
87        /* Then the raw salt */
88        MD5Update(&ctx,sp,sl);
89
90        /* Then just as many characters of the MD5(pw,salt,pw) */
91        MD5Init(&ctx1);
92        MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
93        MD5Update(&ctx1,sp,sl);
94        MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
95        MD5Final(final,&ctx1);
96        for(pl = strlen(pw); pl > 0; pl -= 16)
97                MD5Update(&ctx,final,pl>16 ? 16 : pl);
98
99        /* Don't leave anything around in vm they could use. */
100        memset(final,0,sizeof final);
101
102        /* Then something really weird... */
103        for (i = strlen(pw); i ; i >>= 1)
104                if(i&1)
105                    MD5Update(&ctx, final, 1);
106                else
107                    MD5Update(&ctx, (const unsigned char *)pw, 1);
108
109        /* Now make the output string */
110        strcpy(passwd,(const char *)magic);
111        memcpy(passwd+3,sp,sl);
112        passwd[sl+3]='$';
113        passwd[sl+4]=0;
114
115        MD5Final(final,&ctx);
116
117        /*
118         * and now, just to make sure things don't run too fast
119         * On a 60 Mhz Pentium this takes 34 msec, so you would
120         * need 30 seconds to build a 1000 entry dictionary...
121         */
122        for(i=0;i<1000;i++) {
123                MD5Init(&ctx1);
124                if(i & 1)
125                        MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
126                else
127                        MD5Update(&ctx1,final,16);
128
129                if(i % 3)
130                        MD5Update(&ctx1,sp,sl);
131
132                if(i % 7)
133                        MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
134
135                if(i & 1)
136                        MD5Update(&ctx1,final,16);
137                else
138                        MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
139                MD5Final(final,&ctx1);
140        }
141
142        p = passwd + strlen(passwd);
143
144        l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
145        l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
146        l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
147        l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
148        l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
149        l =                    final[11]                ; to64(p,l,2); p += 2;
150        *p = '\0';
151
152        /* Don't leave anything around in vm they could use. */
153        memset(final,0,sizeof final);
154
155        return passwd;
156}
157
Note: See TracBrowser for help on using the repository browser.