common: integrate crypt-based passwords

Hook into the autoboot flow as an alternative to the existing
mechanisms.

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
Steffen Jaeckel 2021-07-08 15:57:35 +02:00 committed by Tom Rini
parent 29bbe71ccf
commit 1a4a778666
2 changed files with 105 additions and 14 deletions

View file

@ -812,10 +812,17 @@ config AUTOBOOT_ENCRYPTION
depends on AUTOBOOT_KEYED
help
This option allows a string to be entered into U-Boot to stop the
autoboot. The string itself is hashed and compared against the hash
in the environment variable 'bootstopkeysha256'. If it matches then
boot stops and a command-line prompt is presented.
autoboot.
The behavior depends whether CONFIG_CRYPT_PW from lib is enabled
or not.
In case CONFIG_CRYPT_PW is enabled, the string will be forwarded
to the crypt-based functionality and be compared against the
string in the environment variable 'bootstopkeycrypt'.
In case CONFIG_CRYPT_PW is disabled the string itself is hashed
and compared against the hash in the environment variable
'bootstopkeysha256'.
If it matches in either case then boot stops and
a command-line prompt is presented.
This provides a way to ship a secure production device which can also
be accessed at the U-Boot command line.
@ -853,9 +860,30 @@ config AUTOBOOT_KEYED_CTRLC
Setting this variable provides an escape sequence from the
limited "password" strings.
config AUTOBOOT_STOP_STR_ENABLE
bool "Enable fixed string to stop autobooting"
depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION
help
This option enables the feature to add a fixed stop
string that is defined at compile time.
In every case it will be tried to load the stop
string from the environment.
In case this is enabled and there is no stop string
in the environment, this will be used as default value.
config AUTOBOOT_STOP_STR_CRYPT
string "Stop autobooting via crypt-hashed password"
depends on AUTOBOOT_STOP_STR_ENABLE && CRYPT_PW
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 hashed via
one of the supported crypt-style password hashing options
and saved in the environment variable "bootstopkeycrypt".
config AUTOBOOT_STOP_STR_SHA256
string "Stop autobooting via SHA256 encrypted password"
depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION
depends on AUTOBOOT_STOP_STR_ENABLE
help
This option adds the feature to only stop the autobooting,
and therefore boot into the U-Boot prompt, when the input

View file

@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <u-boot/sha256.h>
#include <bootcount.h>
#include <crypt.h>
DECLARE_GLOBAL_DATA_PTR;
@ -38,10 +39,11 @@ DECLARE_GLOBAL_DATA_PTR;
static int stored_bootdelay;
static int menukey;
#ifdef CONFIG_AUTOBOOT_ENCRYPTION
#define AUTOBOOT_STOP_STR_SHA256 CONFIG_AUTOBOOT_STOP_STR_SHA256
#else
#define AUTOBOOT_STOP_STR_SHA256 ""
#if !defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
#define CONFIG_AUTOBOOT_STOP_STR_CRYPT ""
#endif
#if !defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
#define CONFIG_AUTOBOOT_STOP_STR_SHA256 ""
#endif
#ifdef CONFIG_AUTOBOOT_USE_MENUKEY
@ -50,6 +52,63 @@ static int menukey;
#define AUTOBOOT_MENUKEY 0
#endif
/**
* passwd_abort_crypt() - check for a crypt-style hashed key sequence to abort booting
*
* This checks for the user entering a password within a given time.
*
* The entered password is hashed via one of the crypt-style hash methods
* and compared to the pre-defined value from either
* the environment variable "bootstopkeycrypt"
* or
* the config value CONFIG_AUTOBOOT_STOP_STR_CRYPT
*
* @etime: Timeout value ticks (stop when get_ticks() reachs this)
* @return 0 if autoboot should continue, 1 if it should stop
*/
static int passwd_abort_crypt(uint64_t etime)
{
const char *crypt_env_str = env_get("bootstopkeycrypt");
char presskey[MAX_DELAY_STOP_STR];
u_int presskey_len = 0;
int abort = 0;
int err;
if (IS_ENABLED(CONFIG_AUTOBOOT_STOP_STR_ENABLE) && !crypt_env_str)
crypt_env_str = CONFIG_AUTOBOOT_STOP_STR_CRYPT;
if (!crypt_env_str)
return 0;
/* We expect the stop-string to be newline-terminated */
do {
if (tstc()) {
/* Check for input string overflow */
if (presskey_len >= sizeof(presskey))
return 0;
presskey[presskey_len] = getchar();
if ((presskey[presskey_len] == '\r') ||
(presskey[presskey_len] == '\n')) {
presskey[presskey_len] = '\0';
err = crypt_compare(crypt_env_str, presskey,
&abort);
if (err)
debug_bootkeys(
"crypt_compare() failed with: %s\n",
errno_str(err));
/* you had one chance */
break;
} else {
presskey_len++;
}
}
} while (get_ticks() <= etime);
return abort;
}
/*
* Use a "constant-length" time compare function for this
* hash compare:
@ -89,7 +148,7 @@ static int passwd_abort_sha256(uint64_t etime)
int ret;
if (sha_env_str == NULL)
sha_env_str = AUTOBOOT_STOP_STR_SHA256;
sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
presskey = malloc_cache_aligned(MAX_DELAY_STOP_STR);
c = strstr(sha_env_str, ":");
@ -245,10 +304,14 @@ static int abortboot_key_sequence(int bootdelay)
printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
# endif
if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION))
abort = passwd_abort_sha256(etime);
else
if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION)) {
if (IS_ENABLED(CONFIG_CRYPT_PW))
abort = passwd_abort_crypt(etime);
else
abort = passwd_abort_sha256(etime);
} else {
abort = passwd_abort_key(etime);
}
if (!abort)
debug_bootkeys("key timeout\n");
@ -394,4 +457,4 @@ void autoboot_command(const char *s)
if (s)
run_command_list(s, -1, 0);
}
}
}