Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFC - Machine Readable Travel Documents #1866

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
a286c7b
Text input overwrite max size template
qistoph Oct 11, 2022
3eb0c43
[NFC] Recognize MRTD + initial menus
qistoph Oct 11, 2022
67eff89
Show set dates in MRTD auth menu
qistoph Oct 11, 2022
9b861e2
MRTD popup "PACE todo"
qistoph Oct 11, 2022
8235270
MRTD rename mrtd_data.auth.bac to mrtd_data.auth
qistoph Oct 11, 2022
d585eec
MRTD configure docnr for auth
qistoph Oct 11, 2022
c82b555
Make MRTD work along with EMV
qistoph Oct 11, 2022
fc9b378
Minor improvements
qistoph Oct 11, 2022
315294f
MRTD work on reading EF.DIR and EF.CardAccess
qistoph Oct 11, 2022
08afd7c
MRTD select and read file basics
qistoph Oct 11, 2022
0871d27
MRTD add helper functions:
qistoph Oct 11, 2022
44c2299
MRTD use smaller data type of lengths, add sha1 test
qistoph Oct 11, 2022
c4499e2
MRTD add mrtd_bac_keys
qistoph Oct 11, 2022
27a74c4
MRTD generalize app selection
qistoph Oct 11, 2022
ea4762d
Merge branch 'dev' into mrtd
qistoph Sep 2, 2022
66a507b
Add ISO7816 tester
qistoph Oct 11, 2022
b412843
MRTD BAC support and some other improvements
qistoph Oct 11, 2022
0b8a0c7
Minor warning fix in MRTD
qistoph Oct 11, 2022
59efc27
Merge branch 'dev' into mrtd
qistoph Sep 28, 2022
e9bb942
MRTD move scenes to new directory
qistoph Oct 11, 2022
2e58633
MRTD use reader_analyzer instead of deprecated debug_pcap_worker
qistoph Oct 11, 2022
b1f95c5
MRTD add worker method for auhtenticated read
qistoph Oct 11, 2022
2c4e2b4
MRTD rename scene Bac to Auth
qistoph Oct 11, 2022
6b968f7
MRTD reread with auth
qistoph Oct 11, 2022
d9399c6
fixup! MRTD use reader_analyzer instead of deprecated debug_pcap_worker
qistoph Oct 11, 2022
0f24298
MRTD fix KMRZ for BAC
qistoph Oct 11, 2022
6abd967
MRTD set auth method + cleanup nfc_worker
qistoph Oct 11, 2022
8796195
Revert "MRTD add worker method for auhtenticated read"
qistoph Oct 11, 2022
c221c89
MRTD scene for auth. read
qistoph Oct 11, 2022
ab5e564
MRTD WIP secure messaging
qistoph Oct 11, 2022
eaeb887
MRTD Secure Messaging added
qistoph Oct 11, 2022
374f2ac
MRTD decrypt RX APDU
qistoph Oct 11, 2022
b5e420c
MRTD handle BAC decrypt+unpad
qistoph Oct 11, 2022
69ff30e
MRTD TLV parsing (and select)
qistoph Oct 11, 2022
00d674f
Fix indention
qistoph Oct 11, 2022
5e7f13f
MRTD more tlv_select tests
qistoph Oct 11, 2022
2ae8e97
MRTD add file lookup by tag and EF.COM format
qistoph Oct 11, 2022
89d0c31
MRTD multiple changes
qistoph Oct 11, 2022
74faab3
MRTD display AIDs and DGs after auth
qistoph Oct 11, 2022
d3d9b67
MRTD remove some logs. Read DG1, try DG2
qistoph Oct 11, 2022
0ab7d91
MRTD proper parse DO87 multi byte length
qistoph Oct 11, 2022
d1a1cbf
MRTD Read DG1 + small changes
qistoph Oct 11, 2022
6003f85
MRTD Show month as text
qistoph Oct 11, 2022
5d0025d
Merge remote-tracking branch 'upstream/dev' into mrtd
qistoph Oct 11, 2022
033f7f6
MRTD fix string_t -> FuriString*
qistoph Oct 12, 2022
76ef36e
MRTD minor format string fixes
qistoph Oct 12, 2022
13d32f6
MRTD remove testing values
qistoph Oct 12, 2022
49ab1f9
MRTD Support NFC-B documents
qistoph Oct 21, 2022
fe2b5fa
MRTD recognize MRTDs properly
qistoph Oct 25, 2022
c3d7417
MRTD show auth failure message
qistoph Oct 25, 2022
46878d1
MRTD show auth method used
qistoph Oct 26, 2022
496c059
MRTD save/load BAC params
qistoph Oct 27, 2022
5119eaf
MRTD remove auth failed TODO
qistoph Oct 27, 2022
7778904
MRTD move mrtd_helpers to nfc/helpers/
qistoph Oct 27, 2022
ab3c74b
Merge remote-tracking branch 'upstream/dev' into mrtd
qistoph Oct 27, 2022
16ed3cb
MRTD reset auth on retry
qistoph Oct 27, 2022
fc31ddc
MRTD Load params as menu option
qistoph Oct 27, 2022
131578a
MRTD Use u2f icon in load params
qistoph Oct 27, 2022
0a044d6
MRTD Select auth&read after load
qistoph Oct 27, 2022
bd5b0da
MRTD Move MrtdData to helper .h
qistoph Oct 27, 2022
a629a39
MRTD Reference MrtdData from MrtdApplication
qistoph Oct 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@ openocd.log
# PVS Studio temporary files
.PVS-Studio/
PVS-Studio.log

