1/* 2 * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 3 * 4 * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 5 * rights reserved. 6 * 7 * License to copy and use this software is granted provided that it 8 * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 9 * Algorithm" in all material mentioning or referencing this software 10 * or this function. 11 * 12 * License is also granted to make and use derivative works provided 13 * that such works are identified as "derived from the RSA Data 14 * Security, Inc. MD5 Message-Digest Algorithm" in all material 15 * mentioning or referencing the derived work. 16 * 17 * RSA Data Security, Inc. makes no representations concerning either 18 * the merchantability of this software or the suitability of this 19 * software for any particular purpose. It is provided "as is" 20 * without express or implied warranty of any kind. 21 * 22 * These notices must be retained in any copies of any part of this 23 * documentation and/or software. 24 * 25 * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $ 26 * 27 * This code is the same as the code published by RSA Inc. It has been 28 * edited for clarity and style only. 29 * 30 * ---------------------------------------------------------------------------- 31 * The md5_crypt() function was taken from freeBSD's libcrypt and contains 32 * this license: 33 * "THE BEER-WARE LICENSE" (Revision 42): 34 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 35 * can do whatever you want with this stuff. If we meet some day, and you think 36 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 37 * 38 * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $ 39 * 40 * ---------------------------------------------------------------------------- 41 * On April 19th, 2001 md5_crypt() was modified to make it reentrant 42 * by Erik Andersen <andersen@uclibc.org> 43 * 44 * 45 * June 28, 2001 Manuel Novoa III 46 * 47 * "Un-inlined" code using loops and static const tables in order to 48 * reduce generated code size (on i386 from approx 4k to approx 2.5k). 49 * 50 * June 29, 2001 Manuel Novoa III 51 * 52 * Completely removed static PADDING array. 53 * 54 * Reintroduced the loop unrolling in MD5_Transform and added the 55 * MD5_SIZE_OVER_SPEED option for configurability. Define below as: 56 * 0 fully unrolled loops 57 * 1 partially unrolled (4 ops per loop) 58 * 2 no unrolling -- introduces the need to swap 4 variables (slow) 59 * 3 no unrolling and all 4 loops merged into one with switch 60 * in each loop (glacial) 61 * On i386, sizes are roughly (-Os -fno-builtin): 62 * 0: 3k 1: 2.5k 2: 2.2k 3: 2k 63 * 64 * Since SuSv3 does not require crypt_r, modified again August 7, 2002 65 * by Erik Andersen to remove reentrance stuff... 66 */ 67 68/* 69 * UNIX password 70 * 71 * Use MD5 for what it is best at... 72 */ 73#define MD5_OUT_BUFSIZE 36 74static char * 75NOINLINE 76md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt) 77{ 78 char *p; 79 unsigned char final[17]; /* final[16] exists only to aid in looping */ 80 int sl, pl, i, pw_len; 81 md5_ctx_t ctx, ctx1; 82 83 /* NB: in busybox, "$1$" in salt is always present */ 84 85 /* Refine the Salt first */ 86 87 /* Get the length of the salt including "$1$" */ 88 sl = 3; 89 while (salt[sl] && salt[sl] != '$' && sl < (3 + 8)) 90 sl++; 91 92 /* Hash. the password first, since that is what is most unknown */ 93 md5_begin(&ctx); 94 pw_len = strlen((char*)pw); 95 md5_hash(pw, pw_len, &ctx); 96 97 /* Then the salt including "$1$" */ 98 md5_hash(salt, sl, &ctx); 99 100 /* Copy salt to result; skip "$1$" */ 101 memcpy(result, salt, sl); 102 result[sl] = '$'; 103 salt += 3; 104 sl -= 3; 105 106 /* Then just as many characters of the MD5(pw, salt, pw) */ 107 md5_begin(&ctx1); 108 md5_hash(pw, pw_len, &ctx1); 109 md5_hash(salt, sl, &ctx1); 110 md5_hash(pw, pw_len, &ctx1); 111 md5_end(final, &ctx1); 112 for (pl = pw_len; pl > 0; pl -= 16) 113 md5_hash(final, pl > 16 ? 16 : pl, &ctx); 114 115 /* Then something really weird... */ 116 memset(final, 0, sizeof(final)); 117 for (i = pw_len; i; i >>= 1) { 118 md5_hash(((i & 1) ? final : (const unsigned char *) pw), 1, &ctx); 119 } 120 md5_end(final, &ctx); 121 122 /* And now, just to make sure things don't run too fast. 123 * On a 60 Mhz Pentium this takes 34 msec, so you would 124 * need 30 seconds to build a 1000 entry dictionary... 125 */ 126 for (i = 0; i < 1000; i++) { 127 md5_begin(&ctx1); 128 if (i & 1) 129 md5_hash(pw, pw_len, &ctx1); 130 else 131 md5_hash(final, 16, &ctx1); 132 133 if (i % 3) 134 md5_hash(salt, sl, &ctx1); 135 136 if (i % 7) 137 md5_hash(pw, pw_len, &ctx1); 138 139 if (i & 1) 140 md5_hash(final, 16, &ctx1); 141 else 142 md5_hash(pw, pw_len, &ctx1); 143 md5_end(final, &ctx1); 144 } 145 146 p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */ 147 148 /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */ 149 final[16] = final[5]; 150 for (i = 0; i < 5; i++) { 151 unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12]; 152 p = to64(p, l, 4); 153 } 154 p = to64(p, final[11], 2); 155 *p = '\0'; 156 157 /* Don't leave anything around in vm they could use. */ 158 memset(final, 0, sizeof(final)); 159 160 return result; 161} 162