Home | History | Annotate | Download | only in libutil
      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 
     35 static 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 
     47 char *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 
    163 int 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
    174