forked from Flipper-XFW/Xtreme-Firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'Flipper-XFW:dev' into dev
- Loading branch information
Showing
160 changed files
with
8,490 additions
and
3,254 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
App( | ||
appid="ccid_test", | ||
name="CCID Debug", | ||
apptype=FlipperAppType.DEBUG, | ||
entry_point="ccid_test_app", | ||
cdefines=["CCID_TEST"], | ||
requires=[ | ||
"gui", | ||
], | ||
provides=[ | ||
"ccid_test", | ||
], | ||
stack_size=1 * 1024, | ||
order=120, | ||
fap_category="Debug", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
#include <stdint.h> | ||
#include <furi.h> | ||
#include <furi_hal.h> | ||
|
||
#include <gui/view.h> | ||
#include <gui/view_dispatcher.h> | ||
#include <gui/modules/submenu.h> | ||
#include <gui/gui.h> | ||
|
||
#include "iso7816_t0_apdu.h" | ||
|
||
typedef enum { | ||
EventTypeInput, | ||
} EventType; | ||
|
||
typedef struct { | ||
Gui* gui; | ||
ViewPort* view_port; | ||
FuriMessageQueue* event_queue; | ||
FuriHalUsbCcidConfig ccid_cfg; | ||
} CcidTestApp; | ||
|
||
typedef struct { | ||
union { | ||
InputEvent input; | ||
}; | ||
EventType type; | ||
} CcidTestAppEvent; | ||
|
||
typedef enum { | ||
CcidTestSubmenuIndexInsertSmartcard, | ||
CcidTestSubmenuIndexRemoveSmartcard, | ||
CcidTestSubmenuIndexInsertSmartcardReader | ||
} SubmenuIndex; | ||
|
||
void icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) { | ||
UNUSED(context); | ||
|
||
iso7816_answer_to_reset(atrBuffer, atrlen); | ||
} | ||
|
||
void xfr_datablock_callback(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context) { | ||
UNUSED(context); | ||
|
||
struct ISO7816_Response_APDU responseAPDU; | ||
//class not supported | ||
responseAPDU.SW1 = 0x6E; | ||
responseAPDU.SW2 = 0x00; | ||
|
||
iso7816_write_response_apdu(&responseAPDU, dataBlock, dataBlockLen); | ||
} | ||
|
||
static const CcidCallbacks ccid_cb = { | ||
icc_power_on_callback, | ||
xfr_datablock_callback, | ||
}; | ||
|
||
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) { | ||
UNUSED(ctx); | ||
canvas_clear(canvas); | ||
|
||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str(canvas, 0, 10, "CCID Test App"); | ||
|
||
canvas_set_font(canvas, FontSecondary); | ||
canvas_draw_str(canvas, 0, 63, "Hold [back] to exit"); | ||
} | ||
|
||
static void ccid_test_app__input_callback(InputEvent* input_event, void* ctx) { | ||
FuriMessageQueue* event_queue = ctx; | ||
|
||
CcidTestAppEvent event; | ||
event.type = EventTypeInput; | ||
event.input = *input_event; | ||
furi_message_queue_put(event_queue, &event, FuriWaitForever); | ||
} | ||
|
||
uint32_t ccid_test_exit(void* context) { | ||
UNUSED(context); | ||
return VIEW_NONE; | ||
} | ||
|
||
CcidTestApp* ccid_test_app_alloc() { | ||
CcidTestApp* app = malloc(sizeof(CcidTestApp)); | ||
|
||
// Gui | ||
app->gui = furi_record_open(RECORD_GUI); | ||
|
||
//viewport | ||
app->view_port = view_port_alloc(); | ||
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen); | ||
view_port_draw_callback_set(app->view_port, ccid_test_app_render_callback, NULL); | ||
|
||
//message queue | ||
app->event_queue = furi_message_queue_alloc(8, sizeof(CcidTestAppEvent)); | ||
furi_check(app->event_queue); | ||
view_port_input_callback_set(app->view_port, ccid_test_app__input_callback, app->event_queue); | ||
|
||
return app; | ||
} | ||
|
||
void ccid_test_app_free(CcidTestApp* app) { | ||
furi_assert(app); | ||
|
||
//message queue | ||
furi_message_queue_free(app->event_queue); | ||
|
||
//view port | ||
gui_remove_view_port(app->gui, app->view_port); | ||
view_port_free(app->view_port); | ||
|
||
// Close gui record | ||
furi_record_close(RECORD_GUI); | ||
app->gui = NULL; | ||
|
||
// Free rest | ||
free(app); | ||
} | ||
|
||
int32_t ccid_test_app(void* p) { | ||
UNUSED(p); | ||
|
||
//setup view | ||
CcidTestApp* app = ccid_test_app_alloc(); | ||
|
||
//setup CCID USB | ||
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist | ||
app->ccid_cfg.vid = 0x1234; | ||
app->ccid_cfg.pid = 0x5678; | ||
|
||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); | ||
furi_hal_usb_unlock(); | ||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb); | ||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true); | ||
|
||
//handle button events | ||
CcidTestAppEvent event; | ||
while(1) { | ||
FuriStatus event_status = | ||
furi_message_queue_get(app->event_queue, &event, FuriWaitForever); | ||
|
||
if(event_status == FuriStatusOk) { | ||
if(event.type == EventTypeInput) { | ||
if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) { | ||
break; | ||
} | ||
} | ||
} | ||
view_port_update(app->view_port); | ||
} | ||
|
||
//tear down USB | ||
furi_hal_usb_set_config(usb_mode_prev, NULL); | ||
furi_hal_ccid_set_callbacks(NULL); | ||
|
||
//teardown view | ||
ccid_test_app_free(app); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* Implements rudimentary iso7816-3 support for APDU (T=0) */ | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <furi.h> | ||
#include "iso7816_t0_apdu.h" | ||
|
||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen) { | ||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00 | ||
uint8_t AtrBuffer[2] = { | ||
0x3B, //TS (direct convention) | ||
0x00 // T0 (Y(1): b0000, K: 0 (historical bytes)) | ||
}; | ||
*atrlen = 2; | ||
|
||
memcpy(atrBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen)); | ||
} | ||
|
||
void iso7816_read_command_apdu( | ||
struct ISO7816_Command_APDU* command, | ||
const uint8_t* dataBuffer, | ||
uint32_t dataLen) { | ||
furi_assert(dataLen <= 4); | ||
command->CLA = dataBuffer[0]; | ||
command->INS = dataBuffer[1]; | ||
command->P1 = dataBuffer[2]; | ||
command->P2 = dataBuffer[3]; | ||
} | ||
|
||
void iso7816_write_response_apdu( | ||
const struct ISO7816_Response_APDU* response, | ||
uint8_t* dataBuffer, | ||
uint32_t* dataLen) { | ||
dataBuffer[0] = response->SW1; | ||
dataBuffer[1] = response->SW2; | ||
*dataLen = 2; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#ifndef _ISO7816_T0_APDU_H_ | ||
#define _ISO7816_T0_APDU_H_ | ||
|
||
#include <stdint.h> | ||
|
||
struct ISO7816_Command_APDU { | ||
//header | ||
uint8_t CLA; | ||
uint32_t INS; | ||
uint8_t P1; | ||
uint8_t P2; | ||
|
||
//body | ||
uint8_t Nc; | ||
uint8_t Ne; | ||
} __attribute__((packed)); | ||
|
||
struct ISO7816_Response_APDU { | ||
uint8_t SW1; | ||
uint32_t SW2; | ||
} __attribute__((packed)); | ||
|
||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen); | ||
void iso7816_read_command_apdu( | ||
struct ISO7816_Command_APDU* command, | ||
const uint8_t* dataBuffer, | ||
uint32_t dataLen); | ||
void iso7816_write_response_apdu( | ||
const struct ISO7816_Response_APDU* response, | ||
uint8_t* dataBuffer, | ||
uint32_t* dataLen); | ||
#endif //_ISO7816_T0_APDU_H_ |
Oops, something went wrong.