[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:
gornekich 2021-08-20 22:56:43 +03:00 committed by GitHub
parent b1bbf1730c
commit ecff31d228
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1251 additions and 319 deletions

View file

@ -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);
}

View file

@ -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);

View 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;
}

View file

@ -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);

View file

@ -1,5 +1,4 @@
#include "widget_element_i.h"
#include <m-string.h>
typedef struct {
uint8_t x;

View 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;
}

View 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);

View file

@ -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);

View file

@ -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 {

View file

@ -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
View 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);

View file

@ -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,

View file

@ -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,

View file

@ -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(

View file

@ -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);
}

View file

@ -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

View file

@ -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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View 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

View 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

View 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

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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
*

View file

@ -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);

View file

@ -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
*

View file

@ -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;

View file

@ -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;

View file

@ -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
```