diff --git a/examples/device/hid_cdc_passkey/src/main.c b/examples/device/hid_cdc_passkey/src/main.c index 9037be99c..c0dce20b6 100644 --- a/examples/device/hid_cdc_passkey/src/main.c +++ b/examples/device/hid_cdc_passkey/src/main.c @@ -54,14 +54,16 @@ #define TIMEOUT_REPEAT (6U * 60) // maximum time after last repeat to hold the credentials, in minutes static struct config_t { - 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 + char manuf_key[32 + 1]; // the key set by the manufacturer to authenticate the device + char user_key[32 + 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 uint8_t crc; // simple XOR CRC to check config validity } config; +// TODO move manuf key to seperate page, in write protected space + // last available page of last sector to store config #define FLASH_CONFIG_ADDR ((uint32_t)0x08000000 + 0x400 * 27) @@ -187,6 +189,41 @@ end: HAL_FLASH_Lock(); } +// convert bytes to ASCII hex (does not add end zero) +static void b2h(const uint8_t* b, char* h, uint8_t len) +{ + if (!b || !h || !len) { + return; + } + for (uint8_t i = 0; i < len; i++) { + uint8_t nibble = b[i] >> 4; + if (nibble <= 9) { + h[i * 2 + 0] = '0' + nibble; + } else { + h[i * 2 + 0] = 'a' + nibble - 0xa; + } + nibble = b[i] & 0xf; + if (nibble <= 9) { + h[i * 2 + 1] = '0' + nibble; + } else { + h[i * 2 + 1] = 'a' + nibble - 0xa; + } + } +} + +// ensure string is sent +void tud_cdc_write_str_flush(const char* str) +{ + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } + tud_cdc_write_str(str); + tud_cdc_write_flush(); + while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { + tud_task(); + } +} + int main(void) { board_init(); @@ -319,7 +356,12 @@ void cdc_task(void) case 'k': // set user key i = 0; // reset index menu = MENU_KEY; - str = "\r\nenter authentication key (up to 16 char): "; + str = "\r\nenter authentication key (up to 32 char): "; + break; + case 'K': // set manufacturer key + i = 0; // reset index + menu = MENU_MANUF; + str = "\r\nenter manufacturer key (up to 32 char): "; break; case 'a': // run authentication if (0 == strlen(config.user_key) && 0 == strlen(config.manuf_key)) { @@ -339,11 +381,7 @@ void cdc_task(void) tud_cdc_write_flush(); echo = false; for (uint8_t j = 0; j < LENGTH(help_str); j++) { - while (tud_cdc_write_available() < CFG_TUD_CDC_TX_BUFSIZE) { - tud_task(); - } // wait until there is enough space for the complete string - tud_cdc_write_str(help_str[j]); - tud_cdc_write_flush(); + tud_cdc_write_str_flush(help_str[j]); } } break; @@ -386,6 +424,29 @@ void cdc_task(void) } } break; + case MENU_MANUF: + 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.manuf_key, 0, sizeof(config.manuf_key)); + memcpy(config.manuf_key, tmp, i); + save_config(); + str = "\r\nmanufacturer 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_KEY: echo = false; // keep secret for (uint16_t j = 0; j < count; j++) { @@ -414,6 +475,25 @@ void cdc_task(void) if ('\r' == buf[j] || '\n' == buf[j]) { // end received tmp[i] = 0; // end string if (strlen(tmp)) { + echo = false; // we need to write now + if (strlen(config.manuf_key)) { + char uid[4 * 3 * 2 + 1]; + b2h((uint8_t*)UID_BASE, uid, 4 * 3); + uid[sizeof(uid) - 1] = 0; // end string + tud_cdc_write_str_flush("\r\nenter into https://passkey.cuvoodoo.info/: "); + tud_cdc_write_str_flush(uid); + tud_cdc_write_str_flush(tmp); + tud_cdc_write_str_flush("\r\n"); + uint8_t hash_in[sizeof(config.manuf_key) + sizeof(tmp)]; + memcpy(&hash_in[0], config.manuf_key, strlen(config.manuf_key)); + memcpy(&hash_in[strlen(config.user_key)], tmp, strlen(tmp)); + SHA256_HASH hash_out; + Sha256Calculate(hash_in, strlen(config.manuf_key) + strlen(tmp), &hash_out); + char hash_str[SHA256_HASH_SIZE * 2 + 1]; + b2h(hash_out.bytes, hash_str, SHA256_HASH_SIZE); + hash_str[SHA256_HASH_SIZE * 2] = 0; // end string + tud_cdc_write_str_flush(hash_str); // luckily the USB packet len is the same as the string + } 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)); @@ -421,46 +501,14 @@ void cdc_task(void) 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; - } - } + b2h(hash_out.bytes, hash_str, SHA256_HASH_SIZE); 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(); + tud_cdc_write_str_flush("\r\necho -n \""); + tud_cdc_write_str_flush(tmp); + tud_cdc_write_str_flush("\" | sha256sum\r\n"); + tud_cdc_write_str_flush(hash_str); // luckily the USB packet len is the same as the string + tud_cdc_write_str_flush("\r\n"); } - str = "\r\n"; } else { str = "\r\ninvalid input\r\n"; }