diff options
Diffstat (limited to 'common/autoboot.c')
-rw-r--r-- | common/autoboot.c | 119 |
1 files changed, 100 insertions, 19 deletions
diff --git a/common/autoboot.c b/common/autoboot.c index f72eb18..c367076 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -12,6 +12,7 @@ #include <fdtdec.h> #include <menu.h> #include <post.h> +#include <u-boot/sha256.h> DECLARE_GLOBAL_DATA_PTR; @@ -26,15 +27,81 @@ DECLARE_GLOBAL_DATA_PTR; /* Stored value of bootdelay, used by autoboot_command() */ static int stored_bootdelay; -/*************************************************************************** - * Watch for 'delay' seconds for autoboot stop or autoboot delay string. - * returns: 0 - no key string, allow autoboot 1 - got key string, abort +#if defined(CONFIG_AUTOBOOT_KEYED) +#if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256) + +/* + * Use a "constant-length" time compare function for this + * hash compare: + * + * https://crackstation.net/hashing-security.htm */ -# if defined(CONFIG_AUTOBOOT_KEYED) -static int abortboot_keyed(int bootdelay) +static int slow_equals(u8 *a, u8 *b, int len) +{ + int diff = 0; + int i; + + for (i = 0; i < len; i++) + diff |= a[i] ^ b[i]; + + return diff == 0; +} + +static int passwd_abort(uint64_t etime) +{ + const char *sha_env_str = getenv("bootstopkeysha256"); + u8 sha_env[SHA256_SUM_LEN]; + u8 sha[SHA256_SUM_LEN]; + char presskey[MAX_DELAY_STOP_STR]; + const char *algo_name = "sha256"; + u_int presskey_len = 0; + int abort = 0; + int size; + int ret; + + if (sha_env_str == NULL) + sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256; + + /* + * Generate the binary value from the environment hash value + * so that we can compare this value with the computed hash + * from the user input + */ + ret = hash_parse_string(algo_name, sha_env_str, sha_env); + if (ret) { + printf("Hash %s not supported!\n", algo_name); + return 0; + } + + /* + * We don't know how long the stop-string is, so we need to + * generate the sha256 hash upon each input character and + * compare the value with the one saved in the environment + */ + do { + if (tstc()) { + /* Check for input string overflow */ + if (presskey_len >= MAX_DELAY_STOP_STR) + return 0; + + presskey[presskey_len++] = getc(); + + /* Calculate sha256 upon each new char */ + hash_block(algo_name, (const void *)presskey, + presskey_len, sha, &size); + + /* And check if sha matches saved value in env */ + if (slow_equals(sha, sha_env, SHA256_SUM_LEN)) + abort = 1; + } + } while (!abort && get_ticks() <= etime); + + return abort; +} +#else +static int passwd_abort(uint64_t etime) { int abort = 0; - uint64_t etime = endtick(bootdelay); struct { char *str; u_int len; @@ -50,19 +117,6 @@ static int abortboot_keyed(int bootdelay) u_int presskey_max = 0; u_int i; -#ifndef CONFIG_ZERO_BOOTDELAY_CHECK - if (bootdelay == 0) - return 0; -#endif - -# ifdef CONFIG_AUTOBOOT_PROMPT - /* - * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards. - * To print the bootdelay value upon bootup. - */ - printf(CONFIG_AUTOBOOT_PROMPT, bootdelay); -# endif - # ifdef CONFIG_AUTOBOOT_DELAY_STR if (delaykey[0].str == NULL) delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; @@ -119,6 +173,33 @@ static int abortboot_keyed(int bootdelay) } } while (!abort && get_ticks() <= etime); + return abort; +} +#endif + +/*************************************************************************** + * Watch for 'delay' seconds for autoboot stop or autoboot delay string. + * returns: 0 - no key string, allow autoboot 1 - got key string, abort + */ +static int abortboot_keyed(int bootdelay) +{ + int abort; + uint64_t etime = endtick(bootdelay); + +#ifndef CONFIG_ZERO_BOOTDELAY_CHECK + if (bootdelay == 0) + return 0; +#endif + +# ifdef CONFIG_AUTOBOOT_PROMPT + /* + * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards. + * To print the bootdelay value upon bootup. + */ + printf(CONFIG_AUTOBOOT_PROMPT, bootdelay); +# endif + + abort = passwd_abort(etime); if (!abort) debug_bootkeys("key timeout\n"); |