ソースを参照

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>
Stefan Roese 10 年 前
コミット
8f0b1e24e2
4 ファイル変更152 行追加31 行削除
  1. 17 3
      common/Kconfig
  2. 100 19
      common/autoboot.c
  3. 21 9
      common/hash.c
  4. 14 0
      include/hash.h

+ 17 - 3
common/Kconfig

@@ -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"

+ 100 - 19
common/autoboot.c

@@ -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;
 
 
-/***************************************************************************
- * 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;
 	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");
 
 

+ 21 - 9
common/hash.c

@@ -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++) {
-			char *nullp = vsum_str + (i + 1) * 2;
-			char end = *nullp;
-
-			*nullp = '\0';
-			vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16);
-			*nullp = end;
-		}
+		hash_parse_string(algo->name, vsum_str, vsum);
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 14 - 0
include/hash.h

@@ -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