add a new command, md5crypt.

This commit is contained in:
okuji 2000-10-21 00:13:55 +00:00
parent 06adfc82ff
commit 4928cfdad2
7 changed files with 234 additions and 86 deletions

View file

@ -1,3 +1,24 @@
2000-10-21 OKUJI Yoshinori <okuji@gnu.org>
* stage2/md5.c (check_md5_password): Removed.
(md5_password): New function. Mostly copied from
check_md5_password.
(md5_init): Made static.
(md5_update): Likewise.
(md5_final): Likewise.
* stage2/md5.h (check_md5_password): Changed to just a macro.
(md5_password): Declared.
(make_md5_password): New macro.
* stage2/char_io.c [!STAGE1_5] (grub_strstr): Rewriten, because
it was too buggy.
* stage2/builtins.c [USE_MD5_PASSWORDS] (md5crypt_func): New
function.
[USE_MD5_PASSWORDS] (builtin_md5crypt): New variable.
(builtin_table) [USE_MD5_PASSWORDS]: Added a pointer to
BUILTIN_MD5CRYPT.
* docs/tutorial.texi (Security): Added a paragraph about
md5crypt.
2000-10-21 OKUJI Yoshinori <okuji@gnu.org>
* docs/user-ref.texi: Fixed several typos and some inappropriate

1
NEWS
View file

@ -11,6 +11,7 @@ New in 1.0 - XXXX-XX-XX:
is given. This command can now also be used to protect specific menu
items with their own passwords.
* New command, "displayapm".
* New command, "md5crypt".
New in 0.5.96 - 2000-10-04:
* New commands, "reboot" and "halt".

View file

@ -984,8 +984,22 @@ password --md5 PASSWORD
If this is specified, GRUB disallows any interactive control, until you
press the key @key{p} and enter @samp{PASSWORD}. The option
@option{--md5} tells GRUB that @samp{PASSWORD} is in md5 format. If it
is omitted grub assumes the @samp{PASSWORD} is in clear text.
@option{--md5} tells GRUB that @samp{PASSWORD} is in MD5 format. If it
is omitted, GRUB assumes the @samp{PASSWORD} is in clear text.
You can encrypt your password with the command @command{md5crypt}. For
example, run the grub shell (@pxref{Invoking the grub shell}), and enter
your password:
@example
@group
grub> md5crypt
Password: **********
Encrypted: $1$U$JK7xFegdxWH6VuppCUSIb.
@end group
@end example
Then, cut and paste the encrypted password to your configuration file.
Also, you can specify an optional argument to @command{password}. See
this example:

View file

@ -2370,6 +2370,67 @@ static struct builtin builtin_map =
" OS resides at a non-first drive."
};
#ifdef USE_MD5_PASSWORDS
/* md5crypt */
static int
md5crypt_func (char *arg, int flags)
{
char crypted[36];
char key[32];
int saltlen;
int i;
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
/* First create a salt. */
/* The magical prefix. */
grub_memset (crypted, 0, sizeof (crypted));
grub_memmove (crypted, "$1$", 3);
/* Create the length of a salt. */
saltlen = currticks ();
saltlen &= 7;
saltlen++;
/* Generate a salt. */
for (i = 0; i < saltlen; i++)
{
/* FIXME: This should be more random. */
crypted[3 + i] = seedchars[(currticks () >> i) & 0x3f];
}
/* A salt must be terminated with `$', if it is less than 8 chars. */
if (saltlen != 8)
crypted[3 + i] = '$';
#ifdef DEBUG_MD5CRYPT
grub_printf ("salt = %s\n", crypted);
#endif
/* Get a password. */
grub_memset (key, 0, sizeof (key));
get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0);
/* Crypt the key. */
make_md5_password (key, crypted);
grub_printf ("Encrypted: %s\n", crypted);
return 0;
}
static struct builtin builtin_md5crypt =
{
"md5crypt",
md5crypt_func,
BUILTIN_CMDLINE,
"md5crypt",
"Generate a password in MD5 format."
};
#endif /* USE_MD5_PASSWORDS */
/* module */
static int
@ -4118,6 +4179,9 @@ struct builtin *builtin_table[] =
&builtin_lock,
&builtin_makeactive,
&builtin_map,
#ifdef USE_MD5_PASSWORDS
&builtin_md5crypt,
#endif /* USE_MD5_PASSWORDS */
&builtin_module,
&builtin_modulenounzip,
&builtin_partnew,

