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

added ISO15693 (NfcV) reading, saving, emulating and revealing from privacy mode (unlock) #2316

Merged
merged 37 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6e3f50d
added support for ISO15693 (NfcV) emulation, added support for readin…
g3gg0 Dec 28, 2022
9ec2fe0
SLIX: fixed crash situation when an invalid password was requested
g3gg0 Dec 29, 2022
f0a17f1
ISO15693: show emulate menu when opening file
g3gg0 Dec 29, 2022
37be2e8
rename NfcV emulate scene to match other NfcV names
g3gg0 Dec 29, 2022
fd1b0ee
optimize allocation size for signals
g3gg0 Dec 29, 2022
0fcdf39
ISO15693: further optimizations of allocation and free code
g3gg0 Dec 29, 2022
09f30c1
ISO15693: further cleanup
g3gg0 Dec 30, 2022
46a49b3
ISO15693: reduce latency on state machine reset
g3gg0 Dec 30, 2022
a314c16
further code cleanups
g3gg0 Jan 3, 2023
c9a5d60
respond with block security status when option flag is set
g3gg0 Jan 20, 2023
deb5495
increased maximum memory size to match standard
g3gg0 Jan 20, 2023
73c5b3f
added "Listen NfcV Reader" to sniff traffic from reader to card
g3gg0 Jan 21, 2023
64514a5
added correct description to delete menu
g3gg0 Jan 21, 2023
88a5395
also added DSFID/AFI handling and locking
g3gg0 Jan 21, 2023
a3fd5d2
increase sniff log size
g3gg0 Jan 21, 2023
ac1e58a
scale NfcV frequency a bit, add echo mode, fix signal level at the end
g3gg0 Feb 4, 2023
a71b0aa
fix debug print warnings
nvx May 1, 2023
709dd63
Minor fixes
nvx May 9, 2023
3d5a039
update api_symbols.csv
nvx May 9, 2023
13d82c8
use symbolic modulated/unmodulated GPIO levels
g3gg0 May 10, 2023
98064ba
honor AFI field, decrease verbosity and removed debug code
g3gg0 May 10, 2023
5f3e2d7
refactor defines for less namespace pollution by using NFCV_ prefixes
g3gg0 May 12, 2023
984a329
correct an oversight that original cards return an generic error when…
g3gg0 May 12, 2023
4c42e8c
use inverse modulation, increasing readable range significantly
g3gg0 May 12, 2023
f8e5193
rework and better document nfc chip initialization
g3gg0 May 12, 2023
80cc687
Merge remote-tracking branch 'origin/dev' into ISO15693
nvx May 31, 2023
73b1d52
nfcv code review fixes
nvx May 31, 2023
67fd328
Disable accidentally left on signal debug gpio output
nvx Jun 3, 2023
e16ad2e
Improve NFCV Read/Info GUIs.
xMasterX Jun 3, 2023
2f08b58
Fix crash that occurs when you exit from NFCV emulation and start it …
xMasterX Jun 3, 2023
a984dda
Merge remote-tracking branch 'origin/dev' into ISO15693
nvx Jun 3, 2023
45c6396
Remove delay from emulation loop. This improves compatibility when th…
nvx Jun 3, 2023
7b8239c
Merge branch 'dev' into ISO15693
g3gg0 Jun 5, 2023
d8ce1eb
Merge branch 'dev' into ISO15693
gornekich Jun 7, 2023
d777f9e
Merge branch 'dev' into ISO15693
skotopes Jun 8, 2023
6567540
Merge branch 'dev' into ISO15693
skotopes Jun 8, 2023
b660cf8
Lib: digital signal debug output pin info
skotopes Jun 8, 2023
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
2 changes: 2 additions & 0 deletions applications/main/nfc/helpers/nfc_custom_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ enum NfcCustomEvent {
NfcCustomEventDictAttackSkip,
NfcCustomEventRpcLoad,
NfcCustomEventRpcSessionClose,
NfcCustomEventUpdateLog,
NfcCustomEventSaveShadow,
};
3 changes: 3 additions & 0 deletions applications/main/nfc/nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ int32_t nfc_app(void* p) {
} else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate);
DOLPHIN_DEED(DolphinDeedNfcEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVEmulate);
DOLPHIN_DEED(DolphinDeedNfcEmulate);
} else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
} else {
Expand Down
7 changes: 7 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ ADD_SCENE(nfc, file_select, FileSelect)
ADD_SCENE(nfc, emulate_uid, EmulateUid)
ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess)
ADD_SCENE(nfc, nfca_menu, NfcaMenu)
ADD_SCENE(nfc, nfcv_menu, NfcVMenu)
ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu)
ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput)
ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock)
ADD_SCENE(nfc, nfcv_emulate, NfcVEmulate)
ADD_SCENE(nfc, nfcv_sniff, NfcVSniff)
ADD_SCENE(nfc, nfcv_read_success, NfcVReadSuccess)
ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess)
ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData)
ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu)
Expand Down
7 changes: 6 additions & 1 deletion applications/main/nfc/scenes/nfc_scene_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void nfc_scene_delete_on_enter(void* context) {
nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));

