autoboot.c: Add feature to stop autobooting via SHA256 encrypted password

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 <sr@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Stefan Roese 2015-05-18 14:08:24 +02:00 committed by Tom Rini
parent d126e01649
commit 8f0b1e24e2
4 changed files with 152 additions and 31 deletions

View File

@ -45,9 +45,14 @@ config AUTOBOOT_PROMPT
the responsibility of the user to select only such arguments the responsibility of the user to select only such arguments
that are valid in the given context. 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 config AUTOBOOT_DELAY_STR
string "Delay autobooting via specific input key / string" string "Delay autobooting via specific input key / string"
depends on AUTOBOOT_KEYED depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
help help
This option delays the automatic boot feature by issuing This option delays the automatic boot feature by issuing
a specific input key or string. If CONFIG_AUTOBOOT_DELAY_STR a specific input key or string. If CONFIG_AUTOBOOT_DELAY_STR
@ -59,7 +64,7 @@ config AUTOBOOT_DELAY_STR
config AUTOBOOT_STOP_STR config AUTOBOOT_STOP_STR
string "Stop autobooting via specific input key / string" string "Stop autobooting via specific input key / string"
depends on AUTOBOOT_KEYED depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
help help
This option enables stopping (aborting) of the automatic This option enables stopping (aborting) of the automatic
boot feature only by issuing a specific input key or boot feature only by issuing a specific input key or
@ -71,7 +76,7 @@ config AUTOBOOT_STOP_STR
config AUTOBOOT_KEYED_CTRLC config AUTOBOOT_KEYED_CTRLC
bool "Enable Ctrl-C autoboot interruption" bool "Enable Ctrl-C autoboot interruption"
depends on AUTOBOOT_KEYED depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
default n default n
help help
This option allows for the boot sequence to be interrupted 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 Setting this variable provides an escape sequence from the
limited "password" strings. 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 endmenu
comment "Commands" comment "Commands"

View File

@ -12,6 +12,7 @@
#include <fdtdec.h> #include <fdtdec.h>
#include <menu.h> #include <menu.h>
#include <post.h> #include <post.h>
#include <u-boot/sha256.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -26,15 +27,81 @@ DECLARE_GLOBAL_DATA_PTR;
/* Stored value of bootdelay, used by autoboot_command() */ /* Stored value of bootdelay, used by autoboot_command() */
static int stored_bootdelay; static int stored_bootdelay;
/*************************************************************************** #if defined(CONFIG_AUTOBOOT_KEYED)
* Watch for 'delay' seconds for autoboot stop or autoboot delay string. #if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
* returns: 0 - no key string, allow autoboot 1 - got key string, abort
/*
* Use a "constant-length" time compare function for this
* hash compare:
*
* https://crackstation.net/hashing-security.htm
*/ */
# if defined(CONFIG_AUTOBOOT_KEYED) static int slow_equals(u8 *a, u8 *b, int len)
static int abortboot_keyed(int bootdelay) {
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; int abort = 0;
uint64_t etime = endtick(bootdelay);
struct { struct {
char *str; char *str;
u_int len; u_int len;
@ -50,19 +117,6 @@ static int abortboot_keyed(int bootdelay)
u_int presskey_max = 0; u_int presskey_max = 0;
u_int i; 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 # ifdef CONFIG_AUTOBOOT_DELAY_STR
if (delaykey[0].str == NULL) if (delaykey[0].str == NULL)
delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
@ -119,6 +173,33 @@ static int abortboot_keyed(int bootdelay)
} }
} while (!abort && get_ticks() <= etime); } 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) if (!abort)
debug_bootkeys("key timeout\n"); debug_bootkeys("key timeout\n");

View File

@ -227,6 +227,26 @@ int hash_progressive_lookup_algo(const char *algo_name,
} }
#ifndef USE_HOSTCC #ifndef USE_HOSTCC
int hash_parse_string(const char *algo_name, const char *str, uint8_t *result)
{
struct hash_algo *algo;
int ret;
int i;
ret = hash_lookup_algo(algo_name, &algo);
if (ret)
return ret;
for (i = 0; i < algo->digest_size; i++) {
char chr[3];
strncpy(chr, &str[i * 2], 2);
result[i] = simple_strtoul(chr, NULL, 16);
}
return 0;
}
/** /**
* store_result: Store the resulting sum to an address or variable * store_result: Store the resulting sum to an address or variable
* *
@ -315,7 +335,6 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str,
buf = map_sysmem(addr, algo->digest_size); buf = map_sysmem(addr, algo->digest_size);
memcpy(vsum, buf, algo->digest_size); memcpy(vsum, buf, algo->digest_size);
} else { } else {
unsigned int i;
char *vsum_str; char *vsum_str;
int digits = algo->digest_size * 2; int digits = algo->digest_size * 2;
@ -335,14 +354,7 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str,
} }
} }
for (i = 0; i < algo->digest_size; i++) { hash_parse_string(algo->name, vsum_str, vsum);
char *nullp = vsum_str + (i + 1) * 2;
char end = *nullp;
*nullp = '\0';
vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16);
*nullp = end;
}
} }
return 0; return 0;
} }

View File

@ -158,4 +158,18 @@ int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
int hash_progressive_lookup_algo(const char *algo_name, int hash_progressive_lookup_algo(const char *algo_name,
struct hash_algo **algop); struct hash_algo **algop);
/**
* hash_parse_string() - Parse hash string into a binary array
*
* The function parses a hash string into a binary array that
* can for example easily be used to compare to hash values.
*
* @algo_name: Hash algorithm to look up
* @str: Hash string to get parsed
* @result: Binary array of the parsed hash string
*
* @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
*/
int hash_parse_string(const char *algo_name, const char *str, uint8_t *result);
#endif #endif