mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
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:
committed by
GitHub
parent
fa2d611652
commit
4a58930247
@@ -105,7 +105,7 @@ void ccid_test_app_free(CcidTestApp* app) {
|
|||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
app->gui = NULL;
|
app->gui = NULL;
|
||||||
|
|
||||||
free(app->iso7816_handler);
|
iso7816_handler_free(app->iso7816_handler);
|
||||||
|
|
||||||
// Free rest
|
// Free rest
|
||||||
free(app);
|
free(app);
|
||||||
@@ -121,8 +121,7 @@ int32_t ccid_test_app(void* p) {
|
|||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
|
|
||||||
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(
|
iso7816_handler_set_usb_ccid_callbacks();
|
||||||
(CcidCallbacks*)&app->iso7816_handler->ccid_callbacks, app->iso7816_handler);
|
|
||||||
furi_hal_usb_ccid_insert_smartcard();
|
furi_hal_usb_ccid_insert_smartcard();
|
||||||
|
|
||||||
//handle button events
|
//handle button events
|
||||||
@@ -142,7 +141,7 @@ int32_t ccid_test_app(void* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//tear down USB
|
//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);
|
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||||
|
|
||||||
//teardown view
|
//teardown view
|
||||||
|
|||||||
@@ -6,11 +6,17 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#include "iso7816_handler.h"
|
||||||
|
|
||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
#include "iso7816_atr.h"
|
#include "iso7816_atr.h"
|
||||||
#include "iso7816_handler.h"
|
|
||||||
#include "iso7816_response.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) {
|
void iso7816_icc_power_on_callback(uint8_t* atr_data, uint32_t* atr_data_len, void* context) {
|
||||||
furi_check(context);
|
furi_check(context);
|
||||||
|
|
||||||
@@ -40,12 +46,11 @@ void iso7816_xfr_datablock_callback(
|
|||||||
|
|
||||||
Iso7816Handler* handler = (Iso7816Handler*)context;
|
Iso7816Handler* handler = (Iso7816Handler*)context;
|
||||||
|
|
||||||
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)&handler->response_apdu_buffer;
|
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)response_apdu_buffer;
|
||||||
|
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)command_apdu_buffer;
|
||||||
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)&handler->command_apdu_buffer;
|
|
||||||
|
|
||||||
uint8_t result = iso7816_read_command_apdu(
|
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) {
|
if(result == ISO7816_READ_COMMAND_APDU_OK) {
|
||||||
handler->iso7816_process_command(command_apdu, response_apdu);
|
handler->iso7816_process_command(command_apdu, response_apdu);
|
||||||
@@ -61,8 +66,31 @@ void iso7816_xfr_datablock_callback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Iso7816Handler* iso7816_handler_alloc() {
|
Iso7816Handler* iso7816_handler_alloc() {
|
||||||
Iso7816Handler* handler = malloc(sizeof(Iso7816Handler));
|
iso7816_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;
|
command_apdu_buffer = malloc(sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE);
|
||||||
return handler;
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CcidCallbacks ccid_callbacks;
|
|
||||||
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
||||||
void (*iso7816_process_command)(
|
void (*iso7816_process_command)(
|
||||||
const ISO7816_Command_APDU* command,
|
const ISO7816_Command_APDU* command,
|
||||||
ISO7816_Response_APDU* response);
|
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;
|
||||||
|
|
||||||
Iso7816Handler* iso7816_handler_alloc();
|
Iso7816Handler* iso7816_handler_alloc();
|
||||||
|
|
||||||
|
void iso7816_handler_free(Iso7816Handler* handler);
|
||||||
|
void iso7816_handler_set_usb_ccid_callbacks();
|
||||||
|
void iso7816_handler_reset_usb_ccid_callbacks();
|
||||||
|
|||||||
@@ -1,49 +1,48 @@
|
|||||||
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <furi.h>
|
|
||||||
#include <furi_hal.h>
|
|
||||||
#include "iso7816_t0_apdu.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
|
//extra data will be pointed to commandDataBuffer
|
||||||
uint8_t iso7816_read_command_apdu(
|
uint8_t iso7816_read_command_apdu(
|
||||||
ISO7816_Command_APDU* command,
|
ISO7816_Command_APDU* command,
|
||||||
const uint8_t* dataBuffer,
|
const uint8_t* pc_to_reader_datablock,
|
||||||
uint32_t dataLen) {
|
uint32_t pc_to_reader_datablock_len,
|
||||||
command->CLA = dataBuffer[0];
|
uint32_t max_apdu_size) {
|
||||||
command->INS = dataBuffer[1];
|
command->CLA = pc_to_reader_datablock[0];
|
||||||
command->P1 = dataBuffer[2];
|
command->INS = pc_to_reader_datablock[1];
|
||||||
command->P2 = dataBuffer[3];
|
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->Lc = 0;
|
||||||
command->Le = 0;
|
command->Le = 0;
|
||||||
command->LePresent = false;
|
command->LePresent = false;
|
||||||
|
|
||||||
return ISO7816_READ_COMMAND_APDU_OK;
|
return ISO7816_READ_COMMAND_APDU_OK;
|
||||||
} else if(dataLen == 5) {
|
} else if(pc_to_reader_datablock_len == 5) {
|
||||||
//short le
|
//short le
|
||||||
|
|
||||||
command->Lc = 0;
|
command->Lc = 0;
|
||||||
command->Le = dataBuffer[4];
|
command->Le = pc_to_reader_datablock[4];
|
||||||
command->LePresent = true;
|
command->LePresent = true;
|
||||||
|
|
||||||
return ISO7816_READ_COMMAND_APDU_OK;
|
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
|
//short lc
|
||||||
|
|
||||||
command->Lc = dataBuffer[4];
|
command->Lc = pc_to_reader_datablock[4];
|
||||||
if(command->Lc > 0 && command->Lc < CCID_SHORT_APDU_SIZE) { //-V560
|
if(command->Lc > 0 && command->Lc < max_apdu_size) { //-V560
|
||||||
memcpy(command->Data, &dataBuffer[5], command->Lc);
|
memcpy(command->Data, &pc_to_reader_datablock[5], command->Lc);
|
||||||
|
|
||||||
//does it have a short le too?
|
//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->Le = 0;
|
||||||
command->LePresent = false;
|
command->LePresent = false;
|
||||||
return ISO7816_READ_COMMAND_APDU_OK;
|
return ISO7816_READ_COMMAND_APDU_OK;
|
||||||
} else if(dataLen == (uint32_t)(command->Lc + 6)) {
|
} else if(pc_to_reader_datablock_len == (uint32_t)(command->Lc + 6)) {
|
||||||
command->Le = dataBuffer[dataLen - 1];
|
command->Le = pc_to_reader_datablock[pc_to_reader_datablock_len - 1];
|
||||||
command->LePresent = true;
|
command->LePresent = true;
|
||||||
|
|
||||||
return ISO7816_READ_COMMAND_APDU_OK;
|
return ISO7816_READ_COMMAND_APDU_OK;
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ typedef struct {
|
|||||||
uint8_t iso7816_read_command_apdu(
|
uint8_t iso7816_read_command_apdu(
|
||||||
ISO7816_Command_APDU* command,
|
ISO7816_Command_APDU* command,
|
||||||
const uint8_t* pc_to_reader_datablock,
|
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(
|
void iso7816_write_response_apdu(
|
||||||
const ISO7816_Response_APDU* response,
|
const ISO7816_Response_APDU* response,
|
||||||
uint8_t* reader_to_pc_datablock,
|
uint8_t* reader_to_pc_datablock,
|
||||||
|
|||||||
Reference in New Issue
Block a user