#TODO: remove
applications/main/nfc/test_bac_creds.h
11 changes: 11 additions & 0 deletions applications/main/nfc/nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ Nfc* nfc_alloc() {
nfc->view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box));
nfc->text_box_store = furi_string_alloc();

// Variable Item List
nfc->variable_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
nfc->view_dispatcher,
NfcViewVarItemList,
variable_item_list_get_view(nfc->variable_item_list));

// Custom Widget
nfc->widget = widget_alloc();
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget));
Expand Down Expand Up @@ -155,6 +162,10 @@ void nfc_free(Nfc* nfc) {
text_box_free(nfc->text_box);
furi_string_free(nfc->text_box_store);

// Variable Item List
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewVarItemList);
variable_item_list_free(nfc->variable_item_list);

// Custom Widget
view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget);
widget_free(nfc->widget);
Expand Down
3 changes: 3 additions & 0 deletions applications/main/nfc/nfc_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <gui/modules/byte_input.h>
#include <gui/modules/text_box.h>
#include <gui/modules/widget.h>
#include <gui/modules/variable_item_list.h>

#include <lib/nfc/nfc_types.h>
#include <lib/nfc/nfc_worker.h>
Expand Down Expand Up @@ -77,6 +78,7 @@ struct Nfc {
TextInput* text_input;
ByteInput* byte_input;
TextBox* text_box;
VariableItemList* variable_item_list;
Widget* widget;
DictAttack* dict_attack;
DetectReader* detect_reader;
Expand All @@ -92,6 +94,7 @@ typedef enum {
NfcViewTextInput,
NfcViewByteInput,
NfcViewTextBox,
NfcViewVarItemList,
NfcViewWidget,
NfcViewDictAttack,
NfcViewDetectReader,
Expand Down
8 changes: 8 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
ADD_SCENE(nfc, emv_menu, EmvMenu)
ADD_SCENE(nfc, passport_read, PassportReadSuccess)
ADD_SCENE(nfc, passport_read_auth, PassportReadAuthSuccess)
ADD_SCENE(nfc, passport_menu, PassportMenu)
ADD_SCENE(nfc, passport_auth, PassportAuth)
ADD_SCENE(nfc, passport_auth_save_name, PassportAuthSaveName)
ADD_SCENE(nfc, passport_date, PassportDate)
ADD_SCENE(nfc, passport_docnr, PassportDocNr)
ADD_SCENE(nfc, passport_pace_todo, PassportPaceTodo)
ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence)
ADD_SCENE(nfc, device_info, DeviceInfo)
ADD_SCENE(nfc, delete, Delete)
Expand Down
4 changes: 3 additions & 1 deletion applications/main/nfc/scenes/nfc_scene_nfc_data_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
// Set tag type
if(protocol == NfcDeviceProtocolEMV) {
furi_string_cat_printf(temp_str, "\e#EMV Bank Card\n");
} else if(protocol == NfcDeviceProtocolMRTD) {
furi_string_cat_printf(temp_str, "\e#Passport/ID\n");
} else if(protocol == NfcDeviceProtocolMifareUl) {
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true));
Expand Down Expand Up @@ -131,4 +133,4 @@ void nfc_scene_nfc_data_info_on_exit(void* context) {
Nfc* nfc = context;

widget_reset(nfc->widget);
}
}
189 changes: 189 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_passport_auth.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#include "../nfc_i.h"

