Commit 8f0b1e24e2887713bdcbf35b08902e9555ee7b92

Authored by Stefan Roese
Committed by Tom Rini
1 parent d126e01649

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>

Showing 4 changed files with 152 additions and 31 deletions Side-by-side Diff

... ... @@ -45,9 +45,14 @@
45 45 the responsibility of the user to select only such arguments
46 46 that are valid in the given context.
47 47  
  48 +config AUTOBOOT_ENCRYPTION
  49 + bool "Enable encryption in autoboot stopping"
  50 + depends on AUTOBOOT_KEYED
  51 + default n
  52 +
48 53 config AUTOBOOT_DELAY_STR
49 54 string "Delay autobooting via specific input key / string"
50   - depends on AUTOBOOT_KEYED
  55 + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
51 56 help
52 57 This option delays the automatic boot feature by issuing
53 58 a specific input key or string. If CONFIG_AUTOBOOT_DELAY_STR
... ... @@ -59,7 +64,7 @@
59 64  
60 65 config AUTOBOOT_STOP_STR
61 66 string "Stop autobooting via specific input key / string"
62   - depends on AUTOBOOT_KEYED
  67 + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
63 68 help
64 69 This option enables stopping (aborting) of the automatic
65 70 boot feature only by issuing a specific input key or
66 71  
... ... @@ -71,13 +76,22 @@
71 76  
72 77 config AUTOBOOT_KEYED_CTRLC
73 78 bool "Enable Ctrl-C autoboot interruption"
74   - depends on AUTOBOOT_KEYED
  79 + depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION
75 80 default n
76 81 help
77 82 This option allows for the boot sequence to be interrupted
78 83 by ctrl-c, in addition to the "bootdelaykey" and "bootstopkey".
79 84 Setting this variable provides an escape sequence from the
80 85 limited "password" strings.
  86 +
  87 +config AUTOBOOT_STOP_STR_SHA256
  88 + string "Stop autobooting via SHA256 encrypted password"
  89 + depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION
  90 + help
  91 + This option adds the feature to only stop the autobooting,
  92 + and therefore boot into the U-Boot prompt, when the input
  93 + string / password matches a values that is encypted via
  94 + a SHA256 hash and saved in the environment.
81 95  
82 96 endmenu
83 97  
... ... @@ -12,6 +12,7 @@
12 12 #include <fdtdec.h>
13 13 #include <menu.h>
14 14 #include <post.h>
  15 +#include <u-boot/sha256.h>
15 16  
16 17 DECLARE_GLOBAL_DATA_PTR;
17 18  
18 19  
19 20  
20 21  
... ... @@ -26,15 +27,81 @@
26 27 /* Stored value of bootdelay, used by autoboot_command() */
27 28 static int stored_bootdelay;
28 29  
29   -/***************************************************************************
30   - * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
31   - * returns: 0 - no key string, allow autoboot 1 - got key string, abort
  30 +#if defined(CONFIG_AUTOBOOT_KEYED)
  31 +#if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
  32 +
  33 +/*
  34 + * Use a "constant-length" time compare function for this
  35 + * hash compare:
  36 + *
  37 + * https://crackstation.net/hashing-security.htm
32 38 */
33   -# if defined(CONFIG_AUTOBOOT_KEYED)
34   -static int abortboot_keyed(int bootdelay)
  39 +static int slow_equals(u8 *a, u8 *b, int len)
