diff --git a/ccid.c b/ccid.c index 45d4bc9..0b6cabe 100644 --- a/ccid.c +++ b/ccid.c @@ -78,16 +78,15 @@ void seader_ccid_GetSlotStatus(SeaderUartBridge* seader_uart, uint8_t slot) { furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx); } -void seader_ccid_SetParameters(Seader* seader, uint8_t slot, uint8_t* atr, size_t atr_len) { +void seader_ccid_SetParameters(Seader* seader, uint8_t slot) { SeaderWorker* seader_worker = seader->worker; SeaderUartBridge* seader_uart = seader_worker->uart; - UNUSED(atr_len); FURI_LOG_D(TAG, "seader_ccid_SetParameters(%d)", slot); uint8_t payloadLen = 0; if(seader_uart->T == 0) { payloadLen = 5; - } else if(atr[4] == 0xB1 && seader_uart->T == 1) { + } else if(seader_uart->T == 1) { payloadLen = 7; } memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE); @@ -101,20 +100,31 @@ void seader_ccid_SetParameters(Seader* seader, uint8_t slot, uint8_t* atr, size_ seader_uart->tx_buf[2 + 8] = 0; seader_uart->tx_buf[2 + 9] = 0; + uint8_t* atr = seader->ATR; + seader_uart->IFSC = atr[5]; + if(seader_uart->T == 0) { // I'm leaving this here for completeness, but it was actually causing ICC_MUTE on the first apdu. - seader_uart->tx_buf[2 + 10] = 0x96; //atr[2]; //bmFindexDindex + seader_uart->tx_buf[2 + 10] = 0x11; //atr[2]; //bmFindexDindex seader_uart->tx_buf[2 + 11] = 0x00; //bmTCCKST1 seader_uart->tx_buf[2 + 12] = 0x00; //bGuardTimeT0 seader_uart->tx_buf[2 + 13] = 0x0a; //bWaitingIntegerT0 seader_uart->tx_buf[2 + 14] = 0x00; //bClockStop - } else if(seader_uart->T == 1) { + } else if(atr[4] == 0xB1 && seader_uart->T == 1) { seader_uart->tx_buf[2 + 10] = atr[2]; //bmFindexDindex seader_uart->tx_buf[2 + 11] = 0x10; //bmTCCKST1 seader_uart->tx_buf[2 + 12] = 0xfe; //bGuardTimeT1 seader_uart->tx_buf[2 + 13] = atr[6]; //bWaitingIntegerT1 seader_uart->tx_buf[2 + 14] = atr[8]; //bClockStop - seader_uart->tx_buf[2 + 15] = atr[5]; //bIFSC + seader_uart->tx_buf[2 + 15] = seader_uart->IFSC; //bIFSC + seader_uart->tx_buf[2 + 16] = 0x00; //bNadValue + } else if(seader_uart->T == 1) { + seader_uart->tx_buf[2 + 10] = 0x11; //atr[2]; //bmFindexDindex + seader_uart->tx_buf[2 + 11] = 0x10; //bmTCCKST1 + seader_uart->tx_buf[2 + 12] = 0x00; //bGuardTimeT1 + seader_uart->tx_buf[2 + 13] = 0x4d; //atr[6]; //bWaitingIntegerT1 + seader_uart->tx_buf[2 + 14] = 0x00; //atr[8]; //bClockStop + seader_uart->tx_buf[2 + 15] = seader_uart->IFSC; //bIFSC seader_uart->tx_buf[2 + 16] = 0x00; //bNadValue } @@ -373,27 +383,31 @@ size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) { FURI_LOG_I(TAG, "SAM ATR!"); hasSAM = true; sam_slot = message.bSlot; + seader->ATR_len = sizeof(SAM_ATR); + memcpy(seader->ATR, message.payload, seader->ATR_len); if(seader_uart->T == 0) { seader_ccid_GetParameters(seader_uart); } else if(seader_uart->T == 1) { - seader_ccid_SetParameters( - seader, sam_slot, message.payload, message.dwLength); + seader_ccid_SetParameters(seader, sam_slot); } } else if(memcmp(SAM_ATR2, message.payload, sizeof(SAM_ATR2)) == 0) { FURI_LOG_I(TAG, "SAM ATR2!"); hasSAM = true; sam_slot = message.bSlot; + seader->ATR_len = sizeof(SAM_ATR); + memcpy(seader->ATR, message.payload, seader->ATR_len); // I don't have an ATR2 to test with seader_ccid_GetParameters(seader_uart); } else if(memcmp(SAM_ATR3, message.payload, sizeof(SAM_ATR3)) == 0) { FURI_LOG_I(TAG, "SAM ATR3!"); hasSAM = true; sam_slot = message.bSlot; + seader->ATR_len = sizeof(SAM_ATR); + memcpy(seader->ATR, message.payload, seader->ATR_len); if(seader_uart->T == 0) { seader_ccid_GetParameters(seader_uart); } else if(seader_uart->T == 1) { - seader_ccid_SetParameters( - seader, sam_slot, message.payload, message.dwLength); + seader_ccid_SetParameters(seader, sam_slot); } } else { FURI_LOG_W(TAG, "Unknown ATR"); diff --git a/ccid.h b/ccid.h index ab2c917..33a2489 100644 --- a/ccid.h +++ b/ccid.h @@ -99,7 +99,6 @@ struct CCID_Message { void seader_ccid_check_for_sam(SeaderUartBridge* seader_uart); void seader_ccid_IccPowerOn(SeaderUartBridge* seader_uart, uint8_t slot); void seader_ccid_GetSlotStatus(SeaderUartBridge* seader_uart, uint8_t slot); -void seader_ccid_SetParameters(Seader* seader, uint8_t slot, uint8_t* atr, size_t atr_len); void seader_ccid_GetParameters(SeaderUartBridge* seader_uart); void seader_ccid_XfrBlock(SeaderUartBridge* seader_uart, uint8_t* data, size_t len); void seader_ccid_XfrBlockToSlot( diff --git a/seader_bridge.h b/seader_bridge.h index 0c68abe..32eefa8 100644 --- a/seader_bridge.h +++ b/seader_bridge.h @@ -45,6 +45,7 @@ struct SeaderUartBridge { // T=0 or T=1 uint8_t T; + uint8_t IFSC; }; typedef struct SeaderUartBridge SeaderUartBridge; diff --git a/seader_i.h b/seader_i.h index d6305b8..8854160 100644 --- a/seader_i.h +++ b/seader_i.h @@ -63,6 +63,7 @@ #define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtSamRx) #define SEADER_TEXT_STORE_SIZE 128 +#define SEADER_MAX_ATR_SIZE 33 enum SeaderCustomEvent { // Reserve first 100 events for button types and indexes, starting from 0 @@ -107,6 +108,8 @@ struct Seader { SeaderUartBridge* uart; SeaderCredential* credential; SamCommand_PR samCommand; + uint8_t ATR[SEADER_MAX_ATR_SIZE]; + size_t ATR_len; char text_store[SEADER_TEXT_STORE_SIZE + 1]; FuriString* text_box_store; diff --git a/t_1.c b/t_1.c index 4ee9baf..f750a46 100644 --- a/t_1.c +++ b/t_1.c @@ -7,10 +7,10 @@ /* I know my T=1 is terrible, but I'm also only targetting one specific 'card' */ #define MORE_BIT 0x20 -#define IFSD_VALUE 0xfe -#define IFSC_VALUE 0xfe // Fom the SAM ATR #define R_BLOCK 0x80 +#define S_BLOCK 0xC0 #define R_SEQUENCE_NUMBER_MASK 0x10 +#define T1_S_IFS 0x01 // TODO: T1 struct uint8_t NAD = 0x00; @@ -44,9 +44,26 @@ void seader_t_1_set_IFSD(Seader* seader) { uint8_t frame_len = 0; frame[0] = NAD; - frame[1] = 0xC1; // S(IFS request) + frame[1] = S_BLOCK | T1_S_IFS; // S(IFS request) frame[2] = 0x01; - frame[3] = IFSD_VALUE; + frame[3] = seader_uart->IFSC; + frame_len = 4; + + frame_len = seader_add_lrc(frame, frame_len); + + seader_ccid_XfrBlock(seader_uart, frame, frame_len); +} + +void seader_t_1_IFSD_response(Seader* seader) { + SeaderWorker* seader_worker = seader->worker; + SeaderUartBridge* seader_uart = seader_worker->uart; + uint8_t frame[5]; + uint8_t frame_len = 0; + + frame[0] = NAD; + frame[1] = 0xE0 | 0x01; // S(IFS response) + frame[2] = 0x01; + frame[3] = seader_uart->IFSC; frame_len = 4; frame_len = seader_add_lrc(frame, frame_len); @@ -96,19 +113,21 @@ void seader_send_t1_chunk(SeaderUartBridge* seader_uart, uint8_t PCB, uint8_t* c } void seader_send_t1(SeaderUartBridge* seader_uart, uint8_t* apdu, size_t len) { - if(len > IFSC_VALUE) { + uint8_t ifsc = seader_uart->IFSC; + + if(len > ifsc) { if(seader_t_1_tx_buffer == NULL) { seader_t_1_tx_buffer = bit_buffer_alloc(768); bit_buffer_copy_bytes(seader_t_1_tx_buffer, apdu, len); } size_t remaining = (bit_buffer_get_size_bytes(seader_t_1_tx_buffer) - seader_t_1_tx_buffer_offset); - size_t copy_length = remaining > IFSC_VALUE ? IFSC_VALUE : remaining; + size_t copy_length = remaining > ifsc ? ifsc : remaining; uint8_t* chunk = (uint8_t*)bit_buffer_get_data(seader_t_1_tx_buffer) + seader_t_1_tx_buffer_offset; - if(remaining > IFSC_VALUE) { + if(remaining > ifsc) { uint8_t PCB = seader_next_dpcb() | MORE_BIT; seader_send_t1_chunk(seader_uart, PCB, chunk, copy_length); } else { @@ -144,6 +163,7 @@ bool seader_recv_t1(Seader* seader, CCID_Message* message) { if(rPCB == 0xE1) { // S(IFS response) + //FURI_LOG_D(TAG, "Received IFS Response"); seader_worker_send_version(seader); SeaderWorker* seader_worker = seader->worker; if(seader_worker->callback) { @@ -190,6 +210,13 @@ bool seader_recv_t1(Seader* seader, CCID_Message* message) { bit_buffer_append_bytes(seader_t_1_rx_buffer, message->payload + 3, LEN); seader_t_1_send_ack(seader); return false; + } else if((rPCB & S_BLOCK) == S_BLOCK) { + //FURI_LOG_D(TAG, "Received S-Block"); + if((rPCB & 0x0F) == T1_S_IFS) { + seader_t_1_IFSD_response(seader); + return false; + } + } else if((rPCB & R_BLOCK) == R_BLOCK) { uint8_t R_SEQ = (rPCB & R_SEQUENCE_NUMBER_MASK) >> 4; uint8_t I_SEQ = (dPCB ^ 0x40) >> 6;