1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

CCID: Add CCIDWorker (#3785)

* CCID: Add CCIDWorker
  This new thread allows for Flipper to receive CCID messages bigger than CCID_EPSIZE
  by receiving multiple packaged in a row and adding them to the buffer
* Fixed data types
* Format sources
* Review feedback
* Variable names
* FuriHal: cleanup and fortify code in furi_hal_usb_ccid
* Review feedbacks (also added extra checks)
* Fixed use after free
* Fix lint
* Sync API Symbols version
* Sync API Symbols version again
* FuriHal: fix clangd warnings, add doxygen comments for furi_hal_usb_ccid.h

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Filipe Paz Rodrigues
2024-07-18 02:04:38 -05:00
committed by GitHub
parent 79d82da9b2
commit 703ed83fd8
6 changed files with 284 additions and 155 deletions

View File

@@ -133,8 +133,8 @@ void handle_instruction_01(ISO7816_Response_APDU* responseAPDU) {
void handle_instruction_02( void handle_instruction_02(
uint8_t p1, uint8_t p1,
uint8_t p2, uint8_t p2,
uint8_t lc, uint16_t lc,
uint8_t le, uint16_t le,
ISO7816_Response_APDU* responseAPDU) { ISO7816_Response_APDU* responseAPDU) {
if(p1 == 0 && p2 == 0 && lc == 0 && le >= 2) { if(p1 == 0 && p2 == 0 && lc == 0 && le >= 2) {
responseAPDU->Data[0] = 0x62; responseAPDU->Data[0] = 0x62;
@@ -153,7 +153,11 @@ void handle_instruction_02(
//Instruction 3: sends a command with a body with two bytes, receives a response with no bytes //Instruction 3: sends a command with a body with two bytes, receives a response with no bytes
//APDU example: 0x01:0x03:0x00:0x00:0x02:CA:FE //APDU example: 0x01:0x03:0x00:0x00:0x02:CA:FE
//response SW1=0x90, SW2=0x00 //response SW1=0x90, SW2=0x00
void handle_instruction_03(uint8_t p1, uint8_t p2, uint8_t lc, ISO7816_Response_APDU* responseAPDU) { void handle_instruction_03(
uint8_t p1,
uint8_t p2,
uint16_t lc,
ISO7816_Response_APDU* responseAPDU) {
if(p1 == 0 && p2 == 0 && lc == 2) { if(p1 == 0 && p2 == 0 && lc == 2) {
responseAPDU->DataLen = 0; responseAPDU->DataLen = 0;
iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK); iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK);
@@ -170,8 +174,8 @@ void handle_instruction_03(uint8_t p1, uint8_t p2, uint8_t lc, ISO7816_Response_
void handle_instruction_04( void handle_instruction_04(
uint8_t p1, uint8_t p1,
uint8_t p2, uint8_t p2,
uint8_t lc, uint16_t lc,
uint8_t le, uint16_t le,
const uint8_t* commandApduDataBuffer, const uint8_t* commandApduDataBuffer,
ISO7816_Response_APDU* responseAPDU) { ISO7816_Response_APDU* responseAPDU) {
if(p1 == 0 && p2 == 0 && lc > 0 && le > 0 && le >= lc) { if(p1 == 0 && p2 == 0 && lc > 0 && le > 0 && le >= lc) {
@@ -249,8 +253,10 @@ int32_t ccid_test_app(void* p) {
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
furi_hal_usb_unlock(); furi_hal_usb_unlock();
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true); furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
furi_hal_usb_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
furi_hal_usb_ccid_insert_smartcard();
iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb); iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb);
@@ -271,8 +277,8 @@ int32_t ccid_test_app(void* p) {
} }
//tear down USB //tear down USB
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
furi_hal_usb_set_config(usb_mode_prev, NULL); furi_hal_usb_set_config(usb_mode_prev, NULL);
furi_hal_ccid_set_callbacks(NULL, NULL);
iso7816_set_callbacks(NULL); iso7816_set_callbacks(NULL);

9
applications/debug/ccid_test/client/ccid_client.py Normal file → Executable file
View File

@@ -1,3 +1,4 @@
#!/usr/bin/env python
# pylint: disable=missing-module-docstring, too-many-arguments, consider-using-f-string, missing-function-docstring # pylint: disable=missing-module-docstring, too-many-arguments, consider-using-f-string, missing-function-docstring
from smartcard.System import readers from smartcard.System import readers
@@ -100,12 +101,14 @@ def main():
small_apdu, small_apdu,
) )
max_apdu = list(range(0, 0x30)) upper_bound = 0xF0
max_apdu = list(range(0, upper_bound))
test_apdu( test_apdu(
connection, connection,
"INS 0x04: Lc=0x30, data=max_apdu, Le=0x30. Expect 0x30 bytes data in return", "INS 0x04: Lc=0x%x, data=max_apdu, Le=0x%x. Expect 0x%x bytes data in return"
[0x01, 0x04, 0x00, 0x00, 0x30] + max_apdu + [0x30], % (upper_bound, upper_bound, upper_bound),
[0x01, 0x04, 0x00, 0x00, upper_bound] + max_apdu + [upper_bound],
0x90, 0x90,
0x00, 0x00,
max_apdu, max_apdu,

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,68.1,, Version,+,69.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
@@ -1178,9 +1178,6 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void, Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
Function,+,furi_hal_ccid_set_callbacks,void,"CcidCallbacks*, void*"
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t" Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@@ -1454,6 +1451,9 @@ Function,-,furi_hal_spi_config_init_early,void,
Function,-,furi_hal_spi_dma_init,void, Function,-,furi_hal_spi_dma_init,void,
Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle* Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle*
Function,+,furi_hal_switch,void,void* Function,+,furi_hal_switch,void,void*
Function,+,furi_hal_usb_ccid_insert_smartcard,void,
Function,+,furi_hal_usb_ccid_remove_smartcard,void,
Function,+,furi_hal_usb_ccid_set_callbacks,void,"CcidCallbacks*, void*"
Function,+,furi_hal_usb_disable,void, Function,+,furi_hal_usb_disable,void,
Function,+,furi_hal_usb_enable,void, Function,+,furi_hal_usb_enable,void,
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*, Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
1 entry status name type params
2 Version + 68.1 69.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/bt/bt_service/bt_keys_storage.h
5 Header + applications/services/cli/cli.h
1178 Function + furi_hal_bus_init_early void
1179 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
1180 Function + furi_hal_bus_reset void FuriHalBus
Function + furi_hal_ccid_ccid_insert_smartcard void
Function + furi_hal_ccid_ccid_remove_smartcard void
Function + furi_hal_ccid_set_callbacks void CcidCallbacks*, void*
1181 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
1182 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
1183 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
1451 Function - furi_hal_spi_dma_init void
1452 Function + furi_hal_spi_release void FuriHalSpiBusHandle*
1453 Function + furi_hal_switch void void*
1454 Function + furi_hal_usb_ccid_insert_smartcard void
1455 Function + furi_hal_usb_ccid_remove_smartcard void
1456 Function + furi_hal_usb_ccid_set_callbacks void CcidCallbacks*, void*
1457 Function + furi_hal_usb_disable void
1458 Function + furi_hal_usb_enable void
1459 Function + furi_hal_usb_get_config FuriHalUsbInterface*

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,68.1,, Version,+,69.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
@@ -1283,9 +1283,6 @@ Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void, Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
Function,+,furi_hal_ccid_set_callbacks,void,"CcidCallbacks*, void*"
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t" Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@@ -1668,6 +1665,9 @@ Function,+,furi_hal_subghz_stop_async_tx,void,
Function,+,furi_hal_subghz_tx,_Bool, Function,+,furi_hal_subghz_tx,_Bool,
Function,+,furi_hal_subghz_write_packet,void,"const uint8_t*, uint8_t" Function,+,furi_hal_subghz_write_packet,void,"const uint8_t*, uint8_t"
Function,+,furi_hal_switch,void,void* Function,+,furi_hal_switch,void,void*
Function,+,furi_hal_usb_ccid_insert_smartcard,void,
Function,+,furi_hal_usb_ccid_remove_smartcard,void,
Function,+,furi_hal_usb_ccid_set_callbacks,void,"CcidCallbacks*, void*"
Function,+,furi_hal_usb_disable,void, Function,+,furi_hal_usb_disable,void,
Function,+,furi_hal_usb_enable,void, Function,+,furi_hal_usb_enable,void,
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*, Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
1 entry status name type params
2 Version + 68.1 69.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
1283 Function + furi_hal_bus_init_early void
1284 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
1285 Function + furi_hal_bus_reset void FuriHalBus
Function + furi_hal_ccid_ccid_insert_smartcard void
Function + furi_hal_ccid_ccid_remove_smartcard void
Function + furi_hal_ccid_set_callbacks void CcidCallbacks*, void*
1286 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
1287 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
1288 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
1665 Function + furi_hal_subghz_tx _Bool
1666 Function + furi_hal_subghz_write_packet void const uint8_t*, uint8_t
1667 Function + furi_hal_switch void void*
1668 Function + furi_hal_usb_ccid_insert_smartcard void
1669 Function + furi_hal_usb_ccid_remove_smartcard void
1670 Function + furi_hal_usb_ccid_set_callbacks void CcidCallbacks*, void*
1671 Function + furi_hal_usb_disable void
1672 Function + furi_hal_usb_enable void
1673 Function + furi_hal_usb_get_config FuriHalUsbInterface*

View File

@@ -4,28 +4,27 @@
#include <furi_hal_usb_ccid.h> #include <furi_hal_usb_ccid.h>
#include <furi.h> #include <furi.h>
#include "usb.h" #include <usb_ccid.h>
#include "usb_ccid.h"
static const uint8_t USB_DEVICE_NO_CLASS = 0x0; #define USB_DEVICE_NO_CLASS (0x0)
static const uint8_t USB_DEVICE_NO_SUBCLASS = 0x0; #define USB_DEVICE_NO_SUBCLASS (0x0)
static const uint8_t USB_DEVICE_NO_PROTOCOL = 0x0; #define USB_DEVICE_NO_PROTOCOL (0x0)
#define FIXED_CONTROL_ENDPOINT_SIZE 8 #define FIXED_CONTROL_ENDPOINT_SIZE (8)
#define IF_NUM_MAX 1 #define IF_NUM_MAX (1)
#define CCID_VID_DEFAULT 0x1234 #define CCID_VID_DEFAULT (0x1234)
#define CCID_PID_DEFAULT 0xABCD #define CCID_PID_DEFAULT (0xABCD)
#define CCID_TOTAL_SLOTS 1 #define CCID_TOTAL_SLOTS (1)
#define CCID_SLOT_INDEX 0 #define CCID_SLOT_INDEX (0)
#define CCID_DATABLOCK_SIZE \ #define CCID_DATABLOCK_SIZE \
(4 + 1 + CCID_SHORT_APDU_SIZE + 1) //APDU Header + Lc + Short APDU size + Le (4 + 1 + CCID_SHORT_APDU_SIZE + 1) //APDU Header + Lc + Short APDU size + Le
#define ENDPOINT_DIR_IN 0x80 #define ENDPOINT_DIR_IN (0x80)
#define ENDPOINT_DIR_OUT 0x00 #define ENDPOINT_DIR_OUT (0x00)
#define INTERFACE_ID_CCID 0 #define INTERFACE_ID_CCID (0)
#define CCID_IN_EPADDR (ENDPOINT_DIR_IN | 2) #define CCID_IN_EPADDR (ENDPOINT_DIR_IN | 2)
@@ -65,6 +64,18 @@ enum CCID_Features_ExchangeLevel_t {
CCID_Features_ExchangeLevel_ShortExtendedAPDU = 0x00040000 CCID_Features_ExchangeLevel_ShortExtendedAPDU = 0x00040000
}; };
typedef enum {
WorkerEvtStop = (1 << 0),
WorkerEvtRequest = (1 << 1),
} WorkerEvtFlags;
typedef struct ccid_bulk_message_header {
uint8_t bMessageType;
uint32_t dwLength;
uint8_t bSlot;
uint8_t bSeq;
} FURI_PACKED ccid_bulk_message_header_t;
/* Device descriptor */ /* Device descriptor */
static struct usb_device_descriptor ccid_device_desc = { static struct usb_device_descriptor ccid_device_desc = {
.bLength = sizeof(struct usb_device_descriptor), .bLength = sizeof(struct usb_device_descriptor),
@@ -163,6 +174,7 @@ static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
static void ccid_deinit(usbd_device* dev); static void ccid_deinit(usbd_device* dev);
static void ccid_on_wakeup(usbd_device* dev); static void ccid_on_wakeup(usbd_device* dev);
static void ccid_on_suspend(usbd_device* dev); static void ccid_on_suspend(usbd_device* dev);
static int32_t ccid_worker(void* context);
FuriHalUsbInterface usb_ccid = { FuriHalUsbInterface usb_ccid = {
.init = ccid_init, .init = ccid_init,
@@ -181,11 +193,22 @@ FuriHalUsbInterface usb_ccid = {
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg); static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg);
static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback); static usbd_respond ccid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
static usbd_device* usb_dev;
static bool connected = false; typedef struct {
static bool smartcard_inserted = true; bool connected;
static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL}; bool smartcard_inserted;
static void* cb_ctx[CCID_TOTAL_SLOTS]; CcidCallbacks* callbacks[CCID_TOTAL_SLOTS];
void* cb_ctx[CCID_TOTAL_SLOTS];
FuriThread* ccid_thread;
FuriSemaphore* ccid_semaphore;
usbd_device* usb_dev;
uint16_t receive_buffer_data_index;
uint8_t send_buffer[sizeof(ccid_bulk_message_header_t) + CCID_DATABLOCK_SIZE];
uint8_t receive_buffer[sizeof(ccid_bulk_message_header_t) + CCID_DATABLOCK_SIZE];
} FuriHalUsbCcid;
static FuriHalUsbCcid* furi_hal_usb_ccid = NULL;
static void* ccid_set_string_descr(char* str) { static void* ccid_set_string_descr(char* str) {
furi_check(str); furi_check(str);
@@ -205,7 +228,11 @@ static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
FuriHalUsbCcidConfig* cfg = (FuriHalUsbCcidConfig*)ctx; FuriHalUsbCcidConfig* cfg = (FuriHalUsbCcidConfig*)ctx;
usb_dev = dev; furi_check(furi_hal_usb_ccid == NULL);
furi_hal_usb_ccid = malloc(sizeof(FuriHalUsbCcid));
furi_hal_usb_ccid->usb_dev = dev;
furi_hal_usb_ccid->ccid_semaphore = furi_semaphore_alloc(1, 1);
usb_ccid.dev_descr->iManufacturer = 0; usb_ccid.dev_descr->iManufacturer = 0;
usb_ccid.dev_descr->iProduct = 0; usb_ccid.dev_descr->iProduct = 0;
@@ -233,42 +260,50 @@ static void ccid_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
usbd_reg_control(dev, ccid_control); usbd_reg_control(dev, ccid_control);
usbd_connect(dev, true); usbd_connect(dev, true);
furi_hal_usb_ccid->receive_buffer_data_index = 0;
furi_hal_usb_ccid->ccid_thread = furi_thread_alloc_ex("CcidWorker", 2048, ccid_worker, ctx);
furi_thread_start(furi_hal_usb_ccid->ccid_thread);
} }
static void ccid_deinit(usbd_device* dev) { static void ccid_deinit(usbd_device* dev) {
furi_thread_flags_set(furi_thread_get_id(furi_hal_usb_ccid->ccid_thread), WorkerEvtStop);
furi_thread_join(furi_hal_usb_ccid->ccid_thread);
furi_thread_free(furi_hal_usb_ccid->ccid_thread);
usbd_reg_config(dev, NULL); usbd_reg_config(dev, NULL);
usbd_reg_control(dev, NULL); usbd_reg_control(dev, NULL);
free(usb_ccid.str_prod_descr); free(usb_ccid.str_prod_descr);
free(usb_ccid.str_serial_descr); free(usb_ccid.str_serial_descr);
free(furi_hal_usb_ccid);
furi_hal_usb_ccid = NULL;
} }
static void ccid_on_wakeup(usbd_device* dev) { static void ccid_on_wakeup(usbd_device* dev) {
UNUSED(dev); UNUSED(dev);
connected = true; furi_check(furi_hal_usb_ccid);
furi_hal_usb_ccid->connected = true;
} }
static void ccid_on_suspend(usbd_device* dev) { static void ccid_on_suspend(usbd_device* dev) {
UNUSED(dev); UNUSED(dev);
connected = false; furi_check(furi_hal_usb_ccid);
furi_hal_usb_ccid->connected = false;
} }
typedef struct ccid_bulk_message_header {
uint8_t bMessageType;
uint32_t dwLength;
uint8_t bSlot;
uint8_t bSeq;
} FURI_PACKED ccid_bulk_message_header_t;
uint8_t SendBuffer[sizeof(ccid_bulk_message_header_t) + CCID_DATABLOCK_SIZE];
//stores the data p
uint8_t ReceiveBuffer[sizeof(ccid_bulk_message_header_t) + CCID_DATABLOCK_SIZE];
void CALLBACK_CCID_GetSlotStatus( void CALLBACK_CCID_GetSlotStatus(
uint8_t slot, uint8_t slot,
uint8_t seq, uint8_t seq,
struct rdr_to_pc_slot_status* responseSlotStatus) { struct rdr_to_pc_slot_status* responseSlotStatus) {
furi_check(responseSlotStatus);
furi_check(furi_hal_usb_ccid);
responseSlotStatus->bMessageType = RDR_TO_PC_SLOTSTATUS; responseSlotStatus->bMessageType = RDR_TO_PC_SLOTSTATUS;
responseSlotStatus->bSlot = slot; responseSlotStatus->bSlot = slot;
@@ -279,7 +314,7 @@ void CALLBACK_CCID_GetSlotStatus(
if(responseSlotStatus->bSlot == CCID_SLOT_INDEX) { if(responseSlotStatus->bSlot == CCID_SLOT_INDEX) {
responseSlotStatus->bError = CCID_ERROR_NOERROR; responseSlotStatus->bError = CCID_ERROR_NOERROR;
if(smartcard_inserted) { if(furi_hal_usb_ccid->smartcard_inserted) {
responseSlotStatus->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | responseSlotStatus->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDACTIVE; CCID_ICCSTATUS_PRESENTANDACTIVE;
} else { } else {
@@ -293,9 +328,16 @@ void CALLBACK_CCID_GetSlotStatus(
} }
void CALLBACK_CCID_SetParametersT0( void CALLBACK_CCID_SetParametersT0(
struct pc_to_rdr_set_parameters_t0* requestSetParametersT0, struct pc_to_rdr_set_parameters_t0* requestSetParametersT0,
struct rdr_to_pc_parameters_t0* responseSetParametersT0) { struct rdr_to_pc_parameters_t0* responseSetParametersT0) {
furi_check(requestSetParametersT0);
furi_check(responseSetParametersT0);
furi_check(furi_hal_usb_ccid);
furi_check(requestSetParametersT0->bProtocolNum == 0x00); //T0 furi_check(requestSetParametersT0->bProtocolNum == 0x00); //T0
responseSetParametersT0->bMessageType = RDR_TO_PC_PARAMETERS; responseSetParametersT0->bMessageType = RDR_TO_PC_PARAMETERS;
responseSetParametersT0->bSlot = requestSetParametersT0->bSlot; responseSetParametersT0->bSlot = requestSetParametersT0->bSlot;
responseSetParametersT0->bSeq = requestSetParametersT0->bSeq; responseSetParametersT0->bSeq = requestSetParametersT0->bSeq;
@@ -305,7 +347,7 @@ void CALLBACK_CCID_SetParametersT0(
if(responseSetParametersT0->bSlot == CCID_SLOT_INDEX) { if(responseSetParametersT0->bSlot == CCID_SLOT_INDEX) {
responseSetParametersT0->bError = CCID_ERROR_NOERROR; responseSetParametersT0->bError = CCID_ERROR_NOERROR;
if(smartcard_inserted) { if(furi_hal_usb_ccid->smartcard_inserted) {
responseSetParametersT0->bProtocolNum = requestSetParametersT0->bProtocolNum; responseSetParametersT0->bProtocolNum = requestSetParametersT0->bProtocolNum;
responseSetParametersT0->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | responseSetParametersT0->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDACTIVE; CCID_ICCSTATUS_PRESENTANDACTIVE;
@@ -323,6 +365,10 @@ void CALLBACK_CCID_IccPowerOn(
uint8_t slot, uint8_t slot,
uint8_t seq, uint8_t seq,
struct rdr_to_pc_data_block* responseDataBlock) { struct rdr_to_pc_data_block* responseDataBlock) {
furi_check(responseDataBlock);
furi_check(furi_hal_usb_ccid);
responseDataBlock->bMessageType = RDR_TO_PC_DATABLOCK; responseDataBlock->bMessageType = RDR_TO_PC_DATABLOCK;
responseDataBlock->dwLength = 0; responseDataBlock->dwLength = 0;
responseDataBlock->bSlot = slot; responseDataBlock->bSlot = slot;
@@ -330,12 +376,12 @@ void CALLBACK_CCID_IccPowerOn(
if(responseDataBlock->bSlot == CCID_SLOT_INDEX) { if(responseDataBlock->bSlot == CCID_SLOT_INDEX) {
responseDataBlock->bError = CCID_ERROR_NOERROR; responseDataBlock->bError = CCID_ERROR_NOERROR;
if(smartcard_inserted) { if(furi_hal_usb_ccid->smartcard_inserted) {
if(callbacks[CCID_SLOT_INDEX] != NULL) { if(furi_hal_usb_ccid->callbacks[CCID_SLOT_INDEX] != NULL) {
callbacks[CCID_SLOT_INDEX]->icc_power_on_callback( furi_hal_usb_ccid->callbacks[CCID_SLOT_INDEX]->icc_power_on_callback(
responseDataBlock->abData, responseDataBlock->abData,
&responseDataBlock->dwLength, &responseDataBlock->dwLength,
cb_ctx[CCID_SLOT_INDEX]); furi_hal_usb_ccid->cb_ctx[CCID_SLOT_INDEX]);
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDACTIVE; CCID_ICCSTATUS_PRESENTANDACTIVE;
} else { } else {
@@ -355,6 +401,11 @@ void CALLBACK_CCID_IccPowerOn(
void CALLBACK_CCID_XfrBlock( void CALLBACK_CCID_XfrBlock(
struct pc_to_rdr_xfr_block* receivedXfrBlock, struct pc_to_rdr_xfr_block* receivedXfrBlock,
struct rdr_to_pc_data_block* responseDataBlock) { struct rdr_to_pc_data_block* responseDataBlock) {
furi_check(receivedXfrBlock);
furi_check(responseDataBlock);
furi_check(furi_hal_usb_ccid);
responseDataBlock->bMessageType = RDR_TO_PC_DATABLOCK; responseDataBlock->bMessageType = RDR_TO_PC_DATABLOCK;
responseDataBlock->bSlot = receivedXfrBlock->bSlot; responseDataBlock->bSlot = receivedXfrBlock->bSlot;
responseDataBlock->bSeq = receivedXfrBlock->bSeq; responseDataBlock->bSeq = receivedXfrBlock->bSeq;
@@ -362,14 +413,14 @@ void CALLBACK_CCID_XfrBlock(
if(responseDataBlock->bSlot == CCID_SLOT_INDEX) { if(responseDataBlock->bSlot == CCID_SLOT_INDEX) {
responseDataBlock->bError = CCID_ERROR_NOERROR; responseDataBlock->bError = CCID_ERROR_NOERROR;
if(smartcard_inserted) { if(furi_hal_usb_ccid->smartcard_inserted) {
if(callbacks[CCID_SLOT_INDEX] != NULL) { if(furi_hal_usb_ccid->callbacks[CCID_SLOT_INDEX] != NULL) {
callbacks[CCID_SLOT_INDEX]->xfr_datablock_callback( furi_hal_usb_ccid->callbacks[CCID_SLOT_INDEX]->xfr_datablock_callback(
(const uint8_t*)receivedXfrBlock->abData, (const uint8_t*)receivedXfrBlock->abData,
receivedXfrBlock->dwLength, receivedXfrBlock->dwLength,
responseDataBlock->abData, responseDataBlock->abData,
&responseDataBlock->dwLength, &responseDataBlock->dwLength,
cb_ctx[CCID_SLOT_INDEX]); furi_hal_usb_ccid->cb_ctx[CCID_SLOT_INDEX]);
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
CCID_ICCSTATUS_PRESENTANDACTIVE; CCID_ICCSTATUS_PRESENTANDACTIVE;
} else { } else {
@@ -386,118 +437,177 @@ void CALLBACK_CCID_XfrBlock(
} }
} }
void furi_hal_ccid_ccid_insert_smartcard(void) { void furi_hal_usb_ccid_insert_smartcard(void) {
smartcard_inserted = true; furi_check(furi_hal_usb_ccid);
furi_hal_usb_ccid->smartcard_inserted = true;
} }
void furi_hal_ccid_ccid_remove_smartcard(void) { void furi_hal_usb_ccid_remove_smartcard(void) {
smartcard_inserted = false; furi_check(furi_hal_usb_ccid);
furi_hal_usb_ccid->smartcard_inserted = false;
} }
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb, void* context) { void furi_hal_usb_ccid_set_callbacks(CcidCallbacks* cb, void* context) {
callbacks[CCID_SLOT_INDEX] = cb; furi_check(furi_hal_usb_ccid);
cb_ctx[CCID_SLOT_INDEX] = context;
furi_hal_usb_ccid->callbacks[CCID_SLOT_INDEX] = cb;
furi_hal_usb_ccid->cb_ctx[CCID_SLOT_INDEX] = context;
}
void ccid_send_packet(uint8_t* data, uint8_t len) {
furi_check(furi_hal_usb_ccid);
if(furi_hal_usb_ccid->ccid_semaphore == NULL || furi_hal_usb_ccid->connected == false) return;
furi_check(
furi_semaphore_acquire(furi_hal_usb_ccid->ccid_semaphore, FuriWaitForever) ==
FuriStatusOk);
if(furi_hal_usb_ccid->connected == true) {
usbd_ep_write(furi_hal_usb_ccid->usb_dev, CCID_IN_EPADDR, data, len);
}
}
void ccid_send_response(uint8_t* data, uint32_t len) {
uint32_t data_to_send = len;
uint32_t data_index = 0;
while(data_to_send >= CCID_EPSIZE) {
ccid_send_packet(&data[data_index], CCID_EPSIZE);
data_to_send = data_to_send - CCID_EPSIZE;
data_index = data_index + CCID_EPSIZE;
}
ccid_send_packet(&data[data_index], data_to_send);
} }
static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
UNUSED(dev); UNUSED(dev);
UNUSED(event); UNUSED(event);
UNUSED(ep); UNUSED(ep);
furi_check(furi_hal_usb_ccid);
furi_semaphore_release(furi_hal_usb_ccid->ccid_semaphore);
} }
static void ccid_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { static void ccid_tx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
UNUSED(dev); UNUSED(dev);
UNUSED(ep);
if(event == usbd_evt_eprx) { if(event == usbd_evt_eprx) {
if(connected == false) return; furi_check(furi_hal_usb_ccid);
//read initial CCID message header
int32_t bytes_read = usbd_ep_read( int32_t bytes_read = usbd_ep_read(
usb_dev, ep, &ReceiveBuffer, sizeof(ccid_bulk_message_header_t) + CCID_DATABLOCK_SIZE); furi_hal_usb_ccid->usb_dev,
//minimum request size is header size CCID_OUT_EPADDR,
furi_check((uint16_t)bytes_read >= sizeof(ccid_bulk_message_header_t)); &furi_hal_usb_ccid->receive_buffer[furi_hal_usb_ccid->receive_buffer_data_index],
ccid_bulk_message_header_t* message = (ccid_bulk_message_header_t*)&ReceiveBuffer; //-V641 CCID_EPSIZE);
if(message->bMessageType == PC_TO_RDR_ICCPOWERON) { if(bytes_read > 0) {
struct pc_to_rdr_icc_power_on* requestDataBlock = furi_hal_usb_ccid->receive_buffer_data_index =
(struct pc_to_rdr_icc_power_on*)message; //-V641 furi_hal_usb_ccid->receive_buffer_data_index + bytes_read;
struct rdr_to_pc_data_block* responseDataBlock =
(struct rdr_to_pc_data_block*)&SendBuffer;
CALLBACK_CCID_IccPowerOn( furi_thread_flags_set(
requestDataBlock->bSlot, requestDataBlock->bSeq, responseDataBlock); furi_thread_get_id(furi_hal_usb_ccid->ccid_thread), WorkerEvtRequest);
usbd_ep_write(
usb_dev,
CCID_IN_EPADDR,
responseDataBlock,
sizeof(struct rdr_to_pc_data_block) +
(sizeof(uint8_t) * responseDataBlock->dwLength));
} else if(message->bMessageType == PC_TO_RDR_ICCPOWEROFF) {
struct pc_to_rdr_icc_power_off* requestIccPowerOff =
(struct pc_to_rdr_icc_power_off*)message; //-V641
struct rdr_to_pc_slot_status* responseSlotStatus =
(struct rdr_to_pc_slot_status*)&SendBuffer; //-V641
CALLBACK_CCID_GetSlotStatus(
requestIccPowerOff->bSlot, requestIccPowerOff->bSeq, responseSlotStatus);
usbd_ep_write(
usb_dev, CCID_IN_EPADDR, responseSlotStatus, sizeof(struct rdr_to_pc_slot_status));
} else if(message->bMessageType == PC_TO_RDR_GETSLOTSTATUS) {
struct pc_to_rdr_get_slot_status* requestSlotStatus =
(struct pc_to_rdr_get_slot_status*)message; //-V641
struct rdr_to_pc_slot_status* responseSlotStatus =
(struct rdr_to_pc_slot_status*)&SendBuffer; //-V641
CALLBACK_CCID_GetSlotStatus(
requestSlotStatus->bSlot, requestSlotStatus->bSeq, responseSlotStatus);
usbd_ep_write(
usb_dev, CCID_IN_EPADDR, responseSlotStatus, sizeof(struct rdr_to_pc_slot_status));
} else if(message->bMessageType == PC_TO_RDR_XFRBLOCK) {
struct pc_to_rdr_xfr_block* receivedXfrBlock = (struct pc_to_rdr_xfr_block*)message;
struct rdr_to_pc_data_block* responseDataBlock =
(struct rdr_to_pc_data_block*)&SendBuffer;
furi_check(receivedXfrBlock->dwLength <= CCID_DATABLOCK_SIZE);
furi_check(
(uint16_t)bytes_read >=
sizeof(ccid_bulk_message_header_t) + receivedXfrBlock->dwLength);
CALLBACK_CCID_XfrBlock(receivedXfrBlock, responseDataBlock);
furi_check(responseDataBlock->dwLength <= CCID_DATABLOCK_SIZE);
usbd_ep_write(
usb_dev,
CCID_IN_EPADDR,
responseDataBlock,
sizeof(struct rdr_to_pc_data_block) +
(sizeof(uint8_t) * responseDataBlock->dwLength));
} else if(message->bMessageType == PC_TO_RDR_SETPARAMETERS) {
struct pc_to_rdr_set_parameters_t0* requestSetParametersT0 =
(struct pc_to_rdr_set_parameters_t0*)message; //-V641
struct rdr_to_pc_parameters_t0* responseSetParametersT0 =
(struct rdr_to_pc_parameters_t0*)&SendBuffer; //-V641
furi_check(requestSetParametersT0->dwLength <= CCID_DATABLOCK_SIZE);
furi_check(
(uint16_t)bytes_read >=
sizeof(ccid_bulk_message_header_t) + requestSetParametersT0->dwLength);
CALLBACK_CCID_SetParametersT0(requestSetParametersT0, responseSetParametersT0);
usbd_ep_write(
usb_dev,
CCID_IN_EPADDR,
responseSetParametersT0,
sizeof(struct rdr_to_pc_parameters_t0));
} }
} }
} }
static int32_t ccid_worker(void* context) {
UNUSED(context);
while(1) {
furi_check(furi_hal_usb_ccid);
uint32_t flags = furi_thread_flags_wait(
WorkerEvtStop | WorkerEvtRequest, FuriFlagWaitAny, FuriWaitForever);
if(flags & WorkerEvtRequest) {
//read initial CCID message header
ccid_bulk_message_header_t* message =
(ccid_bulk_message_header_t*)&furi_hal_usb_ccid->receive_buffer; //-V641
furi_check(message);
if(message->bMessageType == PC_TO_RDR_ICCPOWERON) {
struct pc_to_rdr_icc_power_on* requestDataBlock =
(struct pc_to_rdr_icc_power_on*)message; //-V641
struct rdr_to_pc_data_block* responseDataBlock =
(struct rdr_to_pc_data_block*)&furi_hal_usb_ccid->send_buffer;
CALLBACK_CCID_IccPowerOn(
requestDataBlock->bSlot, requestDataBlock->bSeq, responseDataBlock);
ccid_send_response(
furi_hal_usb_ccid->send_buffer,
sizeof(struct rdr_to_pc_data_block) +
(sizeof(uint8_t) * responseDataBlock->dwLength));
furi_hal_usb_ccid->receive_buffer_data_index = 0;
} else if(message->bMessageType == PC_TO_RDR_ICCPOWEROFF) {
struct pc_to_rdr_icc_power_off* requestIccPowerOff =
(struct pc_to_rdr_icc_power_off*)message; //-V641
struct rdr_to_pc_slot_status* responseSlotStatus =
(struct rdr_to_pc_slot_status*)&furi_hal_usb_ccid->send_buffer; //-V641
CALLBACK_CCID_GetSlotStatus(
requestIccPowerOff->bSlot, requestIccPowerOff->bSeq, responseSlotStatus);
ccid_send_response(
furi_hal_usb_ccid->send_buffer, sizeof(struct rdr_to_pc_slot_status));
furi_hal_usb_ccid->receive_buffer_data_index = 0;
} else if(message->bMessageType == PC_TO_RDR_GETSLOTSTATUS) {
struct pc_to_rdr_get_slot_status* requestSlotStatus =
(struct pc_to_rdr_get_slot_status*)message; //-V641
struct rdr_to_pc_slot_status* responseSlotStatus =
(struct rdr_to_pc_slot_status*)&furi_hal_usb_ccid->send_buffer; //-V641
CALLBACK_CCID_GetSlotStatus(
requestSlotStatus->bSlot, requestSlotStatus->bSeq, responseSlotStatus);
ccid_send_response(
furi_hal_usb_ccid->send_buffer, sizeof(struct rdr_to_pc_slot_status));
furi_hal_usb_ccid->receive_buffer_data_index = 0;
} else if(message->bMessageType == PC_TO_RDR_XFRBLOCK) {
struct pc_to_rdr_xfr_block* receivedXfrBlock =
(struct pc_to_rdr_xfr_block*)message;
struct rdr_to_pc_data_block* responseDataBlock =
(struct rdr_to_pc_data_block*)&furi_hal_usb_ccid->send_buffer;
if(furi_hal_usb_ccid->receive_buffer_data_index >=
sizeof(struct pc_to_rdr_xfr_block) + receivedXfrBlock->dwLength) {
CALLBACK_CCID_XfrBlock(receivedXfrBlock, responseDataBlock);
ccid_send_response(
furi_hal_usb_ccid->send_buffer,
sizeof(struct rdr_to_pc_data_block) +
(sizeof(uint8_t) * responseDataBlock->dwLength));
furi_hal_usb_ccid->receive_buffer_data_index = 0;
}
} else if(message->bMessageType == PC_TO_RDR_SETPARAMETERS) {
struct pc_to_rdr_set_parameters_t0* requestSetParametersT0 =
(struct pc_to_rdr_set_parameters_t0*)message; //-V641
struct rdr_to_pc_parameters_t0* responseSetParametersT0 =
(struct rdr_to_pc_parameters_t0*)&furi_hal_usb_ccid->send_buffer; //-V641
CALLBACK_CCID_SetParametersT0(requestSetParametersT0, responseSetParametersT0);
ccid_send_response(
furi_hal_usb_ccid->send_buffer, sizeof(struct rdr_to_pc_parameters_t0));
furi_hal_usb_ccid->receive_buffer_data_index = 0;
}
} else if(flags & WorkerEvtStop) {
break;
}
}
return 0;
}
/* Configure endpoints */ /* Configure endpoints */
static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg) { static usbd_respond ccid_ep_config(usbd_device* dev, uint8_t cfg) {
switch(cfg) { switch(cfg) {

View File

@@ -1,9 +1,11 @@
#pragma once #pragma once
#include "hid_usage_desktop.h" #include "hid_usage_desktop.h"
#include "hid_usage_button.h" #include "hid_usage_button.h"
#include "hid_usage_keyboard.h" #include "hid_usage_keyboard.h"
#include "hid_usage_consumer.h" #include "hid_usage_consumer.h"
#include "hid_usage_led.h" #include "hid_usage_led.h"
#include <stdint.h>
#define CCID_SHORT_APDU_SIZE (0xFF) #define CCID_SHORT_APDU_SIZE (0xFF)
@@ -28,10 +30,18 @@ typedef struct {
void* context); void* context);
} CcidCallbacks; } CcidCallbacks;
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb, void* context); /** Set CCID callbacks
*
* @param cb CcidCallbacks instance
* @param context The context for callbacks
*/
void furi_hal_usb_ccid_set_callbacks(CcidCallbacks* cb, void* context);
void furi_hal_ccid_ccid_insert_smartcard(void); /** Insert Smart Card */
void furi_hal_ccid_ccid_remove_smartcard(void); void furi_hal_usb_ccid_insert_smartcard(void);
/** Remove Smart Card */
void furi_hal_usb_ccid_remove_smartcard(void);
#ifdef __cplusplus #ifdef __cplusplus
} }