Initial structure for UL-C dictionary attacks

This commit is contained in:
noproto
2024-10-28 19:56:28 -04:00
parent 3f34537b5b
commit 60e0a697fa
9 changed files with 330 additions and 11 deletions

View File

@@ -166,15 +166,26 @@ static void nfc_scene_read_on_enter_mf_ultralight(NfcApp* instance) {
bool nfc_scene_read_on_event_mf_ultralight(NfcApp* instance, SceneManagerEvent event) { bool nfc_scene_read_on_event_mf_ultralight(NfcApp* instance, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) { if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventCardDetected) { if(event.event == NfcCustomEventPollerSuccess) {
nfc_unlock_helper_card_detected_handler(instance); notification_message(instance->notifications, &sequence_success);
} else if(event.event == NfcCustomEventPollerIncomplete) {
notification_message(instance->notifications, &sequence_semi_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess); scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
dolphin_deed(DolphinDeedNfcReadSuccess); dolphin_deed(DolphinDeedNfcReadSuccess);
return true;
} else if(event.event == NfcCustomEventPollerIncomplete) {
const MfUltralightData* data =
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
if(data->type == MfUltralightTypeMfulC) {
// Start dict attack for MFUL C cards
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightCDictAttack);
} else {
notification_message(instance->notifications, &sequence_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
dolphin_deed(DolphinDeedNfcReadSuccess);
}
return true;
} }
} }
return true; return false;
} }
static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instance) { static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instance) {

View File

@@ -47,6 +47,7 @@
#include <lib/nfc/nfc.h> #include <lib/nfc/nfc.h>
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a.h> #include <lib/nfc/protocols/iso14443_3a/iso14443_3a.h>
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h> #include <lib/nfc/protocols/iso14443_3a/iso14443_3a_listener.h>
#include <lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
#include <lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h> #include <lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h>
#include <nfc/nfc_poller.h> #include <nfc/nfc_poller.h>
@@ -80,6 +81,10 @@
#define NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH (NFC_APP_FOLDER "/assets/mf_classic_dict.nfc") #define NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH (NFC_APP_FOLDER "/assets/mf_classic_dict.nfc")
#define NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH \ #define NFC_APP_MF_CLASSIC_DICT_SYSTEM_NESTED_PATH \
(NFC_APP_FOLDER "/assets/mf_classic_dict_nested.nfc") (NFC_APP_FOLDER "/assets/mf_classic_dict_nested.nfc")
#define NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH \
(NFC_APP_FOLDER "/assets/mf_ultralight_c_dict_user.nfc")
#define NFC_APP_MF_ULTRALIGHT_C_DICT_SYSTEM_PATH \
(NFC_APP_FOLDER "/assets/mf_ultralight_c_dict.nfc")
typedef enum { typedef enum {
NfcRpcStateIdle, NfcRpcStateIdle,
@@ -105,6 +110,14 @@ typedef struct {
bool enhanced_dict; bool enhanced_dict;
} NfcMfClassicDictAttackContext; } NfcMfClassicDictAttackContext;
typedef struct {
KeysDict* dict;
bool auth_success;
bool is_card_present;
size_t dict_keys_total;
size_t dict_keys_current;
} NfcMfUltralightCDictContext;
struct NfcApp { struct NfcApp {
DialogsApp* dialogs; DialogsApp* dialogs;
Storage* storage; Storage* storage;
@@ -143,6 +156,7 @@ struct NfcApp {
MfUltralightAuth* mf_ul_auth; MfUltralightAuth* mf_ul_auth;
SlixUnlock* slix_unlock; SlixUnlock* slix_unlock;
NfcMfClassicDictAttackContext nfc_dict_context; NfcMfClassicDictAttackContext nfc_dict_context;
NfcMfUltralightCDictContext mf_ultralight_c_dict_context;
Mfkey32Logger* mfkey32_logger; Mfkey32Logger* mfkey32_logger;
MfUserDict* mf_user_dict; MfUserDict* mf_user_dict;
MfClassicKeyCache* mfc_key_cache; MfClassicKeyCache* mfc_key_cache;

View File

@@ -25,6 +25,7 @@ ADD_SCENE(nfc, retry_confirm, RetryConfirm)
ADD_SCENE(nfc, exit_confirm, ExitConfirm) ADD_SCENE(nfc, exit_confirm, ExitConfirm)
ADD_SCENE(nfc, save_confirm, SaveConfirm) ADD_SCENE(nfc, save_confirm, SaveConfirm)
ADD_SCENE(nfc, mf_ultralight_c_dict_attack, MfUltralightCDictAttack)
ADD_SCENE(nfc, mf_ultralight_write, MfUltralightWrite) ADD_SCENE(nfc, mf_ultralight_write, MfUltralightWrite)
ADD_SCENE(nfc, mf_ultralight_write_success, MfUltralightWriteSuccess) ADD_SCENE(nfc, mf_ultralight_write_success, MfUltralightWriteSuccess)
ADD_SCENE(nfc, mf_ultralight_write_fail, MfUltralightWriteFail) ADD_SCENE(nfc, mf_ultralight_write_fail, MfUltralightWriteFail)

View File

@@ -3,6 +3,7 @@
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexReadCardType, SubmenuIndexReadCardType,
SubmenuIndexMfClassicKeys, SubmenuIndexMfClassicKeys,
SubmenuIndexMfUlCKeys,
SubmenuIndexMfUltralightUnlock, SubmenuIndexMfUltralightUnlock,
SubmenuIndexSlixUnlock, SubmenuIndexSlixUnlock,
}; };
@@ -29,6 +30,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
SubmenuIndexMfClassicKeys, SubmenuIndexMfClassicKeys,
nfc_scene_extra_actions_submenu_callback, nfc_scene_extra_actions_submenu_callback,
instance); instance);
submenu_add_item(
submenu,
"MIFARE Ultralight C Keys",
SubmenuIndexMfUlCKeys,
nfc_scene_extra_actions_submenu_callback,
instance);
submenu_add_item( submenu_add_item(
submenu, submenu,
"Unlock NTAG/Ultralight", "Unlock NTAG/Ultralight",
@@ -54,6 +61,9 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexMfClassicKeys) { if(event.event == SubmenuIndexMfClassicKeys) {
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicKeys); scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicKeys);
consumed = true; consumed = true;
} else if(event.event == SubmenuIndexMfUlCKeys) {
// TODO: Add MFUL C key management scene here
consumed = true;
} else if(event.event == SubmenuIndexMfUltralightUnlock) { } else if(event.event == SubmenuIndexMfUltralightUnlock) {
mf_ultralight_auth_reset(instance->mf_ul_auth); mf_ultralight_auth_reset(instance->mf_ul_auth);
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu); scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu);

