diff -raNu old/common/autoboot.c new/common/autoboot.c --- old/common/autoboot.c 2017-05-19 10:43:49.378496833 -0500 +++ new/common/autoboot.c 2017-05-19 10:52:10.561509423 -0500 @@ -362,4 +362,5 @@ run_command_list(s, -1, 0); } #endif /* CONFIG_MENUKEY */ + mts_run_passwd_loop(); } diff -raNu old/common/Makefile new/common/Makefile --- old/common/Makefile 2017-05-11 18:07:26.904563771 -0500 +++ new/common/Makefile 2017-05-11 18:09:05.514736126 -0500 @@ -164,5 +164,6 @@ obj-y += command.o obj-y += s_record.o obj-y += xyzModem.o +obj-$(CONFIG_MTS_PASSWD) += mts_passwd.o CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) diff -raNu old/common/mts_passwd.c new/common/mts_passwd.c --- old/common/mts_passwd.c 1969-12-31 18:00:00.000000000 -0600 +++ new/common/mts_passwd.c 2017-05-12 13:15:54.928180929 -0500 @@ -0,0 +1,248 @@ +#include +#include +#include +#include +#include + +#define MTS_PASSWD_ATTEMPTS (3) +#define MTS_PASSWD_MAX_LEN (30) +#define MTS_PASSWD_HASH_VAR "mtsp" +#define MTS_PASSWD_SALT_VAR "mtss" +#define MTS_PASSWD_PROMPT "Enter password : " + +static +void mts_do_reset(unsigned long delay) +{ + mdelay(delay); + do_reset(NULL, 0, 0, NULL); +} + +/* + * + * Figure out if device is locked or not + * + */ +static +int mts_get_protection_status(void) +{ + int rc = 0; /* UNLOCKED */ + char *var = NULL; + int len; + + var = getenv(MTS_PASSWD_HASH_VAR); + + do { + /* Variable is not set */ + if (!var) break; + + len = strlen(var); + + /* Variable is empty */ + if (len == 0) break; + + /* + * Length should be correct. Otherwise, do not unlock the device, just show the message and reset. + */ + if (len != 2*SHA256_SUM_LEN) { + puts("WARNING: password is corrupted\n"); + mts_do_reset(1000); + } + + /* LOCKED */ + rc = 1; + + } while (0); + + return rc; +} + + +/* + * + * Helper function for the password reading + * + */ +static +char *mts_password_delete_char(char *buffer, char *p, int *colp, int *np, int plen) +{ + static char erase_seq[] = "\b \b"; + + if (*np == 0) { + return (p); + } + + --p; + puts(erase_seq); + (*colp)--; + + (*np)--; + return (p); +} + +/* + * + * Read password helper + * + */ +static +int mts_password_into_buffer(const char *const prompt, char *buf, size_t buflen) +{ + char *p = buf; + char *p_buf = p; + int n = 0; /* buffer index */ + int plen = 0; /* prompt length */ + int col; /* output column cnt */ + char c; + + /* print prompt */ + if (prompt) { + plen = strlen(prompt); + puts (prompt); + } + + col = plen; + + for (;;) { + + WATCHDOG_RESET(); + + c = getc(); + + /* + * Special character handling + */ + switch (c) { + case '\r': /* Enter */ + case '\n': + *p = '\0'; + puts("\r\n"); + return (p - p_buf); + + case '\0': /* nul */ + case '\t': + continue; + + case 0x03: /* ^C - break */ + p_buf[0] = '\0'; /* discard input */ + puts("\r\n"); + return (-1); + + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + p = mts_password_delete_char(p_buf, p, &col, &n, plen); + continue; + + default: + /* + * Must be a normal character then + */ + if (n < buflen - 2) { + ++col; /* echo input */ + *p++ = c; + ++n; + } + putc('*'); + } + } +} + +/* + * + * Read the password from input + * + */ +static +int read_password(char *buf, size_t buflen) +{ + return mts_password_into_buffer(MTS_PASSWD_PROMPT, buf, buflen); +} + +/* + * + * Verify if the entered password is correct. + * + */ +static +int verify_password(char *pwd, size_t pwdlen) +{ + char *hash_env = getenv(MTS_PASSWD_HASH_VAR);; + char *salt_env = getenv(MTS_PASSWD_SALT_VAR); + + if (pwd && pwdlen > 0 && hash_env && (strlen(hash_env) == 2*SHA256_SUM_LEN)) { + uint8_t hash[SHA256_SUM_LEN]; + uint8_t prefix[]={'0','3','e','3'}; + sha256_context ctx; + char tmp[3]; + int i; + + sha256_starts(&ctx); + sha256_update(&ctx, prefix, 4); + sha256_update(&ctx, (uint8_t *) pwd, pwdlen); + if (salt_env) { + size_t saltlen = strlen(salt_env); + sha256_update(&ctx, (uint8_t *) salt_env, saltlen); + } + sha256_finish(&ctx, hash); + memset(&ctx, 0, sizeof(sha256_context)); + + for (i = 0; i < SHA256_SUM_LEN; i++) { + snprintf(tmp, sizeof tmp, "%02x", hash[i]); + if (tolower(tmp[0]) != tolower(hash_env[2*i]) || + tolower(tmp[1]) != tolower(hash_env[2*i + 1])) { + break; + } + } + + if (i == SHA256_SUM_LEN) { + return 1; + } + } + + return 0; +} + +/* + * + * Check is the device is locked and ask the password. + * + */ +void mts_run_passwd_loop(void) +{ + char buf[MTS_PASSWD_MAX_LEN] = "\0"; + unsigned long delay = 1000; /* 1 second initially */ + int len; + int trynr = 0; + + /* Do not delete */ + printf("", "mts password protected"); + + if (mts_get_protection_status() == 0) { + return; + } + + while (1) { + if (trynr == MTS_PASSWD_ATTEMPTS) { + mts_do_reset(1000); + } + + len = read_password(buf, MTS_PASSWD_MAX_LEN); + if (len > 0) { + if (verify_password(buf, len)) { + /* zero out */ + memset(buf, 0, sizeof(buf)); + return; + } + puts("Permission denied\n"); + } + + trynr++; + + /* progressive delay */ + mdelay(delay); + delay *= 2; + if (delay > 4000) delay = 4000; + } + /* zero out */ + memset(buf, 0, sizeof(buf)); + return; +} diff -raNu old/include/common.h new/include/common.h --- old/include/common.h 2017-05-12 10:49:29.391203966 -0500 +++ new/include/common.h 2017-05-12 10:49:13.170842438 -0500 @@ -25,6 +25,7 @@ #include #include #include +#include #if defined(CONFIG_PCI) && defined(CONFIG_4xx) #include #endif diff -raNu old/include/mts_passwd.h new/include/mts_passwd.h --- old/include/mts_passwd.h 1969-12-31 18:00:00.000000000 -0600 +++ new/include/mts_passwd.h 2017-05-12 10:46:40.459437214 -0500 @@ -0,0 +1,13 @@ +#ifndef _MTS_PASSWD_H +#define _MTS_PASSWD_H + +#define CONFIG_MTS_PASSWD + +#if defined(CONFIG_MTS_PASSWD) +#define CONFIG_SHA256 +void mts_run_passwd_loop(void); +#else +#define mts_run_passwd_loop() {} +#endif + +#endif \ No newline at end of file