NfcProtocol protocol = nfc->dev->dev_data.protocol;
const char* nfc_type = "NFC-A";

if(protocol == NfcDeviceProtocolEMV) {
furi_string_set(temp_str, "EMV bank card");
} else if(protocol == NfcDeviceProtocolMifareUl) {
Expand All @@ -39,12 +41,15 @@ void nfc_scene_delete_on_enter(void* context) {
furi_string_set(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type));
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
furi_string_set(temp_str, "MIFARE DESFire");
} else if(protocol == NfcDeviceProtocolNfcV) {
furi_string_set(temp_str, "ISO15693 tag");
nfc_type = "NFC-V";
} else {
furi_string_set(temp_str, "Unknown ISO tag");
}
widget_add_string_element(
nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(temp_str));
widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A");
widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, nfc_type);
furi_string_free(temp_str);

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
Expand Down
20 changes: 20 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_extra_actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ enum SubmenuIndex {
SubmenuIndexReadCardType,
SubmenuIndexMfClassicKeys,
SubmenuIndexMfUltralightUnlock,
SubmenuIndexNfcVUnlock,
SubmenuIndexNfcVSniff,
};

void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
Expand Down Expand Up @@ -34,6 +36,18 @@ void nfc_scene_extra_actions_on_enter(void* context) {
SubmenuIndexMfUltralightUnlock,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Unlock SLIX-L",
SubmenuIndexNfcVUnlock,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Listen NfcV Reader",
SubmenuIndexNfcVSniff,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
Expand All @@ -58,6 +72,12 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType);
consumed = true;
} else if(event.event == SubmenuIndexNfcVUnlock) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlockMenu);
consumed = true;
} else if(event.event == SubmenuIndexNfcVSniff) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVSniff);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
}
Expand Down
162 changes: 155 additions & 7 deletions applications/main/nfc/scenes/nfc_scene_nfc_data_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,165 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type));
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
furi_string_cat_printf(temp_str, "\e#MIFARE DESFire\n");
} else if(protocol == NfcDeviceProtocolNfcV) {
switch(dev_data->nfcv_data.sub_type) {
case NfcVTypePlain:
furi_string_cat_printf(temp_str, "\e#ISO15693\n");
break;
case NfcVTypeSlix:
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX\n");
break;
case NfcVTypeSlixS:
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-S\n");
break;
case NfcVTypeSlixL:
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-L\n");
break;
case NfcVTypeSlix2:
furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX2\n");
break;
default:
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
break;
}
} else {
furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
}

// Set tag iso data
char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3';
furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
if(protocol == NfcDeviceProtocolNfcV) {
NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data;

furi_string_cat_printf(temp_str, "UID:\n");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
}
furi_string_cat_printf(temp_str, "\n");

