diff --git a/examples/device/hid_cdc_passkey/src/main.c b/examples/device/hid_cdc_passkey/src/main.c index 93265c580..9037be99c 100644 --- a/examples/device/hid_cdc_passkey/src/main.c +++ b/examples/device/hid_cdc_passkey/src/main.c @@ -34,6 +34,7 @@ #include "usb_descriptors.h" #include "hid.h" +#include "WjCryptLib_Sha256.h" // get the length of an array #define LENGTH(x) (sizeof(x) / sizeof((x)[0])) @@ -53,8 +54,8 @@ #define TIMEOUT_REPEAT (6U * 60) // maximum time after last repeat to hold the credentials, in minutes static struct config_t { - uint8_t manuf_key[16]; // the key set by the manufacturer to authenticate the device - uint8_t user_key[16]; // the key set by the user to authenticate the device + char manuf_key[16 + 1]; // the key set by the manufacturer to authenticate the device + char user_key[16 + 1]; // the key set by the user to authenticate the device bool button_swap; // the order of the buttons (which is for username or password) uint16_t timeout_global; // time to hold the credentials, in minutes uint16_t timeout_repeat; // time after last repeat to hold the credentials, in minutes @@ -96,10 +97,9 @@ enum { MENU_HOME, MENU_USER, MENU_PASS, - MENU_ENTER_MANUF, - MENU_ENTER_USER, - MENU_AUTH_MANUF, - MENU_AUTH_USER, + MENU_MANUF, + MENU_KEY, + MENU_AUTH, MENU_TIMEOUT_GLOBAL, MENU_TIMEOUT_REPEAT, } menu = MENU_HOME; @@ -316,6 +316,20 @@ void cdc_task(void) menu = MENU_TIMEOUT_REPEAT; str = "\r\nenter repeat timeout in minutes: "; break; + case 'k': // set user key + i = 0; // reset index + menu = MENU_KEY; + str = "\r\nenter authentication key (up to 16 char): "; + break; + case 'a': // run authentication + if (0 == strlen(config.user_key) && 0 == strlen(config.manuf_key)) { + str = "\r\nno key set\r\n"; + } else { + i = 0; // reset index + menu = MENU_AUTH; + str = "\r\nenter random string (up to 60 char): "; + } + break; case '\r': case '\n': break; // nothing to do @@ -372,6 +386,94 @@ void cdc_task(void) } } break; + case MENU_KEY: + echo = false; // keep secret + for (uint16_t j = 0; j < count; j++) { + if ('\r' == buf[j] || '\n' == buf[j]) { // end received + tmp[i] = 0; // end key + if (strlen(tmp)) { + memset(config.user_key, 0, sizeof(config.user_key)); + memcpy(config.user_key, tmp, i); + save_config(); + str = "\r\nauthentication key saved\r\n"; + } else { + str = "\r\ninvalid input\r\n"; + } + i = 0; // reset index + menu = MENU_HOME; // go to next menu + } else if (i >= sizeof(config.user_key) - 2) { + memset(tmp, 0, sizeof(tmp)); // clear password + str = "\r\nlimit reached\r\n"; + } else { + tmp[i++] = buf[j]; // save password + } + } + break; + case MENU_AUTH: + for (uint16_t j = 0; j < count; j++) { + if ('\r' == buf[j] || '\n' == buf[j]) { // end received + tmp[i] = 0; // end string + if (strlen(tmp)) { + if (strlen(config.user_key)) { + uint8_t hash_in[sizeof(config.user_key) + sizeof(tmp)]; + memcpy(&hash_in[0], config.user_key, strlen(config.user_key)); + memcpy(&hash_in[strlen(config.user_key)], tmp, strlen(tmp)); + SHA256_HASH hash_out; + Sha256Calculate(hash_in, strlen(config.user_key) + strlen(tmp), &hash_out); + char hash_str[SHA256_HASH_SIZE * 2 + 1]; + for (uint8_t k = 0; k < SHA256_HASH_SIZE; k++) { + uint8_t nibble = hash_out.bytes[k] >> 4; + if (nibble <= 9) { + hash_str[k * 2 + 0] = '0' + nibble; + } else { + hash_str[k * 2 + 0] = 'a' + nibble - 0xa; + } + nibble = hash_out.bytes[k] & 0xf; + if (nibble <= 9) { + hash_str[k * 2 + 1] = '0' + nibble; + } else { + hash_str[k * 2 + 1] = 'a' + nibble - 0xa; + } + } + hash_str[SHA256_HASH_SIZE * 2] = 0; // end string + echo = false; // we need to write now + tud_cdc_write_str("\r\necho -n \""); + tud_cdc_write_flush(); + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } + tud_cdc_write_str(tmp); + tud_cdc_write_flush(); + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } + tud_cdc_write_str("\" | sha256sum\r\n"); + tud_cdc_write_flush(); + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } + tud_cdc_write_str(hash_str); // luckily the USB packet len is the same as the string + tud_cdc_write_flush(); + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } + tud_cdc_write_str("\r\n"); + tud_cdc_write_flush(); + } + str = "\r\n"; + } else { + str = "\r\ninvalid input\r\n"; + } + i = 0; // reset index + menu = MENU_HOME; // go to next menu + } else if (i >= sizeof(config.user_key) - 2) { + memset(tmp, 0, sizeof(tmp)); // clear password + str = "\r\nlimit reached\r\n"; + } else { + tmp[i++] = buf[j]; // save password + } + } + break; case MENU_TIMEOUT_GLOBAL: for (uint16_t j = 0; j < count; j++) { if ('\r' == buf[j] || '\n' == buf[j]) { // end received