diff --git a/lib/nfc/protocols/mf_plus/mf_plus_poller.c b/lib/nfc/protocols/mf_plus/mf_plus_poller.c index a2deeb1a2..fb1e8db39 100644 --- a/lib/nfc/protocols/mf_plus/mf_plus_poller.c +++ b/lib/nfc/protocols/mf_plus/mf_plus_poller.c @@ -17,6 +17,88 @@ const MfPlusData* mf_plus_poller_get_data(MfPlusPoller* instance) { return instance->data; } +bool mf_plus_poller_get_type_from_iso4(const Iso14443_4aData* iso4_data, MfPlusData* mf_plus_data) { + furi_assert(iso4_data); + furi_assert(mf_plus_data); + + switch(iso4_data->iso14443_3a_data->sak) { + case 0x08: + if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + // Mifare Plus S 2K SL1 + mf_plus_data->type = MfPlusTypeS; + mf_plus_data->size = MfPlusSize2K; + mf_plus_data->security_level = MfPlusSecurityLevel1; + return true; + } else if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + // Mifare Plus X 2K SL1 + mf_plus_data->type = MfPlusTypeX; + mf_plus_data->size = MfPlusSize2K; + mf_plus_data->security_level = MfPlusSecurityLevel1; + return true; + } else if( + memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x00\xF6\xD1", 7) == 0 || + memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x01\xF6\xD1", 7) == 0) { + // Mifare Plus SE 1K SL1 + mf_plus_data->type = MfPlusTypeSE; + mf_plus_data->size = MfPlusSize1K; + mf_plus_data->security_level = MfPlusSecurityLevel1; + return true; + } else { + return false; + } + case 0x18: + if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + // Mifare Plus S 4K SL1 + mf_plus_data->type = MfPlusTypeS; + mf_plus_data->size = MfPlusSize4K; + mf_plus_data->security_level = MfPlusSecurityLevel1; + return true; + } else if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + // Mifare Plus X 4K SL1 + mf_plus_data->type = MfPlusTypeX; + mf_plus_data->size = MfPlusSize4K; + mf_plus_data->security_level = MfPlusSecurityLevel1; + return true; + } else { + return false; + } + case 0x20: + if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + // Mifare Plus S 2/4K SL3 + mf_plus_data->type = MfPlusTypeS; + mf_plus_data->security_level = MfPlusSecurityLevel3; + + if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) { + // + mf_plus_data->size = MfPlusSize2K; + } else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) { + mf_plus_data->size = MfPlusSize4K; + } else { + return false; + } + return true; + + } else if(memcmp(iso4_data->ats_data.t1_tk, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + mf_plus_data->type = MfPlusTypeX; + mf_plus_data->security_level = MfPlusSecurityLevel3; + + if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) { + mf_plus_data->size = MfPlusSize2K; + } else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) { + mf_plus_data->size = MfPlusSize4K; + } else { + return false; + } + + return true; + } else { + return false; + } + } + + return false; +} + MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) { furi_assert(iso14443_4a_poller); @@ -27,6 +109,11 @@ MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) { instance->data = mf_plus_alloc(); + instance->tx_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE); + instance->rx_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE); + instance->input_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE); + instance->result_buffer = bit_buffer_alloc(MF_PLUS_RESULT_BUF_SIZE); + instance->general_event.protocol = NfcProtocolMfPlus; instance->general_event.event_data = &instance->mfp_event; instance->general_event.instance = instance; @@ -126,25 +213,36 @@ void mf_plus_poller_free(MfPlusPoller* instance) { furi_assert(instance); furi_assert(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); mf_plus_free(instance->data); free(instance); } -bool mf_plus_poller_detect(NfcGenericEvent event, void* context) { - furi_assert(event.event_data); +static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) { furi_assert(event.protocol = NfcProtocolIso14443_4a); - furi_assert(context); MfPlusPoller* instance = context; furi_assert(instance); Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data; + furi_assert(iso14443_4a_event); + bool detected = false; if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { MfPlusVersion version = {}; const MfPlusError error = mf_plus_poller_read_version(instance, &version); - detected = (error == MfPlusErrorNone); + if(error == MfPlusErrorNone) { + if(version.hw_major == 0x02 || version.hw_major == 0x82) { + detected = true; + } + } else { + detected = mf_plus_poller_get_type_from_iso4( + iso14443_4a_poller_get_data(instance->iso14443_4a_poller), instance->data); + } } return detected; diff --git a/lib/nfc/protocols/mf_plus/mf_plus_poller_defs.h b/lib/nfc/protocols/mf_plus/mf_plus_poller_defs.h new file mode 100644 index 000000000..366eb5116 --- /dev/null +++ b/lib/nfc/protocols/mf_plus/mf_plus_poller_defs.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern const NfcPollerBase mf_plus_poller; diff --git a/lib/nfc/protocols/nfc_poller_defs.c b/lib/nfc/protocols/nfc_poller_defs.c index 7553c74de..c007740b7 100644 --- a/lib/nfc/protocols/nfc_poller_defs.c +++ b/lib/nfc/protocols/nfc_poller_defs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ const NfcPollerBase* nfc_pollers_api[NfcProtocolNum] = { [NfcProtocolFelica] = &nfc_poller_felica, [NfcProtocolMfUltralight] = &mf_ultralight_poller, [NfcProtocolMfClassic] = &mf_classic_poller, + [NfcProtocolMfPlus] = &mf_plus_poller, [NfcProtocolMfDesfire] = &mf_desfire_poller, [NfcProtocolSlix] = &nfc_poller_slix, /* Add new pollers here */ diff --git a/lib/nfc/protocols/nfc_protocol.c b/lib/nfc/protocols/nfc_protocol.c index 2ea9b3982..970264464 100644 --- a/lib/nfc/protocols/nfc_protocol.c +++ b/lib/nfc/protocols/nfc_protocol.c @@ -61,6 +61,7 @@ static const NfcProtocol nfc_protocol_iso14443_3b_children_protocol[] = { /** List of ISO14443-4A child protocols. */ static const NfcProtocol nfc_protocol_iso14443_4a_children_protocol[] = { NfcProtocolMfDesfire, + NfcProtocolMfPlus, }; /** List of ISO115693-3 child protocols. */ @@ -128,6 +129,12 @@ static const NfcProtocolTreeNode nfc_protocol_nodes[NfcProtocolNum] = { .children_num = 0, .children_protocol = NULL, }, + [NfcProtocolMfPlus] = + { + .parent_protocol = NfcProtocolIso14443_4a, + .children_num = 0, + .children_protocol = NULL, + }, [NfcProtocolMfDesfire] = { .parent_protocol = NfcProtocolIso14443_4a,