#define TAG "PassportAuth"

#define MRTD_AUTH_METHOD_COUNT 4
// Must match MrtdAuthMethod size (lib/nfc/protocols/mrtd_helpers.h)

typedef enum {
NfcScenePassportAuthSelectDob,
NfcScenePassportAuthSelectDoe,
NfcScenePassportAuthSelectDocNr,
NfcScenePassportAuthSelectMethod,
NfcScenePassportAuthSelectAuth,
NfcScenePassportAuthSelectSave,
NfcScenePassportAuthSelectLoad,
} NfcScenePassportAuthSelect;

void nfc_scene_passport_auth_var_list_enter_callback(void* context, uint32_t index) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}

void nfc_scene_passport_auth_method_changed(VariableItem* item) {
Nfc* nfc = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
nfc->dev->dev_data.mrtd_data.auth.method = index;
variable_item_set_current_value_text(item, mrtd_auth_method_string(index));
}

bool nfc_scene_passport_auth_load(Nfc* nfc) {
const DialogsFileBrowserOptions browser_options = {
.extension = MRTD_APP_EXTENSION,
.skip_assets = true,
.icon = &I_u2f_10px,
.hide_ext = true,
.item_loader_callback = NULL,
.item_loader_context = NULL,
};

FuriString* mrtd_app_folder;
mrtd_app_folder = furi_string_alloc_set(MRTD_APP_FOLDER);

FuriString* file_path;
file_path = furi_string_alloc();

bool res = dialog_file_browser_show(nfc->dev->dialogs, file_path, mrtd_app_folder, &browser_options);

furi_string_free(mrtd_app_folder);

if(res) {
mrtd_auth_params_load(
nfc->dev->storage,
nfc->dev->dialogs,
&nfc->dev->dev_data.mrtd_data.auth,
furi_string_get_cstr(file_path),
true);

nfc_scene_passport_auth_on_enter(nfc);
variable_item_list_set_selected_item(nfc->variable_item_list, NfcScenePassportAuthSelectAuth);
}

return res;
}

void nfc_scene_passport_auth_on_enter(void* context) {
Nfc* nfc = context;
MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data;

// By entering the Auth menu, we default to Auth: Any
MrtdAuthMethod* auth_method = &mrtd_data->auth.method;
if(*auth_method == MrtdAuthMethodNone) {
*auth_method = MrtdAuthMethodAny;
}

VariableItemList* variable_item_list = nfc->variable_item_list;
variable_item_list_reset(variable_item_list);

VariableItem* item;
uint8_t value_index;

const size_t temp_str_size = 15;
char temp_str[temp_str_size];

snprintf(temp_str, temp_str_size, "%02u%02u%02u",
mrtd_data->auth.birth_date.year,
mrtd_data->auth.birth_date.month,
mrtd_data->auth.birth_date.day);

item = variable_item_list_add(variable_item_list, "Birth Date", 1, NULL, NULL);
variable_item_set_current_value_text(item, temp_str);

snprintf(temp_str, temp_str_size, "%02u%02u%02u",
mrtd_data->auth.expiry_date.year,
mrtd_data->auth.expiry_date.month,
mrtd_data->auth.expiry_date.day);

item = variable_item_list_add(variable_item_list, "Expiry Date", 1, NULL, NULL);
variable_item_set_current_value_text(item, temp_str);

item = variable_item_list_add(variable_item_list, "Document Nr.", 1, NULL, NULL);

strncpy(temp_str, mrtd_data->auth.doc_number, temp_str_size);
temp_str[temp_str_size] = '\x00';
if(strlen(temp_str) > 8) {
temp_str[8] = '.';
temp_str[9] = '.';
temp_str[10] = '.';
temp_str[11] = '\x00';
}
variable_item_set_current_value_text(
item,
temp_str);

item = variable_item_list_add(
variable_item_list,
"Method",
MRTD_AUTH_METHOD_COUNT,
nfc_scene_passport_auth_method_changed,
nfc);

value_index = *auth_method;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, mrtd_auth_method_string(value_index));