View File

@@ -0,0 +1,202 @@
#include "../nfc_app_i.h"
#include <dolphin/dolphin.h>
#define TAG "NfcMfUlCDictAttack"
enum {
DictAttackStateUserDictInProgress,
DictAttackStateSystemDictInProgress,
};
NfcCommand nfc_mf_ultralight_c_dict_attack_worker_callback(NfcGenericEvent event, void* context) {
furi_assert(context);
furi_assert(event.event_data);
furi_assert(event.protocol == NfcProtocolMfUltralight);
NfcCommand command = NfcCommandContinue;
NfcApp* instance = context;
MfUltralightPollerEvent* poller_event = event.event_data;
if(poller_event->type == MfUltralightPollerEventTypeRequestMode) {
poller_event->data->poller_mode = MfUltralightPollerModeDictAttack;
command = NfcCommandContinue;
} else if(poller_event->type == MfUltralightPollerEventTypeRequestKey) {
MfUltralightC3DesAuthKey key = {};
if(keys_dict_get_next_key(
instance->mf_ultralight_c_dict_context.dict,
key.data,
sizeof(MfUltralightC3DesAuthKey))) {
poller_event->data->key_request_data.key = key;
poller_event->data->key_request_data.key_provided = true;
instance->mf_ultralight_c_dict_context.dict_keys_current++;
if(instance->mf_ultralight_c_dict_context.dict_keys_current % 10 == 0) {
view_dispatcher_send_custom_event(
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
}
} else {
poller_event->data->key_request_data.key_provided = false;
}
} else if(poller_event->type == MfUltralightPollerEventTypeReadSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolMfUltralight, nfc_poller_get_data(instance->poller));
view_dispatcher_send_custom_event(
instance->view_dispatcher, NfcCustomEventDictAttackComplete);
command = NfcCommandStop;
}
return command;
}
void nfc_scene_mf_ultralight_c_dict_attack_dict_attack_result_callback(
DictAttackEvent event,
void* context) {
furi_assert(context);
NfcApp* instance = context;
if(event == DictAttackEventSkipPressed) {
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventDictAttackSkip);
}
}
void nfc_scene_mf_ultralight_c_dict_attack_prepare_view(NfcApp* instance) {
uint32_t state =
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfUltralightCDictAttack);
if(state == DictAttackStateUserDictInProgress) {
do {
if(!keys_dict_check_presence(NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH)) {
state = DictAttackStateSystemDictInProgress;
break;
}
instance->mf_ultralight_c_dict_context.dict = keys_dict_alloc(
NFC_APP_MF_ULTRALIGHT_C_DICT_USER_PATH,
KeysDictModeOpenAlways,
sizeof(MfUltralightC3DesAuthKey));
if(keys_dict_get_total_keys(instance->mf_ultralight_c_dict_context.dict) == 0) {
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
state = DictAttackStateSystemDictInProgress;
break;
}
dict_attack_set_header(instance->dict_attack, "MFUL C User Dictionary");
} while(false);
}
if(state == DictAttackStateSystemDictInProgress) {
instance->mf_ultralight_c_dict_context.dict = keys_dict_alloc(
NFC_APP_MF_ULTRALIGHT_C_DICT_SYSTEM_PATH,
KeysDictModeOpenExisting,
sizeof(MfUltralightC3DesAuthKey));
dict_attack_set_header(instance->dict_attack, "MFUL C System Dictionary");
}
instance->mf_ultralight_c_dict_context.dict_keys_total =
keys_dict_get_total_keys(instance->mf_ultralight_c_dict_context.dict);
dict_attack_set_total_dict_keys(
instance->dict_attack, instance->mf_ultralight_c_dict_context.dict_keys_total);
instance->mf_ultralight_c_dict_context.dict_keys_current = 0;
dict_attack_set_callback(
instance->dict_attack,
nfc_scene_mf_ultralight_c_dict_attack_dict_attack_result_callback,
instance);
scene_manager_set_scene_state(instance->scene_manager, NfcSceneMfUltralightCDictAttack, state);
}
void nfc_scene_mf_ultralight_c_dict_attack_on_enter(void* context) {
NfcApp* instance = context;
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfUltralightCDictAttack,
DictAttackStateUserDictInProgress);
nfc_scene_mf_ultralight_c_dict_attack_prepare_view(instance);
// Setup and start worker
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
nfc_poller_start(instance->poller, nfc_mf_ultralight_c_dict_attack_worker_callback, instance);
nfc_blink_read_start(instance);
}
void nfc_scene_mf_ul_c_dict_attack_update_view(NfcApp* instance) {
dict_attack_set_card_state(
instance->dict_attack, instance->mf_ultralight_c_dict_context.is_card_present);
dict_attack_set_current_dict_key(
instance->dict_attack, instance->mf_ultralight_c_dict_context.dict_keys_current);
}
bool nfc_scene_mf_ultralight_c_dict_attack_on_event(void* context, SceneManagerEvent event) {
NfcApp* instance = context;
bool consumed = false;
uint32_t state =
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfUltralightCDictAttack);
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventDictAttackComplete) {
if(state == DictAttackStateUserDictInProgress) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfUltralightCDictAttack,
DictAttackStateSystemDictInProgress);
nfc_scene_mf_ultralight_c_dict_attack_prepare_view(instance);
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
nfc_poller_start(
instance->poller, nfc_mf_ultralight_c_dict_attack_worker_callback, instance);
consumed = true;
} else {
notification_message(instance->notifications, &sequence_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
dolphin_deed(DolphinDeedNfcReadSuccess);
consumed = true;
}
} else if(event.event == NfcCustomEventDictAttackDataUpdate) {
dict_attack_set_current_dict_key(
instance->dict_attack, instance->mf_ultralight_c_dict_context.dict_keys_current);
consumed = true;
} else if(event.event == NfcCustomEventDictAttackSkip) {
if(instance->mf_ultralight_c_dict_context.is_card_present) {
if(state == DictAttackStateUserDictInProgress) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfUltralightCDictAttack,
DictAttackStateSystemDictInProgress);
nfc_scene_mf_ultralight_c_dict_attack_prepare_view(instance);
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
nfc_poller_start(
instance->poller,
nfc_mf_ultralight_c_dict_attack_worker_callback,
instance);
} else {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
notification_message(instance->notifications, &sequence_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
dolphin_deed(DolphinDeedNfcReadSuccess);
}
consumed = true;
}
}
} else if(event.type == SceneManagerEventTypeBack) {
scene_manager_next_scene(instance->scene_manager, NfcSceneExitConfirm);
consumed = true;
}
return consumed;
}
void nfc_scene_mf_ultralight_c_dict_attack_on_exit(void* context) {
NfcApp* instance = context;
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfUltralightCDictAttack,
DictAttackStateUserDictInProgress);
keys_dict_free(instance->mf_ultralight_c_dict_context.dict);
instance->mf_ultralight_c_dict_context.dict_keys_total = 0;
instance->mf_ultralight_c_dict_context.dict_keys_current = 0;
instance->mf_ultralight_c_dict_context.auth_success = false;
instance->mf_ultralight_c_dict_context.is_card_present = false;
nfc_blink_stop(instance);
}

