Hi Stefan, On 8 May 2015 at 01:52, Stefan Roese <s...@denx.de> wrote: > This patch adds the feature to only stop the autobooting, and therefor > boot into the U-Boot prompt, when the input string / password matches > a values that is encypted via a SHA256 hash and saved in the environment. > > This feature is enabled by defined these config options: > CONFIG_AUTOBOOT_KEYED > CONFIG_AUTOBOOT_STOP_STR_SHA256 > > Signed-off-by: Stefan Roese <s...@denx.de> > Cc: Simon Glass <s...@chromium.org> > Cc: Magnus Lilja <lilja.mag...@gmail.com> > --- > v2: > - AUTOBOOT_STOP_STR_SHA256 is a string and not bool > - Add input key length check as suggested by Magnus > - Add "constant-length" time compare function as suggested > by Magnus > > common/Kconfig | 20 +++++++-- > common/autoboot.c | 132 > +++++++++++++++++++++++++++++++++++++++++++++--------- > 2 files changed, 128 insertions(+), 24 deletions(-)
Reviewed-by: Simon Glass <s...@chromium.org> A few optional ideas below. > > diff --git a/common/Kconfig b/common/Kconfig > index ff150f0..71c5c10 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -45,9 +45,14 @@ config AUTOBOOT_PROMPT > the responsibility of the user to select only such arguments > that are valid in the given context. > > +config AUTOBOOT_ENCRYPTION > + bool "Enable encryption in autoboot stopping" > + depends on AUTOBOOT_KEYED > + default n > + > config AUTOBOOT_DELAY_STR > string "Delay autobooting via specific input key / string" > - depends on AUTOBOOT_KEYED > + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION > help > This option delays the automatic boot feature by issuing > a specific input key or string. If CONFIG_AUTOBOOT_DELAY_STR > @@ -59,7 +64,7 @@ config AUTOBOOT_DELAY_STR > > config AUTOBOOT_STOP_STR > string "Stop autobooting via specific input key / string" > - depends on AUTOBOOT_KEYED > + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION > help > This option enables stopping (aborting) of the automatic > boot feature only by issuing a specific input key or > @@ -71,7 +76,7 @@ config AUTOBOOT_STOP_STR > > config AUTOBOOT_KEYED_CTRLC > bool "Enable Ctrl-C autoboot interruption" > - depends on AUTOBOOT_KEYED > + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION > default n > help > This option allows for the boot sequence to be interrupted > @@ -79,6 +84,15 @@ config AUTOBOOT_KEYED_CTRLC > Setting this variable provides an escape sequence from the > limited "password" strings. > > +config AUTOBOOT_STOP_STR_SHA256 > + string "Stop autobooting via SHA256 encrypted password" > + depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION > + help > + This option adds the feature to only stop the autobooting, > + and therefore boot into the U-Boot prompt, when the input > + string / password matches a values that is encypted via > + a SHA256 hash and saved in the environment. > + > endmenu > > comment "Commands" > diff --git a/common/autoboot.c b/common/autoboot.c > index f72eb18..dde3d04 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,80 @@ 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]; > + u_int presskey_len = 0; > + int i; > + int abort = 0; > + > + 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 > + */ > + for (i = 0; i < SHA256_SUM_LEN; i++) { > + char chr[3]; > + > + strncpy(chr, &sha_env_str[i * 2], 2); > + sha_env[i] = simple_strtoul(chr, NULL, 16); > + } > + There is similar code in parse_verify_sum() in hash.c. Not sure if it is worth putting it in a function, like: hash_parse_string(const char *algo_name, cost char *str, u8 *result) It could support other algorithms for autoboot in the future if that became useful. > + /* > + * 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 */ > + sha256_csum_wd((unsigned char *)presskey, > presskey_len, > + sha, CHUNKSZ_SHA256); Could use hash_block() > + > + /* 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; > @@ -42,7 +108,9 @@ static int abortboot_keyed(int bootdelay) > } > delaykey[] = { > { .str = getenv("bootdelaykey"), .retry = 1 }, > + { .str = getenv("bootdelaykey2"), .retry = 1 }, > { .str = getenv("bootstopkey"), .retry = 0 }, > + { .str = getenv("bootstopkey2"), .retry = 0 }, > }; > > char presskey[MAX_DELAY_STOP_STR]; > @@ -50,26 +118,21 @@ 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; > # endif > -# ifdef CONFIG_AUTOBOOT_STOP_STR > +# ifdef CONFIG_AUTOBOOT_DELAY_STR2 > if (delaykey[1].str == NULL) > - delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR; > + delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; > +# endif > +# ifdef CONFIG_AUTOBOOT_STOP_STR > + if (delaykey[2].str == NULL) > + delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; > +# endif > +# ifdef CONFIG_AUTOBOOT_STOP_STR2 > + if (delaykey[3].str == NULL) > + delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; > # endif > > for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) { > @@ -119,6 +182,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"); > > -- > 2.4.0 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot