From e5825df5cb44ff5854c5d38f3723ffc8c3de766c Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 20 Dec 2022 23:41:24 +0100 Subject: [PATCH] Added capability to add multiple interfaces: HID and CCID at compile time. Depending on compiling flags, HID and/or CCID may be enabled independently and run simultaneously. Signed-off-by: Pol Henarejos --- pico_hsm_sdk_import.cmake | 23 +- src/apdu.c | 28 ++- src/apdu.h | 2 +- src/hsm.h | 7 - src/hsm_version.h | 2 +- src/usb/ccid/ccid.c | 47 ++-- src/usb/ccid/ccid.h | 6 - src/usb/ccid/tusb_config.h | 119 ---------- src/usb/hid/hid.c | 90 ++++---- src/usb/hid/usb_descriptors.c | 205 ----------------- src/usb/{hid => }/tusb_config.h | 5 +- src/usb/usb.c | 324 ++++++++++++++++----------- src/usb/usb.h | 59 ++++- src/usb/{ccid => }/usb_descriptors.c | 159 +++++++++---- src/usb/{ccid => }/usb_descriptors.h | 0 15 files changed, 467 insertions(+), 609 deletions(-) delete mode 100644 src/usb/ccid/tusb_config.h delete mode 100644 src/usb/hid/usb_descriptors.c rename src/usb/{hid => }/tusb_config.h (95%) rename src/usb/{ccid => }/usb_descriptors.c (72%) rename src/usb/{ccid => }/usb_descriptors.h (100%) diff --git a/pico_hsm_sdk_import.cmake b/pico_hsm_sdk_import.cmake index 3833a67..482ea8b 100644 --- a/pico_hsm_sdk_import.cmake +++ b/pico_hsm_sdk_import.cmake @@ -26,9 +26,7 @@ add_definitions(-DUSB_PID=${USB_PID}) if (NOT DEFINED DEBUG_APDU) set(DEBUG_APDU 0) endif() -if (NOT DEFINED HSM_DRIVER) - set(HSM_DRIVER "ccid") -endif() + option(ENABLE_DELAYED_BOOT "Enable/disable delayed boot" OFF) if(ENABLE_DELAYED_BOOT) add_definitions(-DPICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) @@ -36,10 +34,18 @@ if(ENABLE_DELAYED_BOOT) else() message("Disabling delayed boot") endif(ENABLE_DELAYED_BOOT) +if(USB_ITF_HID) + add_definitions(-DUSB_ITF_HID=1) + message("Enabling USB HID interface") +endif(USB_ITF_HID) +if(USB_ITF_CCID) + add_definitions(-DUSB_ITF_CCID=1) + message("Enabling USB CCID interface") +endif(USB_ITF_CCID) add_definitions(-DDEBUG_APDU=${DEBUG_APDU}) + configure_file(${CMAKE_CURRENT_LIST_DIR}/config/mbedtls_config.h ${CMAKE_CURRENT_LIST_DIR}/mbedtls/include/mbedtls COPYONLY) -message(STATUS "HSM driver: ${HSM_DRIVER}") message(STATUS "USB VID/PID: ${USB_VID}:${USB_PID}") configure_file(${CMAKE_CURRENT_LIST_DIR}/config/mbedtls_config.h ${CMAKE_CURRENT_LIST_DIR}/mbedtls/include/mbedtls COPYONLY) @@ -50,6 +56,7 @@ if (NOT TARGET pico_hsm_sdk) target_sources(pico_hsm_sdk INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/main.c ${CMAKE_CURRENT_LIST_DIR}/src/usb/usb.c + ${CMAKE_CURRENT_LIST_DIR}/src/usb/usb_descriptors.c ${CMAKE_CURRENT_LIST_DIR}/src/fs/file.c ${CMAKE_CURRENT_LIST_DIR}/src/fs/flash.c ${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c @@ -89,19 +96,17 @@ if (NOT TARGET pico_hsm_sdk) ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/poly1305.c ) - if (${HSM_DRIVER} STREQUAL "ccid") + if (${USB_ITF_CCID}) target_sources(pico_hsm_sdk INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/usb_descriptors.c ${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/ccid.c ) - target_include_directories(pico_hsm_sdk INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid ) - elseif (${HSM_DRIVER} STREQUAL "hid") + endif() + if (${USB_ITF_HID}) target_sources(pico_hsm_sdk INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/hid.c - ${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/usb_descriptors.c ${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborencoder.c ${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborparser.c ${CMAKE_CURRENT_LIST_DIR}/tinycbor/src/cborparser_dup_string.c diff --git a/src/apdu.c b/src/apdu.c index d68608d..7e546cf 100644 --- a/src/apdu.c +++ b/src/apdu.c @@ -42,7 +42,7 @@ int process_apdu() { return set_res_sw(0x6D, 0x00); } -size_t apdu_process(const uint8_t *buffer, size_t buffer_size) { +size_t apdu_process(uint8_t itf, const uint8_t *buffer, size_t buffer_size) { apdu.header = (uint8_t *)buffer; apdu.nc = apdu.ne = 0; if (buffer_size == 4) { @@ -89,11 +89,18 @@ size_t apdu_process(const uint8_t *buffer, size_t buffer_size) { timeout_stop(); *(uint16_t *)rdata_gr = rdata_bk; if (apdu.rlen <= apdu.ne) { - driver_exec_finished_cont(apdu.rlen+2, rdata_gr-usb_get_tx()); +#ifdef USB_ITF_HID + if (itf == ITF_HID) + driver_exec_finished_cont_hid(apdu.rlen+2, rdata_gr-usb_get_tx(itf)); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + driver_exec_finished_cont_ccid(apdu.rlen+2, rdata_gr-usb_get_tx(itf)); +#endif //Prepare next RAPDU apdu.sw = 0; apdu.rlen = 0; - usb_prepare_response(); + usb_prepare_response(itf); } else { rdata_gr += apdu.ne; @@ -103,7 +110,18 @@ size_t apdu_process(const uint8_t *buffer, size_t buffer_size) { rdata_gr[1] = 0; else rdata_gr[1] = apdu.rlen - apdu.ne; - driver_exec_finished_cont(apdu.ne+2, rdata_gr-apdu.ne-usb_get_tx()); + if (card_locked_itf == ITF_TOTAL) + printf("CRITICAL ERROR: CARD LOCKED WITHOUT ITF\n"); + else { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + driver_exec_finished_cont_hid(apdu.ne+2, rdata_gr-apdu.ne-usb_get_tx(card_locked_itf)); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + driver_exec_finished_cont_ccid(apdu.ne+2, rdata_gr-apdu.ne-usb_get_tx(card_locked_itf)); +#endif + } apdu.rlen -= apdu.ne; } return 0; @@ -111,7 +129,7 @@ size_t apdu_process(const uint8_t *buffer, size_t buffer_size) { else { apdu.sw = 0; apdu.rlen = 0; - apdu.rdata = usb_prepare_response(); + apdu.rdata = usb_prepare_response(itf); rdata_gr = apdu.rdata; return 1; } diff --git a/src/apdu.h b/src/apdu.h index 551f40c..c2a0bee 100644 --- a/src/apdu.h +++ b/src/apdu.h @@ -91,7 +91,7 @@ extern struct apdu apdu; extern uint16_t set_res_sw (uint8_t sw1, uint8_t sw2); extern int process_apdu(); -extern size_t apdu_process(const uint8_t *buffer, size_t buffer_size); +extern size_t apdu_process(uint8_t, const uint8_t *buffer, size_t buffer_size); extern void apdu_finish(); extern size_t apdu_next(); extern void apdu_thread(); diff --git a/src/hsm.h b/src/hsm.h index 8c0e6b9..ab12d49 100644 --- a/src/hsm.h +++ b/src/hsm.h @@ -22,17 +22,10 @@ #include "pico/unique_id.h" #include - -extern int driver_init(); -extern void driver_task(); extern bool wait_button(); extern void low_flash_init_core1(); -extern int driver_write(const uint8_t *, size_t); -extern size_t driver_read(uint8_t *, size_t); -extern size_t usb_rx(const uint8_t *buffer, size_t len); - static inline const uint16_t make_uint16_t(uint8_t b1, uint8_t b2) { return (b1 << 8) | b2; } diff --git a/src/hsm_version.h b/src/hsm_version.h index 5e77971..b619ac4 100644 --- a/src/hsm_version.h +++ b/src/hsm_version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define HSM_SDK_VERSION 0x0304 +#define HSM_SDK_VERSION 0x0400 #define HSM_SDK_VERSION_MAJOR ((HSM_SDK_VERSION >> 8) & 0xff) #define HSM_SDK_VERSION_MINOR (HSM_SDK_VERSION & 0xff) diff --git a/src/usb/ccid/ccid.c b/src/usb/ccid/ccid.c index 450a090..78a7ccf 100644 --- a/src/usb/ccid/ccid.c +++ b/src/usb/ccid/ccid.c @@ -105,9 +105,9 @@ uint8_t ccid_status = 1; static uint8_t itf_num; void ccid_write_offset(uint16_t size, uint16_t offset) { - if (*usb_get_tx()+offset != 0x81) - DEBUG_PAYLOAD(usb_get_tx()+offset,size+10); - usb_write_offset(size+10, offset); + if (*usb_get_tx(ITF_CCID)+offset != 0x81) + DEBUG_PAYLOAD(usb_get_tx(ITF_CCID)+offset,size+10); + usb_write_offset(ITF_CCID, size+10, offset); } void ccid_write(uint16_t size) { @@ -117,14 +117,14 @@ void ccid_write(uint16_t size) { struct ccid_header *ccid_response; struct ccid_header *ccid_header; -int driver_init() { - ccid_header = (struct ccid_header *)usb_get_rx(); +int driver_init_ccid() { + ccid_header = (struct ccid_header *)usb_get_rx(ITF_CCID); apdu.header = &ccid_header->apdu; - ccid_response = (struct ccid_header *)usb_get_tx(); + ccid_response = (struct ccid_header *)usb_get_tx(ITF_CCID); apdu.rdata = &ccid_response->apdu; - usb_set_timeout_counter(1500); + usb_set_timeout_counter(ITF_CCID, 1500); return CCID_OK; } @@ -133,33 +133,34 @@ void tud_vendor_rx_cb(uint8_t itf) { (void) itf; uint32_t len = tud_vendor_available(); - usb_rx(NULL, len); + usb_rx(ITF_CCID, NULL, len); } void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) { printf("written %ld\n",sent_bytes); - usb_write_flush(); + usb_write_flush(ITF_CCID); } -int driver_write(const uint8_t *buffer, size_t buffer_size) { +int driver_write_ccid(const uint8_t *buffer, size_t buffer_size) { return tud_vendor_write(buffer, buffer_size); } -size_t driver_read(uint8_t *buffer, size_t buffer_size) { +size_t driver_read_ccid(uint8_t *buffer, size_t buffer_size) { return tud_vendor_read(buffer, buffer_size); } -int driver_process_usb_nopacket() { +int driver_process_usb_nopacket_ccid() { return 0; } -int driver_process_usb_packet(uint16_t rx_read) { +int driver_process_usb_packet_ccid(uint16_t rx_read) { if (rx_read >= 10) { + driver_init_ccid(); //printf("%d %d %x\r\n",tccid->dwLength,rx_read-10,tccid->bMessageType); if (ccid_header->dwLength <= rx_read-10) { size_t apdu_sent = 0; if (ccid_header->bMessageType != 0x65) - DEBUG_PAYLOAD(usb_get_rx(),usb_read_available()); + DEBUG_PAYLOAD(usb_get_rx(ITF_CCID),usb_read_available(ITF_CCID)); if (ccid_header->bMessageType == 0x65) { ccid_response->bMessageType = CCID_SLOT_STATUS_RET; ccid_response->dwLength = 0; @@ -196,9 +197,9 @@ int driver_process_usb_packet(uint16_t rx_read) { ccid_write(0); } else if (ccid_header->bMessageType == 0x6F) { - apdu_sent = apdu_process(&ccid_header->apdu, ccid_header->dwLength); + apdu_sent = apdu_process(ITF_CCID, &ccid_header->apdu, ccid_header->dwLength); } - usb_clear_rx(); + usb_clear_rx(ITF_CCID); return apdu_sent; } } @@ -215,11 +216,11 @@ int driver_process_usb_packet(uint16_t rx_read) { return 0; } -bool driver_mounted() { +bool driver_mounted_ccid() { return tud_vendor_mounted(); } -void driver_exec_timeout() { +void driver_exec_timeout_ccid() { ccid_response->bMessageType = CCID_DATA_BLOCK_RET; ccid_response->dwLength = 0; ccid_response->bSlot = 0; @@ -229,7 +230,7 @@ void driver_exec_timeout() { ccid_write(0); } -void driver_exec_finished(size_t size_next) { +void driver_exec_finished_ccid(size_t size_next) { ccid_response->bMessageType = CCID_DATA_BLOCK_RET; ccid_response->dwLength = size_next; ccid_response->bSlot = 0; @@ -239,9 +240,9 @@ void driver_exec_finished(size_t size_next) { ccid_write(size_next); } -void driver_exec_finished_cont(size_t size_next, size_t offset) { +void driver_exec_finished_cont_ccid(size_t size_next, size_t offset) { - ccid_response = (struct ccid_header *)(usb_get_tx()+offset-10); + ccid_response = (struct ccid_header *)(usb_get_tx(ITF_CCID)+offset-10); ccid_response->bMessageType = CCID_DATA_BLOCK_RET; ccid_response->dwLength = size_next; ccid_response->bSlot = 0; @@ -251,8 +252,8 @@ void driver_exec_finished_cont(size_t size_next, size_t offset) { ccid_write_offset(size_next, offset-10); } -uint8_t *driver_prepare_response() { - ccid_response = (struct ccid_header *)usb_get_tx(); +uint8_t *driver_prepare_response_ccid() { + ccid_response = (struct ccid_header *)usb_get_tx(ITF_CCID); return &ccid_response->apdu; } #define USB_CONFIG_ATT_ONE TU_BIT(7) diff --git a/src/usb/ccid/ccid.h b/src/usb/ccid/ccid.h index 136f81c..2a5e4d2 100644 --- a/src/usb/ccid/ccid.h +++ b/src/usb/ccid/ccid.h @@ -40,10 +40,4 @@ enum ccid_state { extern const uint8_t *ccid_atr; -extern uint8_t *usb_get_rx(); -extern uint8_t *usb_get_tx(); -extern uint32_t usb_write_offset(uint16_t len, uint16_t offset); -extern uint16_t usb_read_available(); -extern void usb_clear_rx(); -extern uint32_t usb_write_flush(); #endif //_CCID_H_ diff --git a/src/usb/ccid/tusb_config.h b/src/usb/ccid/tusb_config.h deleted file mode 100644 index 88d5868..0000000 --- a/src/usb/ccid/tusb_config.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -//-------------------------------------------------------------------- -// COMMON CONFIGURATION -//-------------------------------------------------------------------- - -// defined by board.mk -#ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined -#endif - -// RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 -#endif - -// RHPort max operational speed can defined by board.mk -// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed -#ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X) - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED - #else - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED - #endif -#endif - -// Device mode with rhport and speed defined by board.mk -#if BOARD_DEVICE_RHPORT_NUM == 0 - #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#elif BOARD_DEVICE_RHPORT_NUM == 1 - #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#else - #error "Incorrect RHPort configuration" -#endif - -#ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_PICO -#endif - -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 - -/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. - * Tinyusb use follows macros to declare transferring memory so that they can be put - * into those specific section. - * e.g - * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) - * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) - */ -#ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION -#endif - -#ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) -#endif - -//-------------------------------------------------------------------- -// DEVICE CONFIGURATION -//-------------------------------------------------------------------- - -#ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 -#endif - -//------------- CLASS -------------// -#define CFG_TUD_HID 0 -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 1 - -// HID buffer size Should be sufficient to hold ID (if any) + Data -#define CFG_TUD_HID_EP_BUFSIZE 16 - -#define CFG_TUD_VENDOR_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -#define CFG_TUD_VENDOR_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - -#include "pico/types.h" -static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); } -static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); } - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CONFIG_H_ */ - diff --git a/src/usb/hid/hid.c b/src/usb/hid/hid.c index eccf7ad..4193709 100644 --- a/src/usb/hid/hid.c +++ b/src/usb/hid/hid.c @@ -40,27 +40,25 @@ void tud_mount_cb() mounted = true; } -bool driver_mounted() { +bool driver_mounted_hid() { return mounted; } CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL; -int driver_init() { +int driver_init_hid() { tud_init(BOARD_TUD_RHPORT); - ctap_req = (CTAPHID_FRAME *)usb_get_rx(); + ctap_req = (CTAPHID_FRAME *)usb_get_rx(ITF_HID); apdu.header = ctap_req->init.data; - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); apdu.rdata = ctap_resp->init.data; - usb_set_timeout_counter(200); + usb_set_timeout_counter(ITF_HID, 200); return 0; } -void driver_task() { - tud_task(); // tinyusb device task -} + //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ @@ -83,9 +81,9 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t } uint32_t hid_write_offset(uint16_t size, uint16_t offset) { - if (*usb_get_tx() != 0x81) - DEBUG_PAYLOAD(usb_get_tx()+offset, size); - return usb_write_offset(size, offset); + if (*usb_get_tx(ITF_HID) != 0x81) + DEBUG_PAYLOAD(usb_get_tx(ITF_HID)+offset, size); + return usb_write_offset(ITF_HID, size, offset); } uint32_t hid_write(uint16_t size) { @@ -102,14 +100,14 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint1 ctap_resp->cid = ctap_req->cid; ctap_resp->cont.seq = seq; } - if (hid_write_offset(64, (uint8_t *)ctap_resp - (usb_get_tx())) > 0) { + if (hid_write_offset(64, (uint8_t *)ctap_resp - (usb_get_tx(ITF_HID))) > 0) { send_buffer_size -= MIN(64 - 5, send_buffer_size); ctap_resp = (CTAPHID_FRAME *)((uint8_t *)ctap_resp + 64 - 5); } } } -int driver_write(const uint8_t *buffer, size_t buffer_size) { +int driver_write_hid(const uint8_t *buffer, size_t buffer_size) { last_write_result = tud_hid_report(0, buffer, buffer_size); printf("result %d\n", last_write_result); if (last_write_result == false) @@ -117,31 +115,31 @@ int driver_write(const uint8_t *buffer, size_t buffer_size) { return MIN(64, buffer_size); } -size_t driver_read(uint8_t *buffer, size_t buffer_size) { +size_t driver_read_hid(uint8_t *buffer, size_t buffer_size) { return 0; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -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) -{ - // This example doesn't use multiple report and report ID - (void) itf; - (void) report_id; - (void) report_type; - usb_rx(buffer, bufsize); +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) { + // This example doesn't use multiple report and report ID + (void) itf; + (void) report_id; + (void) report_type; + + usb_rx(ITF_HID, buffer, bufsize); } uint32_t last_cmd_time = 0, last_packet_time = 0; int ctap_error(uint8_t error) { - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = CTAPHID_ERROR; ctap_resp->init.bcntl = 1; ctap_resp->init.data[0] = error; hid_write(64); - usb_clear_rx(); + usb_clear_rx(ITF_HID); last_packet_time = 0; return 0; } @@ -155,7 +153,7 @@ uint8_t thread_type = 0; //1 is APDU, 2 is CBOR extern void cbor_thread(); extern bool cancel_button; -int driver_process_usb_nopacket() { +int driver_process_usb_nopacket_hid() { if (last_packet_time > 0 && last_packet_time+500 < board_millis()) { ctap_error(CTAP1_ERR_MSG_TIMEOUT); last_packet_time = 0; @@ -164,12 +162,12 @@ int driver_process_usb_nopacket() { return 0; } -int driver_process_usb_packet(uint16_t read) { +int driver_process_usb_packet_hid(uint16_t read) { int apdu_sent = 0; - if (read >= 5) - { + if (read >= 5) { + driver_init_hid(); last_packet_time = board_millis(); - DEBUG_PAYLOAD(usb_get_rx(),64); + DEBUG_PAYLOAD(usb_get_rx(ITF_HID),64); memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); if (ctap_req->cid == 0x0 || (ctap_req->cid == CID_BROADCAST && ctap_req->init.cmd != CTAPHID_INIT)) return ctap_error(CTAP1_ERR_INVALID_CHANNEL); @@ -217,7 +215,7 @@ int driver_process_usb_packet(uint16_t read) { if (ctap_req->init.cmd == CTAPHID_INIT) { init_fido(false); - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); memset(ctap_resp, 0, 64); CTAPHID_INIT_REQ *req = (CTAPHID_INIT_REQ *)ctap_req->init.data; CTAPHID_INIT_RESP *resp = (CTAPHID_INIT_RESP *)ctap_resp->init.data; @@ -232,7 +230,7 @@ int driver_process_usb_packet(uint16_t read) { ctap_resp->init.cmd = CTAPHID_INIT; ctap_resp->init.bcntl = 17; ctap_resp->init.bcnth = 0; - driver_exec_finished(17); + driver_exec_finished_hid(17); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } @@ -240,7 +238,7 @@ int driver_process_usb_packet(uint16_t read) { if (MSG_LEN(ctap_req) != 0) { return ctap_error(CTAP1_ERR_INVALID_LEN); } - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); memcpy(ctap_resp, ctap_req, sizeof(CTAPHID_FRAME)); sleep_ms(1000); //For blinking the device during 1 seg hid_write(64); @@ -248,10 +246,10 @@ int driver_process_usb_packet(uint16_t read) { last_packet_time = 0; } else if ((last_cmd == CTAPHID_PING || last_cmd == CTAPHID_SYNC) && (msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) { - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) { memcpy(ctap_resp->init.data, msg_packet.data, msg_packet.len); - driver_exec_finished(msg_packet.len); + driver_exec_finished_hid(msg_packet.len); } else { memcpy(ctap_resp->init.data, ctap_req->init.data, MSG_LEN(ctap_req)); @@ -270,7 +268,7 @@ int driver_process_usb_packet(uint16_t read) { if (ctap_req->init.data[0] > 10) return ctap_error(CTAP1_ERR_INVALID_PARAMETER); lock = board_millis() + ctap_req->init.data[0] * 1000; - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); + ctap_resp = (CTAPHID_FRAME *)usb_get_tx(ITF_HID); memset(ctap_resp, 0, 64); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = ctap_req->init.cmd; @@ -286,9 +284,9 @@ int driver_process_usb_packet(uint16_t read) { thread_type = 1; if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) - apdu_sent = apdu_process(msg_packet.data, msg_packet.len); + apdu_sent = apdu_process(ITF_HID, msg_packet.data, msg_packet.len); else - apdu_sent = apdu_process(ctap_req->init.data, MSG_LEN(ctap_req)); + apdu_sent = apdu_process(ITF_HID, ctap_req->init.data, MSG_LEN(ctap_req)); DEBUG_PAYLOAD(apdu.data, (int)apdu.nc); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; @@ -320,13 +318,13 @@ int driver_process_usb_packet(uint16_t read) { // echo back anything we received from host //tud_hid_report(0, buffer, bufsize); //printf("END\n"); - usb_clear_rx(); + usb_clear_rx(ITF_HID); } return apdu_sent; } void send_keepalive() { - CTAPHID_FRAME *resp = (CTAPHID_FRAME *)(usb_get_tx() + 4096); + CTAPHID_FRAME *resp = (CTAPHID_FRAME *)(usb_get_tx(ITF_HID) + 4096); //memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); resp->cid = ctap_req->cid; resp->init.cmd = CTAPHID_KEEPALIVE; @@ -336,32 +334,32 @@ void send_keepalive() { hid_write_offset(64, 4096); } -void driver_exec_timeout() { +void driver_exec_timeout_hid() { if (thread_type == 2) send_keepalive(); } -uint8_t *driver_prepare_response() { - ctap_resp = (CTAPHID_FRAME *)usb_get_tx(); +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; - memset(usb_get_tx(), 0, 4096); + memset(usb_get_tx(ITF_HID), 0, 4096); return ctap_resp->init.data; } -void driver_exec_finished(size_t size_next) { +void driver_exec_finished_hid(size_t size_next) { if (size_next > 0) { if (thread_type == 2 && apdu.sw != 0) ctap_error(apdu.sw & 0xff); else - driver_exec_finished_cont(size_next, 7); + driver_exec_finished_cont_hid(size_next, 7); } apdu.sw = 0; } -void driver_exec_finished_cont(size_t size_next, size_t offset) { +void driver_exec_finished_cont_hid(size_t size_next, size_t offset) { offset -= 7; - ctap_resp = (CTAPHID_FRAME *)(usb_get_tx() + offset); + ctap_resp = (CTAPHID_FRAME *)(usb_get_tx(ITF_HID) + offset); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = last_cmd; ctap_resp->init.bcnth = size_next >> 8; diff --git a/src/usb/hid/usb_descriptors.c b/src/usb/hid/usb_descriptors.c deleted file mode 100644 index 843eb82..0000000 --- a/src/usb/hid/usb_descriptors.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "tusb.h" -#include "ctap_hid.h" -#include "pico/unique_id.h" -#include "hsm_version.h" - -#ifndef USB_VID -#define USB_VID 0xFEFF -#endif -#ifndef USB_PID -#define USB_PID 0xFCFD -#endif - -/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. - * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. - * - * Auto ProductID layout's Bitmap: - * [MSB] HID | MSC | CDC [LSB] - */ - - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = (USB_VID), - .idProduct = (USB_PID), - .bcdDevice = HSM_SDK_VERSION, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 -}; - -// Invoked when received GET DEVICE DESCRIPTOR -// Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; -} - -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ - -#define TUD_HID_REPORT_DESC_CTAP(report_size, ...) \ - HID_USAGE_PAGE_N ( FIDO_USAGE_PAGE, 2 ),\ - HID_USAGE ( FIDO_USAGE_CTAPHID ),\ - HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ - /* Report ID if any */\ - __VA_ARGS__ \ - /* Input */ \ - HID_USAGE ( FIDO_USAGE_DATA_IN ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - /* Output */ \ - HID_USAGE ( FIDO_USAGE_DATA_OUT ),\ - HID_LOGICAL_MIN ( 0x00 ),\ - HID_LOGICAL_MAX_N ( 0xff, 2 ),\ - HID_REPORT_SIZE ( 8 ),\ - HID_REPORT_COUNT( report_size ),\ - HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\ - HID_COLLECTION_END \ - -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_CTAP(CFG_TUD_HID_EP_BUFSIZE) -}; - -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) -{ - printf("report_cb %d\n", itf); - return desc_hid_report; -} - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ - -enum -{ - ITF_NUM_HID, - ITF_NUM_TOTAL -}; - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN) - -#define EPNUM_HID 0x01 - -uint8_t const desc_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - - // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) -}; - -// Invoked when received GET CONFIGURATION DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations - return desc_configuration; -} - -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - -// array of pointer to string descriptors -char const* string_desc_arr [] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "Pol Henarejos", // 1: Manufacturer - "Pico HSM HID", // 2: Product - "123456", // 3: Serials, should use chip ID -}; - -static uint16_t _desc_str[32]; - -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ - (void) langid; - - uint8_t chr_count; - - if (index == 0) { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - } - else { - // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) - return NULL; - - const char* str = string_desc_arr[index]; - char unique_id_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1]; - if (index == 3) { - pico_unique_board_id_t unique_id; - pico_get_unique_board_id(&unique_id); - pico_get_unique_board_id_string(unique_id_str, 2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1); - str = unique_id_str; - } - - chr_count = strlen(str); - if ( chr_count > 31 ) - chr_count = 31; - - // Convert ASCII string into UTF-16 - for(uint8_t i=0; i // Device specific functions -static uint8_t rx_buffer[4096], tx_buffer[4096+64]; -static uint16_t w_offset = 0, r_offset = 0; -static uint16_t w_len = 0, tx_r_offset = 0; -static uint32_t timeout_counter = 0; +static uint8_t rx_buffer[ITF_TOTAL][4096] = {0}, tx_buffer[ITF_TOTAL][4096+64] = {0}; +static uint16_t w_offset[ITF_TOTAL] = {0}, r_offset[ITF_TOTAL] = {0}; +static uint16_t w_len[ITF_TOTAL] = {0}, tx_r_offset[ITF_TOTAL] = {0}; +static uint32_t timeout_counter[ITF_TOTAL] = {0}; +uint8_t card_locked_itf = ITF_TOTAL; // no locked -void usb_set_timeout_counter(uint32_t v) { - timeout_counter = v; +void usb_set_timeout_counter(uint8_t itf, uint32_t v) { + timeout_counter[itf] = v; } -uint32_t usb_write_offset(uint16_t len, uint16_t offset) { +uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset) { uint8_t pkt_max = 64; int w = 0; - if (len > sizeof(tx_buffer)) - len = sizeof(tx_buffer); - w_len = len; - tx_r_offset = offset; - w = driver_write(tx_buffer+offset, MIN(len, pkt_max)); - w_len -= w; - tx_r_offset += w; + if (len > sizeof(tx_buffer[itf])) + len = sizeof(tx_buffer[itf]); + w_len[itf] = len; + tx_r_offset[itf] = offset; +#ifdef USB_ITF_HID + if (itf == ITF_HID) + w = driver_write_hid(tx_buffer[itf]+offset, MIN(len, pkt_max)); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + w = driver_write_ccid(tx_buffer[itf]+offset, MIN(len, pkt_max)); +#endif + w_len[itf] -= w; + tx_r_offset[itf] += w; return w; } -size_t usb_rx(const uint8_t *buffer, size_t len) { - uint16_t size = MIN(sizeof(rx_buffer) - w_offset, len); +size_t usb_rx(uint8_t itf, const uint8_t *buffer, size_t len) { + uint16_t size = MIN(sizeof(rx_buffer[itf]) - w_offset[itf], len); if (size > 0) { - if (buffer == NULL) - size = driver_read(rx_buffer + w_offset, size); + if (buffer == NULL) { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + size = driver_read_hid(rx_buffer[itf] + w_offset[itf], size); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + size = driver_read_ccid(rx_buffer[itf] + w_offset[itf], size); +#endif + } else - memcpy(rx_buffer + w_offset, buffer, size); - w_offset += size; + memcpy(rx_buffer + w_offset[itf], buffer, size); + w_offset[itf] += size; } return size; } -uint32_t usb_write_flush() { +uint32_t usb_write_flush(uint8_t itf) { int w = 0; - if (w_len > 0) { - w = driver_write(tx_buffer+tx_r_offset, MIN(w_len, 64)); - tx_r_offset += w; - w_len -= w; + if (w_len[itf] > 0) { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + w = driver_write_hid(tx_buffer[itf]+tx_r_offset[itf], MIN(w_len[itf], 64)); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + w = driver_write_ccid(tx_buffer[itf]+tx_r_offset[itf], MIN(w_len[itf], 64)); +#endif + tx_r_offset[itf] += w; + w_len[itf] -= w; } return w; } -uint32_t usb_write(uint16_t len) { - return usb_write_offset(len, 0); +uint32_t usb_write(uint8_t itf, uint16_t len) { + return usb_write_offset(itf, len, 0); } -uint16_t usb_read_available() { - return w_offset - r_offset; +uint16_t usb_read_available(uint8_t itf) { + return w_offset[itf] - r_offset[itf]; } -uint16_t usb_write_available() { - return w_len > 0; +uint16_t usb_write_available(uint8_t itf) { + return w_len[itf] > 0; } -uint8_t *usb_get_rx() { - return rx_buffer; +uint8_t *usb_get_rx(uint8_t itf) { + return rx_buffer[itf]; } -uint8_t *usb_get_tx() { - return tx_buffer; +uint8_t *usb_get_tx(uint8_t itf) { + return tx_buffer[itf]; } -void usb_clear_rx() { - w_offset = r_offset = 0; -} - -uint16_t usb_read(uint8_t *buffer, size_t buffer_size) { - uint16_t size = MIN(buffer_size, w_offset-r_offset); - if (size > 0) { - memcpy(buffer, rx_buffer+r_offset, size); - r_offset += size; - if (r_offset == w_offset) { - r_offset = w_offset = 0; - } - return size; - } - return 0; +void usb_clear_rx(uint8_t itf) { + w_offset[itf] = r_offset[itf] = 0; } #ifndef USB_VID @@ -133,21 +143,37 @@ queue_t card_to_usb_q; void usb_init() { queue_init(&card_to_usb_q, sizeof(uint32_t), 64); queue_init(&usb_to_card_q, sizeof(uint32_t), 64); - driver_init(); } extern int driver_process_usb_nopacket(); -static int usb_event_handle() { - uint16_t rx_read = usb_read_available(); - if (driver_process_usb_packet(rx_read) > 0) { +static int usb_event_handle(uint8_t itf) { + uint16_t rx_read = usb_read_available(itf); + int proc_packet = 0; +#ifdef USB_ITF_HID + if (itf == ITF_HID) + proc_packet = driver_process_usb_packet_hid(rx_read); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + proc_packet = driver_process_usb_packet_ccid(rx_read); +#endif + if (proc_packet > 0) { + card_locked_itf = itf; uint32_t flag = EV_CMD_AVAILABLE; queue_add_blocking(&usb_to_card_q, &flag); timeout_start(); } - else - driver_process_usb_nopacket(); - + else { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + driver_process_usb_nopacket_hid(); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + driver_process_usb_nopacket_ccid(); +#endif + } return 0; } @@ -177,83 +203,113 @@ void card_exit() { uint32_t flag = EV_EXIT; queue_try_add(&usb_to_card_q, &flag); led_set_blink(BLINK_SUSPENDED); + card_locked_itf = ITF_TOTAL; } void usb_task() { - if (driver_mounted()) { - if (usb_event_handle() != 0) { + bool mounted = false; + for (uint8_t itf = 0; itf < ITF_TOTAL; itf++) { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + mounted = driver_mounted_hid(); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + mounted = driver_mounted_ccid(); +#endif - } - usb_write_flush(); - uint32_t m = 0x0; - bool has_m = queue_try_remove(&card_to_usb_q, &m); - //if (m != 0) - // printf("\r\n ------ M = %lu\r\n",m); - if (has_m) { - if (m == EV_EXEC_FINISHED) { - timeout_stop(); - driver_exec_finished(finished_data_size); - led_set_blink(BLINK_MOUNTED); - } - else if (m == EV_PRESS_BUTTON) { - uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED; - queue_try_add(&usb_to_card_q, &flag); - } - /* - if (m == EV_RX_DATA_READY) { - c->ccid_state = ccid_handle_data(c); - timeout = 0; - c->timeout_cnt = 0; - } - else if (m == EV_EXEC_FINISHED) { - if (c->ccid_state == CCID_STATE_EXECUTE) { - exec_done: - if (c->a->sw == CCID_THREAD_TERMINATED) { - c->sw1sw2[0] = 0x90; - c->sw1sw2[1] = 0x00; - c->state = APDU_STATE_RESULT; - ccid_send_data_block(c); - c->ccid_state = CCID_STATE_EXITED; - c->application = 0; - return; - } + if (mounted == true) { + if (usb_event_handle(itf) != 0) { - c->a->cmd_apdu_data_len = 0; - c->sw1sw2[0] = c->a->sw >> 8; - c->sw1sw2[1] = c->a->sw & 0xff; - if (c->a->res_apdu_data_len <= c->a->expected_res_size) { - c->state = APDU_STATE_RESULT; - ccid_send_data_block(c); - c->ccid_state = CCID_STATE_WAIT; - } - else { - c->state = APDU_STATE_RESULT_GET_RESPONSE; - c->p = c->a->res_apdu_data; - c->len = c->a->res_apdu_data_len; - ccid_send_data_block_gr(c, c->a->expected_res_size); - c->ccid_state = CCID_STATE_WAIT; - } - } - else { - DEBUG_INFO ("ERR05\r\n"); - } - led_set_blink(BLINK_MOUNTED); } - else if (m == EV_TX_FINISHED){ - if (c->state == APDU_STATE_RESULT) - ccid_reset(c); - else - c->tx_busy = 0; - if (c->state == APDU_STATE_WAIT_COMMAND || c->state == APDU_STATE_COMMAND_CHAINING || c->state == APDU_STATE_RESULT_GET_RESPONSE) - ccid_prepare_receive(c); - } - */ - } - else { - if (timeout > 0) { - if (timeout + timeout_counter < board_millis()) { - driver_exec_timeout(); - timeout = board_millis(); + usb_write_flush(itf); + if (card_locked_itf == itf) { + uint32_t m = 0x0; + bool has_m = queue_try_remove(&card_to_usb_q, &m); + //if (m != 0) + // printf("\r\n ------ M = %lu\r\n",m); + if (has_m) { + if (m == EV_EXEC_FINISHED) { + timeout_stop(); +#ifdef USB_ITF_HID + if (itf == ITF_HID) + driver_exec_finished_hid(finished_data_size); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + driver_exec_finished_ccid(finished_data_size); +#endif + led_set_blink(BLINK_MOUNTED); + card_locked_itf = ITF_TOTAL; + } + else if (m == EV_PRESS_BUTTON) { + uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED; + queue_try_add(&usb_to_card_q, &flag); + } + /* + if (m == EV_RX_DATA_READY) { + c->ccid_state = ccid_handle_data(c); + timeout = 0; + c->timeout_cnt = 0; + } + else if (m == EV_EXEC_FINISHED) { + if (c->ccid_state == CCID_STATE_EXECUTE) { + exec_done: + if (c->a->sw == CCID_THREAD_TERMINATED) { + c->sw1sw2[0] = 0x90; + c->sw1sw2[1] = 0x00; + c->state = APDU_STATE_RESULT; + ccid_send_data_block(c); + c->ccid_state = CCID_STATE_EXITED; + c->application = 0; + return; + } + + c->a->cmd_apdu_data_len = 0; + c->sw1sw2[0] = c->a->sw >> 8; + c->sw1sw2[1] = c->a->sw & 0xff; + if (c->a->res_apdu_data_len <= c->a->expected_res_size) { + c->state = APDU_STATE_RESULT; + ccid_send_data_block(c); + c->ccid_state = CCID_STATE_WAIT; + } + else { + c->state = APDU_STATE_RESULT_GET_RESPONSE; + c->p = c->a->res_apdu_data; + c->len = c->a->res_apdu_data_len; + ccid_send_data_block_gr(c, c->a->expected_res_size); + c->ccid_state = CCID_STATE_WAIT; + } + } + else { + DEBUG_INFO ("ERR05\r\n"); + } + led_set_blink(BLINK_MOUNTED); + } + else if (m == EV_TX_FINISHED){ + if (c->state == APDU_STATE_RESULT) + ccid_reset(c); + else + c->tx_busy = 0; + if (c->state == APDU_STATE_WAIT_COMMAND || c->state == APDU_STATE_COMMAND_CHAINING || c->state == APDU_STATE_RESULT_GET_RESPONSE) + ccid_prepare_receive(c); + } + */ + } + else { + if (timeout > 0) { + if (timeout + timeout_counter[itf] < board_millis()) { + #ifdef USB_ITF_HID + if (itf == ITF_HID) + driver_exec_timeout_hid(); + #endif + #ifdef USB_ITF_CCID + if (itf == ITF_CCID) + driver_exec_timeout_ccid(); + #endif + timeout = board_millis(); + } + } } } } @@ -268,6 +324,14 @@ void timeout_start() { timeout = board_millis(); } -uint8_t *usb_prepare_response() { - return driver_prepare_response(); +uint8_t *usb_prepare_response(uint8_t itf) { +#ifdef USB_ITF_HID + if (itf == ITF_HID) + return driver_prepare_response_hid(); +#endif +#ifdef USB_ITF_CCID + if (itf == ITF_CCID) + return driver_prepare_response_ccid(); +#endif + return NULL; } \ No newline at end of file diff --git a/src/usb/usb.h b/src/usb/usb.h index 238b7b7..eacbb0b 100644 --- a/src/usb/usb.h +++ b/src/usb/usb.h @@ -36,28 +36,63 @@ #define EV_BUTTON_TIMEOUT 16 #define EV_BUTTON_PRESSED 32 + +enum { +#ifdef USB_ITF_HID + ITF_HID, +#endif +#ifdef USB_ITF_CCID + ITF_CCID, +#endif + ITF_TOTAL +}; + + extern void usb_task(); extern queue_t usb_to_card_q; extern queue_t card_to_usb_q; -extern int driver_process_usb_packet(uint16_t rx_read); -extern void driver_exec_finished(size_t size_next); -extern void driver_exec_finished_cont(size_t size_next, size_t offset); -extern void driver_exec_timeout(); -extern bool driver_mounted(); -extern uint8_t *driver_prepare_response(); +extern uint8_t card_locked_itf; + +#ifdef USB_ITF_HID +extern int driver_process_usb_packet_hid(uint16_t rx_read); +extern void driver_exec_finished_hid(size_t size_next); +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 size_t driver_read_hid(uint8_t *, size_t); +extern int driver_process_usb_nopacket_hid(); +#endif + +#ifdef USB_ITF_CCID +extern int driver_process_usb_packet_ccid(uint16_t rx_read); +extern void driver_exec_finished_ccid(size_t size_next); +extern void driver_exec_finished_cont_ccid(size_t size_next, size_t offset); +extern void driver_exec_timeout_ccid(); +extern bool driver_mounted_ccid(); +extern uint8_t *driver_prepare_response_ccid(); +extern int driver_write_ccid(const uint8_t *, size_t); +extern size_t driver_read_ccid(uint8_t *, size_t); +extern int driver_process_usb_nopacket_ccid(); +#endif + +extern size_t usb_rx(uint8_t itf, const uint8_t *buffer, size_t len); extern void card_start(void (*func)(void)); extern void card_exit(); extern void usb_init(); -extern uint8_t *usb_prepare_response(); +extern uint8_t *usb_prepare_response(uint8_t itf); extern void timeout_stop(); extern void timeout_start(); -extern uint8_t *usb_get_rx(); -extern uint8_t *usb_get_tx(); -extern uint32_t usb_write_offset(uint16_t len, uint16_t offset); -extern void usb_clear_rx(); +extern uint8_t *usb_get_rx(uint8_t itf); +extern uint8_t *usb_get_tx(uint8_t itf); +extern uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset); +extern void usb_clear_rx(uint8_t itf); extern size_t finished_data_size; -extern void usb_set_timeout_counter(uint32_t v); +extern void usb_set_timeout_counter(uint8_t itf, uint32_t v); extern void card_init_core1(); +extern uint32_t usb_write_flush(uint8_t itf); +extern uint16_t usb_read_available(uint8_t itf); #endif diff --git a/src/usb/ccid/usb_descriptors.c b/src/usb/usb_descriptors.c similarity index 72% rename from src/usb/ccid/usb_descriptors.c rename to src/usb/usb_descriptors.c index 220bdd3..9a59305 100644 --- a/src/usb/ccid/usb_descriptors.c +++ b/src/usb/usb_descriptors.c @@ -19,6 +19,7 @@ #include "usb_descriptors.h" #include "pico/unique_id.h" #include "hsm_version.h" +#include "usb.h" #ifndef USB_VID #define USB_VID 0xFEFF @@ -33,32 +34,6 @@ #define MAX_USB_POWER 1 -static const struct ccid_class_descriptor desc_ccid = { - .bLength = sizeof(struct ccid_class_descriptor), - .bDescriptorType = 0x21, - .bcdCCID = (0x0110), - .bMaxSlotIndex = 0, - .bVoltageSupport = 0x01, // 5.0V - .dwProtocols = ( - 0x01| // T=0 - 0x02), // T=1 - .dwDefaultClock = (0xDFC), - .dwMaximumClock = (0xDFC), - .bNumClockSupport = 0, - .dwDataRate = (0x2580), - .dwMaxDataRate = (0x2580), - .bNumDataRatesSupported = 0, - .dwMaxIFSD = (0xFE), // IFSD is handled by the real reader driver - .dwSynchProtocols = (0), - .dwMechanical = (0), - .dwFeatures = 0x40840, //USB-ICC, short & extended APDU - .dwMaxCCIDMessageLength = 65544+10, - .bClassGetResponse = 0xFF, - .bclassEnvelope = 0xFF, - .wLcdLayout = 0x0, - .bPINSupport = 0x0, - .bMaxCCIDBusySlots = 0x01, -}; //--------------------------------------------------------------------+ // Device Descriptors @@ -90,18 +65,6 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } -tusb_desc_interface_t const desc_interface = -{ - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = TUSB_CLASS_SMART_CARD, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 5, -}; //--------------------------------------------------------------------+ // Configuration Descriptor @@ -111,14 +74,55 @@ tusb_desc_configuration_t const desc_config = { .bLength = sizeof(tusb_desc_configuration_t), .bDescriptorType = TUSB_DESC_CONFIGURATION, - .wTotalLength = (sizeof(tusb_desc_configuration_t) + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)), - .bNumInterfaces = 1, + .wTotalLength = (sizeof(tusb_desc_configuration_t) + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)) + TUD_HID_INOUT_DESC_LEN, + .bNumInterfaces = ITF_TOTAL, .bConfigurationValue = 1, .iConfiguration = 4, .bmAttributes = USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(MAX_USB_POWER+1), }; +#ifdef USB_ITF_CCID +static const struct ccid_class_descriptor desc_ccid = { + .bLength = sizeof(struct ccid_class_descriptor), + .bDescriptorType = 0x21, + .bcdCCID = (0x0110), + .bMaxSlotIndex = 0, + .bVoltageSupport = 0x01, // 5.0V + .dwProtocols = ( + 0x01| // T=0 + 0x02), // T=1 + .dwDefaultClock = (0xDFC), + .dwMaximumClock = (0xDFC), + .bNumClockSupport = 0, + .dwDataRate = (0x2580), + .dwMaxDataRate = (0x2580), + .bNumDataRatesSupported = 0, + .dwMaxIFSD = (0xFE), // IFSD is handled by the real reader driver + .dwSynchProtocols = (0), + .dwMechanical = (0), + .dwFeatures = 0x40840, //USB-ICC, short & extended APDU + .dwMaxCCIDMessageLength = 65544+10, + .bClassGetResponse = 0xFF, + .bclassEnvelope = 0xFF, + .wLcdLayout = 0x0, + .bPINSupport = 0x0, + .bMaxCCIDBusySlots = 0x01, +}; + +tusb_desc_interface_t const desc_interface = +{ + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + .bInterfaceNumber = ITF_CCID, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = TUSB_CLASS_SMART_CARD, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = ITF_CCID+5, +}; + tusb_desc_endpoint_t const desc_ep1 = { .bLength = sizeof(tusb_desc_endpoint_t), @@ -138,8 +142,65 @@ tusb_desc_endpoint_t const desc_ep2 = .wMaxPacketSize.size = (64), .bInterval = 0 }; +#endif -static uint8_t desc_config_extended[sizeof(tusb_desc_configuration_t) + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)]; +static uint8_t desc_config_extended[sizeof(tusb_desc_configuration_t) +#ifdef USB_ITF_CCID ++ sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t) +#endif +#ifdef USB_ITF_HID ++ TUD_HID_INOUT_DESC_LEN +#endif +]; + +#ifdef USB_ITF_HID +#define HID_USAGE_PAGE_FIDO 0xF1D0 +enum +{ + HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection + HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report + HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report +}; + +#define TUD_HID_REPORT_DESC_FIDO_U2F(report_size, ...) \ + HID_USAGE_PAGE_N ( HID_USAGE_PAGE_FIDO, 2 ) ,\ + HID_USAGE ( HID_USAGE_FIDO_U2FHID ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + /* Report ID if any */ \ + __VA_ARGS__ \ + /* Usage Data In */ \ + HID_USAGE ( HID_USAGE_FIDO_DATA_IN ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_REPORT_COUNT ( report_size ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* Usage Data Out */ \ + HID_USAGE ( HID_USAGE_FIDO_DATA_OUT ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX_N ( 0xff, 2 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_REPORT_COUNT ( report_size ) ,\ + HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + HID_COLLECTION_END \ + +uint8_t const desc_hid_report[] = +{ + TUD_HID_REPORT_DESC_FIDO_U2F(CFG_TUD_HID_EP_BUFSIZE) +}; +#define EPNUM_HID 0x03 + +static uint8_t desc_hid[] = { + // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval + TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID+5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) +}; + +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) +{ + printf("report_cb %d\n", itf); + return desc_hid_report; +} +#endif uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { @@ -150,10 +211,15 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { uint8_t *p = desc_config_extended; memcpy(p, &desc_config, sizeof(tusb_desc_configuration_t)); p += sizeof(tusb_desc_configuration_t); +#ifdef USB_ITF_HID + memcpy(p, &desc_hid, sizeof(desc_hid)); p += sizeof(desc_hid); +#endif +#ifdef USB_ITF_CCID memcpy(p, &desc_interface, sizeof(tusb_desc_interface_t)); p += sizeof(tusb_desc_interface_t); memcpy(p, &desc_ccid, sizeof(struct ccid_class_descriptor)); p += sizeof(struct ccid_class_descriptor); memcpy(p, &desc_ep1, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); memcpy(p, &desc_ep2, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); +#endif initd = 1; } return (const uint8_t *)desc_config_extended; @@ -183,10 +249,15 @@ char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "Pol Henarejos", // 1: Manufacturer - "Pico HSM CCID", // 2: Product + "Pico Key", // 2: Product "11223344", // 3: Serials, should use chip ID - "Pico HSM Config", // 4: Vendor Interface - "Pico HSM Interface" + "Pico Key Config" // 4: Vendor Interface +#ifdef USB_ITF_HID + ,"Pico Key HID Interface" +#endif +#ifdef USB_ITF_CCID + ,"Pico Key CCID Interface" +#endif }; static uint16_t _desc_str[32]; diff --git a/src/usb/ccid/usb_descriptors.h b/src/usb/usb_descriptors.h similarity index 100% rename from src/usb/ccid/usb_descriptors.h rename to src/usb/usb_descriptors.h