common: integrate crypt-based passwords
authorSteffen Jaeckel <jaeckel-floss@eyet-services.de>
Thu, 8 Jul 2021 13:57:35 +0000 (15:57 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 23 Jul 2021 17:36:20 +0000 (13:36 -0400)
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>
common/Kconfig.boot
common/autoboot.c

index b4dc49e..fe60ad0 100644 (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
index b42148c..107fb15 100644 (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);
        }
-}
+}
\ No newline at end of file