mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 20:49:49 +04:00
@@ -21,5 +21,5 @@ App(
|
|||||||
fap_author="AloneLiberty",
|
fap_author="AloneLiberty",
|
||||||
fap_description="Recover Mifare Classic keys",
|
fap_description="Recover Mifare Classic keys",
|
||||||
fap_weburl="https://github.com/AloneLiberty/FlipperNested",
|
fap_weburl="https://github.com/AloneLiberty/FlipperNested",
|
||||||
fap_version=(1, 4)
|
fap_version="1.5.0"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,28 +5,6 @@
|
|||||||
#include "../../lib/crypto1/crypto1.h"
|
#include "../../lib/crypto1/crypto1.h"
|
||||||
#define TAG "Nested"
|
#define TAG "Nested"
|
||||||
|
|
||||||
void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest) {
|
|
||||||
furi_assert(dest);
|
|
||||||
furi_assert(len <= 8);
|
|
||||||
|
|
||||||
while(len--) {
|
|
||||||
dest[len] = (uint8_t)src;
|
|
||||||
src >>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len) {
|
|
||||||
furi_assert(src);
|
|
||||||
furi_assert(len <= 8);
|
|
||||||
|
|
||||||
uint64_t res = 0;
|
|
||||||
while(len--) {
|
|
||||||
res = (res << 8) | (*src);
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) {
|
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) {
|
||||||
uint16_t crc = 0x6363; // NFCA_CRC_INIT
|
uint16_t crc = 0x6363; // NFCA_CRC_INIT
|
||||||
uint8_t byte = 0;
|
uint8_t byte = 0;
|
||||||
|
|||||||
@@ -396,6 +396,7 @@ void mifare_nested_blink_stop(MifareNested* mifare_nested) {
|
|||||||
|
|
||||||
int32_t mifare_nested_app(void* p) {
|
int32_t mifare_nested_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|
||||||
MifareNested* mifare_nested = mifare_nested_alloc();
|
MifareNested* mifare_nested = mifare_nested_alloc();
|
||||||
|
|
||||||
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart);
|
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include <gui/modules/variable_item_list.h>
|
#include <gui/modules/variable_item_list.h>
|
||||||
#include "mifare_nested_icons.h"
|
#include "mifare_nested_icons.h"
|
||||||
|
|
||||||
#define NESTED_VERSION_APP "1.4.6"
|
#define NESTED_VERSION_APP "1.5.0"
|
||||||
#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
|
#define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
|
||||||
#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
|
#define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
|
||||||
#define NESTED_NONCE_FORMAT_VERSION "3"
|
#define NESTED_NONCE_FORMAT_VERSION "3"
|
||||||
@@ -99,6 +99,7 @@ struct MifareNested {
|
|||||||
|
|
||||||
NestedState* nested_state;
|
NestedState* nested_state;
|
||||||
CheckKeysState* keys_state;
|
CheckKeysState* keys_state;
|
||||||
|
SaveNoncesResult_t* save_state;
|
||||||
|
|
||||||
MifareNestedWorkerState collecting_type;
|
MifareNestedWorkerState collecting_type;
|
||||||
|
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ uint32_t mifare_nested_worker_predict_delay(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This part of attack is my attempt to implement it on Flipper.
|
// This part of attack is my attempt to implement it on Flipper.
|
||||||
// Proxmark can do this in 2 fucking steps, but idk how.
|
// Check README.md for more info
|
||||||
|
|
||||||
// First, we find RPNG rounds per 1000 us
|
// First, we find RPNG rounds per 1000 us
|
||||||
for(uint32_t rtr = 0; rtr < 25; rtr++) {
|
for(uint32_t rtr = 0; rtr < 25; rtr++) {
|
||||||
@@ -448,7 +448,7 @@ uint32_t mifare_nested_worker_predict_delay(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mifare_nested_worker_write_nonces(
|
SaveNoncesResult_t* mifare_nested_worker_write_nonces(
|
||||||
FuriHalNfcDevData* data,
|
FuriHalNfcDevData* data,
|
||||||
Storage* storage,
|
Storage* storage,
|
||||||
NonceList_t* nonces,
|
NonceList_t* nonces,
|
||||||
@@ -459,6 +459,11 @@ void mifare_nested_worker_write_nonces(
|
|||||||
uint32_t distance) {
|
uint32_t distance) {
|
||||||
FuriString* path = furi_string_alloc();
|
FuriString* path = furi_string_alloc();
|
||||||
Stream* file_stream = file_stream_alloc(storage);
|
Stream* file_stream = file_stream_alloc(storage);
|
||||||
|
SaveNoncesResult_t* result = malloc(sizeof(SaveNoncesResult_t));
|
||||||
|
result->saved = 0;
|
||||||
|
result->invalid = 0;
|
||||||
|
result->skipped = 0;
|
||||||
|
|
||||||
mifare_nested_worker_get_nonces_file_path(data, path);
|
mifare_nested_worker_get_nonces_file_path(data, path);
|
||||||
|
|
||||||
file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
|
file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
|
||||||
@@ -472,23 +477,26 @@ void mifare_nested_worker_write_nonces(
|
|||||||
for(uint8_t tries = 0; tries < tries_count; tries++) {
|
for(uint8_t tries = 0; tries < tries_count; tries++) {
|
||||||
for(uint8_t sector = 0; sector < sector_count; sector++) {
|
for(uint8_t sector = 0; sector < sector_count; sector++) {
|
||||||
for(uint8_t key_type = 0; key_type < 2; key_type++) {
|
for(uint8_t key_type = 0; key_type < 2; key_type++) {
|
||||||
if(nonces->nonces[sector][key_type][tries]->collected &&
|
if(nonces->nonces[sector][key_type][tries]->invalid) {
|
||||||
!nonces->nonces[sector][key_type][tries]->skipped) {
|
result->invalid++;
|
||||||
|
} else if(nonces->nonces[sector][key_type][tries]->skipped) {
|
||||||
|
result->skipped++;
|
||||||
|
} else if(nonces->nonces[sector][key_type][tries]->collected) {
|
||||||
if(nonces->nonces[sector][key_type][tries]->hardnested) {
|
if(nonces->nonces[sector][key_type][tries]->hardnested) {
|
||||||
FuriString* path = furi_string_alloc();
|
FuriString* hardnested_path = furi_string_alloc();
|
||||||
mifare_nested_worker_get_hardnested_file_path(
|
mifare_nested_worker_get_hardnested_file_path(
|
||||||
data, path, sector, key_type);
|
data, hardnested_path, sector, key_type);
|
||||||
|
|
||||||
FuriString* str = furi_string_alloc_printf(
|
FuriString* str = furi_string_alloc_printf(
|
||||||
"HardNested: Key %c cuid 0x%08lx file %s sec %u\n",
|
"HardNested: Key %c cuid 0x%08lx file %s sec %u\n",
|
||||||
!key_type ? 'A' : 'B',
|
!key_type ? 'A' : 'B',
|
||||||
nonces->cuid,
|
nonces->cuid,
|
||||||
furi_string_get_cstr(path),
|
furi_string_get_cstr(hardnested_path),
|
||||||
sector);
|
sector);
|
||||||
|
|
||||||
stream_write_string(file_stream, str);
|
stream_write_string(file_stream, str);
|
||||||
|
|
||||||
furi_string_free(path);
|
furi_string_free(hardnested_path);
|
||||||
furi_string_free(str);
|
furi_string_free(str);
|
||||||
} else {
|
} else {
|
||||||
FuriString* str = furi_string_alloc_printf(
|
FuriString* str = furi_string_alloc_printf(
|
||||||
@@ -515,6 +523,8 @@ void mifare_nested_worker_write_nonces(
|
|||||||
stream_write_string(file_stream, str);
|
stream_write_string(file_stream, str);
|
||||||
furi_string_free(str);
|
furi_string_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->saved++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,10 +539,20 @@ void mifare_nested_worker_write_nonces(
|
|||||||
}
|
}
|
||||||
|
|
||||||
free_nonces(nonces, sector_count, free_tries_count);
|
free_nonces(nonces, sector_count, free_tries_count);
|
||||||
furi_string_free(path);
|
|
||||||
file_stream_close(file_stream);
|
file_stream_close(file_stream);
|
||||||
free(file_stream);
|
free(file_stream);
|
||||||
|
|
||||||
|
if(!result->saved) {
|
||||||
|
FURI_LOG_E(TAG, "No nonces collected, removing file...");
|
||||||
|
if(!storage_simply_remove(storage, furi_string_get_cstr(path))) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to remove .nonces file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_free(path);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mifare_nested_worker_check_initial_keys(
|
bool mifare_nested_worker_check_initial_keys(
|
||||||
@@ -759,7 +779,7 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste
|
|||||||
mifare_nested_worker_get_block_by_sector(sector),
|
mifare_nested_worker_get_block_by_sector(sector),
|
||||||
key_type);
|
key_type);
|
||||||
|
|
||||||
info->skipped = true;
|
info->invalid = true;
|
||||||
|
|
||||||
nonces.nonces[sector][key_type][0] = info;
|
nonces.nonces[sector][key_type][0] = info;
|
||||||
|
|
||||||
@@ -818,12 +838,20 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
|
SaveNoncesResult_t* result =
|
||||||
|
mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
|
||||||
|
|
||||||
free(mf_data);
|
free(mf_data);
|
||||||
|
|
||||||
mifare_nested_worker->callback(
|
if(result->saved) {
|
||||||
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
||||||
|
} else {
|
||||||
|
mifare_nested_worker->context->save_state = result;
|
||||||
|
|
||||||
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
|
||||||
|
}
|
||||||
|
|
||||||
nfc_deactivate();
|
nfc_deactivate();
|
||||||
}
|
}
|
||||||
@@ -930,7 +958,7 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_
|
|||||||
mifare_nested_worker_get_block_by_sector(sector),
|
mifare_nested_worker_get_block_by_sector(sector),
|
||||||
key_type);
|
key_type);
|
||||||
|
|
||||||
info->skipped = true;
|
info->invalid = true;
|
||||||
|
|
||||||
nonces.nonces[sector][key_type][0] = info;
|
nonces.nonces[sector][key_type][0] = info;
|
||||||
mifare_nested_worker->context->nonces = &nonces;
|
mifare_nested_worker->context->nonces = &nonces;
|
||||||
@@ -1059,12 +1087,20 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
|
SaveNoncesResult_t* result =
|
||||||
|
mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
|
||||||
|
|
||||||
free(mf_data);
|
free(mf_data);
|
||||||
|
|
||||||
mifare_nested_worker->callback(
|
if(result->saved) {
|
||||||
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
||||||
|
} else {
|
||||||
|
mifare_nested_worker->context->save_state = result;
|
||||||
|
|
||||||
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
|
||||||
|
}
|
||||||
|
|
||||||
nfc_deactivate();
|
nfc_deactivate();
|
||||||
}
|
}
|
||||||
@@ -1368,13 +1404,20 @@ void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worke
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mifare_nested_worker_write_nonces(
|
SaveNoncesResult_t* result = mifare_nested_worker_write_nonces(
|
||||||
&data, storage, &nonces, tries_count, 3, sector_count, delay, distance);
|
&data, storage, &nonces, tries_count, 3, sector_count, delay, distance);
|
||||||
|
|
||||||
free(mf_data);
|
free(mf_data);
|
||||||
|
|
||||||
mifare_nested_worker->callback(
|
if(result->saved) {
|
||||||
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
|
||||||
|
} else {
|
||||||
|
mifare_nested_worker->context->save_state = result;
|
||||||
|
|
||||||
|
mifare_nested_worker->callback(
|
||||||
|
MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
|
||||||
|
}
|
||||||
|
|
||||||
nfc_deactivate();
|
nfc_deactivate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ typedef enum {
|
|||||||
MifareNestedWorkerEventReserved = 1000,
|
MifareNestedWorkerEventReserved = 1000,
|
||||||
|
|
||||||
MifareNestedWorkerEventNoTagDetected,
|
MifareNestedWorkerEventNoTagDetected,
|
||||||
|
MifareNestedWorkerEventNoNoncesCollected,
|
||||||
MifareNestedWorkerEventNoncesCollected,
|
MifareNestedWorkerEventNoncesCollected,
|
||||||
MifareNestedWorkerEventCollecting,
|
MifareNestedWorkerEventCollecting,
|
||||||
|
|
||||||
@@ -64,8 +65,9 @@ typedef struct {
|
|||||||
uint32_t target_nt[2];
|
uint32_t target_nt[2];
|
||||||
uint32_t target_ks[2];
|
uint32_t target_ks[2];
|
||||||
uint8_t parity[2][4];
|
uint8_t parity[2][4];
|
||||||
bool collected;
|
|
||||||
bool skipped;
|
bool skipped;
|
||||||
|
bool invalid;
|
||||||
|
bool collected;
|
||||||
bool hardnested;
|
bool hardnested;
|
||||||
} Nonces;
|
} Nonces;
|
||||||
|
|
||||||
@@ -87,3 +89,9 @@ typedef struct {
|
|||||||
uint32_t sector_keys;
|
uint32_t sector_keys;
|
||||||
bool tag_lost;
|
bool tag_lost;
|
||||||
} KeyInfo_t;
|
} KeyInfo_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t saved;
|
||||||
|
uint32_t invalid;
|
||||||
|
uint32_t skipped;
|
||||||
|
} SaveNoncesResult_t;
|
||||||
@@ -51,7 +51,7 @@ void mifare_nested_scene_about_on_enter(void* context) {
|
|||||||
14,
|
14,
|
||||||
AlignCenter,
|
AlignCenter,
|
||||||
AlignBottom,
|
AlignBottom,
|
||||||
"\e#\e! Flipper (Mifare) Nested \e!\n",
|
"\e#\e! Flipper Nested \e!\n",
|
||||||
false);
|
false);
|
||||||
widget_add_text_scroll_element(
|
widget_add_text_scroll_element(
|
||||||
mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
|
mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
|
||||||
|
|||||||
@@ -56,14 +56,7 @@ bool mifare_nested_scene_check_on_event(void* context, SceneManagerEvent event)
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == MifareNestedWorkerEventNoncesCollected) {
|
if(event.event == MifareNestedWorkerEventCollecting) {
|
||||||
scene_manager_next_scene(
|
|
||||||
mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
|
|
||||||
consumed = true;
|
|
||||||
} else if(event.event == MifareNestedWorkerEventAttackFailed) {
|
|
||||||
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
|
|
||||||
consumed = true;
|
|
||||||
} else if(event.event == MifareNestedWorkerEventCollecting) {
|
|
||||||
if(mifare_nested->run == NestedRunAttack) {
|
if(mifare_nested->run == NestedRunAttack) {
|
||||||
if(mifare_nested->settings->only_hardnested) {
|
if(mifare_nested->settings->only_hardnested) {
|
||||||
FURI_LOG_I("MifareNested", "Using Hard Nested because user settings");
|
FURI_LOG_I("MifareNested", "Using Hard Nested because user settings");
|
||||||
|
|||||||
@@ -84,13 +84,6 @@ bool mifare_nested_scene_check_keys_on_event(void* context, SceneManagerEvent ev
|
|||||||
if(event.event == GuiButtonTypeCenter) {
|
if(event.event == GuiButtonTypeCenter) {
|
||||||
scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
|
scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == MifareNestedWorkerEventNoncesCollected) {
|
|
||||||
scene_manager_next_scene(
|
|
||||||
mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
|
|
||||||
consumed = true;
|
|
||||||
} else if(event.event == MifareNestedWorkerEventNeedKey) {
|
|
||||||
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneNoKeys);
|
|
||||||
consumed = true;
|
|
||||||
} else if(event.event == MifareNestedWorkerEventKeysFound) {
|
} else if(event.event == MifareNestedWorkerEventKeysFound) {
|
||||||
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys);
|
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ bool mifare_nested_scene_collecting_on_event(void* context, SceneManagerEvent ev
|
|||||||
scene_manager_next_scene(
|
scene_manager_next_scene(
|
||||||
mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
|
mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == MifareNestedWorkerEventNoNoncesCollected) {
|
||||||
|
scene_manager_next_scene(
|
||||||
|
mifare_nested->scene_manager, MifareNestedSceneNoNoncesCollected);
|
||||||
|
consumed = true;
|
||||||
} else if(event.event == MifareNestedWorkerEventAttackFailed) {
|
} else if(event.event == MifareNestedWorkerEventAttackFailed) {
|
||||||
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
|
scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ ADD_SCENE(mifare_nested, about, About)
|
|||||||
ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce)
|
ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce)
|
||||||
ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery)
|
ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery)
|
||||||
ADD_SCENE(mifare_nested, need_collection, NeedCollection)
|
ADD_SCENE(mifare_nested, need_collection, NeedCollection)
|
||||||
ADD_SCENE(mifare_nested, settings, Settings)
|
ADD_SCENE(mifare_nested, settings, Settings)
|
||||||
|
ADD_SCENE(mifare_nested, no_nonces_collected, NoNoncesCollected)
|
||||||
94
applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c
vendored
Normal file
94
applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "../mifare_nested_i.h"
|
||||||
|
|
||||||
|
void mifare_nested_scene_no_nonces_collected_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
MifareNested* mifare_nested = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mifare_nested_scene_no_nonces_collected_on_enter(void* context) {
|
||||||
|
MifareNested* mifare_nested = context;
|
||||||
|
Widget* widget = mifare_nested->widget;
|
||||||
|
SaveNoncesResult_t* save_state = mifare_nested->save_state;
|
||||||
|
|
||||||
|
notification_message(mifare_nested->notifications, &sequence_error);
|
||||||
|
|
||||||
|
widget_add_icon_element(widget, 73, 12, &I_DolphinCry);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No nonces collected");
|
||||||
|
|
||||||
|
uint32_t index = 12;
|
||||||
|
|
||||||
|
if(save_state->skipped) {
|
||||||
|
char append_skipped[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'};
|
||||||
|
if(save_state->skipped != 1) {
|
||||||
|
append_skipped[6] = 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
char draw_str[32] = {};
|
||||||
|
snprintf(
|
||||||
|
draw_str, sizeof(draw_str), "Skipped: %lu %s", save_state->skipped, append_skipped);
|
||||||
|
|
||||||
|
widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str);
|
||||||
|
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(already has keys)");
|
||||||
|
|
||||||
|
index += 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(save_state->invalid) {
|
||||||
|
char append_invalid[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'};
|
||||||
|
if(save_state->invalid != 1) {
|
||||||
|
append_invalid[6] = 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
char draw_str[32] = {};
|
||||||
|
snprintf(
|
||||||
|
draw_str, sizeof(draw_str), "Invalid: %lu %s", save_state->invalid, append_invalid);
|
||||||
|
|
||||||
|
widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str);
|
||||||
|
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(can't auth)");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(save_state);
|
||||||
|
|
||||||
|
widget_add_button_element(
|
||||||
|
widget,
|
||||||
|
GuiButtonTypeLeft,
|
||||||
|
"Back",
|
||||||
|
mifare_nested_scene_no_nonces_collected_widget_callback,
|
||||||
|
mifare_nested);
|
||||||
|
|
||||||
|
// Setup and start worker
|
||||||
|
view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mifare_nested_scene_no_nonces_collected_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
MifareNested* mifare_nested = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mifare_nested_scene_no_nonces_collected_on_exit(void* context) {
|
||||||
|
MifareNested* mifare_nested = context;
|
||||||
|
|
||||||
|
widget_reset(mifare_nested->widget);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user