source: bootcd/isolinux/syslinux-6.03/com32/libutil/crypt-md5.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*-
2 * Copyright (c) 2003 Poul-Henning Kamp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <inttypes.h>
28#include <md5.h>
29#include <string.h>
30
31/*
32 * UNIX password
33 */
34
35static char *_crypt_to64(char *s, uint32_t v, int n)
36{
37    static const char itoa64[64] = "./0123456789"
38        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
39
40    while (--n >= 0) {
41        *s++ = itoa64[v & 0x3f];
42        v >>= 6;
43    }
44    return s;
45}
46
47char *crypt_md5(const char *pw, const char *salt)
48{
49    MD5_CTX ctx, ctx1;
50    unsigned long l;
51    int sl, pl;
52    uint32_t i;
53    uint8_t final[MD5_SIZE];
54    const char *sp;
55    static char passwd[120];    /* Output buffer */
56    static const char magic[] = "$1$";
57    char *p;
58    const int magic_len = sizeof magic - 1;
59    int pwlen = strlen(pw);
60
61    /* Refine the Salt first */
62    sp = salt;
63
64    /* If it starts with the magic string, then skip that */
65    if (!strncmp(sp, magic, magic_len))
66        sp += magic_len;
67
68    /* Compute the salt length:
69       it stops at the first '$', max 8 chars */
70    for (sl = 0; sl < 8 && sp[sl] && sp[sl] != '$'; sl++) ;
71
72    MD5Init(&ctx);
73
74    /* The password first, since that is what is most unknown */
75    MD5Update(&ctx, pw, pwlen);
76
77    /* Then our magic string */
78    MD5Update(&ctx, magic, magic_len);
79
80    /* Then the raw salt */
81    MD5Update(&ctx, sp, sl);
82
83    /* Then just as many characters of the MD5(pw,salt,pw) */
84    MD5Init(&ctx1);
85    MD5Update(&ctx1, pw, pwlen);
86    MD5Update(&ctx1, sp, sl);
87    MD5Update(&ctx1, pw, pwlen);
88    MD5Final(final, &ctx1);
89    for (pl = pwlen; pl > 0; pl -= MD5_SIZE)
90        MD5Update(&ctx, final, pl > MD5_SIZE ? MD5_SIZE : pl);
91
92    /* Don't leave anything around in vm they could use. */
93    memset(final, 0, sizeof final);
94
95    /* Then something really weird... */
96    for (i = pwlen; i; i >>= 1)
97        if (i & 1)
98            MD5Update(&ctx, final, 1);
99        else
100            MD5Update(&ctx, pw, 1);
101
102    /* Now make the output string */
103    p = passwd;
104
105    memcpy(p, magic, magic_len);
106    p += magic_len;
107
108    memcpy(p, sp, sl);
109    p += sl;
110
111    *p++ = '$';
112
113    MD5Final(final, &ctx);
114
115    /*
116     * and now, just to make sure things don't run too fast
117     * On a 60 Mhz Pentium this takes 34 msec, so you would
118     * need 30 seconds to build a 1000 entry dictionary...
119     */
120    for (i = 0; i < 1000; i++) {
121        MD5Init(&ctx1);
122        if (i & 1)
123            MD5Update(&ctx1, pw, pwlen);
124        else
125            MD5Update(&ctx1, final, MD5_SIZE);
126
127        if (i % 3)
128            MD5Update(&ctx1, sp, sl);
129
130        if (i % 7)
131            MD5Update(&ctx1, pw, pwlen);
132
133        if (i & 1)
134            MD5Update(&ctx1, final, MD5_SIZE);
135        else
136            MD5Update(&ctx1, pw, pwlen);
137        MD5Final(final, &ctx1);
138    }
139
140    l = (final[0] << 16) | (final[6] << 8) | final[12];
141    p = _crypt_to64(p, l, 4);
142    l = (final[1] << 16) | (final[7] << 8) | final[13];
143    p = _crypt_to64(p, l, 4);
144    l = (final[2] << 16) | (final[8] << 8) | final[14];
145    p = _crypt_to64(p, l, 4);
146    l = (final[3] << 16) | (final[9] << 8) | final[15];
147    p = _crypt_to64(p, l, 4);
148    l = (final[4] << 16) | (final[10] << 8) | final[5];
149    p = _crypt_to64(p, l, 4);
150    l = final[11];
151    p = _crypt_to64(p, l, 2);
152    *p = '\0';
153
154    /* Don't leave anything around in vm they could use. */
155    memset(final, 0, sizeof final);
156
157    return passwd;
158}
159
160#ifdef TEST
161#include <stdio.h>
162
163int main(int argc, char *argv[])
164{
165    int i;
166
167    for (i = 2; i < argc; i += 2) {
168        puts(crypt_md5(argv[i], argv[i - 1]));
169    }
170    return 0;
171}
172
173#endif
Note: See TracBrowser for help on using the repository browser.