--- vanilla_grub2/normal/md5.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/md5.c 2007-08-04 12:26:22.000000000 +0200 @@ -0,0 +1,303 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +/* See RFC 1321 for a description of the MD5 algorithm. */ + +#include +#include +#include + +/* 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 grub_uint32_t 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 grub_uint32_t 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 grub_uint32_t state[4]; +static unsigned int length; +static unsigned char buffer[64]; + +static void +md5_transform (const unsigned char block[64]) +{ + int i, j; + grub_uint32_t a,b,c,d,tmp; + const grub_uint32_t *x = (grub_uint32_t *) 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) + grub_le_to_cpu32 (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) + grub_le_to_cpu32 (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) + grub_le_to_cpu32 (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) + grub_le_to_cpu32 (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) +{ + grub_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) + { + grub_memcpy (buffer + buflen, input, inputlen); + buflen += inputlen; + return; + } + + grub_memcpy (buffer + buflen, input, 64 - buflen); + md5_transform (buffer); + input += 64 - buflen; + inputlen -= 64 - buflen; + while (inputlen >= 64) + { + md5_transform ((const unsigned char*) input); + input += 64; + inputlen -= 64; + } + grub_memcpy (buffer, input, inputlen); + buflen = inputlen; +} + +static unsigned char * +md5_final( void ) +{ + int i, buflen = length & 63; + + buffer[buflen++] = 0x80; + + grub_memset (buffer+buflen, 0, 64 - buflen); + if (buflen > 56) + { + md5_transform (buffer); + grub_memset (buffer, 0, 64); + buflen = 0; + } + + *(grub_uint32_t *) (buffer + 56) = grub_cpu_to_le32 (8 * length); + *(grub_uint32_t *) (buffer + 60) = 0; + md5_transform (buffer); + + for (i = 0; i < 4; i++) + state[i] = grub_cpu_to_le32 (state[i]); + return (unsigned char *) state; +} + +/* 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 +grub_md5_password (const char *key, char *crypted, int check) +{ + int keylen = grub_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) + { + /* If our crypted password isn't 3 chars, then it can't be md5 + crypted. So, they don't match. */ + if (grub_strlen(crypted) <= 3) + return 1; + + saltlen = grub_strstr (salt, "$") - salt; + } + else + { + char *end = grub_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 (); + grub_memcpy (alt_result, digest, 16); + + grub_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 ((char *) alt_result, 16); + md5_update ((char *) alt_result, i); + + for (i = keylen; i > 0; i >>= 1) + md5_update ((char*) (key + ((i & 1) ? keylen : 0)), 1); + digest = md5_final (); + + for (i = 0; i < 1000; i++) + { + grub_memcpy (alt_result, digest, 16); + + grub_memcpy ((char *) state, (char *) initstate, sizeof (initstate)); + length = 0; + if ((i & 1) != 0) + md5_update (key, keylen); + else + md5_update ((char *) 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 ((char *) 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; +} + + --- vanilla_grub2/normal/password.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/password.c 2007-08-05 16:48:31.000000000 +0200 @@ -0,0 +1,249 @@ +/* password.c - Password helper function for other modules */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2006 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. + */ + +#include +#include +#include /* for error codes */ +#include /* for memory mngt */ +#include /* for string manipulation */ +#include +#include + +/** + * The global password, used as default. + */ +static grub_password_t global_password = 0; + + +/* Declare private functions */ +int check_plain_text(const char *entered, const char *correct); +int check_md5(const char *entered, const char *correct); + +grub_err_t +grub_password_command(struct grub_arg_list *state, + int argc, + char **args) +{ + if (argc <= 0) + goto fail; /* too few arguments */ + + if (argc > 2) + goto fail; /* too many arguments */ + + if (global_password == 0) + { + global_password = grub_malloc(sizeof(global_password)); + global_password->password = 0; + global_password->type = GRUB_PASSWORD_TYPE_UNSUPPORTED; + global_password->next_file = 0; + global_password->authenticated = 0; + } + + /* Set the new password */ + if ( global_password->password != 0) + grub_free(global_password->password); + global_password->password = grub_strdup(args[0]); + + /* set the next file to load */ + if ( global_password->next_file != 0) + grub_free(global_password->next_file); + if ( argc > 1) + global_password->next_file = grub_strdup(args[1]); + else + global_password->next_file = 0; + + /* set the password type */ + if (state[0].set) + global_password->type = GRUB_PASSWORD_TYPE_MD5; + else + global_password->type = GRUB_PASSWORD_TYPE_PLAIN_TEXT; + + global_password->authenticated = 0; + + /* OK, done */ + return GRUB_ERR_NONE; + + + fail: + return GRUB_ERR_INVALID_COMMAND; +} + + + +grub_password_t +grub_password_create_password(grub_password_type_t type, + const char *password, + const char *next_file) +{ + if ( password == 0 ) + goto fail; + + if ( next_file == 0 ) + goto fail; + + if ( type == GRUB_PASSWORD_TYPE_UNSUPPORTED ) + goto fail; + + grub_password_t passwd; + passwd = grub_malloc( sizeof(passwd) ); + passwd->type = type; + passwd->password = grub_strdup(password); + passwd->next_file = grub_strdup(next_file); + passwd->authenticated = 0; + + return passwd; + + fail: + return 0; +} + +void +grub_password_free_password(grub_password_t password) +{ + if (password == 0) + goto finished; + + if (password->password != 0) + grub_free(password->password); + + if (password->next_file != 0) + grub_free(password->next_file); + + grub_free(password); + + finished: + return; +} + +int +grub_password_is_password_set(void) +{ + return (global_password != 0); +} + +int +grub_password_is_user_authenticated(grub_password_t password) +{ + grub_password_t passwd; + int result; + + if ( password != 0 ) + passwd = password; + else + passwd = global_password; + + if ( passwd == 0 ) + { + /* No password set : let's say it is OK */ + result = 1; + } + else + { + result = passwd->authenticated; + } + + return result; +} + +int +grub_password_check_password(const char *entered, + grub_password_t password) +{ + int check_result = -1; + grub_password_t checked_passwd; + + /* Sets the password we check against */ + if ( password != 0 ) + checked_passwd = password; + else + checked_passwd = global_password; + + /* If no password set nor passed, OK */ + if (checked_passwd == 0) { + check_result = 0; + goto end_check; + } + + /* Perform actual check */ + switch ( checked_passwd->type ) + { + case (GRUB_PASSWORD_TYPE_PLAIN_TEXT): + check_result = check_plain_text(entered, + checked_passwd->password); + break; + + case (GRUB_PASSWORD_TYPE_MD5): + check_result = check_md5(entered, + checked_passwd->password); + break; + + default: + /* Unknown password type, or unsupported */ + check_result = -1; + } + + if (check_result == 0) + checked_passwd->authenticated = 1; + + + end_check: + return check_result; +} + +char* +grub_password_get_next_file(void) +{ + if (global_password == 0) + return 0; + + if (grub_password_is_user_authenticated(0) == 0) + return 0; + + if (global_password->next_file == 0) + return 0; + + return grub_strdup(global_password->next_file); +} + +/* Start of private functions */ + +int +check_plain_text(const char *entered, + const char *correct) +{ + int result; + result = grub_strcmp(entered, correct); + if (result != 0) + result = -1; + + return result; +} + +int +check_md5(const char *entered, + const char *correct) +{ + int result; + result = grub_md5_check_password(entered, correct); + return result; +} + + + --- vanilla_grub2/include/grub/md5.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/md5.h 2007-08-04 12:44:46.000000000 +0200 @@ -0,0 +1,30 @@ +/* md5.c - an implementation of the MD5 algorithm and MD5 crypt */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + + +/* 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 grub_md5_password (const char *key, char *crypted, int check); + +/* For convenience. */ +#define grub_md5_check_password(key,crypted) grub_md5_password((key), (crypted), 1) +#define grub_md5_make_password(key,crypted) grub_md5_password((key), (crypted), 0) --- vanilla_grub2/include/grub/password.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/password.h 2007-08-05 16:49:06.000000000 +0200 @@ -0,0 +1,147 @@ +/* password.h - Header file for password management */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005 Free Software Foundation, Inc. + * + * GRUB 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 GRUB; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_PASSWORD_H +#define GRUB_PASSWORD_H 1 + + +#include + +/* The max length of the password, in chars */ +#define GRUB_PASSWORD_MAX_LENGTH 64 + +/* the password types */ +enum grub_password_type + { + GRUB_PASSWORD_TYPE_UNSUPPORTED, + GRUB_PASSWORD_TYPE_PLAIN_TEXT, + GRUB_PASSWORD_TYPE_MD5 + }; +typedef enum grub_password_type grub_password_type_t; + + +/* structure holding a password */ +struct grub_password +{ + char *password; /* The password. */ + grub_password_type_t type; /* The type. */ + char *next_file; /* The file to jump after auth */ + int authenticated; /* Flag for passwd verification status */ +}; +typedef struct grub_password *grub_password_t; + +/* The options available for the 'password' command */ +static const struct grub_arg_option grub_password_arg_options[] = + { + {"md5", 'm', GRUB_ARG_OPTION_OPTIONAL, "indicates the password is encrypted with MD5", 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +/* Helper functions */ + +/** + * @brief The 'password' command itself + * + * This is the callback to execute a 'password' command from a + * script. + * See normal.h for information on the parameters + */ +grub_err_t +grub_password_command(struct grub_arg_list *state, + int argc, + char **args); + +/** + * @bried Create a grub_password_t structure based on entered params + * + * This function is helpful for the 'lock' command to generate the + * password against which the user password will be checked. + * + * @param[in] type the password type + * @param[in] password the password + * + * @returns a grub_password_t object properly filled + * @returns 0 is invalid params are passed + */ +grub_password_t +grub_password_create_password(grub_password_type_t type, + const char *password, + const char *next_file); + +/** + * @bried Free a grub_password_t structure + * + * @param[in] password the password + */ +void +grub_password_free_password(grub_password_t password); + + +/** + * @brief Check is a global password is set + * + * @returns 0 if no password is set + * @returns 1 if a password is set + */ +int +grub_password_is_password_set(void); + +/** + * @brief Check if the user has correctly authentificated with a given password + * + * @param[in] password : the password to check. If set to 0, the global + * password is used instead. + * + * @returns 0 if user is not authenticated + * @returns 1 if user is authenticated + * @returns 1 if no password passed and no global password is set + */ +int +grub_password_is_user_authenticated(grub_password_t password); + +/** + * @brief Check a user password + * + * @param[in] entered the user entered password + * @param[in] password the password agains which the user input + * will be checked. If set to 0, the global password, if set, will + * be used. + * + * @returns 0 if the user entered password is correct, or if no password + * had been set AND no password had been specified. + * @returns -1 if the user password is wrong. + */ +int +grub_password_check_password(const char *entered, + grub_password_t password); + + +/** + * @brief get the next file specified with the global password + * + * @returns the next file to jump to. The buffer needs to be freed + * after use... + * @returns 0 if user is not authenticated, or no file given + */ +char* +grub_password_get_next_file(void); + +#endif /* !GRUB_PASSWORD_H */ +