diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index c5830efd2..abc1ba375 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -3,3 +3,9 @@ # Formatting commit 59a948f2838ec0ced714c81c8e268d6016b84057 + +# Temporary formatting commit revert +e6391739c0b6e24df9465eccfb17d86fa9a42a68 + +# Reapply formatting +8c5ba3b82a6523759f3f7a59cb5ea2d2f3a5e12a diff --git a/.github/workflows/build_all_apps.yml b/.github/workflows/build_all_apps.yml index 5217afb98..2faef6792 100644 --- a/.github/workflows/build_all_apps.yml +++ b/.github/workflows/build_all_apps.yml @@ -33,7 +33,6 @@ env: \"app-edgeware\" : \"./app\" , \"app-filecoin\" : \"app\" , \"app-firmachain\" : \"./app\" , - \"app-flow\" : \"app\" , \"app-genshiro\" : \"./app\" , \"app-iov\" : \"app\" , \"app-internetcomputer\" : \"./app\" , diff --git a/Makefile.defines b/Makefile.defines index 01e560663..7e6611bde 100644 --- a/Makefile.defines +++ b/Makefile.defines @@ -179,6 +179,7 @@ DEFINES += HAVE_BAGL_FONT_INTER_REGULAR_24PX DEFINES += HAVE_BAGL_FONT_INTER_SEMIBOLD_24PX DEFINES += HAVE_BAGL_FONT_INTER_REGULAR_32PX DEFINES += HAVE_BAGL_FONT_HMALPHAMONO_MEDIUM_32PX +DEFINES += HAVE_INAPP_BLE_PAIRING DEFINES += HAVE_NBGL DEFINES += HAVE_PIEZO_SOUND DEFINES += HAVE_SE_TOUCH @@ -211,6 +212,7 @@ DEFINES += HAVE_MCU_SERIAL_STORAGE DEFINES += HAVE_FONTS # already defined within apps # DEFINES += HAVE_BLE +DEFINES += HAVE_INAPP_BLE_PAIRING DEFINES += HAVE_BATTERY endif diff --git a/include/ledger_protocol.h b/include/ledger_protocol.h index f564252d4..8656c8e77 100644 --- a/include/ledger_protocol.h +++ b/include/ledger_protocol.h @@ -30,7 +30,8 @@ enum { /* Exported types, structures, unions ----------------------------------------*/ typedef struct ledger_protocol_s { - uint8_t *tx_apdu_buffer; + const uint8_t *tx_apdu_buffer; + uint16_t tx_apdu_length; uint16_t tx_apdu_sequence_number; uint16_t tx_apdu_offset; @@ -45,6 +46,8 @@ typedef struct ledger_protocol_s { uint16_t rx_apdu_length; uint16_t rx_apdu_offset; + uint8_t *rx_dst_buffer; + uint16_t mtu; uint8_t mtu_negotiated; } ledger_protocol_t; @@ -57,5 +60,5 @@ typedef struct ledger_protocol_s { /* Exported functions prototypes--------------------------------------------- */ void LEDGER_PROTOCOL_init(ledger_protocol_t *data); -void LEDGER_PROTOCOL_rx(uint8_t *buffer, uint16_t length); -void LEDGER_PROTOCOL_tx(uint8_t *buffer, uint16_t length); +void LEDGER_PROTOCOL_rx(const uint8_t *buffer, uint16_t length); +void LEDGER_PROTOCOL_tx(const uint8_t *buffer, uint16_t length); diff --git a/include/os_apilevel.h b/include/os_apilevel.h index fce683e0e..7fccf5e0a 100644 --- a/include/os_apilevel.h +++ b/include/os_apilevel.h @@ -19,7 +19,15 @@ #ifndef OS_APILEVEL_H #define OS_APILEVEL_H +#ifndef HAVE_BOLOS +// Obsolete defines - shall not be used +// Replaced by API_LEVEL mechanism enforced directly at app sideloading. +// Hence the app can consider it runs on a OS which match the SDK the app has been built for. +#define CX_APILEVEL _Pragma("GCC warning \"Deprecated constant!\"") 12 +#define CX_COMPAT_APILEVEL _Pragma("GCC warning \"Deprecated constant!\"") 12 +#else #define CX_APILEVEL 12 #define CX_COMPAT_APILEVEL 12 +#endif #endif // OS_APILEVEL_H diff --git a/include/os_id.h b/include/os_id.h index 0121eec4a..389d35ab4 100644 --- a/include/os_id.h +++ b/include/os_id.h @@ -45,7 +45,10 @@ unsigned int os_get_sn(unsigned char *buffer); SYSCALL unsigned int get_api_level(void); #ifndef HAVE_BOLOS -static inline void check_api_level(unsigned int apiLevel) +// Obsolete function - shall not be used +// Replaced by API_LEVEL mechanism enforced directly at app sideloading. +// Hence the app can consider it runs on a OS which match the SDK the app has been built for. +DEPRECATED static inline void check_api_level(unsigned int apiLevel) { if (apiLevel < get_api_level()) { os_sched_exit(-1); diff --git a/include/os_io.h b/include/os_io.h index 864f18b8e..22db95aad 100644 --- a/include/os_io.h +++ b/include/os_io.h @@ -19,6 +19,12 @@ #else #define IO_APDU_BUFFER_SIZE IMPL_IO_APDU_BUFFER_SIZE #endif + +typedef struct apdu_buffer_s { + uint8_t *buf; + uint16_t len; +} apdu_buffer_t; + extern unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; // send tx_len bytes (atr or rapdu) and retrieve the length of the next command apdu (over the diff --git a/include/os_io_usb.h b/include/os_io_usb.h index 441f19cba..d9b6d99c2 100644 --- a/include/os_io_usb.h +++ b/include/os_io_usb.h @@ -20,6 +20,7 @@ #define OS_IO_USB_H #include "os_io_seproxyhal.h" +#include "os_io.h" #ifdef HAVE_USB_APDU @@ -46,7 +47,8 @@ void io_usb_hid_init(void); */ io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, unsigned char *buffer, - unsigned short l); + unsigned short l, + apdu_buffer_t *apdu_buffer); /** * Mark the last chunk transmitted as sent. @@ -57,7 +59,7 @@ void io_usb_hid_sent(io_send_t sndfct); /** * Request transmission of an APDU from the G_io_apdu_buffer using the HID transport protocol */ -void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength); +void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char *apdu_buffer); #endif // HAVE_USB_APDU diff --git a/lib_blewbxx_impl/include/ledger_ble.h b/lib_blewbxx_impl/include/ledger_ble.h index 4183a7a65..8b42e89cd 100644 --- a/lib_blewbxx_impl/include/ledger_ble.h +++ b/lib_blewbxx_impl/include/ledger_ble.h @@ -35,8 +35,9 @@ /* Exported functions prototypes--------------------------------------------- */ void LEDGER_BLE_init(void); -void LEDGER_BLE_send(uint8_t *packet, uint16_t packet_length); -void LEDGER_BLE_receive(void); +void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length); +void LEDGER_BLE_receive(const uint8_t *spi_buffer); +void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length); void LEDGER_BLE_enable_advertising(uint8_t enable); void LEDGER_BLE_reset_pairings(void); diff --git a/lib_blewbxx_impl/src/ledger_ble.c b/lib_blewbxx_impl/src/ledger_ble.c index 7605f0a62..1a9180500 100644 --- a/lib_blewbxx_impl/src/ledger_ble.c +++ b/lib_blewbxx_impl/src/ledger_ble.c @@ -159,17 +159,19 @@ typedef struct { /* Private functions prototypes ----------------------------------------------*/ static void get_device_name(void); static void configure_advertising_mngr(uint16_t opcode); -static void init_mngr(uint16_t opcode, uint8_t *buffer, uint16_t length); -static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length); -static void hci_evt_le_meta_evt(uint8_t *buffer, uint16_t length); -static void hci_evt_vendor(uint8_t *buffer, uint16_t length); +static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length); +static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length); +static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length); +static void hci_evt_vendor(const uint8_t *buffer, uint16_t length); +#ifdef HAVE_INAPP_BLE_PAIRING static void end_pairing_ux(uint8_t pairing_ok); static void ask_user_pairing_numeric_comparison(uint32_t code); static void rsp_user_pairing_numeric_comparison(unsigned int status); static void ask_user_pairing_passkey(void); static void rsp_user_pairing_passkey(unsigned int status); -static void attribute_modified(uint8_t *buffer, uint16_t length); -static void write_permit_request(uint8_t *buffer, uint16_t length); +#endif // HAVE_INAPP_BLE_PAIRING +static void attribute_modified(const uint8_t *buffer, uint16_t length); +static void write_permit_request(const uint8_t *buffer, uint16_t length); static void advertising_enable(uint8_t enable); static void start_advertising(void); static void notify_chunk(void); @@ -198,6 +200,22 @@ static ledger_protocol_t ledger_protocol_data; static ledger_ble_data_t ledger_ble_data; /* Private functions ---------------------------------------------------------*/ +static void copy_apdu_to_app(bool update_wait_status) +{ + // `rx_apdu_length` is already checked to be less than + // `rx_apdu_buffer_max_length` in `process_apdu_chunk()` + memcpy(ledger_protocol_data.rx_dst_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + G_io_app.apdu_state = APDU_BLE; + G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + ledger_protocol_data.rx_apdu_length = 0; + if (update_wait_status) { + ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; + } +} + static void get_device_name(void) { memset(ledger_ble_data.device_name, 0, sizeof(ledger_ble_data.device_name)); @@ -291,7 +309,7 @@ static void configure_advertising_mngr(uint16_t opcode) } } -static void init_mngr(uint16_t opcode, uint8_t *buffer, uint16_t length) +static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length) { UNUSED(length); @@ -462,7 +480,7 @@ static void init_mngr(uint16_t opcode, uint8_t *buffer, uint16_t length) } } -static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) +static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length) { if (length < 3) { return; @@ -492,12 +510,7 @@ static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) if (ledger_ble_data.transfer_mode_enable) { if ((ledger_protocol_data.rx_apdu_length) && (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE)) { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - ledger_protocol_data.rx_apdu_length = 0; + copy_apdu_to_app(false); } } else { @@ -521,7 +534,6 @@ static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) } } } - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; } else if ((opcode == 0xfc81) || (opcode == 0xfc83)) { LOG_BLE("HCI_LE_SET_ADVERTISE_ENABLE %04X %d %d\n", @@ -531,7 +543,9 @@ static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) if (ledger_ble_data.connection.connection_handle != 0xFFFF) { if (G_io_app.disabling_advertising) { // Connected & ordered to disable ble, force disconnection +#ifdef HAVE_INAPP_BLE_PAIRING end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); +#endif // HAVE_INAPP_BLE_PAIRING LEDGER_BLE_init(); } } @@ -564,7 +578,7 @@ static void hci_evt_cmd_complete(uint8_t *buffer, uint16_t length) } } -static void hci_evt_le_meta_evt(uint8_t *buffer, uint16_t length) +static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length) { if (!length) { return; @@ -636,7 +650,7 @@ static void hci_evt_le_meta_evt(uint8_t *buffer, uint16_t length) } } -static void hci_evt_vendor(uint8_t *buffer, uint16_t length) +static void hci_evt_vendor(const uint8_t *buffer, uint16_t length) { if (length < 4) { return; @@ -649,6 +663,7 @@ static void hci_evt_vendor(uint8_t *buffer, uint16_t length) } switch (opcode) { +#ifdef HAVE_INAPP_BLE_PAIRING case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE: LOG_BLE("PAIRING"); switch (buffer[4]) { @@ -688,6 +703,7 @@ static void hci_evt_vendor(uint8_t *buffer, uint16_t length) LOG_BLE("NUMERIC COMP : %d\n", U4LE(buffer, 4)); ask_user_pairing_numeric_comparison(U4LE(buffer, 4)); break; +#endif // HAVE_INAPP_BLE_PAIRING case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE: attribute_modified(&buffer[4], length - 4); @@ -718,7 +734,9 @@ static void hci_evt_vendor(uint8_t *buffer, uint16_t length) case ACI_GATT_PROC_TIMEOUT_VSEVT_CODE: LOG_BLE("PROCEDURE TIMEOUT\n"); +#ifdef HAVE_INAPP_BLE_PAIRING end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); +#endif // HAVE_INAPP_BLE_PAIRING LEDGER_BLE_init(); break; @@ -728,6 +746,7 @@ static void hci_evt_vendor(uint8_t *buffer, uint16_t length) } } +#ifdef HAVE_INAPP_BLE_PAIRING static void end_pairing_ux(uint8_t pairing_ok) { bolos_ux_params_t ux_params; @@ -802,8 +821,9 @@ static void rsp_user_pairing_passkey(unsigned int status) aci_gap_pass_key_resp(ledger_ble_data.connection.connection_handle, ledger_ble_data.pairing_code); } +#endif // HAVE_INAPP_BLE_PAIRING -static void attribute_modified(uint8_t *buffer, uint16_t length) +static void attribute_modified(const uint8_t *buffer, uint16_t length) { if (length < 6) { return; @@ -832,8 +852,6 @@ static void attribute_modified(uint8_t *buffer, uint16_t length) && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted) && (att_data_length)) { LOG_BLE("WRITE CMD %d\n", length - 4); - buffer[4] = 0xDE; - buffer[5] = 0xF1; LEDGER_PROTOCOL_rx(&buffer[4], length - 4); if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { @@ -843,14 +861,7 @@ static void attribute_modified(uint8_t *buffer, uint16_t length) LOG_BLE("Transfer failed 0x%04x\n", U2BE(ledger_ble_data.resp, 0)); G_io_app.transfer_mode = 0; check_transfer_mode(G_io_app.transfer_mode); - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + copy_apdu_to_app(true); } else if (ledger_ble_data.resp_length) { LEDGER_PROTOCOL_tx(ledger_ble_data.resp, ledger_ble_data.resp_length); @@ -859,14 +870,7 @@ static void attribute_modified(uint8_t *buffer, uint16_t length) } } else { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - G_io_app.apdu_state = APDU_BLE; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; + copy_apdu_to_app(true); } } else if (ledger_protocol_data.tx_chunk_length >= 2) { @@ -880,7 +884,7 @@ static void attribute_modified(uint8_t *buffer, uint16_t length) } } -static void write_permit_request(uint8_t *buffer, uint16_t length) +static void write_permit_request(const uint8_t *buffer, uint16_t length) { if (length < 3) { return; @@ -894,8 +898,6 @@ static void write_permit_request(uint8_t *buffer, uint16_t length) if ((att_handle == ledger_ble_data.ledger_gatt_write_characteristic_handle + 1) && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted) && (data_length)) { - buffer[1] = 0xDE; - buffer[2] = 0xF1; LEDGER_PROTOCOL_rx(&buffer[1], length - 1); aci_gatt_write_resp(ledger_ble_data.connection.connection_handle, att_handle, @@ -904,14 +906,7 @@ static void write_permit_request(uint8_t *buffer, uint16_t length) data_length, &buffer[3]); if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { - memcpy(G_io_apdu_buffer, - ledger_protocol_data.rx_apdu_buffer, - ledger_protocol_data.rx_apdu_length); - G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; - ledger_protocol_data.rx_apdu_length = 0; - ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; - G_io_app.apdu_media = IO_APDU_MEDIA_BLE; // for application code - G_io_app.apdu_state = APDU_BLE; // for next call to io_exchange + copy_apdu_to_app(true); } } else { @@ -1014,12 +1009,24 @@ void LEDGER_BLE_init(void) memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data)); ledger_protocol_data.rx_apdu_buffer = ledger_ble_data.apdu_buffer; ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(ledger_ble_data.apdu_buffer); +#ifdef HAVE_LOCAL_APDU_BUFFER + ledger_protocol_data.rx_dst_buffer = NULL; +#else + ledger_protocol_data.rx_dst_buffer = G_io_apdu_buffer; +#endif LEDGER_PROTOCOL_init(&ledger_protocol_data); init_mngr(0, NULL, 0); } -void LEDGER_BLE_send(uint8_t *packet, uint16_t packet_length) +void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length) +{ + ledger_protocol_data.rx_dst_buffer = buffer; + ledger_protocol_data.rx_apdu_buffer_max_length + = MIN(buffer_length, sizeof(ledger_ble_data.apdu_buffer)); +} + +void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length) { if ((ledger_ble_data.transfer_mode_enable != 0) && (packet_length == 2)) { G_io_app.apdu_state = APDU_IDLE; @@ -1046,17 +1053,21 @@ void LEDGER_BLE_send(uint8_t *packet, uint16_t packet_length) } } -void LEDGER_BLE_receive(void) +void LEDGER_BLE_receive(const uint8_t *spi_buffer) { - if (G_io_seproxyhal_spi_buffer[3] == HCI_EVENT_PKT_TYPE) { - switch (G_io_seproxyhal_spi_buffer[4]) { + if (spi_buffer[3] == HCI_EVENT_PKT_TYPE) { + switch (spi_buffer[4]) { case HCI_DISCONNECTION_COMPLETE_EVT_CODE: - LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", G_io_seproxyhal_spi_buffer[9]); + LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", spi_buffer[9]); ledger_ble_data.connection.connection_handle = 0xFFFF; ledger_ble_data.advertising_enabled = 0; ledger_ble_data.connection.encrypted = 0; + ledger_ble_data.transfer_mode_enable = 0; + G_io_app.transfer_mode = 0; +#ifdef HAVE_INAPP_BLE_PAIRING end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED); - if (G_io_seproxyhal_spi_buffer[9] != 0x28) { // Error code : Instant Passed +#endif // HAVE_INAPP_BLE_PAIRING + if (spi_buffer[9] != 0x28) { // Error code : Instant Passed start_advertising(); } else { @@ -1067,9 +1078,8 @@ void LEDGER_BLE_receive(void) break; case HCI_ENCRYPTION_CHANGE_EVT_CODE: - if (U2LE(G_io_seproxyhal_spi_buffer, 7) - == ledger_ble_data.connection.connection_handle) { - if (G_io_seproxyhal_spi_buffer[9]) { + if (U2LE(spi_buffer, 7) == ledger_ble_data.connection.connection_handle) { + if (spi_buffer[9]) { LOG_BLE("Link encrypted\n"); ledger_ble_data.connection.encrypted = 1; } @@ -1080,13 +1090,13 @@ void LEDGER_BLE_receive(void) } else { LOG_BLE("HCI ENCRYPTION CHANGE EVT %d on connection handle \n", - G_io_seproxyhal_spi_buffer[9], - U2LE(G_io_seproxyhal_spi_buffer, 7)); + spi_buffer[9], + U2LE(spi_buffer, 7)); } break; case HCI_COMMAND_COMPLETE_EVT_CODE: - hci_evt_cmd_complete(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + hci_evt_cmd_complete(&spi_buffer[6], spi_buffer[5]); break; case HCI_COMMAND_STATUS_EVT_CODE: @@ -1098,11 +1108,11 @@ void LEDGER_BLE_receive(void) break; case HCI_LE_META_EVT_CODE: - hci_evt_le_meta_evt(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + hci_evt_le_meta_evt(&spi_buffer[6], spi_buffer[5]); break; case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE: - hci_evt_vendor(&G_io_seproxyhal_spi_buffer[6], G_io_seproxyhal_spi_buffer[5]); + hci_evt_vendor(&spi_buffer[6], spi_buffer[5]); break; default: @@ -1150,14 +1160,14 @@ int hci_send_req(struct hci_request *p_cmd, uint8_t async) uint16_t opcode = ((p_cmd->ocf) & 0x03ff) | ((p_cmd->ogf) << 10); - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_BLE_SEND; - G_io_seproxyhal_spi_buffer[1] = (p_cmd->clen + 2) >> 8; - G_io_seproxyhal_spi_buffer[2] = (p_cmd->clen + 2); - G_io_seproxyhal_spi_buffer[3] = opcode >> 8; - G_io_seproxyhal_spi_buffer[4] = opcode; - memmove(G_io_seproxyhal_spi_buffer + 5, p_cmd->cparam, p_cmd->clen); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3 + p_cmd->clen + 2); - + uint8_t tag_buffer[5]; + tag_buffer[0] = SEPROXYHAL_TAG_BLE_SEND; + tag_buffer[1] = (p_cmd->clen + 2) >> 8; + tag_buffer[2] = (p_cmd->clen + 2); + tag_buffer[3] = opcode >> 8; + tag_buffer[4] = opcode; + io_seproxyhal_spi_send(tag_buffer, 5); + io_seproxyhal_spi_send(p_cmd->cparam, p_cmd->clen); return 0; } diff --git a/lib_cxng/include/lcx_ecdsa.h b/lib_cxng/include/lcx_ecdsa.h index cd934a5aa..ae3007d36 100644 --- a/lib_cxng/include/lcx_ecdsa.h +++ b/lib_cxng/include/lcx_ecdsa.h @@ -112,39 +112,61 @@ DEPRECATED static inline size_t cx_ecdsa_sign(const cx_ecfp_private_key_t *pvkey } /** - * @brief Verifies an ECDSA signature according to ECDSA specification. + * @brief Sign a message digest according to ECDSA specification * - * @param[in] pukey Public key initialized with #cx_ecfp_init_public_key_no_throw. + * @param[in] pvkey Private key. + * Shall be initialized with #cx_ecfp_init_private_key_no_throw. * - * @param[in] hash Digest of the message to be verified. - * The length of *hash* must be smaller than the group order size. - * Otherwise it is truncated. + * @param[in] mode Crypto mode flags. + * Supported flags: + * - CX_RND_TRNG + * - CX_RND_RFC6979 * - * @param[in] hash_len Length of the digest in octets. + * @param[in] hashID Message digest algorithm identifier. + * This parameter is mandatory with the flag CX_RND_RFC6979. * - * @param[in] sig Pointer to the signature encoded in TLV: **30 || L || 02 || Lr || r || 02 || - * Ls || s** + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the curve domain size. * - * @param[in] sig_len Length of the signature in octets. + * @param[in] hash_len Length of the digest in octets. * - * @return 1 if the signature is verified, 0 otherwise. + * @param[in] rs_len Length of r and s buffer. 32 for usual curves. + * + * @param[out] sig_r Buffer where to store the signature r value. + * + * @param[out] sig_s Buffer where to store the signature s value. + * + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing + * **[k].G**. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INVALID_PARAMETER + * - CX_INTERNAL_ERROR + * - CX_NOT_UNLOCKED + * - CX_INVALID_PARAMETER_SIZE + * - CX_MEMORY_FULL + * - CX_NOT_LOCKED + * - CX_EC_INVALID_POINT + * - CX_EC_INFINITE_POINT + * - CX_INVALID_PARAMETER_VALUE */ -bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, - const uint8_t *hash, - size_t hash_len, - const uint8_t *sig, - size_t sig_len); +cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + size_t rs_len, + uint8_t *sig_r, + uint8_t *sig_s, + uint32_t *info); /** * @brief Verifies an ECDSA signature according to ECDSA specification. * * @param[in] pukey Public key initialized with #cx_ecfp_init_public_key_no_throw. * - * @param[in] mode ECDSA mode. This parameter is not used. - * - * @param[in] hashID Message digest algorithm identifier. - * This parameter is not used. - * * @param[in] hash Digest of the message to be verified. * The length of *hash* must be smaller than the group order size. * Otherwise it is truncated. @@ -158,13 +180,23 @@ bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, * * @return 1 if the signature is verified, 0 otherwise. */ -static inline bool cx_ecdsa_verify(const cx_ecfp_public_key_t *pukey, - int mode, - cx_md_t hashID, - const unsigned char *hash, - unsigned int hash_len, - const unsigned char *sig, - unsigned int sig_len) +bool cx_ecdsa_verify_no_throw(const cx_ecfp_public_key_t *pukey, + const uint8_t *hash, + size_t hash_len, + const uint8_t *sig, + size_t sig_len); + +/** + * @deprecated + * See #cx_ecdsa_verify_no_throw + */ +DEPRECATED static inline bool cx_ecdsa_verify(const cx_ecfp_public_key_t *pukey, + int mode, + cx_md_t hashID, + const unsigned char *hash, + unsigned int hash_len, + const unsigned char *sig, + unsigned int sig_len) { UNUSED(mode); UNUSED(hashID); diff --git a/lib_standard_app/crypto_helpers.c b/lib_standard_app/crypto_helpers.c index fb6054951..75405f299 100644 --- a/lib_standard_app/crypto_helpers.c +++ b/lib_standard_app/crypto_helpers.c @@ -136,6 +136,37 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256(unsigned return error; } +WARN_UNUSED_RESULT cx_err_t +bip32_derive_with_seed_ecdsa_sign_rs_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t sig_r[static 32], + uint8_t sig_s[static 32], + uint32_t *info, + unsigned char *seed, + size_t seed_len) +{ + cx_err_t error = CX_OK; + cx_ecfp_256_private_key_t privkey; + + // Derive private key according to BIP32 path + CX_CHECK(bip32_derive_with_seed_init_privkey_256( + derivation_mode, curve, path, path_len, &privkey, NULL, seed, seed_len)); + + CX_CHECK(cx_ecdsa_sign_rs_no_throw( + &privkey, sign_mode, hashID, hash, hash_len, 32, sig_r, sig_s, info)); + +end: + explicit_bzero(&privkey, sizeof(privkey)); + + return error; +} + WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256(unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, diff --git a/lib_standard_app/crypto_helpers.h b/lib_standard_app/crypto_helpers.h index beeafc940..cec943336 100644 --- a/lib_standard_app/crypto_helpers.h +++ b/lib_standard_app/crypto_helpers.h @@ -246,6 +246,113 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256(cx_cu 0); } +/** + * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path and + * seed key. + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig_r Buffer where to store the signature r value. + * + * @param[out] sig_s Buffer where to store the signature s value. + * + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when + * computing **[k].G**. + * + * @param[in] seed Seed key to use for derivation. + * + * @param[in] seed_len Seed key length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT cx_err_t +bip32_derive_with_seed_ecdsa_sign_rs_hash_256(unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t sig_r[static 32], + uint8_t sig_s[static 32], + uint32_t *info, + unsigned char *seed, + size_t seed_len); + +/** + * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig_r Buffer where to store the signature r value. + * + * @param[out] sig_s Buffer where to store the signature s value. + * + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when + * computing **[k].G**. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_rs_hash_256( + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t sig_r[static 32], + uint8_t sig_s[static 32], + uint32_t *info) +{ + return bip32_derive_with_seed_ecdsa_sign_rs_hash_256(HDW_NORMAL, + curve, + path, + path_len, + sign_mode, + hashID, + hash, + hash_len, + sig_r, + sig_s, + info, + NULL, + 0); +} + /** * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path and * seed key. diff --git a/lib_standard_app/io.c b/lib_standard_app/io.c index b403be6fe..90b8f4105 100644 --- a/lib_standard_app/io.c +++ b/lib_standard_app/io.c @@ -153,25 +153,28 @@ WEAK int io_recv_command() return ret; } -WEAK int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw) -{ - return io_send_response_buffer(&(const buffer_t){.ptr = ptr, .size = size, .offset = 0}, sw); -} - -WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) +WEAK int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw) { int ret = -1; - if (rdata != NULL) { - if (rdata->size - rdata->offset > IO_APDU_BUFFER_SIZE - 2 || // - !buffer_copy(rdata, G_io_apdu_buffer, sizeof(G_io_apdu_buffer))) { - return io_send_sw(SW_WRONG_RESPONSE_LENGTH); + G_output_len = 0; + if (rdatalist && count > 0) { + for (size_t i = 0; i < count; i++) { + const buffer_t *rdata = &rdatalist[i]; + + if (!buffer_copy(rdata, + G_io_apdu_buffer + G_output_len, + sizeof(G_io_apdu_buffer) - G_output_len - 2)) { + return io_send_sw(SW_WRONG_RESPONSE_LENGTH); + } + G_output_len += rdata->size - rdata->offset; + if (count > 1) { + PRINTF("<= FRAG (%u/%u) RData=%.*H\n", i + 1, count, rdata->size, rdata->ptr); + } } - G_output_len = rdata->size - rdata->offset; - PRINTF("<= SW=%04X | RData=%.*H\n", sw, rdata->size, rdata->ptr); + PRINTF("<= SW=%04X | RData=%.*H\n", sw, G_output_len, G_io_apdu_buffer); } else { - G_output_len = 0; PRINTF("<= SW=%04X | RData=\n", sw); } @@ -209,8 +212,3 @@ WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) return ret; } - -WEAK int io_send_sw(uint16_t sw) -{ - return io_send_response_buffer(NULL, sw); -} diff --git a/lib_standard_app/io.h b/lib_standard_app/io.h index 19248a241..f3abff3e8 100644 --- a/lib_standard_app/io.h +++ b/lib_standard_app/io.h @@ -56,6 +56,22 @@ WEAK void io_init(void); */ WEAK int io_recv_command(void); +/** + * Send APDU response (response data + status word) by filling + * G_io_apdu_buffer. + * + * @param[in] rdatalist + * List of Buffers with APDU response data. + * @param[in] count + * Count of the buffers providded in rdatalist. + * @param[in] sw + * Status word of APDU response. + * + * @return zero or positive integer if success, -1 otherwise. + * + */ +WEAK int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw); + /** * Send APDU response (response data + status word) by filling * G_io_apdu_buffer. @@ -70,7 +86,11 @@ WEAK int io_recv_command(void); * @return zero or positive integer if success, -1 otherwise. * */ -WEAK int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw); +static inline int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw) +{ + return io_send_response_buffers( + &(const buffer_t){.ptr = ptr, .size = size, .offset = 0}, 1, sw); +} /** * Send APDU response (response data + status word) by filling @@ -84,7 +104,10 @@ WEAK int io_send_response_pointer(const uint8_t *ptr, size_t size, uint16_t sw); * @return zero or positive integer if success, -1 otherwise. * */ -WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw); +static inline int io_send_response_buffer(const buffer_t *rdata, uint16_t sw) +{ + return io_send_response_buffers(rdata, 1, sw); +} /** * Send APDU response (only status word) by filling @@ -96,4 +119,7 @@ WEAK int io_send_response_buffer(const buffer_t *rdata, uint16_t sw); * @return zero or positive integer if success, -1 otherwise. * */ -WEAK int io_send_sw(uint16_t sw); +static inline int io_send_sw(uint16_t sw) +{ + return io_send_response_buffers(NULL, 0, sw); +} diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_core.h b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_core.h index bcf2dc206..5fb81ffa6 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_core.h +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/inc/usbd_ccid_core.h @@ -30,6 +30,7 @@ #define _USB_CCID_CORE_H_ #include "os.h" +#include "os_io.h" #include "os_io_seproxyhal.h" #ifdef HAVE_USB_CLASS_CCID @@ -63,7 +64,8 @@ uint8_t USBD_CCID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum); uint8_t USBD_CCID_DataOut (USBD_HandleTypeDef *pdev, - uint8_t epnum, uint8_t* buffer); + uint8_t epnum, uint8_t* buffer, + apdu_buffer_t * apdu_buffer); #endif // HAVE_USB_CLASS_CCID diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_core.c b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_core.c index 8cb3836ec..e60a55243 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_core.c +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_core.c @@ -40,6 +40,8 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_ccid_core.h" +#include "os_io.h" +#include #ifdef HAVE_USB_CLASS_CCID @@ -253,9 +255,17 @@ uint8_t USBD_CCID_DataIn (USBD_HandleTypeDef *pdev, * @retval status */ uint8_t USBD_CCID_DataOut (USBD_HandleTypeDef *pdev, - uint8_t epnum, uint8_t* buffer) + uint8_t epnum, uint8_t* buffer, + apdu_buffer_t * apdu_buffer) { - CCID_BulkMessage_Out(pdev , epnum, buffer, io_seproxyhal_get_ep_rx_size(CCID_BULK_OUT_EP)); +#ifndef HAVE_LOCAL_APDU_BUFFER + UNUSED(apdu_buffer); +#endif + uint16_t rlen = io_seproxyhal_get_ep_rx_size(CCID_BULK_OUT_EP); + CCID_BulkMessage_Out(pdev , epnum, buffer, rlen); +#ifdef HAVE_LOCAL_APDU_BUFFER + memcpy(apdu_buffer->buf, G_io_apdu_buffer, rlen); +#endif return USBD_OK; } diff --git a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c index 0380a026f..ef0302615 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c +++ b/lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c @@ -28,6 +28,7 @@ /* Includes ------------------------------------------------------------------*/ #include "os.h" #include "usbd_ccid_if.h" +#include #ifdef HAVE_USB_CLASS_CCID @@ -104,7 +105,7 @@ void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev, unsigned int remLen = G_io_ccid.UsbMessageLength; // advance with acknowledged sent chunk - if (G_io_ccid.pUsbMessageBuffer == &G_io_ccid.bulk_header) { + if (G_io_ccid.pUsbMessageBuffer == (uint8_t *)&G_io_ccid.bulk_header) { // first part of the bulk in sent. // advance in the data buffer to transmit. (mixed source leap) G_io_ccid.pUsbMessageBuffer = G_io_ccid_data_buffer+MIN(CCID_BULK_EPIN_SIZE, G_io_ccid.UsbMessageLength)-CCID_HEADER_SIZE; @@ -414,13 +415,14 @@ static void CCID_Response_SendData(USBD_HandleTypeDef *pdev, THROW(SWO_IOL_OFW_04); } - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; - G_io_seproxyhal_spi_buffer[1] = (3+len)>>8; - G_io_seproxyhal_spi_buffer[2] = (3+len); - G_io_seproxyhal_spi_buffer[3] = CCID_BULK_IN_EP; - G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; - G_io_seproxyhal_spi_buffer[5] = len; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6); + uint8_t spi_buffer[6]; + spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + spi_buffer[1] = (3+len)>>8; + spi_buffer[2] = (3+len); + spi_buffer[3] = CCID_BULK_IN_EP; + spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + spi_buffer[5] = len; + io_seproxyhal_spi_send(spi_buffer, 6); io_seproxyhal_spi_send(buf, len); } @@ -444,14 +446,15 @@ void CCID_IntMessage(USBD_HandleTypeDef *pdev) CCID_SetIntrTransferStatus(0); /* Reset the Status */ CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */ - - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; - G_io_seproxyhal_spi_buffer[1] = (3+2)>>8; - G_io_seproxyhal_spi_buffer[2] = (3+2); - G_io_seproxyhal_spi_buffer[3] = CCID_INTR_IN_EP; - G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; - G_io_seproxyhal_spi_buffer[5] = 2; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6); + + uint8_t spi_buffer[6]; + spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + spi_buffer[1] = (3+2)>>8; + spi_buffer[2] = (3+2); + spi_buffer[3] = CCID_INTR_IN_EP; + spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + spi_buffer[5] = 2; + io_seproxyhal_spi_send(spi_buffer, 6); io_seproxyhal_spi_send(G_io_ccid.UsbIntMessageBuffer, 2); } } @@ -594,6 +597,14 @@ void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) { CCID_Send_Reply(&USBD_Device); } +void io_usb_ccid_reply_bare(unsigned short length) { + G_io_ccid.bulk_header.bulkin.dwLength = length; + // forge reply + RDR_to_PC_DataBlock(SLOT_NO_ERROR); + // start sending rpely + CCID_Send_Reply(&USBD_Device); +} + // ask for power on void io_usb_ccid_set_card_inserted(unsigned int inserted) { G_io_ccid.ccid_card_inserted = inserted; diff --git a/lib_stusb/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h b/lib_stusb/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h index 4531f90e3..908c7b355 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h +++ b/lib_stusb/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h @@ -116,7 +116,7 @@ uint8_t *USBD_HID_GetReportDescriptor_impl(uint16_t *length); uint8_t USBD_HID_DataOut_impl (USBD_HandleTypeDef *pdev, - uint8_t epnum, uint8_t* buffer); + uint8_t epnum, uint8_t* buffer, apdu_buffer_t*); /** * @} diff --git a/lib_stusb/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c b/lib_stusb/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c index 1135fd15d..50aa5ed67 100644 --- a/lib_stusb/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c +++ b/lib_stusb/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c @@ -44,7 +44,7 @@ * ****************************************************************************** */ -#include "os.h" +#include "os_helpers.h" #include "os_io_seproxyhal.h" diff --git a/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_core.h b/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_core.h index 8ea160e6c..a1c0f2bd1 100644 --- a/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_core.h +++ b/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_core.h @@ -110,7 +110,7 @@ USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup); -USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata, apdu_buffer_t *); USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev); diff --git a/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_def.h index bd3831861..c559b60c5 100644 --- a/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_def.h +++ b/lib_stusb/STM32_USB_Device_Library/Core/Inc/usbd_def.h @@ -35,6 +35,7 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_conf.h" +#include "os_io.h" /** @addtogroup STM32_USBD_DEVICE_LIBRARY * @{ @@ -165,7 +166,7 @@ typedef uint8_t (*EP0_TxSent_t) (struct _USBD_HandleTypeDef *pdev ); typedef uint8_t (*EP0_RxReady_t) (struct _USBD_HandleTypeDef *pdev ); /* Class Specific Endpoints*/ typedef uint8_t (*DataIn_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); -typedef uint8_t (*DataOut_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t* pData); +typedef uint8_t (*DataOut_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t* pData, apdu_buffer_t *); typedef uint8_t (*SOF_t) (struct _USBD_HandleTypeDef *pdev); typedef uint8_t (*IsoINIncomplete_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); typedef uint8_t (*IsoOUTIncomplete_t) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); diff --git a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_core.c b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_core.c index 7f6478ead..b958b038f 100644 --- a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_core.c +++ b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_core.c @@ -26,10 +26,12 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "os.h" +#include "os_helpers.h" +#include "os_io.h" #include "os_pic.h" #include "usbd_core.h" #include "usbd_ioreq.h" +#include /** @addtogroup STM32_USBD_DEVICE_LIBRARY * @{ @@ -273,7 +275,7 @@ USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup) * @param epnum: endpoint index * @retval status */ -USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata, apdu_buffer_t * apdu_buffer) { USBD_EndpointTypeDef *pep; @@ -312,7 +314,7 @@ USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum if( usbd_is_valid_intf(pdev, intf) && (pdev->interfacesClass[intf].pClass->DataOut != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { - ((DataOut_t)PIC(pdev->interfacesClass[intf].pClass->DataOut))(pdev, epnum, pdata); + ((DataOut_t)PIC(pdev->interfacesClass[intf].pClass->DataOut))(pdev, epnum, pdata, apdu_buffer); } } } diff --git a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c index a01bc64f4..4e0b85588 100644 --- a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c +++ b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c @@ -24,7 +24,8 @@ * ****************************************************************************** */ -#include "os.h" +#include "os_helpers.h" +#include "os_io.h" #include "os_pic.h" /* Includes ------------------------------------------------------------------*/ diff --git a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c index be0887210..6923b3fec 100644 --- a/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c +++ b/lib_stusb/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c @@ -26,7 +26,8 @@ */ /* Includes ------------------------------------------------------------------*/ -#include "os.h" +#include "os_io.h" +#include "os_helpers.h" #include "usbd_core.h" #include "usbd_ioreq.h" diff --git a/lib_stusb/usbd_conf.c b/lib_stusb/usbd_conf.c index 0a0b52a39..fdc8afce4 100644 --- a/lib_stusb/usbd_conf.c +++ b/lib_stusb/usbd_conf.c @@ -62,13 +62,15 @@ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev) */ USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev) { + uint8_t buffer[4]; UNUSED(pdev); + // usb off - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_CONFIG; - G_io_seproxyhal_spi_buffer[1] = 0; - G_io_seproxyhal_spi_buffer[2] = 1; - G_io_seproxyhal_spi_buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 4); + buffer[0] = SEPROXYHAL_TAG_USB_CONFIG; + buffer[1] = 0; + buffer[2] = 1; + buffer[3] = SEPROXYHAL_TAG_USB_CONFIG_DISCONNECT; + io_seproxyhal_spi_send(buffer, 4); return USBD_OK; } diff --git a/lib_stusb_impl/usbd_impl.c b/lib_stusb_impl/usbd_impl.c index 741978dad..72b286c45 100644 --- a/lib_stusb_impl/usbd_impl.c +++ b/lib_stusb_impl/usbd_impl.c @@ -981,8 +981,15 @@ uint8_t USBD_U2F_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum) return USBD_OK; } -uint8_t USBD_U2F_DataOut_impl(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *buffer) +uint8_t USBD_U2F_DataOut_impl(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + __attribute__((unused)) apdu_buffer_t *apdu_buf) { +#ifdef HAVE_LOCAL_APDU_BUFFER +#error "Feature not implemented" +#endif + switch (epnum) { // FIDO endpoint case (U2F_EPOUT_ADDR & 0x7F): @@ -1009,7 +1016,10 @@ uint8_t USBD_HID_DataIn_impl(USBD_HandleTypeDef *pdev, uint8_t epnum) return USBD_OK; } -uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *buffer) +uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + apdu_buffer_t *apdu_buf) { // only the data hid endpoint will receive data switch (epnum) { @@ -1022,8 +1032,10 @@ uint8_t USBD_HID_DataOut_impl(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t * // avoid troubles when an apdu has not been replied yet if (G_io_app.apdu_media == IO_APDU_MEDIA_NONE) { // add to the hid transport - switch (io_usb_hid_receive( - io_usb_send_apdu_data, buffer, io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR))) { + switch (io_usb_hid_receive(io_usb_send_apdu_data, + buffer, + io_seproxyhal_get_ep_rx_size(HID_EPOUT_ADDR), + apdu_buf)) { default: break; @@ -1085,7 +1097,10 @@ uint8_t USBD_WEBUSB_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) return USBD_OK; } -uint8_t USBD_WEBUSB_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *buffer) +uint8_t USBD_WEBUSB_DataOut(USBD_HandleTypeDef *pdev, + uint8_t epnum, + uint8_t *buffer, + apdu_buffer_t *apdu_buf) { // only the data hid endpoint will receive data switch (epnum) { @@ -1099,7 +1114,8 @@ uint8_t USBD_WEBUSB_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum, uint8_t *bu // add to the hid transport switch (io_usb_hid_receive(io_usb_send_apdu_data_ep0x83, buffer, - io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR))) { + io_seproxyhal_get_ep_rx_size(WEBUSB_EPOUT_ADDR), + apdu_buf)) { default: break; diff --git a/src/cx_wrappers.c b/src/cx_wrappers.c new file mode 100644 index 000000000..f1db2af9a --- /dev/null +++ b/src/cx_wrappers.c @@ -0,0 +1,62 @@ + +/******************************************************************************* + * (c) 2023 Ledger SAS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include // uint*_t +#include // memset, explicit_bzero +#include // bool + +#include "cx.h" +#include "lib_cxng/src/cx_ecfp.h" + +// At some point this could/should be migrated to a cx func included in the cx_lib +cx_err_t cx_ecdsa_sign_rs_no_throw(const cx_ecfp_private_key_t *key, + uint32_t mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + size_t rs_size, + uint8_t *sig_r, + uint8_t *sig_s, + uint32_t *info) +{ + cx_err_t error = CX_OK; + uint8_t sig_der[100]; + size_t sig_der_len = sizeof(sig_der); + const uint8_t *r; + const uint8_t *s; + size_t r_len, s_len; + + explicit_bzero(sig_r, rs_size); + explicit_bzero(sig_s, rs_size); + + CX_CHECK( + cx_ecdsa_sign_no_throw(key, mode, hashID, hash, hash_len, sig_der, &sig_der_len, info)); + + if (cx_ecfp_decode_sig_der(sig_der, sig_der_len, rs_size, &r, &r_len, &s, &s_len) != 1) { + error = CX_INVALID_PARAMETER; + goto end; + } + + // Copy R and S. No need to pad as the full buffer has been memset + memcpy(sig_r + rs_size - r_len, r, r_len); + memcpy(sig_s + rs_size - s_len, s, s_len); + +end: + if (error != CX_OK) { + *info = 0; + } + return error; +} diff --git a/src/ledger_protocol.c b/src/ledger_protocol.c index 5f2a23c5e..281c50c43 100644 --- a/src/ledger_protocol.c +++ b/src/ledger_protocol.c @@ -47,7 +47,7 @@ /* Private macros-------------------------------------------------------------*/ /* Private functions prototypes ----------------------------------------------*/ -static void process_apdu_chunk(uint8_t *buffer, uint16_t length); +static void process_apdu_chunk(const uint8_t *buffer, uint16_t length); /* Exported variables --------------------------------------------------------*/ @@ -57,7 +57,7 @@ static const uint8_t protocol_version[4] = {0x00, 0x00, 0x00, 0x00}; static ledger_protocol_t *ledger_protocol; /* Private functions ---------------------------------------------------------*/ -static void process_apdu_chunk(uint8_t *buffer, uint16_t length) +static void process_apdu_chunk(const uint8_t *buffer, uint16_t length) { // Check the sequence number if ((length < 2) || ((uint16_t) U2BE(buffer, 0) != ledger_protocol->rx_apdu_sequence_number)) { @@ -118,14 +118,18 @@ void LEDGER_PROTOCOL_init(ledger_protocol_t *data) ledger_protocol->rx_apdu_sequence_number = 0; } -void LEDGER_PROTOCOL_rx(uint8_t *buffer, uint16_t length) +void LEDGER_PROTOCOL_rx(const uint8_t *buffer, uint16_t length) { if (!buffer || length < 3) { return; } memset(ledger_protocol->tx_chunk, 0, sizeof(ledger_protocol->tx_chunk)); - memcpy(ledger_protocol->tx_chunk, buffer, 2); // Copy channel ID + + // For all calls to this function, the buffer was pre-initialized to the same constant + // In order for the input buffer to be 'const', this constant is forced directly here + ledger_protocol->tx_chunk[0] = 0xDE; + ledger_protocol->tx_chunk[1] = 0xF1; switch (buffer[2]) { case TAG_GET_PROTOCOL_VERSION: @@ -172,7 +176,7 @@ void LEDGER_PROTOCOL_rx(uint8_t *buffer, uint16_t length) } } -void LEDGER_PROTOCOL_tx(uint8_t *buffer, uint16_t length) +void LEDGER_PROTOCOL_tx(const uint8_t *buffer, uint16_t length) { if (!buffer && !ledger_protocol->tx_apdu_buffer) { return; diff --git a/src/os.c b/src/os.c index e1ed865c9..232b82375 100644 --- a/src/os.c +++ b/src/os.c @@ -24,8 +24,10 @@ #include "os.h" #include +#ifndef HAVE_LOCAL_APDU_BUFFER // apdu buffer must hold a complete apdu to avoid troubles unsigned char G_io_apdu_buffer[IO_APDU_BUFFER_SIZE]; +#endif #ifndef BOLOS_OS_UPGRADER_APP void os_boot(void) diff --git a/src/os_io_seproxyhal.c b/src/os_io_seproxyhal.c index f7ccb8d83..14a3d8272 100644 --- a/src/os_io_seproxyhal.c +++ b/src/os_io_seproxyhal.c @@ -59,6 +59,10 @@ #include "checks.h" #include "lcx_sha512.h" +#ifndef IO_RAPDU_TRANSMIT_TIMEOUT_MS +#define IO_RAPDU_TRANSMIT_TIMEOUT_MS 2000UL +#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS + #ifdef HAVE_IO_U2F #include "u2f_processing.h" #include "u2f_transport.h" @@ -110,17 +114,10 @@ unsigned int os_io_seph_recv_and_process(unsigned int dont_process_ux_events); io_seph_app_t G_io_app; #endif // ! HAVE_BOLOS -// usb endpoint buffer -unsigned char G_io_usb_ep_buffer[MAX(USB_SEGMENT_SIZE, BLE_SEGMENT_SIZE)]; - #if defined(HAVE_BAGL) || defined(HAVE_NBGL) ux_seph_os_and_app_t G_ux_os; #endif -#ifndef IO_RAPDU_TRANSMIT_TIMEOUT_MS -#define IO_RAPDU_TRANSMIT_TIMEOUT_MS 2000UL -#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS - static const unsigned char seph_io_general_status[] = { SEPROXYHAL_TAG_GENERAL_STATUS, 0, @@ -174,14 +171,6 @@ void io_seproxyhal_handle_usb_event(void) } } -uint16_t io_seproxyhal_get_ep_rx_size(uint8_t epnum) -{ - if ((epnum & 0x7F) < IO_USB_MAX_ENDPOINTS) { - return G_io_app.usb_ep_xfer_len[epnum & 0x7F]; - } - return 0; -} - void io_seproxyhal_handle_usb_ep_xfer_event(void) { uint8_t epnum; @@ -216,7 +205,7 @@ void io_seproxyhal_handle_usb_ep_xfer_event(void) = MIN(G_io_seproxyhal_spi_buffer[5], IO_SEPROXYHAL_BUFFER_SIZE_B - 6); #endif // prepare reception - USBD_LL_DataOutStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6]); + USBD_LL_DataOutStage(&USBD_Device, epnum, &G_io_seproxyhal_spi_buffer[6], NULL); } break; } @@ -230,42 +219,6 @@ void io_seproxyhal_handle_usb_ep_xfer_event(void) {} #endif // HAVE_L4_USBLIB -// TODO, refactor this using the USB DataIn event like for the U2F tunnel -// TODO add a blocking parameter, for HID KBD sending, or use a USB busy flag per channel to know if -// the transfer has been processed or not. and move on to the next transfer on the same endpoint -void io_usb_send_ep(unsigned int ep, - unsigned char *buffer, - unsigned short length, - unsigned int timeout) -{ - // don't spoil the timeout :) - if (timeout) { - timeout++; - } - - // won't send if overflowing seproxyhal buffer format - if (length > 255) { - return; - } - - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; - G_io_seproxyhal_spi_buffer[1] = (3 + length) >> 8; - G_io_seproxyhal_spi_buffer[2] = (3 + length); - G_io_seproxyhal_spi_buffer[3] = ep | 0x80; - G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; - G_io_seproxyhal_spi_buffer[5] = length; - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6); - io_seproxyhal_spi_send(buffer, length); - // setup timeout of the endpoint - G_io_app.usb_ep_timeouts[ep & 0x7F].timeout = IO_RAPDU_TRANSMIT_TIMEOUT_MS; -} - -void io_usb_send_apdu_data(unsigned char *buffer, unsigned short length) -{ - // wait for 20 events before hanging up and timeout (~2 seconds of timeout) - io_usb_send_ep(0x82, buffer, length, 20); -} - #ifdef HAVE_WEBUSB void io_usb_send_apdu_data_ep0x83(unsigned char *buffer, unsigned short length) { @@ -326,7 +279,7 @@ unsigned int io_seproxyhal_handle_event(void) #ifdef HAVE_BLE case SEPROXYHAL_TAG_BLE_RECV_EVENT: - LEDGER_BLE_receive(); + LEDGER_BLE_receive(G_io_seproxyhal_spi_buffer); return 1; #endif // HAVE_BLE @@ -450,9 +403,6 @@ static const unsigned char seph_io_mcu_protect[] = { void io_seproxyhal_init(void) { #ifndef HAVE_BOLOS - // Enforce OS compatibility - check_api_level(CX_COMPAT_APILEVEL); - #ifdef HAVE_MCU_PROTECT // engage RDP2 on MCU io_seproxyhal_spi_send(seph_io_mcu_protect, sizeof(seph_io_mcu_protect)); @@ -1362,7 +1312,7 @@ unsigned short io_exchange(unsigned char channel, unsigned short tx_len) case APDU_USB_HID: // only send, don't perform synchronous reception of the next command // (will be done later by the seproxyhal packet processing) - io_usb_hid_send(io_usb_send_apdu_data, tx_len); + io_usb_hid_send(io_usb_send_apdu_data, tx_len, G_io_apdu_buffer); goto break_send; #ifdef HAVE_USB_CLASS_CCID case APDU_USB_CCID: @@ -1371,7 +1321,7 @@ unsigned short io_exchange(unsigned char channel, unsigned short tx_len) #endif // HAVE_USB_CLASS_CCID #ifdef HAVE_WEBUSB case APDU_USB_WEBUSB: - io_usb_hid_send(io_usb_send_apdu_data_ep0x83, tx_len); + io_usb_hid_send(io_usb_send_apdu_data_ep0x83, tx_len, G_io_apdu_buffer); goto break_send; #endif // HAVE_WEBUSB #endif // HAVE_USB_APDU diff --git a/src/os_io_usb.c b/src/os_io_usb.c index 01a7a353a..5af0ee509 100644 --- a/src/os_io_usb.c +++ b/src/os_io_usb.c @@ -23,6 +23,53 @@ #ifdef HAVE_USB_APDU +// usb endpoint buffer +unsigned char G_io_usb_ep_buffer[MAX(USB_SEGMENT_SIZE, BLE_SEGMENT_SIZE)]; + +uint16_t io_seproxyhal_get_ep_rx_size(uint8_t epnum) +{ + if ((epnum & 0x7F) < IO_USB_MAX_ENDPOINTS) { + return G_io_app.usb_ep_xfer_len[epnum & 0x7F]; + } + return 0; +} + +#ifndef IO_RAPDU_TRANSMIT_TIMEOUT_MS +#define IO_RAPDU_TRANSMIT_TIMEOUT_MS 2000UL +#endif // IO_RAPDU_TRANSMIT_TIMEOUT_MS + +// TODO, refactor this using the USB DataIn event like for the U2F tunnel +// TODO add a blocking parameter, for HID KBD sending, or use a USB busy flag per channel to know if +// the transfer has been processed or not. and move on to the next transfer on the same endpoint +void io_usb_send_ep(unsigned int ep, + unsigned char *buffer, + unsigned short length, + __attribute__((unused)) unsigned int timeout) +{ + // won't send if overflowing seproxyhal buffer format + if (length > 255) { + return; + } + + uint8_t buf[6]; + buf[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + buf[1] = (3 + length) >> 8; + buf[2] = (3 + length); + buf[3] = ep | 0x80; + buf[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + buf[5] = length; + io_seproxyhal_spi_send(buf, 6); + io_seproxyhal_spi_send(buffer, length); + // setup timeout of the endpoint + G_io_app.usb_ep_timeouts[ep & 0x7F].timeout = IO_RAPDU_TRANSMIT_TIMEOUT_MS; +} + +void io_usb_send_apdu_data(unsigned char *buffer, unsigned short length) +{ + // wait for 20 events before hanging up and timeout (~2 seconds of timeout) + io_usb_send_ep(0x82, buffer, length, 20); +} + /** * Ledger Protocol * HID Report Content @@ -65,8 +112,23 @@ static uint8_t *G_io_usb_hid_current_buffer; io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, unsigned char *buffer, - unsigned short l) + unsigned short l, + apdu_buffer_t *apdu_buffer) { + uint8_t *apdu_buf; + uint16_t apdu_buf_len; +#ifndef HAVE_LOCAL_APDU_BUFFER + if (apdu_buffer == NULL) { + apdu_buf = G_io_apdu_buffer; + apdu_buf_len = sizeof(G_io_apdu_buffer); + } + else +#endif // HAVE_LOCAL_APDU_BUFFER + { + apdu_buf = apdu_buffer->buf; + apdu_buf_len = apdu_buffer->len; + } + // avoid over/under flows if (buffer != G_io_usb_ep_buffer) { memset(G_io_usb_ep_buffer, 0, sizeof(G_io_usb_ep_buffer)); @@ -94,14 +156,14 @@ io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, 5); //(G_io_usb_ep_buffer[5]<<8)+(G_io_usb_ep_buffer[6]&0xFF); // check for invalid length encoding (more data in chunk that announced in the total // apdu) - if (G_io_usb_hid_total_length > sizeof(G_io_apdu_buffer)) { + if (G_io_usb_hid_total_length > (uint32_t) apdu_buf_len) { goto apdu_reset; } // seq and total length l -= 2; // compute remaining size to receive G_io_usb_hid_remaining_length = G_io_usb_hid_total_length; - G_io_usb_hid_current_buffer = G_io_apdu_buffer; + G_io_usb_hid_current_buffer = apdu_buf; // retain the channel id to use for the reply G_io_usb_hid_channel = U2BE(G_io_usb_ep_buffer, 0); @@ -115,7 +177,7 @@ io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, } // copy data - memmove(G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 7, l); + memmove((void *) G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 7, l); } else { // check for invalid length encoding (more data in chunk that announced in the total @@ -130,7 +192,7 @@ io_usb_hid_receive_status_t io_usb_hid_receive(io_send_t sndfct, /// This is a following chunk // append content - memmove(G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 5, l); + memmove((void *) G_io_usb_hid_current_buffer, G_io_usb_ep_buffer + 5, l); } // factorize (f) G_io_usb_hid_current_buffer += l; @@ -208,7 +270,7 @@ void io_usb_hid_sent(io_send_t sndfct) : G_io_usb_hid_remaining_length); G_io_usb_ep_buffer[5] = G_io_usb_hid_remaining_length >> 8; G_io_usb_ep_buffer[6] = G_io_usb_hid_remaining_length; - memmove(G_io_usb_ep_buffer + 7, G_io_usb_hid_current_buffer, l); + memmove(G_io_usb_ep_buffer + 7, (const void *) G_io_usb_hid_current_buffer, l); G_io_usb_hid_current_buffer += l; G_io_usb_hid_remaining_length -= l; } @@ -216,7 +278,7 @@ void io_usb_hid_sent(io_send_t sndfct) l = ((G_io_usb_hid_remaining_length > IO_HID_EP_LENGTH - 5) ? IO_HID_EP_LENGTH - 5 : G_io_usb_hid_remaining_length); - memmove(G_io_usb_ep_buffer + 5, G_io_usb_hid_current_buffer, l); + memmove(G_io_usb_ep_buffer + 5, (const void *) G_io_usb_hid_current_buffer, l); G_io_usb_hid_current_buffer += l; G_io_usb_hid_remaining_length -= l; } @@ -235,12 +297,12 @@ void io_usb_hid_sent(io_send_t sndfct) } } -void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength) +void io_usb_hid_send(io_send_t sndfct, unsigned short sndlength, unsigned char *apdu_buffer) { // perform send if (sndlength) { G_io_usb_hid_sequence_number = 0; - G_io_usb_hid_current_buffer = G_io_apdu_buffer; + G_io_usb_hid_current_buffer = apdu_buffer; G_io_usb_hid_remaining_length = sndlength; G_io_usb_hid_total_length = sndlength; io_usb_hid_sent(sndfct);