variable_item_list_add(variable_item_list, "Authenticate and read", 1, NULL, NULL);

variable_item_list_add(variable_item_list, "Save parameters", 1, NULL, NULL);
variable_item_list_add(variable_item_list, "Load parameters", 1, NULL, NULL);

variable_item_list_set_enter_callback(
variable_item_list, nfc_scene_passport_auth_var_list_enter_callback, nfc);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewVarItemList);
}

bool nfc_scene_passport_auth_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
FURI_LOG_D(TAG, "event.event: %ld", event.event);
switch(event.event) {
case NfcScenePassportAuthSelectLoad:
nfc_scene_passport_auth_load(nfc);
consumed = true;
break;
case NfcScenePassportAuthSelectDob:
scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 0);
scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate);
consumed = true;
break;
case NfcScenePassportAuthSelectDoe:
scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 1);
scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate);
consumed = true;
break;
case NfcScenePassportAuthSelectDocNr:
scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDocNr);
consumed = true;
break;
case NfcScenePassportAuthSelectMethod:
consumed = true;
break;
case NfcScenePassportAuthSelectAuth:
if(nfc->dev->dev_data.mrtd_data.auth.method == MrtdAuthMethodPace) {
scene_manager_next_scene(nfc->scene_manager, NfcScenePassportPaceTodo);
} else {
nfc_device_clear(nfc->dev);
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
}
consumed = true;
break;
case NfcScenePassportAuthSelectSave:
scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuthSaveName);
consumed = true;
break;
}
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
}

return consumed;
}

void nfc_scene_passport_auth_on_exit(void* context) {
Nfc* nfc = context;

// Clear view
variable_item_list_reset(nfc->variable_item_list);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "../nfc_i.h"
#include <lib/toolbox/random_name.h>
#include <gui/modules/validators.h>
#include <toolbox/path.h>

void nfc_scene_passport_auth_save_name_text_input_callback(void* context) {
Nfc* nfc = context;

view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone);
}

void nfc_scene_passport_auth_save_name_on_enter(void* context) {
Nfc* nfc = context;

MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data;

// Setup view
TextInput* text_input = nfc->text_input;
bool docnr_empty = false;
if(!strcmp(mrtd_data->auth.doc_number, "")) {
set_random_name(nfc->text_store, sizeof(nfc->text_store));
docnr_empty = true;
} else {
nfc_text_store_set(nfc, mrtd_data->auth.doc_number);
}
text_input_set_header_text(text_input, "Name the parameters");
text_input_set_result_callback(
text_input,
nfc_scene_passport_auth_save_name_text_input_callback,
nfc,
nfc->text_store,
NFC_DEV_NAME_MAX_LEN,
docnr_empty);

FuriString* folder_path;
folder_path = furi_string_alloc();

if(furi_string_end_with(nfc->dev->load_path, NFC_APP_EXTENSION)) {
path_extract_dirname(furi_string_get_cstr(nfc->dev->load_path), folder_path);
} else {
furi_string_set(folder_path, NFC_APP_FOLDER);
}

ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, NULL);
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);

furi_string_free(folder_path);
}

bool nfc_scene_passport_auth_save_name_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventTextInputDone) {
if(mrtd_auth_params_save(nfc->dev->storage, nfc->dev->dialogs, &mrtd_data->auth, nfc->text_store)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
consumed = true;
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
}
}
return consumed;
}

void nfc_scene_passport_auth_save_name_on_exit(void* context) {
Nfc* nfc = context;

// Clear view
void* validator_context = text_input_get_validator_callback_context(nfc->text_input);
text_input_set_validator(nfc->text_input, NULL, NULL);
validator_is_file_free(validator_context);

text_input_reset(nfc->text_input);
}
Loading