#include "mf_desfire_poller_i.h" #include #include #define TAG "MfDesfirePoller" #define MF_DESFIRE_BUF_SIZE (64U) #define MF_DESFIRE_RESULT_BUF_SIZE (512U) typedef NfcCommand (*MfDesfirePollerReadHandler)(MfDesfirePoller* instance); const MfDesfireData* mf_desfire_poller_get_data(MfDesfirePoller* instance) { furi_assert(instance); return instance->data; } static MfDesfirePoller* mf_desfire_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) { MfDesfirePoller* instance = malloc(sizeof(MfDesfirePoller)); instance->iso14443_4a_poller = iso14443_4a_poller; instance->data = mf_desfire_alloc(); instance->tx_buffer = bit_buffer_alloc(MF_DESFIRE_BUF_SIZE); instance->rx_buffer = bit_buffer_alloc(MF_DESFIRE_BUF_SIZE); instance->input_buffer = bit_buffer_alloc(MF_DESFIRE_BUF_SIZE); instance->result_buffer = bit_buffer_alloc(MF_DESFIRE_RESULT_BUF_SIZE); instance->mf_desfire_event.data = &instance->mf_desfire_event_data; instance->general_event.protocol = NfcProtocolMfDesfire; instance->general_event.event_data = &instance->mf_desfire_event; instance->general_event.instance = instance; return instance; } static void mf_desfire_poller_free(MfDesfirePoller* instance) { furi_assert(instance); mf_desfire_free(instance->data); bit_buffer_free(instance->tx_buffer); bit_buffer_free(instance->rx_buffer); bit_buffer_free(instance->input_buffer); bit_buffer_free(instance->result_buffer); free(instance); } static NfcCommand mf_desfire_poller_handler_idle(MfDesfirePoller* instance) { bit_buffer_reset(instance->input_buffer); bit_buffer_reset(instance->result_buffer); bit_buffer_reset(instance->tx_buffer); bit_buffer_reset(instance->rx_buffer); iso14443_4a_copy( instance->data->iso14443_4a_data, iso14443_4a_poller_get_data(instance->iso14443_4a_poller)); instance->state = MfDesfirePollerStateReadVersion; return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_version(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_version(instance, &instance->data->version); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read version success"); instance->state = MfDesfirePollerStateReadFreeMemory; } else { FURI_LOG_E(TAG, "Failed to read version"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_free_memory(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_free_memory(instance, &instance->data->free_memory); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read free memory success"); instance->state = MfDesfirePollerStateReadMasterKeySettings; } else { FURI_LOG_E(TAG, "Failed to read free memory"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_master_key_settings(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_key_settings(instance, &instance->data->master_key_settings); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read master key settings success"); instance->state = MfDesfirePollerStateReadMasterKeyVersion; } else { FURI_LOG_E(TAG, "Failed to read master key settings"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_master_key_version(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_key_versions( instance, instance->data->master_key_versions, instance->data->master_key_settings.max_keys); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read master key version success"); instance->state = MfDesfirePollerStateReadApplicationIds; } else { FURI_LOG_E(TAG, "Failed to read master key version"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_application_ids(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_application_ids(instance, instance->data->application_ids); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read application ids success"); instance->state = MfDesfirePollerStateReadApplications; } else { FURI_LOG_E(TAG, "Failed to read application ids"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_applications(MfDesfirePoller* instance) { instance->error = mf_desfire_poller_read_applications( instance, instance->data->application_ids, instance->data->applications); if(instance->error == MfDesfireErrorNone) { FURI_LOG_D(TAG, "Read applications success"); instance->state = MfDesfirePollerStateReadSuccess; } else { FURI_LOG_E(TAG, "Failed to read applications"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->state = MfDesfirePollerStateReadFailed; } return NfcCommandContinue; } static NfcCommand mf_desfire_poller_handler_read_fail(MfDesfirePoller* instance) { FURI_LOG_D(TAG, "Read Failed"); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->mf_desfire_event.data->error = instance->error; NfcCommand command = instance->callback(instance->general_event, instance->context); instance->state = MfDesfirePollerStateIdle; return command; } static NfcCommand mf_desfire_poller_handler_read_success(MfDesfirePoller* instance) { FURI_LOG_D(TAG, "Read success."); iso14443_4a_poller_halt(instance->iso14443_4a_poller); instance->mf_desfire_event.type = MfDesfirePollerEventTypeReadSuccess; NfcCommand command = instance->callback(instance->general_event, instance->context); return command; } static const MfDesfirePollerReadHandler mf_desfire_poller_read_handler[MfDesfirePollerStateNum] = { [MfDesfirePollerStateIdle] = mf_desfire_poller_handler_idle, [MfDesfirePollerStateReadVersion] = mf_desfire_poller_handler_read_version, [MfDesfirePollerStateReadFreeMemory] = mf_desfire_poller_handler_read_free_memory, [MfDesfirePollerStateReadMasterKeySettings] = mf_desfire_poller_handler_read_master_key_settings, [MfDesfirePollerStateReadMasterKeyVersion] = mf_desfire_poller_handler_read_master_key_version, [MfDesfirePollerStateReadApplicationIds] = mf_desfire_poller_handler_read_application_ids, [MfDesfirePollerStateReadApplications] = mf_desfire_poller_handler_read_applications, [MfDesfirePollerStateReadFailed] = mf_desfire_poller_handler_read_fail, [MfDesfirePollerStateReadSuccess] = mf_desfire_poller_handler_read_success, }; static void mf_desfire_poller_set_callback( MfDesfirePoller* instance, NfcGenericCallback callback, void* context) { furi_assert(instance); furi_assert(callback); instance->callback = callback; instance->context = context; } static NfcCommand mf_desfire_poller_run(NfcGenericEvent event, void* context) { furi_assert(event.protocol == NfcProtocolIso14443_4a); MfDesfirePoller* instance = context; furi_assert(instance); furi_assert(instance->callback); const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data; furi_assert(iso14443_4a_event); NfcCommand command = NfcCommandContinue; if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { command = mf_desfire_poller_read_handler[instance->state](instance); } else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) { instance->mf_desfire_event.type = MfDesfirePollerEventTypeReadFailed; command = instance->callback(instance->general_event, instance->context); } return command; } static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) { furi_assert(event.protocol == NfcProtocolIso14443_4a); MfDesfirePoller* instance = context; furi_assert(instance); const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data; furi_assert(iso14443_4a_event); bool protocol_detected = false; if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { MfDesfireVersion version = {}; const MfDesfireError error = mf_desfire_poller_read_version(instance, &version); protocol_detected = (error == MfDesfireErrorNone); } return protocol_detected; } const NfcPollerBase mf_desfire_poller = { .alloc = (NfcPollerAlloc)mf_desfire_poller_alloc, .free = (NfcPollerFree)mf_desfire_poller_free, .set_callback = (NfcPollerSetCallback)mf_desfire_poller_set_callback, .run = (NfcPollerRun)mf_desfire_poller_run, .detect = (NfcPollerDetect)mf_desfire_poller_detect, .get_data = (NfcPollerGetData)mf_desfire_poller_get_data, };