View File

@@ -181,6 +181,10 @@ MfUltralightPoller* mf_ultralight_poller_alloc(Iso14443_3aPoller* iso14443_3a_po
instance->general_event.protocol = NfcProtocolMfUltralight; instance->general_event.protocol = NfcProtocolMfUltralight;
instance->general_event.event_data = &instance->mfu_event; instance->general_event.event_data = &instance->mfu_event;
instance->general_event.instance = instance; instance->general_event.instance = instance;
instance->dict_attack_ctx.auth_success = false;
instance->dict_attack_ctx.is_card_present = false;
mbedtls_des3_init(&instance->des_context); mbedtls_des3_init(&instance->des_context);
return instance; return instance;
} }
@@ -521,7 +525,7 @@ static NfcCommand mf_ultralight_poller_handler_read_pages(MfUltralightPoller* in
} else { } else {
if(instance->data->type == MfUltralightTypeMfulC && if(instance->data->type == MfUltralightTypeMfulC &&
!mf_ultralight_3des_key_valid(instance->data)) { !mf_ultralight_3des_key_valid(instance->data)) {
instance->state = MfUltralightPollerStateCheckMfulCAuthStatus; instance->state = MfUltralightPollerStateDictAttack;
} else { } else {
FURI_LOG_D(TAG, "Read page %d failed", instance->pages_read); FURI_LOG_D(TAG, "Read page %d failed", instance->pages_read);
if(instance->pages_read) { if(instance->pages_read) {
@@ -730,6 +734,63 @@ static NfcCommand mf_ultralight_poller_handler_write_success(MfUltralightPoller*
return command; return command;
} }
static NfcCommand mf_ultralight_poller_handler_dict_attack(MfUltralightPoller* instance) {
NfcCommand command = NfcCommandContinue;
const MfUltralightData* tag_data = instance->data;
uint32_t features = mf_ultralight_get_feature_support_set(tag_data->type);
FURI_LOG_D(TAG, "Dict Attack");
do {
if(!mf_ultralight_support_feature(features, MfUltralightFeatureSupportAuthenticate)) {
instance->error = MfUltralightErrorProtocol;
instance->state = MfUltralightPollerStateReadFailed;
break;
}
instance->dict_attack_ctx.is_card_present = true;
instance->mfu_event.type = MfUltralightPollerEventTypeRequestKey;
command = instance->callback(instance->general_event, instance->context);
if(!instance->mfu_event.data->key_request_data.key_provided) {
instance->state = MfUltralightPollerStateReadSuccess;
break;
}
FURI_LOG_D(TAG, "Trying next 3DES key");
instance->error = MfUltralightErrorNone;
instance->auth_context.auth_success = false;
instance->auth_context.tdes_key = instance->mfu_event.data->key_request_data.key;
do {
uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE];
uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
furi_hal_random_fill_buf(RndA, sizeof(RndA));
instance->error = mf_ultralight_poller_authenticate_start(instance, RndA, output);
if(instance->error != MfUltralightErrorNone) break;
uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
instance->error = mf_ultralight_poller_authenticate_end(
instance, RndB, output, decoded_shifted_RndA);
if(instance->error != MfUltralightErrorNone) break;
mf_ultralight_3des_shift_data(RndA);
instance->auth_context.auth_success =
(memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0);
if(instance->auth_context.auth_success) {
FURI_LOG_D(TAG, "Dict attack success");
instance->state = MfUltralightPollerStateReadPages;
instance->dict_attack_ctx.auth_success = true;
break;
}
} while(false);
if(!instance->auth_context.auth_success) {
FURI_LOG_D(TAG, "Dict attack auth failed");
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
}
} while(false);
return command;
}
static const MfUltralightPollerReadHandler static const MfUltralightPollerReadHandler
mf_ultralight_poller_read_handler[MfUltralightPollerStateNum] = { mf_ultralight_poller_read_handler[MfUltralightPollerStateNum] = {
[MfUltralightPollerStateIdle] = mf_ultralight_poller_handler_idle, [MfUltralightPollerStateIdle] = mf_ultralight_poller_handler_idle,
@@ -755,6 +816,7 @@ static const MfUltralightPollerReadHandler
[MfUltralightPollerStateWritePages] = mf_ultralight_poller_handler_write_pages, [MfUltralightPollerStateWritePages] = mf_ultralight_poller_handler_write_pages,
[MfUltralightPollerStateWriteFail] = mf_ultralight_poller_handler_write_fail, [MfUltralightPollerStateWriteFail] = mf_ultralight_poller_handler_write_fail,
[MfUltralightPollerStateWriteSuccess] = mf_ultralight_poller_handler_write_success, [MfUltralightPollerStateWriteSuccess] = mf_ultralight_poller_handler_write_success,
[MfUltralightPollerStateDictAttack] = mf_ultralight_poller_handler_dict_attack,
}; };

View File

@@ -27,6 +27,7 @@ typedef enum {
MfUltralightPollerEventTypeCardLocked, /**< Presented card is locked by password, AUTH0 or lock bytes. */ MfUltralightPollerEventTypeCardLocked, /**< Presented card is locked by password, AUTH0 or lock bytes. */
MfUltralightPollerEventTypeWriteSuccess, /**< Poller wrote card successfully. */ MfUltralightPollerEventTypeWriteSuccess, /**< Poller wrote card successfully. */
MfUltralightPollerEventTypeWriteFail, /**< Poller failed to write card. */ MfUltralightPollerEventTypeWriteFail, /**< Poller failed to write card. */
MfUltralightPollerEventTypeRequestKey, /**< Poller requests key for dict attack. */
} MfUltralightPollerEventType; } MfUltralightPollerEventType;
/** /**
@@ -35,6 +36,7 @@ typedef enum {
typedef enum { typedef enum {
MfUltralightPollerModeRead, /**< Poller will only read card. It's a default mode. */ MfUltralightPollerModeRead, /**< Poller will only read card. It's a default mode. */
MfUltralightPollerModeWrite, /**< Poller will write already saved card to another presented card. */ MfUltralightPollerModeWrite, /**< Poller will write already saved card to another presented card. */
MfUltralightPollerModeDictAttack, /**< Poller will perform dictionary attack against card. */
} MfUltralightPollerMode; } MfUltralightPollerMode;
/** /**
@@ -42,20 +44,29 @@ typedef enum {
*/ */
typedef struct { typedef struct {
MfUltralightAuthPassword password; /**< Password to be used for authentication. */ MfUltralightAuthPassword password; /**< Password to be used for authentication. */
MfUltralightC3DesAuthKey tdes_key; MfUltralightC3DesAuthKey tdes_key; /**< 3DES key to be used for authentication. */
MfUltralightAuthPack pack; /**< Pack received on successfull authentication. */ MfUltralightAuthPack pack; /**< Pack received on successful authentication. */
bool auth_success; /**< Set to true if authentication succeeded, false otherwise. */ bool auth_success; /**< Set to true if authentication succeeded, false otherwise. */
bool skip_auth; /**< Set to true if authentication should be skipped, false otherwise. */ bool skip_auth; /**< Set to true if authentication should be skipped, false otherwise. */
} MfUltralightPollerAuthContext; } MfUltralightPollerAuthContext;
/**
* @brief MfUltralight poller key request data.
*/
typedef struct {
MfUltralightC3DesAuthKey key; /**< Key to try. */
bool key_provided; /**< Set to true if key was provided, false to stop attack. */
} MfUltralightPollerKeyRequestData;
/** /**
* @brief MfUltralight poller event data. * @brief MfUltralight poller event data.
*/ */
typedef union { typedef union {
MfUltralightPollerAuthContext auth_context; /**< Authentication context. */ MfUltralightPollerAuthContext auth_context; /**< Authentication context. */
MfUltralightError error; /**< Error code indicating reading fail reason. */ MfUltralightError error; /**< Error code indicating reading fail reason. */
const MfUltralightData* write_data; const MfUltralightData* write_data; /**< Data to be written to card. */
MfUltralightPollerMode poller_mode; MfUltralightPollerMode poller_mode; /**< Mode to operate in. */
MfUltralightPollerKeyRequestData key_request_data; /**< Key request data. */
} MfUltralightPollerEventData; } MfUltralightPollerEventData;
/** /**
@@ -64,7 +75,7 @@ typedef union {
* Upon emission of an event, an instance of this struct will be passed to the callback. * Upon emission of an event, an instance of this struct will be passed to the callback.
*/ */
typedef struct { typedef struct {
MfUltralightPollerEventType type; /**< Type of emmitted event. */ MfUltralightPollerEventType type; /**< Type of emitted event. */
MfUltralightPollerEventData* data; /**< Pointer to event specific data. */ MfUltralightPollerEventData* data; /**< Pointer to event specific data. */
} MfUltralightPollerEvent; } MfUltralightPollerEvent;

