mirror of
https://github.com/bettse/seader.git
synced 2026-08-29 07:38:30 +00:00
better ifsc/ifsd handling
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -45,6 +45,7 @@ struct SeaderUartBridge {
|
||||
|
||||
// T=0 or T=1
|
||||
uint8_t T;
|
||||
uint8_t IFSC;
|
||||
};
|
||||
|
||||
typedef struct SeaderUartBridge SeaderUartBridge;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user