Commit 8f0b1e24e2887713bdcbf35b08902e9555ee7b92
Committed by
Tom Rini
1 parent
d126e01649
Exists in
v2017.01-smarct4x
and in
34 other branches
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
common/Kconfig
... | ... | @@ -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 |
common/autoboot.c
... | ... | @@ -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 |
common/hash.c
... | ... | @@ -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 | } |
include/hash.h
... | ... | @@ -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 |