View file

@ -1282,17 +1282,20 @@ nul_terminate (char *str)
char *
grub_strstr (const char *s1, const char *s2)
{
const char *ptr, *tmp;
while (*s1)
{
const char *ptr, *tmp;
ptr = s1;
tmp = s2;
while (*s1 && *s1++ == *tmp++);
while (*tmp && *ptr == *tmp)
ptr++, tmp++;
if (tmp > s2 && !*(tmp - 1))
return (char *) ptr;
if (tmp > s2 && ! *tmp)
return (char *) s1;
s1++;
}
return 0;

View file

@ -23,17 +23,17 @@
#include <md5.h>
#ifndef TEST
#include <shared.h>
# include <shared.h>
#endif
#ifdef TEST
#include <string.h>
#define USE_MD5_PASSWORDS
#define USE_MD5
# include <string.h>
# define USE_MD5_PASSWORDS
# define USE_MD5
#endif
#ifdef USE_MD5_PASSWORDS
#define USE_MD5
# define USE_MD5
#endif
#ifdef USE_MD5
@ -53,7 +53,8 @@ typedef unsigned int UINT4;
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x >> (32 - (n)))))
static UINT4 initstate[4] = {
static UINT4 initstate[4] =
{
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
};
@ -62,7 +63,8 @@ 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] = {
static UINT4 T[64] =
{
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
@ -88,11 +90,12 @@ static UINT4 state[4];
static unsigned int length;
static unsigned char buffer[64];
static void md5_transform (const unsigned char block[64])
static void
md5_transform (const unsigned char block[64])
{
int i, j;
UINT4 a,b,c,d,tmp;
const UINT4 *x = (UINT4*) block;
const UINT4 *x = (UINT4 *) block;
a = state[0];
b = state[1];
@ -102,7 +105,7 @@ static void md5_transform (const unsigned char block[64])
/* Round 1 */
for (i = 0; i < 16; i++)
{
tmp = a + F(b, c, d) + le32_to_cpu(x[i]) + T[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;
@ -110,7 +113,7 @@ static void md5_transform (const unsigned char block[64])
/* 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 = 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;
@ -118,7 +121,7 @@ static void md5_transform (const unsigned char block[64])
/* 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 = 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;
@ -126,7 +129,7 @@ static void md5_transform (const unsigned char block[64])
/* 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 = 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;
@ -138,22 +141,26 @@ static void md5_transform (const unsigned char block[64])
state[3] += d;
}
void md5_init() {
memcpy ((char *)state, (char *)initstate, sizeof (initstate));
static void
md5_init(void)
{
memcpy ((char *) state, (char *) initstate, sizeof (initstate));
length = 0;
}
void md5_update(const char *input, int inputlen) {
static void
md5_update (const char *input, int inputlen)
{
int buflen = length & 63;
length += inputlen;
if (buflen + inputlen < 64)
{
memcpy(buffer + buflen, input, inputlen);
memcpy (buffer + buflen, input, inputlen);
buflen += inputlen;
return;
}
memcpy(buffer + buflen, input, 64 - buflen);
memcpy (buffer + buflen, input, 64 - buflen);
md5_transform (buffer);
input += 64 - buflen;
inputlen -= 64 - buflen;
@ -163,11 +170,12 @@ void md5_update(const char *input, int inputlen) {
input += 64;
inputlen -= 64;
}
memcpy(buffer, input, inputlen);
memcpy (buffer, input, inputlen);
buflen = inputlen;
}
unsigned char* md5_final()
static unsigned char *
md5_final()
{
int i, buflen = length & 63;
@ -180,68 +188,86 @@ unsigned char* md5_final()
buflen = 0;
}
*(UINT4 *) (buffer + 56) = cpu_to_le32(8*length);
*(UINT4 *) (buffer + 56) = cpu_to_le32 (8 * length);
*(UINT4 *) (buffer + 60) = 0;
md5_transform (buffer);
for (i=0; i < 4; i++)
for (i = 0; i < 4; i++)
state[i] = cpu_to_le32 (state[i]);
return (unsigned char*) state;
return (unsigned char *) state;
}
#ifdef USE_MD5_PASSWORDS
/* Check a password for correctness. Returns 0 if password was
correct, and a value != 0 for error, similarly to strcmp. */
int check_md5_password (const char* key, const char* crypted) {
int keylen = strlen(key);
/* 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 = strstr(salt, "$") - salt;
int i,n;
int saltlen;
int i, n;
unsigned char alt_result[16];
unsigned char *digest;
md5_init();
md5_update(key, keylen);
md5_update(salt, saltlen);
md5_update(key, keylen);
digest = md5_final();
memcpy(alt_result, digest, 16);
if (check)
saltlen = strstr (salt, "$") - salt;
else
{
char *end = strstr (salt, "$");
if (end && end - salt < 8)
saltlen = end - salt;
else
saltlen = 8;
memcpy ((char *)state, (char *)initstate, sizeof (initstate));
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 */
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);
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();
md5_update (key + ((i & 1) ? keylen : 0), 1);
digest = md5_final ();
for (i = 0; i < 1000; i++)
{
memcpy(alt_result, digest, 16);
memcpy (alt_result, digest, 16);
memcpy ((char *)state, (char *)initstate, sizeof (initstate));
memcpy ((char *) state, (char *) initstate, sizeof (initstate));
length = 0;
if ((i & 1) != 0)
md5_update(key, keylen);
md5_update (key, keylen);
else
md5_update(alt_result, 16);
md5_update (alt_result, 16);
if (i % 3 != 0)
md5_update(salt, saltlen);
md5_update (salt, saltlen);
if (i % 7 != 0)
md5_update(key, keylen);
md5_update (key, keylen);
if ((i & 1) != 0)
md5_update(alt_result, 16);
md5_update (alt_result, 16);
else
md5_update(key, keylen);
digest = md5_final();
md5_update (key, keylen);
digest = md5_final ();
}
p = salt + saltlen + 1;
@ -251,8 +277,16 @@ int check_md5_password (const char* key, const char* crypted) {
digest[i == 4 ? 5 : 12+i] | (digest[6+i] << 8) | (digest[i] << 16);
for (n = 4; n-- > 0;)
{
if (*p++ != b64t[w & 0x3f])
return 1;
if (check)
{
if (*p++ != b64t[w & 0x3f])
return 1;
}
else
{
*p++ = b64t[w & 0x3f];
}
w >>= 6;
}
}
@ -260,25 +294,39 @@ int check_md5_password (const char* key, const char* crypted) {
unsigned int w = digest[11];
for (n = 2; n-- > 0;)
{
if (*p++ != b64t[w & 0x3f])
return 1;
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)
static char *
md5 (const char *input)
{
memcpy ((char *)state, (char *)initstate, sizeof (initstate));
memcpy ((char *) state, (char *) initstate, sizeof (initstate));
length = 0;
md5_update(input, strlen (input));
return md5_final();
md5_update (input, strlen (input));
return md5_final ();
}
static void test (char *buffer, char *expected)
static void
test (char *buffer, char *expected)
{
char result[16 * 3 +1];
unsigned char* digest = md5 (buffer);
@ -293,7 +341,8 @@ static void test (char *buffer, char *expected)
printf ("MD5(%s) OK\n", buffer);
}
int main ()
int
main (void)
{
test ("", "d41d8cd98f00b204e9800998ecf8427e");
test ("a", "0cc175b9c0f1b6a831c399e269772661");
@ -315,11 +364,11 @@ int main ()
test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz34567890123",
"80063db1e6b70a2e91eac903f0e46b85");
if (check_md5_password("Hello world!",
"$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1"))
printf("Password differs\n");
if (check_md5_password ("Hello world!",
"$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1"))
printf ("Password differs\n");
else
printf("Password OK\n");
printf ("Password OK\n");
return 0;
}
#endif

View file

@ -18,17 +18,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Initialize the buffers to compute a new md5 checksum. This will
destroy any previously calculated md5 sum. */
extern void md5_init(void);
/* 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. */
extern int md5_password (const char *key, char *crypted, int check);
/* Digestify the given input. This may be called multiple times. */
extern void md5_update(const char *input, int inputlen);
/* Calculate the 16 byte md5 check sum. The result will be valid until
the next md5_init(). */
extern unsigned char* md5_final(void);
/* Check a md5 password for validity. Returns 0 if password was
correct, and a value != 0 for error, similarly to strcmp. */
extern int check_md5_password (const char* key, const char* crypted);
/* For convenience. */
#define check_md5_password(key,crypted) md5_password((key), (crypted), 1)
#define make_md5_password(key,crypted) md5_password((key), (crypted), 0)