X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=second%2Fmd5.c;fp=second%2Fmd5.c;h=3b67209839ce3ae6b84102d5905e6fca173b79b7;hb=f4ebbd9f7ea23e3f0fcbe098754580c220894628;hp=0000000000000000000000000000000000000000;hpb=f42aaadb5c8c5f7f15e5159cbc251e64e1a4ac8f;p=tonyb-yaboot.git diff --git a/second/md5.c b/second/md5.c new file mode 100644 index 0000000..3b67209 --- /dev/null +++ b/second/md5.c @@ -0,0 +1,380 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* See RFC 1321 for a description of the MD5 algorithm. + */ + +#include "string.h" +#include "md5.h" + +#ifdef TEST +# include +# define USE_MD5_PASSWORDS +# define USE_MD5 +#endif + +#ifdef USE_MD5_PASSWORDS +# define USE_MD5 +#endif + +#ifdef USE_MD5 +#define cpu_to_le32(x) le32_to_cpu((x)) +unsigned long le32_to_cpu(unsigned long x) +{ + return (((x & 0x000000ffU) << 24) | + ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | + ((x & 0xff000000U) >> 24)); +} + +typedef unsigned int UINT4; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x >> (32 - (n))))) + +static UINT4 initstate[4] = +{ + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 +}; + +static char s1[4] = { 7, 12, 17, 22 }; +static char s2[4] = { 5, 9, 14, 20 }; +static char s3[4] = { 4, 11, 16, 23 }; +static char s4[4] = { 6, 10, 15, 21 }; + +static UINT4 T[64] = +{ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + +static const char *b64t = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static UINT4 state[4]; +static unsigned int length; +static unsigned char buffer[64]; + +static void +md5_transform (const unsigned char block[64]) +{ + int i, j; + UINT4 a,b,c,d,tmp; + const UINT4 *x = (UINT4 *) block; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + + /* Round 1 */ + for (i = 0; i < 16; i++) + { + tmp = a + F (b, c, d) + le32_to_cpu (x[i]) + T[i]; + tmp = ROTATE_LEFT (tmp, s1[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 2 */ + for (i = 0, j = 1; i < 16; i++, j += 5) + { + tmp = a + G (b, c, d) + le32_to_cpu (x[j & 15]) + T[i+16]; + tmp = ROTATE_LEFT (tmp, s2[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 3 */ + for (i = 0, j = 5; i < 16; i++, j += 3) + { + tmp = a + H (b, c, d) + le32_to_cpu (x[j & 15]) + T[i+32]; + tmp = ROTATE_LEFT (tmp, s3[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + /* Round 4 */ + for (i = 0, j = 0; i < 16; i++, j += 7) + { + tmp = a + I (b, c, d) + le32_to_cpu (x[j & 15]) + T[i+48]; + tmp = ROTATE_LEFT (tmp, s4[i & 3]); + tmp += b; + a = d; d = c; c = b; b = tmp; + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +static void +md5_init(void) +{ + memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; +} + +static void +md5_update (const char *input, int inputlen) +{ + int buflen = length & 63; + length += inputlen; + if (buflen + inputlen < 64) + { + memcpy (buffer + buflen, input, inputlen); + buflen += inputlen; + return; + } + + memcpy (buffer + buflen, input, 64 - buflen); + md5_transform (buffer); + input += 64 - buflen; + inputlen -= 64 - buflen; + while (inputlen >= 64) + { + md5_transform (input); + input += 64; + inputlen -= 64; + } + memcpy (buffer, input, inputlen); + buflen = inputlen; +} + +static unsigned char * +md5_final() +{ + int i, buflen = length & 63; + + buffer[buflen++] = 0x80; + memset (buffer+buflen, 0, 64 - buflen); + if (buflen > 56) + { + md5_transform (buffer); + memset (buffer, 0, 64); + buflen = 0; + } + + *(UINT4 *) (buffer + 56) = cpu_to_le32 (8 * length); + *(UINT4 *) (buffer + 60) = 0; + md5_transform (buffer); + + for (i = 0; i < 4; i++) + state[i] = cpu_to_le32 (state[i]); + return (unsigned char *) state; +} + +#ifdef USE_MD5_PASSWORDS +/* If CHECK is true, check a password for correctness. Returns 0 + if password was correct, and a value != 0 for error, similarly + to strcmp. + If CHECK is false, crypt KEY and save the result in CRYPTED. + CRYPTED must have a salt. */ +int +md5_password (const char *key, char *crypted, int check) +{ + int keylen = strlen (key); + char *salt = crypted + 3; /* skip $1$ header */ + char *p; + int saltlen; + int i, n; + unsigned char alt_result[16]; + unsigned char *digest; + + if (check) + saltlen = strstr (salt, "$") - salt; + else + { + char *end = strstr (salt, "$"); + if (end && end - salt < 8) + saltlen = end - salt; + else + saltlen = 8; + + salt[saltlen] = '$'; + } + + md5_init (); + md5_update (key, keylen); + md5_update (salt, saltlen); + md5_update (key, keylen); + digest = md5_final (); + memcpy (alt_result, digest, 16); + + memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + md5_update (key, keylen); + md5_update (crypted, 3 + saltlen); /* include the $1$ header */ + for (i = keylen; i > 16; i -= 16) + md5_update (alt_result, 16); + md5_update (alt_result, i); + + for (i = keylen; i > 0; i >>= 1) + md5_update (key + ((i & 1) ? keylen : 0), 1); + digest = md5_final (); + + for (i = 0; i < 1000; i++) + { + memcpy (alt_result, digest, 16); + + memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + if ((i & 1) != 0) + md5_update (key, keylen); + else + md5_update (alt_result, 16); + + if (i % 3 != 0) + md5_update (salt, saltlen); + + if (i % 7 != 0) + md5_update (key, keylen); + + if ((i & 1) != 0) + md5_update (alt_result, 16); + else + md5_update (key, keylen); + digest = md5_final (); + } + + p = salt + saltlen + 1; + for (i = 0; i < 5; i++) + { + unsigned int w = + digest[i == 4 ? 5 : 12+i] | (digest[6+i] << 8) | (digest[i] << 16); + for (n = 4; n-- > 0;) + { + if (check) + { + if (*p++ != b64t[w & 0x3f]) + return 1; + } + else + { + *p++ = b64t[w & 0x3f]; + } + + w >>= 6; + } + } + { + unsigned int w = digest[11]; + for (n = 2; n-- > 0;) + { + if (check) + { + if (*p++ != b64t[w & 0x3f]) + return 1; + } + else + { + *p++ = b64t[w & 0x3f]; + } + + w >>= 6; + } + } + + if (! check) + *p = '\0'; + + return *p; +} +#endif + +#ifdef TEST +static char * +md5 (const char *input) +{ + memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + md5_update (input, strlen (input)); + return md5_final (); +} + +static void +test (char *buffer, char *expected) +{ + char result[16 * 3 +1]; + unsigned char* digest = md5 (buffer); + int i; + + for (i=0; i < 16; i++) + sprintf (result+2*i, "%02x", digest[i]); + + if (strcmp (result, expected)) + printf ("MD5(%s) failed: %s\n", buffer, result); + else + printf ("MD5(%s) OK\n", buffer); +} + +int +main (void) +{ + test ("", "d41d8cd98f00b204e9800998ecf8427e"); + test ("a", "0cc175b9c0f1b6a831c399e269772661"); + test ("abc", "900150983cd24fb0d6963f7d28e17f72"); + test ("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); + test ("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f"); + test ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz3456", + "6831fa90115bb9a54fbcd4f9fee0b5c4"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz345", + "bc40505cc94a43b7ff3e2ac027325233"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz34567", + "fa94b73a6f072a0239b52acacfbcf9fa"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz345678901234", + "bd201eae17f29568927414fa326f1267"); + test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz34567890123", + "80063db1e6b70a2e91eac903f0e46b85"); + + if (check_md5_password ("Hello world!", + "$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1")) + printf ("Password differs\n"); + else + printf ("Password OK\n"); + return 0; +} +#endif + +#endif