1 // SPDX-License-Identifier: GPL-2.0+
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
22 #include <asm/global_data.h>
23 #include <linux/delay.h>
24 #include <u-boot/sha256.h>
25 #include <bootcount.h>
27 #include <dm/ofnode.h>
29 DECLARE_GLOBAL_DATA_PTR
;
31 #define DELAY_STOP_STR_MAX_LENGTH 64
33 #ifndef DEBUG_BOOTKEYS
34 #define DEBUG_BOOTKEYS 0
36 #define debug_bootkeys(fmt, args...) \
37 debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
39 /* Stored value of bootdelay, used by autoboot_command() */
40 static int stored_bootdelay
;
43 #if defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
44 #define AUTOBOOT_STOP_STR_CRYPT CONFIG_AUTOBOOT_STOP_STR_CRYPT
46 #define AUTOBOOT_STOP_STR_CRYPT ""
48 #if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
49 #define AUTOBOOT_STOP_STR_SHA256 CONFIG_AUTOBOOT_STOP_STR_SHA256
51 #define AUTOBOOT_STOP_STR_SHA256 ""
54 #ifdef CONFIG_AUTOBOOT_USE_MENUKEY
55 #define AUTOBOOT_MENUKEY CONFIG_AUTOBOOT_MENUKEY
57 #define AUTOBOOT_MENUKEY 0
61 * passwd_abort_crypt() - check for a crypt-style hashed key sequence to abort booting
63 * This checks for the user entering a password within a given time.
65 * The entered password is hashed via one of the crypt-style hash methods
66 * and compared to the pre-defined value from either
67 * the environment variable "bootstopkeycrypt"
69 * the config value CONFIG_AUTOBOOT_STOP_STR_CRYPT
71 * In case the config value CONFIG_AUTOBOOT_NEVER_TIMEOUT has been enabled
72 * this function never times out if the user presses the <Enter> key
73 * before starting to enter the password.
75 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
76 * Return: 0 if autoboot should continue, 1 if it should stop
78 static int passwd_abort_crypt(uint64_t etime
)
80 const char *crypt_env_str
= env_get("bootstopkeycrypt");
81 char presskey
[DELAY_STOP_STR_MAX_LENGTH
];
82 u_int presskey_len
= 0;
84 int never_timeout
= 0;
87 if (IS_ENABLED(CONFIG_AUTOBOOT_STOP_STR_ENABLE
) && !crypt_env_str
)
88 crypt_env_str
= AUTOBOOT_STOP_STR_CRYPT
;
93 /* We expect the stop-string to be newline-terminated */
96 /* Check for input string overflow */
97 if (presskey_len
>= sizeof(presskey
))
100 presskey
[presskey_len
] = getchar();
102 if ((presskey
[presskey_len
] == '\r') ||
103 (presskey
[presskey_len
] == '\n')) {
104 if (IS_ENABLED(CONFIG_AUTOBOOT_NEVER_TIMEOUT
) &&
109 presskey
[presskey_len
] = '\0';
110 err
= crypt_compare(crypt_env_str
, presskey
,
114 "crypt_compare() failed with: %s\n",
116 /* you had one chance */
123 } while (never_timeout
|| get_ticks() <= etime
);
129 * Use a "constant-length" time compare function for this
132 * https://crackstation.net/hashing-security.htm
134 static int slow_equals(u8
*a
, u8
*b
, int len
)
139 for (i
= 0; i
< len
; i
++)
146 * passwd_abort_sha256() - check for a hashed key sequence to abort booting
148 * This checks for the user entering a SHA256 hash within a given time.
150 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
151 * Return: 0 if autoboot should continue, 1 if it should stop
153 static int passwd_abort_sha256(uint64_t etime
)
155 const char *sha_env_str
= env_get("bootstopkeysha256");
156 u8 sha_env
[SHA256_SUM_LEN
];
160 const char *algo_name
= "sha256";
161 u_int presskey_len
= 0;
163 int size
= sizeof(sha
);
166 if (sha_env_str
== NULL
)
167 sha_env_str
= AUTOBOOT_STOP_STR_SHA256
;
169 presskey
= malloc_cache_aligned(DELAY_STOP_STR_MAX_LENGTH
);
173 c
= strstr(sha_env_str
, ":");
174 if (c
&& (c
- sha_env_str
< DELAY_STOP_STR_MAX_LENGTH
)) {
175 /* preload presskey with salt */
176 memcpy(presskey
, sha_env_str
, c
- sha_env_str
);
177 presskey_len
= c
- sha_env_str
;
181 * Generate the binary value from the environment hash value
182 * so that we can compare this value with the computed hash
183 * from the user input
185 ret
= hash_parse_string(algo_name
, sha_env_str
, sha_env
);
187 printf("Hash %s not supported!\n", algo_name
);
191 sha
= malloc_cache_aligned(SHA256_SUM_LEN
);
192 size
= SHA256_SUM_LEN
;
194 * We don't know how long the stop-string is, so we need to
195 * generate the sha256 hash upon each input character and
196 * compare the value with the one saved in the environment
200 /* Check for input string overflow */
201 if (presskey_len
>= DELAY_STOP_STR_MAX_LENGTH
) {
207 presskey
[presskey_len
++] = getchar();
209 /* Calculate sha256 upon each new char */
210 hash_block(algo_name
, (const void *)presskey
,
211 presskey_len
, sha
, &size
);
213 /* And check if sha matches saved value in env */
214 if (slow_equals(sha
, sha_env
, SHA256_SUM_LEN
))
218 } while (!abort
&& get_ticks() <= etime
);
226 * passwd_abort_key() - check for a key sequence to aborted booting
228 * This checks for the user entering a string within a given time.
230 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
231 * Return: 0 if autoboot should continue, 1 if it should stop
233 static int passwd_abort_key(uint64_t etime
)
242 { .str
= env_get("bootdelaykey"), .retry
= 1 },
243 { .str
= env_get("bootstopkey"), .retry
= 0 },
246 char presskey
[DELAY_STOP_STR_MAX_LENGTH
];
247 int presskey_len
= 0;
248 int presskey_max
= 0;
251 # ifdef CONFIG_AUTOBOOT_DELAY_STR
252 if (delaykey
[0].str
== NULL
)
253 delaykey
[0].str
= CONFIG_AUTOBOOT_DELAY_STR
;
255 # ifdef CONFIG_AUTOBOOT_STOP_STR
256 if (delaykey
[1].str
== NULL
)
257 delaykey
[1].str
= CONFIG_AUTOBOOT_STOP_STR
;
260 for (i
= 0; i
< sizeof(delaykey
) / sizeof(delaykey
[0]); i
++) {
261 delaykey
[i
].len
= delaykey
[i
].str
== NULL
?
262 0 : strlen(delaykey
[i
].str
);
263 delaykey
[i
].len
= delaykey
[i
].len
> DELAY_STOP_STR_MAX_LENGTH
?
264 DELAY_STOP_STR_MAX_LENGTH
: delaykey
[i
].len
;
266 presskey_max
= presskey_max
> delaykey
[i
].len
?
267 presskey_max
: delaykey
[i
].len
;
269 debug_bootkeys("%s key:<%s>\n",
270 delaykey
[i
].retry
? "delay" : "stop",
271 delaykey
[i
].str
? delaykey
[i
].str
: "NULL");
274 /* In order to keep up with incoming data, check timeout only
279 if (presskey_len
< presskey_max
) {
280 presskey
[presskey_len
++] = getchar();
282 for (i
= 0; i
< presskey_max
- 1; i
++)
283 presskey
[i
] = presskey
[i
+ 1];
285 presskey
[i
] = getchar();
289 for (i
= 0; i
< sizeof(delaykey
) / sizeof(delaykey
[0]); i
++) {
290 if (delaykey
[i
].len
> 0 &&
291 presskey_len
>= delaykey
[i
].len
&&
292 memcmp(presskey
+ presskey_len
-
293 delaykey
[i
].len
, delaykey
[i
].str
,
294 delaykey
[i
].len
) == 0) {
295 debug_bootkeys("got %skey\n",
296 delaykey
[i
].retry
? "delay" :
299 /* don't retry auto boot */
300 if (!delaykey
[i
].retry
)
301 bootretry_dont_retry();
306 } while (!abort
&& get_ticks() <= etime
);
312 * flush_stdin() - drops all pending characters from stdin
314 static void flush_stdin(void)
321 * fallback_to_sha256() - check whether we should fall back to sha256
324 * This checks for the environment variable `bootstopusesha256` in case
325 * sha256-fallback has been enabled via the config setting
326 * `AUTOBOOT_SHA256_FALLBACK`.
328 * Return: `false` if we must not fall-back, `true` if plain sha256 should be tried
330 static bool fallback_to_sha256(void)
332 if (IS_ENABLED(CONFIG_AUTOBOOT_SHA256_FALLBACK
))
333 return env_get_yesno("bootstopusesha256") == 1;
334 else if (IS_ENABLED(CONFIG_CRYPT_PW
))
340 /***************************************************************************
341 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
342 * returns: 0 - no key string, allow autoboot 1 - got key string, abort
344 static int abortboot_key_sequence(int bootdelay
)
347 uint64_t etime
= endtick(bootdelay
);
349 if (IS_ENABLED(CONFIG_AUTOBOOT_FLUSH_STDIN
))
351 # ifdef CONFIG_AUTOBOOT_PROMPT
353 * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
354 * To print the bootdelay value upon bootup.
356 printf(CONFIG_AUTOBOOT_PROMPT
, bootdelay
);
359 if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION
)) {
360 if (IS_ENABLED(CONFIG_CRYPT_PW
) && !fallback_to_sha256())
361 abort
= passwd_abort_crypt(etime
);
363 abort
= passwd_abort_sha256(etime
);
365 abort
= passwd_abort_key(etime
);
368 debug_bootkeys("key timeout\n");
373 static int abortboot_single_key(int bootdelay
)
378 printf("Hit any key to stop autoboot: %2d ", bootdelay
);
381 * Check if key already pressed
383 if (tstc()) { /* we got a key press */
384 getchar(); /* consume input */
386 abort
= 1; /* don't auto boot */
389 while ((bootdelay
> 0) && (!abort
)) {
394 if (tstc()) { /* we got a key press */
397 abort
= 1; /* don't auto boot */
398 bootdelay
= 0; /* no more delay */
399 key
= getchar();/* consume input */
400 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY
))
405 } while (!abort
&& get_timer(ts
) < 1000);
407 printf("\b\b\b%2d ", bootdelay
);
415 static int abortboot(int bootdelay
)
419 if (bootdelay
>= 0) {
420 if (autoboot_keyed())
421 abort
= abortboot_key_sequence(bootdelay
);
423 abort
= abortboot_single_key(bootdelay
);
426 if (IS_ENABLED(CONFIG_SILENT_CONSOLE
) && abort
)
427 gd
->flags
&= ~GD_FLG_SILENT
;
432 static void process_fdt_options(void)
434 #ifdef CONFIG_TEXT_BASE
437 /* Add an env variable to point to a kernel payload, if available */
438 addr
= ofnode_conf_read_int("kernel-offset", 0);
440 env_set_addr("kernaddr", (void *)(CONFIG_TEXT_BASE
+ addr
));
442 /* Add an env variable to point to a root disk, if available */
443 addr
= ofnode_conf_read_int("rootdisk-offset", 0);
445 env_set_addr("rootaddr", (void *)(CONFIG_TEXT_BASE
+ addr
));
446 #endif /* CONFIG_TEXT_BASE */
449 const char *bootdelay_process(void)
456 s
= env_get("bootdelay");
457 bootdelay
= s
? (int)simple_strtol(s
, NULL
, 10) : CONFIG_BOOTDELAY
;
460 * Does it really make sense that the devicetree overrides the user
461 * setting? It is possibly helpful for security since the device tree
462 * may be signed whereas the environment is often loaded from storage.
464 if (IS_ENABLED(CONFIG_OF_CONTROL
))
465 bootdelay
= ofnode_conf_read_int("bootdelay", bootdelay
);
467 debug("### main_loop entered: bootdelay=%d\n\n", bootdelay
);
469 if (IS_ENABLED(CONFIG_AUTOBOOT_MENU_SHOW
))
470 bootdelay
= menu_show(bootdelay
);
471 bootretry_init_cmd_timeout();
474 if (gd
->flags
& GD_FLG_POSTFAIL
) {
475 s
= env_get("failbootcmd");
477 #endif /* CONFIG_POST */
478 if (bootcount_error())
479 s
= env_get("altbootcmd");
481 s
= env_get("bootcmd");
483 if (IS_ENABLED(CONFIG_OF_CONTROL
))
484 process_fdt_options();
485 stored_bootdelay
= bootdelay
;
490 void autoboot_command(const char *s
)
492 debug("### main_loop: bootcmd=\"%s\"\n", s
? s
: "<UNDEFINED>");
494 if (s
&& (stored_bootdelay
== -2 ||
495 (stored_bootdelay
!= -1 && !abortboot(stored_bootdelay
)))) {
499 lock
= autoboot_keyed() &&
500 !IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC
);
502 prev
= disable_ctrlc(1); /* disable Ctrl-C checking */
504 run_command_list(s
, -1, 0);
507 disable_ctrlc(prev
); /* restore Ctrl-C checking */
510 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY
) &&
511 menukey
== AUTOBOOT_MENUKEY
) {
512 s
= env_get("menucmd");
514 run_command_list(s
, -1, 0);