35 40 {
  41 + int diff = 0;
  42 + int i;
  43 +
  44 + for (i = 0; i < len; i++)
  45 + diff |= a[i] ^ b[i];
  46 +
  47 + return diff == 0;
  48 +}
  49 +
  50 +static int passwd_abort(uint64_t etime)
  51 +{
  52 + const char *sha_env_str = getenv("bootstopkeysha256");
  53 + u8 sha_env[SHA256_SUM_LEN];
  54 + u8 sha[SHA256_SUM_LEN];
  55 + char presskey[MAX_DELAY_STOP_STR];
  56 + const char *algo_name = "sha256";
  57 + u_int presskey_len = 0;
36 58 int abort = 0;
37   - uint64_t etime = endtick(bootdelay);
  59 + int size;
  60 + int ret;
  61 +
  62 + if (sha_env_str == NULL)
  63 + sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
  64 +
  65 + /*
  66 + * Generate the binary value from the environment hash value
  67 + * so that we can compare this value with the computed hash
  68 + * from the user input
  69 + */
  70 + ret = hash_parse_string(algo_name, sha_env_str, sha_env);
  71 + if (ret) {
  72 + printf("Hash %s not supported!\n", algo_name);
  73 + return 0;
  74 + }
  75 +
  76 + /*
  77 + * We don't know how long the stop-string is, so we need to
  78 + * generate the sha256 hash upon each input character and
  79 + * compare the value with the one saved in the environment
  80 + */
  81 + do {
  82 + if (tstc()) {
  83 + /* Check for input string overflow */
  84 + if (presskey_len >= MAX_DELAY_STOP_STR)
  85 + return 0;
  86 +
  87 + presskey[presskey_len++] = getc();
  88 +
  89 + /* Calculate sha256 upon each new char */
  90 + hash_block(algo_name, (const void *)presskey,
  91 + presskey_len, sha, &size);
  92 +
  93 + /* And check if sha matches saved value in env */
  94 + if (slow_equals(sha, sha_env, SHA256_SUM_LEN))
  95 + abort = 1;
  96 + }
  97 + } while (!abort && get_ticks() <= etime);
  98 +
  99 + return abort;
  100 +}
  101 +#else
  102 +static int passwd_abort(uint64_t etime)
  103 +{
  104 + int abort = 0;
38 105 struct {
39 106 char *str;
40 107 u_int len;
... ... @@ -50,19 +117,6 @@
50 117 u_int presskey_max = 0;
51 118 u_int i;
52 119  
53   -#ifndef CONFIG_ZERO_BOOTDELAY_CHECK
54   - if (bootdelay == 0)
55   - return 0;
56   -#endif
57   -
58   -# ifdef CONFIG_AUTOBOOT_PROMPT
59   - /*
60   - * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
61   - * To print the bootdelay value upon bootup.
62   - */
63   - printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
64   -# endif
65   -
66 120 # ifdef CONFIG_AUTOBOOT_DELAY_STR
67 121 if (delaykey[0].str == NULL)
68 122 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
... ... @@ -119,6 +173,33 @@
119 173 }
120 174 } while (!abort && get_ticks() <= etime);
121 175  
  176 + return abort;
  177 +}
  178 +#endif
  179 +
  180 +/***************************************************************************
  181 + * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
  182 + * returns: 0 - no key string, allow autoboot 1 - got key string, abort
  183 + */
  184 +static int abortboot_keyed(int bootdelay)
  185 +{
  186 + int abort;
  187 + uint64_t etime = endtick(bootdelay);
  188 +
  189 +#ifndef CONFIG_ZERO_BOOTDELAY_CHECK
  190 + if (bootdelay == 0)
  191 + return 0;
  192 +#endif
  193 +
  194 +# ifdef CONFIG_AUTOBOOT_PROMPT
  195 + /*
  196 + * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
  197 + * To print the bootdelay value upon bootup.
  198 + */
  199 + printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
  200 +# endif
  201 +
  202 + abort = passwd_abort(etime);
122 203 if (!abort)
123 204 debug_bootkeys("key timeout\n");
124 205  
... ... @@ -227,6 +227,26 @@
227 227 }
228 228  
229 229 #ifndef USE_HOSTCC
  230 +int hash_parse_string(const char *algo_name, const char *str, uint8_t *result)
  231 +{
  232 + struct hash_algo *algo;
  233 + int ret;
  234 + int i;
  235 +
  236 + ret = hash_lookup_algo(algo_name, &algo);
  237 + if (ret)
  238 + return ret;
  239 +
  240 + for (i = 0; i < algo->digest_size; i++) {
  241 + char chr[3];
  242 +
  243 + strncpy(chr, &str[i * 2], 2);
  244 + result[i] = simple_strtoul(chr, NULL, 16);
  245 + }
  246 +
  247 + return 0;
  248 +}
  249 +
230 250 /**
231 251 * store_result: Store the resulting sum to an address or variable
232 252 *
... ... @@ -315,7 +335,6 @@
315 335 buf = map_sysmem(addr, algo->digest_size);
316 336 memcpy(vsum, buf, algo->digest_size);
317 337 } else {
318   - unsigned int i;
319 338 char *vsum_str;
320 339 int digits = algo->digest_size * 2;
321 340  
... ... @@ -335,14 +354,7 @@
335 354 }
336 355 }
337 356  
338   - for (i = 0; i < algo->digest_size; i++) {
339   - char *nullp = vsum_str + (i + 1) * 2;
340   - char end = *nullp;
341   -
342   - *nullp = '\0';
343   - vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16);
344   - *nullp = end;
345   - }
  357 + hash_parse_string(algo->name, vsum_str, vsum);
346 358 }
347 359 return 0;
348 360 }
... ... @@ -158,5 +158,19 @@
158 158 int hash_progressive_lookup_algo(const char *algo_name,
159 159 struct hash_algo **algop);
160 160  
  161 +/**
  162 + * hash_parse_string() - Parse hash string into a binary array
  163 + *
  164 + * The function parses a hash string into a binary array that
  165 + * can for example easily be used to compare to hash values.
  166 + *
  167 + * @algo_name: Hash algorithm to look up
  168 + * @str: Hash string to get parsed
  169 + * @result: Binary array of the parsed hash string
  170 + *
  171 + * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
  172 + */
  173 +int hash_parse_string(const char *algo_name, const char *str, uint8_t *result);
  174 +
161 175 #endif