furi_string_cat_printf(
temp_str,
"DSFID: %02X %s\n",
nfcv_data->dsfid,
(nfcv_data->security_status[0] & NfcVLockBitDsfid) ? "(locked)" : "");
furi_string_cat_printf(
temp_str,
"AFI: %02X %s\n",
nfcv_data->afi,
(nfcv_data->security_status[0] & NfcVLockBitAfi) ? "(locked)" : "");
furi_string_cat_printf(temp_str, "IC Ref: %02X\n", nfcv_data->ic_ref);
furi_string_cat_printf(temp_str, "Blocks: %02X\n", nfcv_data->block_num);
furi_string_cat_printf(temp_str, "Blocksize: %02X\n", nfcv_data->block_size);

switch(dev_data->nfcv_data.sub_type) {
case NfcVTypePlain:
furi_string_cat_printf(temp_str, "Type: Plain\n");
break;
case NfcVTypeSlix:
furi_string_cat_printf(temp_str, "Type: SLIX\n");
furi_string_cat_printf(temp_str, "Keys:\n");
furi_string_cat_printf(
temp_str,
" EAS %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_eas, 4));
break;
case NfcVTypeSlixS:
furi_string_cat_printf(temp_str, "Type: SLIX-S\n");
furi_string_cat_printf(temp_str, "Keys:\n");
furi_string_cat_printf(
temp_str,
" Read %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_read, 4));
furi_string_cat_printf(
temp_str,
" Write %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_write, 4));
furi_string_cat_printf(
temp_str,
" Privacy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_privacy, 4));
furi_string_cat_printf(
temp_str,
" Destroy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_destroy, 4));
furi_string_cat_printf(
temp_str,
" EAS %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_eas, 4));
break;
case NfcVTypeSlixL:
furi_string_cat_printf(temp_str, "Type: SLIX-L\n");
furi_string_cat_printf(temp_str, "Keys:\n");
furi_string_cat_printf(
temp_str,
" Privacy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_privacy, 4));
furi_string_cat_printf(
temp_str,
" Destroy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_destroy, 4));
furi_string_cat_printf(
temp_str,
" EAS %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_eas, 4));
break;
case NfcVTypeSlix2:
furi_string_cat_printf(temp_str, "Type: SLIX2\n");
furi_string_cat_printf(temp_str, "Keys:\n");
furi_string_cat_printf(
temp_str,
" Read %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_read, 4));
furi_string_cat_printf(
temp_str,
" Write %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_write, 4));
furi_string_cat_printf(
temp_str,
" Privacy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_privacy, 4));
furi_string_cat_printf(
temp_str,
" Destroy %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_destroy, 4));
furi_string_cat_printf(
temp_str,
" EAS %08llX\n",
nfc_util_bytes2num(nfcv_data->sub_data.slix.key_eas, 4));
break;
default:
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
break;
}

furi_string_cat_printf(
temp_str, "Data (%d byte)\n", nfcv_data->block_num * nfcv_data->block_size);

int maxBlocks = nfcv_data->block_num;
if(maxBlocks > 32) {
maxBlocks = 32;
furi_string_cat_printf(temp_str, "(truncated to %d blocks)\n", maxBlocks);
}

for(int block = 0; block < maxBlocks; block++) {
const char* status = (nfcv_data->security_status[block] & 0x01) ? "(lck)" : "";
for(int pos = 0; pos < nfcv_data->block_size; pos++) {
furi_string_cat_printf(
temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]);
}
furi_string_cat_printf(temp_str, " %s\n", status);
}

} else {
char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3';
furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type);
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
}
furi_string_cat_printf(
temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
}
furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);

// Set application specific data
if(protocol == NfcDeviceProtocolMifareDesfire) {
Expand Down Expand Up @@ -139,6 +285,8 @@ bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) {
consumed = true;
} else if(protocol == NfcDeviceProtocolMifareClassic) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicData);
} else if(protocol == NfcDeviceProtocolNfcV) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu);
consumed = true;
}
}
Expand Down
Loading