View File

@@ -68,10 +68,17 @@ typedef enum {
MfUltralightPollerStateWritePages, MfUltralightPollerStateWritePages,
MfUltralightPollerStateWriteFail, MfUltralightPollerStateWriteFail,
MfUltralightPollerStateWriteSuccess, MfUltralightPollerStateWriteSuccess,
MfUltralightPollerStateDictAttack,
MfUltralightPollerStateNum, MfUltralightPollerStateNum,
} MfUltralightPollerState; } MfUltralightPollerState;
typedef struct {
uint8_t sectors_total;
bool auth_success;
bool is_card_present;
} MfUltralightPollerDictAttackContext;
struct MfUltralightPoller { struct MfUltralightPoller {
Iso14443_3aPoller* iso14443_3a_poller; Iso14443_3aPoller* iso14443_3a_poller;
MfUltralightPollerState state; MfUltralightPollerState state;
@@ -89,6 +96,7 @@ struct MfUltralightPoller {
uint8_t tearing_flag_total; uint8_t tearing_flag_total;
uint16_t current_page; uint16_t current_page;
MfUltralightError error; MfUltralightError error;
MfUltralightPollerDictAttackContext dict_attack_ctx;
mbedtls_des3_context des_context; mbedtls_des3_context des_context;
NfcGenericEvent general_event; NfcGenericEvent general_event;