diff --git a/src/hsm.h b/src/hsm.h index 33d1eae..d1e0490 100644 --- a/src/hsm.h +++ b/src/hsm.h @@ -57,6 +57,8 @@ extern int flash_clear_file(file_t *file); extern void timeout_stop(); extern void timeout_start(); +extern int (*button_pressed_cb)(uint8_t); + enum { BLINK_NOT_MOUNTED = (250 << 16) | 250, BLINK_MOUNTED = (250 << 16) | 250, diff --git a/src/main.c b/src/main.c index 648b497..6858150 100644 --- a/src/main.c +++ b/src/main.c @@ -119,6 +119,8 @@ int register_app(app_t *(*select_aid)(app_t *, const uint8_t *, uint8_t)) { return 0; } +int (*button_pressed_cb)(uint8_t) = NULL; + static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; void led_set_blink(uint32_t mode) { @@ -153,6 +155,9 @@ uint32_t board_millis() { } #else +bool button_pressed_state = false; +uint32_t button_pressed_time = 0; +uint8_t button_press = 0; bool wait_button() { uint32_t start_button = board_millis(); bool timeout = false; @@ -304,6 +309,24 @@ int main(void) { execute_tasks(); neug_task(); do_flash(); + if (board_millis() > 1000) { // wait 1 second to boot up + bool current_button_state = board_button_read(); + if (current_button_state != button_pressed_state) { + if (current_button_state == false) { // unpressed + if (button_pressed_time == 0 || button_pressed_time + 1000 > board_millis()) { + button_press++; + } + button_pressed_time = board_millis(); + } + button_pressed_state = current_button_state; + } + if (button_pressed_time > 0 && button_press > 0 && button_pressed_time + 1000 < board_millis() && button_pressed_state == false) { + if (button_pressed_cb != NULL) { + (*button_pressed_cb)(button_press); + } + button_pressed_time = button_press = 0; + } + } } return 0; diff --git a/src/usb/emulation/emulation.c b/src/usb/emulation/emulation.c index 41637bf..6b01383 100644 --- a/src/usb/emulation/emulation.c +++ b/src/usb/emulation/emulation.c @@ -160,7 +160,7 @@ extern void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, const uint8_t *complete_report = NULL; uint16_t complete_len = 0; extern bool last_write_result; -extern uint16_t send_buffer_size; +extern uint16_t send_buffer_size[ITF_TOTAL]; int driver_write_emul(uint8_t itf, const uint8_t *buffer, size_t buffer_size) { uint16_t size = htons(buffer_size); int sock = get_sock_itf(itf); diff --git a/src/usb/hid/hid.c b/src/usb/hid/hid.c index d5cfaba..eaff1b3 100644 --- a/src/usb/hid/hid.c +++ b/src/usb/hid/hid.c @@ -62,6 +62,43 @@ int driver_init_hid() { return 0; } +uint16_t send_buffer_size[ITF_TOTAL] = {0}; +bool last_write_result[ITF_TOTAL] = {false}; + +uint8_t otp_frame_rx[70] = {0}; +uint8_t otp_frame_tx[70] = {0}; +uint8_t otp_exp_seq = 0, otp_curr_seq = 0; +uint8_t otp_header[4] = {0}; + +uint16_t calculate_crc(const uint8_t *data, size_t data_len) { + uint16_t crc = 0xFFFF; + for (size_t idx = 0; idx < data_len; idx++) { + crc ^= data[idx]; + for (uint8_t i = 0; i < 8; i++) { + uint16_t j = crc & 0x1; + crc >>= 1; + if (j == 1) { + crc ^= 0x8408; + } + } + } + return crc & 0xFFFF; +} + +int otp_send_frame(uint8_t *frame, size_t frame_len) { + uint16_t crc = calculate_crc(frame, frame_len); + frame[frame_len] = ~crc & 0xff; + frame[frame_len + 1] = ~crc >> 8; + frame_len += 2; + send_buffer_size[ITF_KEYBOARD] = frame_len; + otp_exp_seq = (frame_len / 7); + if (frame_len % 7) { + otp_exp_seq++; + } + otp_curr_seq = 0; + return 0; +} + //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ @@ -70,6 +107,7 @@ int driver_init_hid() { // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request +extern uint16_t otp_status(); uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, @@ -81,10 +119,26 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, (void) report_type; (void) buffer; (void) reqlen; - printf("get_report %d %d %d\n", itf, report_id, report_type); - DEBUG_PAYLOAD(buffer, reqlen); - buffer[1] = HSM_SDK_VERSION_MAJOR; - buffer[2] = HSM_SDK_VERSION_MINOR; + //printf("get_report %d %d %d\n", itf, report_id, report_type); + //DEBUG_PAYLOAD(buffer, reqlen); + if (send_buffer_size[ITF_KEYBOARD] > 0) { + uint8_t seq = otp_curr_seq++; + memset(buffer, 0, 8); + memcpy(buffer, otp_frame_tx + 7 * seq, MIN(7, send_buffer_size[ITF_KEYBOARD])); + buffer[7] = 0x40 | seq; + DEBUG_DATA(buffer, 8); + send_buffer_size[ITF_KEYBOARD] -= MIN(7, send_buffer_size[ITF_KEYBOARD]); + } + else if (otp_curr_seq == otp_exp_seq && otp_exp_seq > 0) { + memset(buffer, 0, 7); + buffer[7] = 0x40; + DEBUG_DATA(buffer,8); + otp_curr_seq = otp_exp_seq = 0; + } + else { + otp_status(); + memcpy(buffer, res_APDU, 7); + } return reqlen; } @@ -101,9 +155,6 @@ uint32_t hid_write(uint16_t size) { return hid_write_offset(size, 0); } -uint16_t send_buffer_size = 0; -bool last_write_result = false; - #ifndef ENABLE_EMULATION static uint8_t keyboard_buffer[256]; static uint8_t keyboard_buffer_len = 0; @@ -177,24 +228,24 @@ void hid_task(void) { #endif void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { - if (send_buffer_size > 0 && instance == ITF_HID) { + if (send_buffer_size[instance] > 0 && instance == ITF_HID) { uint8_t seq = report[4] & TYPE_MASK ? 0 : report[4] + 1; - if (last_write_result == true) { + if (last_write_result[instance] == true) { ctap_resp->cid = ctap_req->cid; ctap_resp->cont.seq = seq; } if (hid_write_offset(64, (uint8_t *) ctap_resp - (usb_get_tx(ITF_HID))) > 0) { - send_buffer_size -= MIN(64 - 5, send_buffer_size); + send_buffer_size[instance] -= MIN(64 - 5, send_buffer_size[instance]); ctap_resp = (CTAPHID_FRAME *) ((uint8_t *) ctap_resp + 64 - 5); } } } #ifndef ENABLE_EMULATION -int driver_write_hid(const uint8_t *buffer, size_t buffer_size) { - last_write_result = tud_hid_n_report(ITF_HID, 0, buffer, buffer_size); - printf("result %d\n", last_write_result); - if (last_write_result == false) { +int driver_write_hid(uint8_t itf, const uint8_t *buffer, size_t buffer_size) { + last_write_result[itf] = tud_hid_n_report(itf, 0, buffer, buffer_size); + printf("result %d\n", last_write_result[itf]); + if (last_write_result[itf] == false) { return 0; } return MIN(64, buffer_size); @@ -208,20 +259,57 @@ size_t driver_read_hid(uint8_t *buffer, size_t buffer_size) { #ifndef ENABLE_EMULATION // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) + +extern int otp_process_apdu(); void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, - uint16_t bufsize) { + uint16_t bufsize) +{ // This example doesn't use multiple report and report ID (void) itf; (void) report_id; (void) report_type; - printf("set_report %d %d %d\n", itf, report_id, report_type); - if (itf == ITF_KEYBOARD) { - DEBUG_PAYLOAD(buffer, bufsize); + //printf("set_report %d %d %d\n", itf, report_id, report_type); + if (itf == ITF_KEYBOARD && report_type == 3) { + //DEBUG_PAYLOAD(buffer, bufsize); + if (buffer[7] == 0xFF) { // reset + send_buffer_size[ITF_KEYBOARD] = 0; + otp_curr_seq = otp_exp_seq = 0; + memset(otp_frame_tx, 0, sizeof(otp_frame_tx)); + } + else if (buffer[7] & 0x80) { // a frame + uint8_t rseq = buffer[7] & 0x1F; + if (rseq < 10) { + if (rseq == 0) { + memset(otp_frame_rx, 0, sizeof(otp_frame_rx)); + } + memcpy(otp_frame_rx + rseq * 7, buffer, 7); + if (rseq == 9) { + DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx)); + uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = (otp_frame_rx[66] << 8 | otp_frame_rx[65]); + uint8_t slot_id = otp_frame_rx[64]; + if (residual_crc == rcrc) { + apdu.data = otp_frame_rx; + apdu.nc = 64; + apdu.rdata = otp_frame_tx; + apdu.header[1] = 0x01; + apdu.header[2] = slot_id; + int ret = otp_process_apdu(); + if (ret == 0x9000 && res_APDU_size > 0) { + otp_send_frame(apdu.rdata, apdu.rlen); + } + } + else { + printf("[OTP] Bad CRC!\n"); + } + } + } + } } - usb_rx(itf, buffer, bufsize); + else + usb_rx(itf, buffer, bufsize); } #endif @@ -467,7 +555,7 @@ void send_keepalive() { resp->init.cmd = CTAPHID_KEEPALIVE; resp->init.bcntl = 1; resp->init.data[0] = is_req_button_pending() ? 2 : 1; - send_buffer_size = 0; + send_buffer_size[ITF_HID] = 0; hid_write_offset(64, 4096); } @@ -480,7 +568,7 @@ void driver_exec_timeout_hid() { uint8_t *driver_prepare_response_hid() { ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); apdu.rdata = ctap_resp->init.data; - send_buffer_size = 0; + send_buffer_size[ITF_HID] = 0; memset(usb_get_tx(ITF_HID), 0, 4096); return ctap_resp->init.data; } @@ -504,10 +592,9 @@ void driver_exec_finished_cont_hid(size_t size_next, size_t offset) { ctap_resp->init.cmd = last_cmd; ctap_resp->init.bcnth = size_next >> 8; ctap_resp->init.bcntl = size_next & 0xff; - send_buffer_size = size_next; + send_buffer_size[ITF_HID] = size_next; if (hid_write_offset(64, offset) > 0) { ctap_resp = (CTAPHID_FRAME *) ((uint8_t *) ctap_resp + 64 - 5); - - send_buffer_size -= MIN(64 - 7, send_buffer_size); + send_buffer_size[ITF_HID] -= MIN(64 - 7, send_buffer_size[ITF_HID]); } } diff --git a/src/usb/usb.c b/src/usb/usb.c index 22465da..4c123e1 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -55,8 +55,8 @@ uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset) { tx_r_offset[itf] = offset; #ifndef ENABLE_EMULATION #ifdef USB_ITF_HID - if (itf == ITF_HID) { - w = driver_write_hid(tx_buffer[itf] + offset, MIN(len, pkt_max)); + if (itf == ITF_HID || itf == ITF_KEYBOARD) { + w = driver_write_hid(itf, tx_buffer[itf] + offset, MIN(len, pkt_max)); } #endif #ifdef USB_ITF_CCID @@ -100,8 +100,8 @@ uint32_t usb_write_flush(uint8_t itf) { if (w_len[itf] > 0) { #ifndef ENABLE_EMULATION #ifdef USB_ITF_HID - if (itf == ITF_HID) { - w = driver_write_hid(tx_buffer[itf] + tx_r_offset[itf], MIN(w_len[itf], 64)); + if (itf == ITF_HID || itf == ITF_KEYBOARD) { + w = driver_write_hid(itf, tx_buffer[itf] + tx_r_offset[itf], MIN(w_len[itf], 64)); } #endif #ifdef USB_ITF_CCID diff --git a/src/usb/usb.h b/src/usb/usb.h index fe19dea..ee5db74 100644 --- a/src/usb/usb.h +++ b/src/usb/usb.h @@ -71,7 +71,7 @@ extern void driver_exec_finished_cont_hid(size_t size_next, size_t offset); extern void driver_exec_timeout_hid(); extern bool driver_mounted_hid(); extern uint8_t *driver_prepare_response_hid(); -extern int driver_write_hid(const uint8_t *, size_t); +extern int driver_write_hid(uint8_t, const uint8_t *, size_t); extern size_t driver_read_hid(uint8_t *, size_t); extern int driver_process_usb_nopacket_hid(); #endif