[FL-1643] NFC emv assets (#661)
* assets: add EMV AID table for NFC app * file-worker: add searching for value by the key * nfc: add emv parser helpers * assets: add country and currency codes * nfc: add country and currency code parsing * emv_decoder: add country and currency code support * nfc: add AID. currency and country display * nfc: rework bank_card view * nfc: add currency and country save * assets: change emv chip asset * nfc: change asset in bank card * gui: add frame element to widget * nfc: add bank card frame, add documentation * rfal: fix long APDU command emulation * nfc: fix typos * Scripts ReadMe: assets delivery command Co-authored-by: あく <alleteam@gmail.com> Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
parent
b1bbf1730c
commit
ecff31d228
@ -150,3 +150,15 @@ void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* i
|
||||
WidgetElement* icon_element = widget_element_icon_create(x, y, icon);
|
||||
widget_add_element(widget, icon_element);
|
||||
}
|
||||
|
||||
void widget_add_frame_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius) {
|
||||
furi_assert(widget);
|
||||
WidgetElement* frame_element = widget_element_frame_create(x, y, width, height, radius);
|
||||
widget_add_element(widget, frame_element);
|
||||
}
|
||||
|
@ -59,8 +59,24 @@ void widget_add_button_element(
|
||||
|
||||
/** Add Icon Element
|
||||
* @param widget Widget instance
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param x top left x coordinate
|
||||
* @param y top left y coordinate
|
||||
* @param icon Icon instance
|
||||
*/
|
||||
void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon);
|
||||
|
||||
/** Add Frame Element
|
||||
* @param widget Widget instance
|
||||
* @param x top left x coordinate
|
||||
* @param y top left y coordinate
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param radius frame radius
|
||||
*/
|
||||
void widget_add_frame_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
||||
|
48
applications/gui/modules/widget_elements/widget_element_frame.c
Executable file
48
applications/gui/modules/widget_elements/widget_element_frame.c
Executable file
@ -0,0 +1,48 @@
|
||||
#include "widget_element_i.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t radius;
|
||||
} GuiFrameModel;
|
||||
|
||||
static void gui_frame_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiFrameModel* model = element->model;
|
||||
canvas_draw_rframe(canvas, model->x, model->y, model->width, model->height, model->radius);
|
||||
}
|
||||
|
||||
static void gui_frame_free(WidgetElement* gui_frame) {
|
||||
furi_assert(gui_frame);
|
||||
|
||||
free(gui_frame->model);
|
||||
free(gui_frame);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_frame_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius) {
|
||||
// Allocate and init model
|
||||
GuiFrameModel* model = furi_alloc(sizeof(GuiFrameModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->width = width;
|
||||
model->height = height;
|
||||
model->radius = radius;
|
||||
|
||||
// Allocate and init Element
|
||||
WidgetElement* gui_frame = furi_alloc(sizeof(WidgetElement));
|
||||
gui_frame->parent = NULL;
|
||||
gui_frame->input = NULL;
|
||||
gui_frame->draw = gui_frame_draw;
|
||||
gui_frame->free = gui_frame_free;
|
||||
gui_frame->model = model;
|
||||
|
||||
return gui_frame;
|
||||
}
|
@ -44,5 +44,13 @@ WidgetElement* widget_element_button_create(
|
||||
ButtonCallback callback,
|
||||
void* context);
|
||||
|
||||
/* Create icon element element */
|
||||
/* Create icon element */
|
||||
WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon);
|
||||
|
||||
/* Create frame element */
|
||||
WidgetElement* widget_element_frame_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
@ -1,5 +1,4 @@
|
||||
#include "widget_element_i.h"
|
||||
#include <m-string.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t x;
|
||||
|
49
applications/nfc/helpers/nfc_emv_parser.c
Executable file
49
applications/nfc/helpers/nfc_emv_parser.c
Executable file
@ -0,0 +1,49 @@
|
||||
#include "nfc_emv_parser.h"
|
||||
|
||||
#include <file-worker.h>
|
||||
|
||||
static bool
|
||||
nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) {
|
||||
bool found = false;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
|
||||
if(file_worker_open(file_worker, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name) {
|
||||
bool result = false;
|
||||
string_t key;
|
||||
string_init(key);
|
||||
for(uint8_t i = 0; i < aid_len; i++) {
|
||||
string_cat_printf(key, "%02X", aid[i]);
|
||||
}
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/aid.nfc", key, ' ', aid_name);
|
||||
string_clear(key);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) {
|
||||
bool result = false;
|
||||
string_t key;
|
||||
string_init_printf(key, "%04X", country_code);
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/country_code.nfc", key, ' ', country_name);
|
||||
string_clear(key);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) {
|
||||
bool result = false;
|
||||
string_t key;
|
||||
string_init_printf(key, "%04X", currency_code);
|
||||
result = nfc_emv_parser_get_value("/ext/nfc/emv/currency_code.nfc", key, ' ', currency_name);
|
||||
string_clear(key);
|
||||
return result;
|
||||
}
|
27
applications/nfc/helpers/nfc_emv_parser.h
Executable file
27
applications/nfc/helpers/nfc_emv_parser.h
Executable file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <m-string.h>
|
||||
|
||||
/** Get EMV application name by number
|
||||
* @param aid - AID number array
|
||||
* @param aid_len - AID length
|
||||
* @param aid_name - string to keep AID name
|
||||
* @return - true if AID found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name);
|
||||
|
||||
/** Get country name by country code
|
||||
* @param country_code - ISO 3166 country code
|
||||
* @param country_name - string to keep country name
|
||||
* @return - true if country found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name);
|
||||
|
||||
/** Get currency name by currency code
|
||||
* @param currency_code - ISO 3166 currency code
|
||||
* @param currency_name - string to keep currency name
|
||||
* @return - true if currency found, false otherwies
|
||||
*/
|
||||
bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name);
|
@ -10,7 +10,7 @@ static const char* nfc_app_folder = "/any/nfc";
|
||||
static const char* nfc_app_extension = ".nfc";
|
||||
static const char* nfc_app_shadow_extension = ".shd";
|
||||
|
||||
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) {
|
||||
static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len, uint8_t delim_len) {
|
||||
string_strim(str);
|
||||
uint8_t nibble_high = 0;
|
||||
uint8_t nibble_low = 0;
|
||||
@ -20,7 +20,7 @@ static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) {
|
||||
if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) &&
|
||||
hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) {
|
||||
buff[i] = (nibble_high << 4) | nibble_low;
|
||||
string_right(str, 3);
|
||||
string_right(str, delim_len + 2);
|
||||
} else {
|
||||
parsed = false;
|
||||
break;
|
||||
@ -81,22 +81,22 @@ bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) {
|
||||
do {
|
||||
// strlen("UID len: ") = 9
|
||||
string_right(uid_string, 9);
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1)) {
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("UID: ") = 5
|
||||
string_right(uid_string, 5);
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len)) {
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("ATQA: ") = 6
|
||||
string_right(uid_string, 6);
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2)) {
|
||||
if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2, 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("SAK: ") = 5
|
||||
string_right(uid_string, 5);
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1)) {
|
||||
if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
parsed = true;
|
||||
@ -149,13 +149,13 @@ bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string
|
||||
do {
|
||||
// strlen("Signature: ") = 11
|
||||
string_right(mifare_ul_string, 11);
|
||||
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature))) {
|
||||
if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) {
|
||||
break;
|
||||
}
|
||||
// strlen("Version: ") = 9
|
||||
string_right(mifare_ul_string, 9);
|
||||
if(!nfc_device_read_hex(
|
||||
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version))) {
|
||||
mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) {
|
||||
break;
|
||||
}
|
||||
string_strim(mifare_ul_string);
|
||||
@ -184,7 +184,7 @@ bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string
|
||||
string_right(mifare_ul_string, ws + 1);
|
||||
// Read data
|
||||
for(uint16_t i = 0; i < data->data_size; i += 4) {
|
||||
if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4)) {
|
||||
if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4, 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -208,6 +208,12 @@ uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_
|
||||
string_cat_printf(
|
||||
bank_card_string, "\nExp date: %02X/%02X", data->exp_mon, data->exp_year);
|
||||
}
|
||||
if(data->country_code) {
|
||||
string_cat_printf(bank_card_string, "\nCountry code: %04X", data->country_code);
|
||||
}
|
||||
if(data->currency_code) {
|
||||
string_cat_printf(bank_card_string, "\nCurrency code: %04X", data->currency_code);
|
||||
}
|
||||
return string_size(bank_card_string);
|
||||
}
|
||||
|
||||
@ -215,6 +221,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string
|
||||
NfcEmvData* data = &dev->dev_data.emv_data;
|
||||
bool parsed = false;
|
||||
int res = 0;
|
||||
uint8_t code[2] = {};
|
||||
memset(data, 0, sizeof(NfcEmvData));
|
||||
|
||||
do {
|
||||
@ -226,7 +233,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string
|
||||
string_right(bank_card_string, 9);
|
||||
size_t ws = string_search_char(bank_card_string, ':');
|
||||
string_right(bank_card_string, ws + 1);
|
||||
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len)) {
|
||||
if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) {
|
||||
break;
|
||||
}
|
||||
res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name);
|
||||
@ -237,7 +244,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string
|
||||
string_right(bank_card_string, ws + 1);
|
||||
// strlen("Number: ") = 8
|
||||
string_right(bank_card_string, 8);
|
||||
if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number))) {
|
||||
if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number), 1)) {
|
||||
break;
|
||||
}
|
||||
parsed = true;
|
||||
@ -246,8 +253,24 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Exp date: ") = 10
|
||||
string_right(bank_card_string, 10);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_mon, 1);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_year, 1);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_mon, 1, 1);
|
||||
nfc_device_read_hex(bank_card_string, &data->exp_year, 1, 1);
|
||||
}
|
||||
// Check country code presence
|
||||
ws = string_search_str(bank_card_string, "Country code: ");
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Country code: ") = 14
|
||||
string_right(bank_card_string, 14);
|
||||
nfc_device_read_hex(bank_card_string, code, 2, 0);
|
||||
data->country_code = code[0] << 8 | code[1];
|
||||
}
|
||||
// Check currency code presence
|
||||
ws = string_search_str(bank_card_string, "Currency code: ");
|
||||
if(ws != STRING_FAILURE) {
|
||||
// strlen("Currency code: ") = 15
|
||||
string_right(bank_card_string, 15);
|
||||
nfc_device_read_hex(bank_card_string, code, 2, 0);
|
||||
data->currency_code = code[0] << 8 | code[1];
|
||||
}
|
||||
} while(0);
|
||||
|
||||
|
@ -43,7 +43,8 @@ typedef struct {
|
||||
uint8_t number[8];
|
||||
uint8_t exp_mon;
|
||||
uint8_t exp_year;
|
||||
char cardholder[32];
|
||||
uint16_t country_code;
|
||||
uint16_t currency_code;
|
||||
} NfcEmvData;
|
||||
|
||||
typedef struct {
|
||||
|
@ -328,6 +328,12 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) {
|
||||
result->emv_data.exp_mon = emv_app.exp_month;
|
||||
result->emv_data.exp_year = emv_app.exp_year;
|
||||
}
|
||||
if(emv_app.country_code) {
|
||||
result->emv_data.country_code = emv_app.country_code;
|
||||
}
|
||||
if(emv_app.currency_code) {
|
||||
result->emv_data.currency_code = emv_app.currency_code;
|
||||
}
|
||||
// Notify caller and exit
|
||||
if(nfc_worker->callback) {
|
||||
nfc_worker->callback(nfc_worker->context);
|
||||
|
31
applications/nfc/scenes/nfc_scene_device_info.c
Normal file → Executable file
31
applications/nfc/scenes/nfc_scene_device_info.c
Normal file → Executable file
@ -1,6 +1,6 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
#define NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT (0UL)
|
||||
#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL)
|
||||
|
||||
enum {
|
||||
NfcSceneDeviceInfoUid,
|
||||
@ -8,26 +8,27 @@ enum {
|
||||
};
|
||||
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_text_box_callback(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT);
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_on_enter(void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Nfc* nfc = context;
|
||||
|
||||
// Setup Custom Widget view
|
||||
widget_add_string_element(
|
||||
@ -107,19 +108,23 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
BankCard* bank_card = nfc->bank_card;
|
||||
bank_card_set_name(bank_card, emv_data->name);
|
||||
bank_card_set_number(bank_card, emv_data->number);
|
||||
if(!strcmp(emv_data->name, "")) {
|
||||
bank_card_set_cardholder_name(bank_card, emv_data->cardholder);
|
||||
}
|
||||
bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc);
|
||||
if(emv_data->exp_mon) {
|
||||
bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year);
|
||||
}
|
||||
if(emv_data->country_code) {
|
||||
bank_card_set_country_name(bank_card, emv_data->country_code);
|
||||
}
|
||||
if(emv_data->currency_code) {
|
||||
bank_card_set_currency_name(bank_card, emv_data->currency_code);
|
||||
}
|
||||
}
|
||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid);
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
const bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
Nfc* nfc = context;
|
||||
bool consumed = false;
|
||||
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
#define NFC_SCENE_READ_SUCCESS_SHIFT " "
|
||||
|
||||
@ -21,9 +22,12 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) {
|
||||
dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21);
|
||||
// Display UID and AID
|
||||
string_t aid;
|
||||
string_init_printf(aid, "AID:");
|
||||
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
|
||||
string_cat_printf(aid, " %02X", emv_data->aid[i]);
|
||||
string_init(aid);
|
||||
bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid);
|
||||
if(!aid_found) {
|
||||
for(uint8_t i = 0; i < emv_data->aid_len; i++) {
|
||||
string_cat_printf(aid, " %02X", emv_data->aid[i]);
|
||||
}
|
||||
}
|
||||
nfc_text_store_set(
|
||||
nfc,
|
||||
|
@ -16,6 +16,8 @@ const void nfc_scene_read_emv_data_on_enter(void* context) {
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||
// Clear emv data
|
||||
memset(&nfc->dev.dev_data.emv_data, 0, sizeof(nfc->dev.dev_data.emv_data));
|
||||
// Start worker
|
||||
nfc_worker_start(
|
||||
nfc->worker,
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
@ -15,6 +16,9 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
nfc_device_set_name(&nfc->dev, "");
|
||||
|
||||
// Setup Custom Widget view
|
||||
// Add frame
|
||||
widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6);
|
||||
// Add buttons
|
||||
widget_add_button_element(
|
||||
nfc->widget,
|
||||
GuiButtonTypeLeft,
|
||||
@ -27,8 +31,10 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
"Save",
|
||||
nfc_scene_read_emv_data_success_widget_callback,
|
||||
nfc);
|
||||
// Add card name
|
||||
widget_add_string_element(
|
||||
nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name);
|
||||
// Add cad number
|
||||
char pan_str[32];
|
||||
snprintf(
|
||||
pan_str,
|
||||
@ -43,9 +49,41 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
emv_data->number[6],
|
||||
emv_data->number[7]);
|
||||
widget_add_string_element(nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, pan_str);
|
||||
// Parse country code
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if((emv_data->country_code) &&
|
||||
nfc_emv_parser_get_country_name(emv_data->country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country));
|
||||
string_clear(disp_country);
|
||||
}
|
||||
string_clear(country_name);
|
||||
// Parse currency code
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if((emv_data->currency_code) &&
|
||||
nfc_emv_parser_get_currency_name(emv_data->currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
nfc->widget,
|
||||
121,
|
||||
23,
|
||||
AlignRight,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_currency));
|
||||
string_clear(disp_currency);
|
||||
}
|
||||
string_clear(currency_name);
|
||||
// Add ATQA
|
||||
char atqa_str[16];
|
||||
snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]);
|
||||
widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, atqa_str);
|
||||
// Add UID
|
||||
char uid_str[32];
|
||||
snprintf(
|
||||
uid_str,
|
||||
@ -56,9 +94,11 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
nfc_data->uid[2],
|
||||
nfc_data->uid[3]);
|
||||
widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, uid_str);
|
||||
// Add SAK
|
||||
char sak_str[16];
|
||||
snprintf(sak_str, sizeof(sak_str), "SAK: %02X", nfc_data->sak);
|
||||
widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, sak_str);
|
||||
// Add expiration date
|
||||
if(emv_data->exp_mon) {
|
||||
char exp_str[16];
|
||||
snprintf(
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "bank_card.h"
|
||||
#include <gui/modules/widget.h>
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
#include <m-string.h>
|
||||
|
||||
struct BankCard {
|
||||
@ -43,10 +43,20 @@ void bank_card_set_number(BankCard* bank_card, uint8_t* number) {
|
||||
for(uint8_t i = 0; i < 8; i += 2) {
|
||||
string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]);
|
||||
}
|
||||
// Add number
|
||||
widget_add_string_element(
|
||||
bank_card->widget, 25, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(num_str));
|
||||
widget_add_icon_element(bank_card->widget, 6, 20, &I_EMV_Chip_14x11);
|
||||
bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str));
|
||||
string_clear(num_str);
|
||||
// Add icon
|
||||
widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13);
|
||||
// Add frame
|
||||
widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6);
|
||||
}
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(callback);
|
||||
widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context);
|
||||
}
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
|
||||
@ -57,8 +67,42 @@ void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) {
|
||||
bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str);
|
||||
}
|
||||
|
||||
void bank_card_set_cardholder_name(BankCard* bank_card, char* name) {
|
||||
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code) {
|
||||
furi_assert(bank_card);
|
||||
furi_assert(name);
|
||||
widget_add_string_element(bank_card->widget, 6, 37, AlignLeft, AlignTop, FontSecondary, name);
|
||||
string_t country_name;
|
||||
string_init(country_name);
|
||||
if(nfc_emv_parser_get_country_name(country_code, country_name)) {
|
||||
string_t disp_country;
|
||||
string_init_printf(disp_country, "Reg:%s", country_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget,
|
||||
120,
|
||||
18,
|
||||
AlignRight,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_country));
|
||||
string_clear(disp_country);
|
||||
}
|
||||
string_clear(country_name);
|
||||
}
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code) {
|
||||
furi_assert(bank_card);
|
||||
string_t currency_name;
|
||||
string_init(currency_name);
|
||||
if(nfc_emv_parser_get_currency_name(currency_code, currency_name)) {
|
||||
string_t disp_currency;
|
||||
string_init_printf(disp_currency, "Cur:%s", currency_name);
|
||||
widget_add_string_element(
|
||||
bank_card->widget,
|
||||
31,
|
||||
18,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
string_get_cstr(disp_currency));
|
||||
string_clear(disp_currency);
|
||||
}
|
||||
string_clear(currency_name);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
typedef struct BankCard BankCard;
|
||||
|
||||
typedef void (*BankCardBackCallback)(void);
|
||||
|
||||
BankCard* bank_card_alloc();
|
||||
|
||||
void bank_card_free(BankCard* bank_card);
|
||||
@ -14,10 +13,14 @@ void bank_card_clear(BankCard* bank_card);
|
||||
|
||||
View* bank_card_get_view(BankCard* bank_card);
|
||||
|
||||
void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context);
|
||||
|
||||
void bank_card_set_name(BankCard* bank_card, char* name);
|
||||
|
||||
void bank_card_set_number(BankCard* bank_card, uint8_t* number);
|
||||
|
||||
void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year);
|
||||
|
||||
void bank_card_set_cardholder_name(BankCard* bank_card, char* name);
|
||||
void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code);
|
||||
|
||||
void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code);
|
||||
|
File diff suppressed because one or more lines are too long
@ -3,61 +3,61 @@
|
||||
|
||||
extern const Icon A_WatchingTV_128x64;
|
||||
extern const Icon A_Wink_128x64;
|
||||
extern const Icon I_dir_10px;
|
||||
extern const Icon I_Nfc_10px;
|
||||
extern const Icon I_sub1_10px;
|
||||
extern const Icon I_ir_10px;
|
||||
extern const Icon I_ibutt_10px;
|
||||
extern const Icon I_unknown_10px;
|
||||
extern const Icon I_ble_10px;
|
||||
extern const Icon I_sub1_10px;
|
||||
extern const Icon I_dir_10px;
|
||||
extern const Icon I_unknown_10px;
|
||||
extern const Icon I_ibutt_10px;
|
||||
extern const Icon I_125_10px;
|
||||
extern const Icon I_ButtonRightSmall_3x5;
|
||||
extern const Icon I_ButtonLeft_4x7;
|
||||
extern const Icon I_ButtonLeftSmall_3x5;
|
||||
extern const Icon I_Warning_30x23;
|
||||
extern const Icon I_ButtonRight_4x7;
|
||||
extern const Icon I_Warning_30x23;
|
||||
extern const Icon I_ButtonRightSmall_3x5;
|
||||
extern const Icon I_ButtonCenter_7x7;
|
||||
extern const Icon I_ButtonLeftSmall_3x5;
|
||||
extern const Icon I_DolphinOkay_41x43;
|
||||
extern const Icon I_DolphinFirstStart4_67x53;
|
||||
extern const Icon I_DolphinFirstStart2_59x51;
|
||||
extern const Icon I_DolphinFirstStart5_54x49;
|
||||
extern const Icon I_DolphinFirstStart0_70x53;
|
||||
extern const Icon I_DolphinFirstStart6_58x54;
|
||||
extern const Icon I_DolphinFirstStart1_59x53;
|
||||
extern const Icon I_DolphinFirstStart8_56x51;
|
||||
extern const Icon I_DolphinFirstStart7_61x51;
|
||||
extern const Icon I_Flipper_young_80x60;
|
||||
extern const Icon I_DolphinFirstStart4_67x53;
|
||||
extern const Icon I_DolphinFirstStart3_57x48;
|
||||
extern const Icon I_PassportBottom_128x17;
|
||||
extern const Icon I_DoorLeft_8x56;
|
||||
extern const Icon I_Flipper_young_80x60;
|
||||
extern const Icon I_DolphinFirstStart0_70x53;
|
||||
extern const Icon I_DolphinFirstStart2_59x51;
|
||||
extern const Icon I_DolphinFirstStart6_58x54;
|
||||
extern const Icon I_DolphinFirstStart5_54x49;
|
||||
extern const Icon I_DolphinFirstStart8_56x51;
|
||||
extern const Icon I_DolphinFirstStart1_59x53;
|
||||
extern const Icon I_DoorRight_70x55;
|
||||
extern const Icon I_DoorLocked_10x56;
|
||||
extern const Icon I_DoorRight_8x56;
|
||||
extern const Icon I_DoorLeft_70x55;
|
||||
extern const Icon I_PassportLeft_6x47;
|
||||
extern const Icon I_DoorRight_70x55;
|
||||
extern const Icon I_DoorRight_8x56;
|
||||
extern const Icon I_DoorLeft_8x56;
|
||||
extern const Icon I_LockPopup_100x49;
|
||||
extern const Icon I_Mute_25x27;
|
||||
extern const Icon I_IrdaArrowUp_4x8;
|
||||
extern const Icon I_Up_hvr_25x27;
|
||||
extern const Icon I_Mute_hvr_25x27;
|
||||
extern const Icon I_Vol_down_25x27;
|
||||
extern const Icon I_Down_25x27;
|
||||
extern const Icon I_Power_hvr_25x27;
|
||||
extern const Icon I_IrdaLearnShort_128x31;
|
||||
extern const Icon I_IrdaArrowDown_4x8;
|
||||
extern const Icon I_Vol_down_hvr_25x27;
|
||||
extern const Icon I_IrdaLearn_128x64;
|
||||
extern const Icon I_Down_hvr_25x27;
|
||||
extern const Icon I_Fill_marker_7x7;
|
||||
extern const Icon I_Power_25x27;
|
||||
extern const Icon I_PassportBottom_128x17;
|
||||
extern const Icon I_Vol_up_25x27;
|
||||
extern const Icon I_Up_25x27;
|
||||
extern const Icon I_Back_15x10;
|
||||
extern const Icon I_IrdaSend_128x64;
|
||||
extern const Icon I_IrdaSendShort_128x34;
|
||||
extern const Icon I_Fill_marker_7x7;
|
||||
extern const Icon I_IrdaArrowUp_4x8;
|
||||
extern const Icon I_Down_hvr_25x27;
|
||||
extern const Icon I_Vol_up_hvr_25x27;
|
||||
extern const Icon I_KeySave_24x11;
|
||||
extern const Icon I_Power_25x27;
|
||||
extern const Icon I_Vol_down_25x27;
|
||||
extern const Icon I_IrdaSend_128x64;
|
||||
extern const Icon I_Up_hvr_25x27;
|
||||
extern const Icon I_Back_15x10;
|
||||
extern const Icon I_IrdaSendShort_128x34;
|
||||
extern const Icon I_Mute_hvr_25x27;
|
||||
extern const Icon I_IrdaLearnShort_128x31;
|
||||
extern const Icon I_Down_25x27;
|
||||
extern const Icon I_Up_25x27;
|
||||
extern const Icon I_Mute_25x27;
|
||||
extern const Icon I_Vol_down_hvr_25x27;
|
||||
extern const Icon I_Power_hvr_25x27;
|
||||
extern const Icon I_IrdaLearn_128x64;
|
||||
extern const Icon I_IrdaArrowDown_4x8;
|
||||
extern const Icon I_KeyBackspaceSelected_16x9;
|
||||
extern const Icon I_KeySave_24x11;
|
||||
extern const Icon I_KeySaveSelected_24x11;
|
||||
extern const Icon I_KeyBackspace_16x9;
|
||||
extern const Icon A_125khz_14;
|
||||
@ -76,38 +76,38 @@ extern const Icon A_Tamagotchi_14;
|
||||
extern const Icon A_U2F_14;
|
||||
extern const Icon A_iButton_14;
|
||||
extern const Icon I_Medium_chip_22x21;
|
||||
extern const Icon I_EMV_Chip_14x11;
|
||||
extern const Icon I_Detailed_chip_17x13;
|
||||
extern const Icon I_Health_16x16;
|
||||
extern const Icon I_FaceCharging_29x14;
|
||||
extern const Icon I_FaceNopower_29x14;
|
||||
extern const Icon I_Battery_16x16;
|
||||
extern const Icon I_BatteryBody_52x28;
|
||||
extern const Icon I_FaceConfused_29x14;
|
||||
extern const Icon I_FaceCharging_29x14;
|
||||
extern const Icon I_FaceNormal_29x14;
|
||||
extern const Icon I_Voltage_16x16;
|
||||
extern const Icon I_Temperature_16x16;
|
||||
extern const Icon I_FaceNopower_29x14;
|
||||
extern const Icon I_FaceNormal_29x14;
|
||||
extern const Icon I_Battery_16x16;
|
||||
extern const Icon I_FaceConfused_29x14;
|
||||
extern const Icon I_RFIDDolphinSuccess_108x57;
|
||||
extern const Icon I_RFIDBigChip_37x36;
|
||||
extern const Icon I_RFIDDolphinSend_97x61;
|
||||
extern const Icon I_RFIDDolphinReceive_97x61;
|
||||
extern const Icon I_RFIDDolphinSend_97x61;
|
||||
extern const Icon I_RFIDBigChip_37x36;
|
||||
extern const Icon I_RFIDDolphinSuccess_108x57;
|
||||
extern const Icon I_SDQuestion_35x43;
|
||||
extern const Icon I_SDError_43x35;
|
||||
extern const Icon I_BadUsb_9x8;
|
||||
extern const Icon I_PlaceholderR_30x13;
|
||||
extern const Icon I_Background_128x8;
|
||||
extern const Icon I_Lock_8x8;
|
||||
extern const Icon I_Battery_26x8;
|
||||
extern const Icon I_PlaceholderL_11x13;
|
||||
extern const Icon I_Battery_19x8;
|
||||
extern const Icon I_SDcardMounted_11x8;
|
||||
extern const Icon I_SDcardFail_11x8;
|
||||
extern const Icon I_USBConnected_15x8;
|
||||
extern const Icon I_Bluetooth_5x8;
|
||||
extern const Icon I_BadUsb_9x8;
|
||||
extern const Icon I_PlaceholderR_30x13;
|
||||
extern const Icon I_USBConnected_15x8;
|
||||
extern const Icon I_Battery_19x8;
|
||||
extern const Icon I_Lock_8x8;
|
||||
extern const Icon I_Background_128x11;
|
||||
extern const Icon I_DolphinMafia_115x62;
|
||||
extern const Icon I_DolphinExcited_64x63;
|
||||
extern const Icon I_iButtonDolphinSuccess_109x60;
|
||||
extern const Icon I_Background_128x8;
|
||||
extern const Icon I_SDcardFail_11x8;
|
||||
extern const Icon I_SDcardMounted_11x8;
|
||||
extern const Icon I_iButtonDolphinVerySuccess_108x52;
|
||||
extern const Icon I_iButtonKey_49x44;
|
||||
extern const Icon I_DolphinMafia_115x62;
|
||||
extern const Icon I_iButtonDolphinSuccess_109x60;
|
||||
extern const Icon I_DolphinExcited_64x63;
|
||||
extern const Icon I_DolphinNice_96x59;
|
||||
extern const Icon I_iButtonKey_49x44;
|
||||
extern const Icon I_DolphinWait_61x59;
|
||||
|
BIN
assets/icons/NFC/Detailed_chip_17x13.png
Normal file
BIN
assets/icons/NFC/Detailed_chip_17x13.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 981 B |
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
148
assets/resources/nfc/emv/aid.nfc
Normal file
148
assets/resources/nfc/emv/aid.nfc
Normal file
@ -0,0 +1,148 @@
|
||||
A00000000305076010 VISA ELO Credit
|
||||
A0000000031010 VISA Debit/Credit (Classic)
|
||||
A000000003101001 VISA Credit
|
||||
A000000003101002 VISA Debit
|
||||
A0000000032010 VISA Electron
|
||||
A0000000032020 VISA
|
||||
A0000000033010 VISA Interlink
|
||||
A0000000034010 VISA Specific
|
||||
A0000000035010 VISA Specific
|
||||
A0000000036010 Domestic Visa Cash
|
||||
A0000000036020 International Visa Cash
|
||||
A0000000038002 VISA Auth EMV-CAP (DPA)
|
||||
A0000000038010 VISA Plus
|
||||
A0000000039010 VISA Loyalty
|
||||
A000000003999910 VISA Proprietary ATM
|
||||
A00000000401 MasterCard PayPass
|
||||
A0000000041010 MasterCard Global
|
||||
A00000000410101213 MasterCard Credit
|
||||
A00000000410101215 MasterCard Credit
|
||||
A0000000042010 MasterCard Specific
|
||||
A0000000043010 MasterCard Specific
|
||||
A0000000043060 Maestro (Debit)
|
||||
A000000004306001 Maestro (Debit)
|
||||
A0000000044010 MasterCard Specific
|
||||
A0000000045010 MasterCard Specific
|
||||
A0000000046000 Cirrus
|
||||
A0000000048002 SecureCode EMV-CAP
|
||||
A0000000049999 MasterCard PayPass
|
||||
A0000000050001 Maestro UK
|
||||
A0000000050002 Solo
|
||||
A00000002401 Self Service
|
||||
A000000025 American Express
|
||||
A0000000250000 American Express
|
||||
A00000002501 American Express
|
||||
A000000025010402 American Express
|
||||
A000000025010701 ExpressPay
|
||||
A000000025010801 American Express
|
||||
A0000000291010 Link / American Express
|
||||
A0000000421010 Cartes Bancaire EMV Card
|
||||
A0000000426010 Apple Pay
|
||||
A00000006510 JCB
|
||||
A0000000651010 JCB J Smart Credit
|
||||
A00000006900 Moneo
|
||||
A000000077010000021000000000003B Visa AEPN
|
||||
A000000098 Debit Card
|
||||
A0000000980848 Debit Card
|
||||
A0000001211010 Dankort VISA GEM Vision
|
||||
A0000001410001 PagoBANCOMAT
|
||||
A0000001523010 Discover, Pulse D Pas
|
||||
A0000001524010 Discover
|
||||
A0000001544442 Banricompras Debito
|
||||
A000000172950001 BAROC Taiwan
|
||||
A0000002281010 SPAN (M/Chip)
|
||||
A0000002282010 SPAN (VIS)
|
||||
A0000002771010 INTERAC
|
||||
A00000031510100528 Currence PuC
|
||||
A0000003156020 Chipknip
|
||||
A0000003591010028001 Girocard EAPS
|
||||
A0000003710001 InterSwitch Verve Card
|
||||
A0000004540010 Etranzact Genesis Card
|
||||
A0000004540011 Etranzact Genesis Card 2
|
||||
A0000004766C GOOGLE_PAYMENT
|
||||
A0000005241010 RuPay
|
||||
A0000006723010 TROY chip credit card
|
||||
A0000006723020 TROY chip debit card
|
||||
A0000007705850 XTRAPOWER
|
||||
B012345678 Maestro TEST
|
||||
D27600002545500100 Girocard
|
||||
D5780000021010 Bankaxept
|
||||
F0000000030001 BRADESCO
|
||||
A000000003000000 (VISA) Card Manager
|
||||
A000000003534441 Schlumberger SD
|
||||
A0000000035350 Security Domain
|
||||
A000000003535041 Security Domain
|
||||
A0000000040000 MasterCard Card Manager
|
||||
A000000018434D Gemplus card manager
|
||||
A000000018434D00 Gemplus Security Domain
|
||||
A0000000960200 Proton WISD
|
||||
A0000001510000 Global Platform SD
|
||||
A00000015153504341534400 CASD_AID
|
||||
A000000476A010 GSD_MANAGER_AID
|
||||
A000000476A110 GSD_MANAGER_AID
|
||||
315041592E5359532E4444463031 Visa PSE
|
||||
325041592E5359532E4444463031 Visa PPSE
|
||||
A0000000042203 MasterCard Specific
|
||||
A0000000045555 APDULogger
|
||||
A0000000090001FF44FF1289 Orange
|
||||
A0000000101030 Maestro-CH
|
||||
A00000001800 Gemplus
|
||||
A0000000181001 gemplus util packages
|
||||
A000000025010104 American Express
|
||||
A00000002949034010100001 HSBC
|
||||
A00000002949282010100000 Barclay
|
||||
A00000005945430100 Girocard Electronic Cash
|
||||
A0000000980840 Visa Common Debit
|
||||
A0000001570010 AMEX
|
||||
A0000001570020 MasterCard
|
||||
A0000001570021 Maestro
|
||||
A0000001570022 Maestro
|
||||
A0000001570023 CASH
|
||||
A0000001570030 VISA
|
||||
A0000001570031 VISA
|
||||
A0000001570040 JCB
|
||||
A0000001570050 Postcard
|
||||
A0000001570051 Postcard
|
||||
A0000001570100 MCard
|
||||
A0000001570104 MyOne
|
||||
A000000157010C WIRCard
|
||||
A000000157010D Power Card
|
||||
A0000001574443 DINERS CLUB
|
||||
A0000001574444 Supercard Plus
|
||||
A00000022820101010 SPAN
|
||||
A000000308000010000100 ID-ONE PIV BIO
|
||||
A0000003241010 Discover Zip
|
||||
A000000333010101 UnionPay Debit
|
||||
A000000333010102 UnionPay Credit
|
||||
A000000333010103 UnionPay Quasi Credit
|
||||
A000000333010106 UnionPay Electronic Cash
|
||||
A000000333010108 U.S. UnionPay Common Debit
|
||||
A000000337102000 Classic
|
||||
A000000337101001 Prepaye Online
|
||||
A000000337102001 Prepaye Possibile Offiline
|
||||
A000000337601001 Porte Monnaie Electronique
|
||||
A0000006581010 MIR Credit
|
||||
A0000006581011 MIR Credit
|
||||
A0000006582010 MIR Debit
|
||||
D040000001000002 Paylife Quick IEP
|
||||
D040000002000002 RFU
|
||||
D040000003000002 POS
|
||||
D040000004000002 ATM
|
||||
D04000000B000002 Retail
|
||||
D04000000C000002 Bank_Data
|
||||
D04000000D000002 Shopping
|
||||
D040000013000001 DF_UNI_Kepler1
|
||||
D040000013000001 DF_Schüler1
|
||||
D040000013000002 DF_UNI_Kepler2
|
||||
D040000013000002 DF_Schüler2
|
||||
D040000014000001 DF_Mensa
|
||||
D040000015000001 DF_UNI_Ausweis
|
||||
D040000015000001 DF_Ausweis
|
||||
D0400000190001 EMV ATM Maestro
|
||||
D0400000190002 EMV POS Maestro
|
||||
D0400000190003 EMV ATM MasterCard
|
||||
D0400000190004 EMV POS MasterCard
|
||||
D276000025 Girocard
|
||||
D27600002547410100 Girocard ATM
|
||||
D7560000010101 Reka Card
|
||||
D7560000300101 M Budget
|
249
assets/resources/nfc/emv/country_code.nfc
Normal file
249
assets/resources/nfc/emv/country_code.nfc
Normal file
@ -0,0 +1,249 @@
|
||||
0004 AFG
|
||||
0008 ALB
|
||||
0010 ATA
|
||||
0012 DZA
|
||||
0016 ASM
|
||||
0020 AND
|
||||
0024 AGO
|
||||
0028 ATG
|
||||
0031 AZE
|
||||
0032 ARG
|
||||
0036 AUS
|
||||
0040 AUT
|
||||
0044 BHS
|
||||
0048 BHR
|
||||
0050 BGD
|
||||
0051 ARM
|
||||
0052 BRB
|
||||
0056 BEL
|
||||
0060 BMU
|
||||
0064 BTN
|
||||
0068 BOL
|
||||
0070 BIH
|
||||
0072 BWA
|
||||
0074 BVT
|
||||
0076 BRA
|
||||
0084 BLZ
|
||||
0086 IOT
|
||||
0090 SLB
|
||||
0092 VGB
|
||||
0096 BRN
|
||||
0100 BGR
|
||||
0104 MMR
|
||||
0108 BDI
|
||||
0112 BLR
|
||||
0116 KHM
|
||||
0120 CMR
|
||||
0124 CAN
|
||||
0132 CPV
|
||||
0136 CYM
|
||||
0140 CAF
|
||||
0144 LKA
|
||||
0148 TCD
|
||||
0152 CHL
|
||||
0156 CHN
|
||||
0158 TWN
|
||||
0162 CXR
|
||||
0166 CCK
|
||||
0170 COL
|
||||
0174 COM
|
||||
0175 MYT
|
||||
0178 COG
|
||||
0180 COD
|
||||
0184 COK
|
||||
0188 CRI
|
||||
0191 HRV
|
||||
0192 CUB
|
||||
0196 CYP
|
||||
0203 CZE
|
||||
0204 BEN
|
||||
0208 DNK
|
||||
0212 DMA
|
||||
0214 DOM
|
||||
0218 ECU
|
||||
0222 SLV
|
||||
0226 GNQ
|
||||
0231 ETH
|
||||
0232 ERI
|
||||
0233 EST
|
||||
0234 FRO
|
||||
0238 FLK
|
||||
0239 SGS
|
||||
0242 FJI
|
||||
0246 FIN
|
||||
0248 ALA
|
||||
0250 FRA
|
||||
0254 GUF
|
||||
0258 PYF
|
||||
0260 ATF
|
||||
0262 DJI
|
||||
0266 GAB
|
||||
0268 GEO
|
||||
0270 GMB
|
||||
0275 PSE
|
||||
0276 DEU
|
||||
0288 GHA
|
||||
0292 GIB
|
||||
0296 KIR
|
||||
0300 GRC
|
||||
0304 GRL
|
||||
0308 GRD
|
||||
0312 GLP
|
||||
0316 GUM
|
||||
0320 GTM
|
||||
0324 GIN
|
||||
0328 GUY
|
||||
0332 HTI
|
||||
0334 HMD
|
||||
0336 VAT
|
||||
0340 HND
|
||||
0344 HKG
|
||||
0348 HUN
|
||||
0352 ISL
|
||||
0356 IND
|
||||
0360 IDN
|
||||
0364 IRN
|
||||
0368 IRQ
|
||||
0372 IRL
|
||||
0376 ISR
|
||||
0380 ITA
|
||||
0384 CIV
|
||||
0388 JAM
|
||||
0392 JPN
|
||||
0398 KAZ
|
||||
0400 JOR
|
||||
0404 KEN
|
||||
0408 PRK
|
||||
0410 KOR
|
||||
0414 KWT
|
||||
0417 KGZ
|
||||
0418 LAO
|
||||
0422 LBN
|
||||
0426 LSO
|
||||
0428 LVA
|
||||
0430 LBR
|
||||
0434 LBY
|
||||
0438 LIE
|
||||
0440 LTU
|
||||
0442 LUX
|
||||
0446 MAC
|
||||
0450 MDG
|
||||
0454 MWI
|
||||
0458 MYS
|
||||
0462 MDV
|
||||
0466 MLI
|
||||
0470 MLT
|
||||
0474 MTQ
|
||||
0478 MRT
|
||||
0480 MUS
|
||||
0484 MEX
|
||||
0492 MCO
|
||||
0496 MNG
|
||||
0498 MDA
|
||||
0499 MNE
|
||||
0500 MSR
|
||||
0504 MAR
|
||||
0508 MOZ
|
||||
0512 OMN
|
||||
0516 NAM
|
||||
0520 NRU
|
||||
0524 NPL
|
||||
0528 NLD
|
||||
0531 CUW
|
||||
0533 ABW
|
||||
0534 SXM
|
||||
0535 BES
|
||||
0540 NCL
|
||||
0548 VUT
|
||||
0554 NZL
|
||||
0558 NIC
|
||||
0562 NER
|
||||
0566 NGA
|
||||
0570 NIU
|
||||
0574 NFK
|
||||
0578 NOR
|
||||
0580 MNP
|
||||
0581 UMI
|
||||
0583 FSM
|
||||
0584 MHL
|
||||
0585 PLW
|
||||
0586 PAK
|
||||
0591 PAN
|
||||
0598 PNG
|
||||
0600 PRY
|
||||
0604 PER
|
||||
0608 PHL
|
||||
0612 PCN
|
||||
0616 POL
|
||||
0620 PRT
|
||||
0624 GNB
|
||||
0626 TLS
|
||||
0630 PRI
|
||||
0634 QAT
|
||||
0638 REU
|
||||
0642 ROU
|
||||
0643 RUS
|
||||
0646 RWA
|
||||
0652 BLM
|
||||
0654 SHN
|
||||
0659 KNA
|
||||
0660 AIA
|
||||
0662 LCA
|
||||
0663 MAF
|
||||
0666 SPM
|
||||
0670 VCT
|
||||
0674 SMR
|
||||
0678 STP
|
||||
0682 SAU
|
||||
0686 SEN
|
||||
0688 SRB
|
||||
0690 SYC
|
||||
0694 SLE
|
||||
0702 SGP
|
||||
0703 SVK
|
||||
0704 VNM
|
||||
0705 SVN
|
||||
0706 SOM
|
||||
0710 ZAF
|
||||
0716 ZWE
|
||||
0724 ESP
|
||||
0728 SSD
|
||||
0729 SDN
|
||||
0732 ESH
|
||||
0740 SUR
|
||||
0744 SJM
|
||||
0748 SWZ
|
||||
0752 SWE
|
||||
0756 CHE
|
||||
0760 SYR
|
||||
0762 TJK
|
||||
0764 THA
|
||||
0768 TGO
|
||||
0772 TKL
|
||||
0776 TON
|
||||
0780 TTO
|
||||
0784 ARE
|
||||
0788 TUN
|
||||
0792 TUR
|
||||
0795 TKM
|
||||
0796 TCA
|
||||
0798 TUV
|
||||
0800 UGA
|
||||
0804 UKR
|
||||
0807 MKD
|
||||
0818 EGY
|
||||
0826 GBR
|
||||
0831 GGY
|
||||
0832 JEY
|
||||
0833 IMN
|
||||
0834 TZA
|
||||
0840 USA
|
||||
0850 VIR
|
||||
0854 BFA
|
||||
0858 URY
|
||||
0860 UZB
|
||||
0862 VEN
|
||||
0876 WLF
|
||||
0882 WSM
|
||||
0887 YEM
|
||||
0894 ZMB
|
168
assets/resources/nfc/emv/currency_code.nfc
Normal file
168
assets/resources/nfc/emv/currency_code.nfc
Normal file
@ -0,0 +1,168 @@
|
||||
0997 USN
|
||||
0994 XSU
|
||||
0990 CLF
|
||||
0986 BRL
|
||||
0985 PLN
|
||||
0984 BOV
|
||||
0981 GEL
|
||||
0980 UAH
|
||||
0979 MXV
|
||||
0978 EUR
|
||||
0977 BAM
|
||||
0976 CDF
|
||||
0975 BGN
|
||||
0973 AOA
|
||||
0972 TJS
|
||||
0971 AFN
|
||||
0970 COU
|
||||
0969 MGA
|
||||
0968 SRD
|
||||
0967 ZMW
|
||||
0965 XUA
|
||||
0960 XDR
|
||||
0953 XPF
|
||||
0952 XOF
|
||||
0951 XCD
|
||||
0950 XAF
|
||||
0949 TRY
|
||||
0948 CHW
|
||||
0947 CHE
|
||||
0946 RON
|
||||
0944 AZN
|
||||
0943 MZN
|
||||
0941 RSD
|
||||
0940 UYI
|
||||
0938 SDG
|
||||
0937 VEF
|
||||
0936 GHS
|
||||
0934 TMT
|
||||
0933 BYN
|
||||
0932 ZWL
|
||||
0931 CUC
|
||||
0930 STN
|
||||
0929 MRU
|
||||
0901 TWD
|
||||
0886 YER
|
||||
0882 WST
|
||||
0860 UZS
|
||||
0858 UYU
|
||||
0840 USD
|
||||
0834 TZS
|
||||
0826 GBP
|
||||
0818 EGP
|
||||
0807 MKD
|
||||
0800 UGX
|
||||
0788 TND
|
||||
0784 AED
|
||||
0780 TTD
|
||||
0776 TOP
|
||||
0764 THB
|
||||
0760 SYP
|
||||
0756 CHF
|
||||
0752 SEK
|
||||
0748 SZL
|
||||
0728 SSP
|
||||
0710 ZAR
|
||||
0706 SOS
|
||||
0704 VND
|
||||
0702 SGD
|
||||
0694 SLL
|
||||
0690 SCR
|
||||
0682 SAR
|
||||
0654 SHP
|
||||
0646 RWF
|
||||
0643 RUB
|
||||
0634 QAR
|
||||
0608 PHP
|
||||
0604 PEN
|
||||
0600 PYG
|
||||
0598 PGK
|
||||
0590 PAB
|
||||
0586 PKR
|
||||
0578 NOK
|
||||
0566 NGN
|
||||
0558 NIO
|
||||
0554 NZD
|
||||
0548 VUV
|
||||
0533 AWG
|
||||
0532 ANG
|
||||
0524 NPR
|
||||
0516 NAD
|
||||
0512 OMR
|
||||
0504 MAD
|
||||
0498 MDL
|
||||
0496 MNT
|
||||
0484 MXN
|
||||
0480 MUR
|
||||
0462 MVR
|
||||
0458 MYR
|
||||
0454 MWK
|
||||
0446 MOP
|
||||
0434 LYD
|
||||
0430 LRD
|
||||
0426 LSL
|
||||
0422 LBP
|
||||
0418 LAK
|
||||
0417 KGS
|
||||
0414 KWD
|
||||
0410 KRW
|
||||
0408 KPW
|
||||
0404 KES
|
||||
0400 JOD
|
||||
0398 KZT
|
||||
0392 JPY
|
||||
0388 JMD
|
||||
0376 ILS
|
||||
0368 IQD
|
||||
0364 IRR
|
||||
0360 IDR
|
||||
0356 INR
|
||||
0352 ISK
|
||||
0348 HUF
|
||||
0344 HKD
|
||||
0340 HNL
|
||||
0332 HTG
|
||||
0328 GYD
|
||||
0324 GNF
|
||||
0320 GTQ
|
||||
0292 GIP
|
||||
0270 GMD
|
||||
0262 DJF
|
||||
0242 FJD
|
||||
0238 FKP
|
||||
0232 ERN
|
||||
0230 ETB
|
||||
0222 SVC
|
||||
0214 DOP
|
||||
0208 DKK
|
||||
0203 CZK
|
||||
0192 CUP
|
||||
0191 HRK
|
||||
0188 CRC
|
||||
0174 KMF
|
||||
0170 COP
|
||||
0156 CNY
|
||||
0152 CLP
|
||||
0144 LKR
|
||||
0136 KYD
|
||||
0132 CVE
|
||||
0124 CAD
|
||||
0116 KHR
|
||||
0108 BIF
|
||||
0104 MMK
|
||||
0096 BND
|
||||
0090 SBD
|
||||
0084 BZD
|
||||
0072 BWP
|
||||
0068 BOB
|
||||
0064 BTN
|
||||
0060 BMD
|
||||
0052 BBD
|
||||
0051 AMD
|
||||
0050 BDT
|
||||
0048 BHD
|
||||
0044 BSD
|
||||
0036 AUD
|
||||
0032 ARS
|
||||
0012 DZD
|
||||
0008 ALL
|
@ -575,7 +575,9 @@ ReturnCode rfalNfcDataExchangeStart( uint8_t *txData, uint16_t txDataLen, uint8_
|
||||
*rvdLen = (uint16_t*)&gNfcDev.rxLen;
|
||||
*rxData = (uint8_t*)( (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? gNfcDev.rxBuf.isoDepBuf.apdu :
|
||||
((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? gNfcDev.rxBuf.nfcDepBuf.pdu : gNfcDev.rxBuf.rfBuf));
|
||||
gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE;
|
||||
if(gNfcDev.disc.activate_after_sak) {
|
||||
gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE;
|
||||
}
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,10 @@ bool FileWorkerCpp::read_until_buffered(string_t str_result, char* file_buf, siz
|
||||
return file_worker_read_until_buffered(file_worker, str_result, file_buf, file_buf_cnt, max_length, separator);
|
||||
}
|
||||
|
||||
bool FileWorkerCpp::get_value_from_key(string_t key, char delimiter, string_t value) {
|
||||
return file_worker_get_value_from_key(file_worker, key, delimiter, value);
|
||||
}
|
||||
|
||||
bool FileWorkerCpp::is_file_exist(const char* filename, bool* exist) {
|
||||
return file_worker_is_file_exist(file_worker, filename, exist);
|
||||
}
|
||||
|
@ -143,6 +143,17 @@ public:
|
||||
*/
|
||||
bool read_until_buffered(string_t str_result, char* file_buf, size_t* file_buf_cnt, size_t max_length, char separator = '\n');
|
||||
|
||||
/**
|
||||
* @brief Gets value from key
|
||||
*
|
||||
* @param file_worker FileWorker instance
|
||||
* @param key key
|
||||
* @param delimeter key-value delimeter
|
||||
* @param value value for given key
|
||||
* @return true on success
|
||||
*/
|
||||
bool get_value_from_key(string_t key, char delimiter, string_t value);
|
||||
|
||||
/**
|
||||
* @brief Check whether file exist or not
|
||||
*
|
||||
|
@ -355,6 +355,34 @@ bool file_worker_read_until_buffered(
|
||||
return string_size(str_result) || *file_buf_cnt;
|
||||
}
|
||||
|
||||
bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value) {
|
||||
bool found = false;
|
||||
string_t next_line;
|
||||
string_t next_key;
|
||||
string_init(next_line);
|
||||
string_init(next_key);
|
||||
size_t delim_pos = 0;
|
||||
|
||||
while(file_worker_read_until(file_worker, next_line, '\n')) {
|
||||
delim_pos = string_search_char(next_line, delimiter);
|
||||
if(delim_pos == STRING_FAILURE) {
|
||||
break;
|
||||
}
|
||||
string_set_n(next_key, next_line, 0, delim_pos);
|
||||
if(string_equal_p(next_key, key)) {
|
||||
string_right(next_line, delim_pos);
|
||||
string_strim(next_line);
|
||||
string_set(value, next_line);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(next_line);
|
||||
string_clear(next_key);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool file_worker_rename(FileWorker* file_worker, const char* old_path, const char* new_path) {
|
||||
FS_Error fs_result = storage_common_rename(file_worker->api, old_path, new_path);
|
||||
|
||||
|
@ -185,6 +185,17 @@ bool file_worker_read_until_buffered(
|
||||
size_t max_length,
|
||||
char separator);
|
||||
|
||||
/**
|
||||
* @brief Gets value from key
|
||||
*
|
||||
* @param file_worker FileWorker instance
|
||||
* @param key key
|
||||
* @param delimeter key-value delimeter
|
||||
* @param value value for given key
|
||||
* @return true on success
|
||||
*/
|
||||
bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value);
|
||||
|
||||
/**
|
||||
* @brief Check whether file exist or not
|
||||
*
|
||||
|
@ -63,6 +63,14 @@ static uint16_t emv_parse_TLV(uint8_t* dest, uint8_t* src, uint16_t* idx) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool emv_decode_search_tag_u16_r(uint16_t tag, uint8_t* buff, uint16_t* idx) {
|
||||
if((buff[*idx] << 8 | buff[*idx + 1]) == tag) {
|
||||
*idx = *idx + 3;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t emv_prepare_select_ppse(uint8_t* dest) {
|
||||
const uint8_t emv_select_ppse[] = {
|
||||
0x00, 0xA4, // SELECT ppse
|
||||
@ -219,10 +227,15 @@ bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app
|
||||
if(buff[i] == EMV_TAG_PAN) {
|
||||
memcpy(app->card_number, &buff[i + 2], 8);
|
||||
pan_parsed = true;
|
||||
} else if((buff[i] << 8 | buff[i + 1]) == EMV_TAG_EXP_DATE) {
|
||||
i += 3;
|
||||
} else if(emv_decode_search_tag_u16_r(EMV_TAG_EXP_DATE, buff, &i)) {
|
||||
app->exp_year = buff[i++];
|
||||
app->exp_month = buff[i++];
|
||||
} else if(emv_decode_search_tag_u16_r(EMV_TAG_CURRENCY_CODE, buff, &i)) {
|
||||
app->currency_code = (buff[i] << 8) | buff[i + 1];
|
||||
i += 2;
|
||||
} else if(emv_decode_search_tag_u16_r(EMV_TAG_COUNTRY_CODE, buff, &i)) {
|
||||
app->country_code = (buff[i] << 8) | buff[i + 1];
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return pan_parsed;
|
||||
|
@ -17,6 +17,8 @@
|
||||
#define EMV_TAG_PAN 0x5A
|
||||
#define EMV_TAG_AFL 0x94
|
||||
#define EMV_TAG_EXP_DATE 0x5F24
|
||||
#define EMV_TAG_COUNTRY_CODE 0x5F28
|
||||
#define EMV_TAG_CURRENCY_CODE 0x9F42
|
||||
#define EMV_TAG_CARDHOLDER_NAME 0x5F20
|
||||
|
||||
typedef struct {
|
||||
@ -39,7 +41,8 @@ typedef struct {
|
||||
uint8_t card_number[8];
|
||||
uint8_t exp_month;
|
||||
uint8_t exp_year;
|
||||
char crdholder_name[32];
|
||||
uint16_t country_code;
|
||||
uint16_t currency_code;
|
||||
APDU pdol;
|
||||
APDU afl;
|
||||
} EmvApplication;
|
||||
|
@ -53,3 +53,11 @@ Setting option bytes:
|
||||
```bash
|
||||
ob.py set
|
||||
```
|
||||
|
||||
# Assets delivery
|
||||
|
||||
Run in the root folder of the repo:
|
||||
|
||||
```bash
|
||||
python scripts/storage.py -p <flipper_cli_port> send assets/resources /ext
|
||||
```
|
Loading…
Reference in New Issue
Block a user