CCID: App changes (#3837)

- Keep ccid_callback and buffer as private to the iso7816_handler
- set usb ccid callback from iso7816_handler (to ensure the right structure is being passed)
- make iso7816 related code independent from furi related code (goal is to make it independently testable)
- rename vars

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Filipe Paz Rodrigues 2024-09-05 08:04:32 -07:00 committed by GitHub
parent fa2d611652
commit 4a58930247
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 64 additions and 37 deletions

View file

@ -105,7 +105,7 @@ void ccid_test_app_free(CcidTestApp* app) {
furi_record_close(RECORD_GUI);
app->gui = NULL;
free(app->iso7816_handler);
iso7816_handler_free(app->iso7816_handler);
// Free rest
free(app);
@ -121,8 +121,7 @@ int32_t ccid_test_app(void* p) {
furi_hal_usb_unlock();
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
furi_hal_usb_ccid_set_callbacks(
(CcidCallbacks*)&app->iso7816_handler->ccid_callbacks, app->iso7816_handler);
iso7816_handler_set_usb_ccid_callbacks();
furi_hal_usb_ccid_insert_smartcard();
//handle button events
@ -142,7 +141,7 @@ int32_t ccid_test_app(void* p) {
}
//tear down USB
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
iso7816_handler_reset_usb_ccid_callbacks();
furi_hal_usb_set_config(usb_mode_prev, NULL);
//teardown view

View file

@ -6,11 +6,17 @@
#include <furi.h>
#include <furi_hal.h>
#include "iso7816_handler.h"
#include "iso7816_t0_apdu.h"
#include "iso7816_atr.h"
#include "iso7816_handler.h"
#include "iso7816_response.h"
static Iso7816Handler* iso7816_handler;
static CcidCallbacks* ccid_callbacks;
static uint8_t* command_apdu_buffer;
static uint8_t* response_apdu_buffer;
void iso7816_icc_power_on_callback(uint8_t* atr_data, uint32_t* atr_data_len, void* context) {
furi_check(context);
@ -40,12 +46,11 @@ void iso7816_xfr_datablock_callback(
Iso7816Handler* handler = (Iso7816Handler*)context;
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)&handler->response_apdu_buffer;
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)&handler->command_apdu_buffer;
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)response_apdu_buffer;
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)command_apdu_buffer;
uint8_t result = iso7816_read_command_apdu(
command_apdu, pc_to_reader_datablock, pc_to_reader_datablock_len);
command_apdu, pc_to_reader_datablock, pc_to_reader_datablock_len, CCID_SHORT_APDU_SIZE);
if(result == ISO7816_READ_COMMAND_APDU_OK) {
handler->iso7816_process_command(command_apdu, response_apdu);
@ -61,8 +66,31 @@ void iso7816_xfr_datablock_callback(
}
Iso7816Handler* iso7816_handler_alloc() {
Iso7816Handler* handler = malloc(sizeof(Iso7816Handler));
handler->ccid_callbacks.icc_power_on_callback = iso7816_icc_power_on_callback;
handler->ccid_callbacks.xfr_datablock_callback = iso7816_xfr_datablock_callback;
return handler;
iso7816_handler = malloc(sizeof(Iso7816Handler));
command_apdu_buffer = malloc(sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE);
response_apdu_buffer = malloc(sizeof(ISO7816_Response_APDU) + CCID_SHORT_APDU_SIZE);
ccid_callbacks = malloc(sizeof(CcidCallbacks));
ccid_callbacks->icc_power_on_callback = iso7816_icc_power_on_callback;
ccid_callbacks->xfr_datablock_callback = iso7816_xfr_datablock_callback;
return iso7816_handler;
}
void iso7816_handler_set_usb_ccid_callbacks() {
furi_hal_usb_ccid_set_callbacks(ccid_callbacks, iso7816_handler);
}
void iso7816_handler_reset_usb_ccid_callbacks() {
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
}
void iso7816_handler_free(Iso7816Handler* handler) {
free(ccid_callbacks);
free(command_apdu_buffer);
free(response_apdu_buffer);
free(handler);
}

View file

@ -5,14 +5,14 @@
#include "iso7816_t0_apdu.h"
typedef struct {
CcidCallbacks ccid_callbacks;
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
void (*iso7816_process_command)(
const ISO7816_Command_APDU* command,
ISO7816_Response_APDU* response);
uint8_t command_apdu_buffer[sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE];
uint8_t response_apdu_buffer[sizeof(ISO7816_Response_APDU) + CCID_SHORT_APDU_SIZE];
} Iso7816Handler;
Iso7816Handler* iso7816_handler_alloc();
void iso7816_handler_free(Iso7816Handler* handler);
void iso7816_handler_set_usb_ccid_callbacks();
void iso7816_handler_reset_usb_ccid_callbacks();

View file

@ -1,49 +1,48 @@
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
#include <stdint.h>
#include <string.h>
#include <furi.h>
#include <furi_hal.h>
#include "iso7816_t0_apdu.h"
//reads dataBuffer with dataLen size, translate it into a ISO7816_Command_APDU type
//reads pc_to_reader_datablock_len with pc_to_reader_datablock_len size, translate it into a ISO7816_Command_APDU type
//extra data will be pointed to commandDataBuffer
uint8_t iso7816_read_command_apdu(
ISO7816_Command_APDU* command,
const uint8_t* dataBuffer,
uint32_t dataLen) {
command->CLA = dataBuffer[0];
command->INS = dataBuffer[1];
command->P1 = dataBuffer[2];
command->P2 = dataBuffer[3];
const uint8_t* pc_to_reader_datablock,
uint32_t pc_to_reader_datablock_len,
uint32_t max_apdu_size) {
command->CLA = pc_to_reader_datablock[0];
command->INS = pc_to_reader_datablock[1];
command->P1 = pc_to_reader_datablock[2];
command->P2 = pc_to_reader_datablock[3];
if(dataLen == 4) {
if(pc_to_reader_datablock_len == 4) {
command->Lc = 0;
command->Le = 0;
command->LePresent = false;
return ISO7816_READ_COMMAND_APDU_OK;
} else if(dataLen == 5) {
} else if(pc_to_reader_datablock_len == 5) {
//short le
command->Lc = 0;
command->Le = dataBuffer[4];
command->Le = pc_to_reader_datablock[4];
command->LePresent = true;
return ISO7816_READ_COMMAND_APDU_OK;
} else if(dataLen > 5 && dataBuffer[4] != 0x00) {
} else if(pc_to_reader_datablock_len > 5 && pc_to_reader_datablock[4] != 0x00) {
//short lc
command->Lc = dataBuffer[4];
if(command->Lc > 0 && command->Lc < CCID_SHORT_APDU_SIZE) { //-V560
memcpy(command->Data, &dataBuffer[5], command->Lc);
command->Lc = pc_to_reader_datablock[4];
if(command->Lc > 0 && command->Lc < max_apdu_size) { //-V560
memcpy(command->Data, &pc_to_reader_datablock[5], command->Lc);
//does it have a short le too?
if(dataLen == (uint32_t)(command->Lc + 5)) {
if(pc_to_reader_datablock_len == (uint32_t)(command->Lc + 5)) {
command->Le = 0;
command->LePresent = false;
return ISO7816_READ_COMMAND_APDU_OK;
} else if(dataLen == (uint32_t)(command->Lc + 6)) {
command->Le = dataBuffer[dataLen - 1];
} else if(pc_to_reader_datablock_len == (uint32_t)(command->Lc + 6)) {
command->Le = pc_to_reader_datablock[pc_to_reader_datablock_len - 1];
command->LePresent = true;
return ISO7816_READ_COMMAND_APDU_OK;

View file

@ -34,7 +34,8 @@ typedef struct {
uint8_t iso7816_read_command_apdu(
ISO7816_Command_APDU* command,
const uint8_t* pc_to_reader_datablock,
uint32_t pc_to_reader_datablock_len);
uint32_t pc_to_reader_datablock_len,
uint32_t max_apdu_size);
void iso7816_write_response_apdu(
const ISO7816_Response_APDU* response,
uint8_t* reader_to_pc_datablock,