mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-12 23:48:10 -07:00
Merge remote-tracking branch 'OFW/dev' into dev
This commit is contained in:
@@ -4,6 +4,46 @@
|
||||
|
||||
#define MF_DESFIRE_PROTOCOL_NAME "Mifare DESFire"
|
||||
|
||||
#define MF_DESFIRE_HW_MINOR_TYPE (0x00)
|
||||
#define MF_DESFIRE_HW_MINOR_TYPE_MF3ICD40 (0x02)
|
||||
|
||||
#define MF_DESFIRE_HW_MAJOR_TYPE_EV1 (0x01)
|
||||
#define MF_DESFIRE_HW_MAJOR_TYPE_EV2 (0x12)
|
||||
#define MF_DESFIRE_HW_MAJOR_TYPE_EV2_XL (0x22)
|
||||
#define MF_DESFIRE_HW_MAJOR_TYPE_EV3 (0x33)
|
||||
#define MF_DESFIRE_HW_MAJOR_TYPE_MF3ICD40 (0x00)
|
||||
|
||||
#define MF_DESFIRE_STORAGE_SIZE_2K (0x16)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_4K (0x18)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_8K (0x1A)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_16K (0x1C)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_32K (0x1E)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_MF3ICD40 (0xFF)
|
||||
#define MF_DESFIRE_STORAGE_SIZE_UNKNOWN (0xFF)
|
||||
|
||||
#define MF_DESFIRE_TEST_TYPE_MF3ICD40(major, minor, storage) \
|
||||
(((major) == MF_DESFIRE_HW_MAJOR_TYPE_MF3ICD40) && \
|
||||
((minor) == MF_DESFIRE_HW_MINOR_TYPE_MF3ICD40) && \
|
||||
((storage) == MF_DESFIRE_STORAGE_SIZE_MF3ICD40))
|
||||
|
||||
static const char* mf_desfire_type_strings[] = {
|
||||
[MfDesfireTypeMF3ICD40] = "(MF3ICD40)",
|
||||
[MfDesfireTypeEV1] = "EV1",
|
||||
[MfDesfireTypeEV2] = "EV2",
|
||||
[MfDesfireTypeEV2XL] = "EV2 XL",
|
||||
[MfDesfireTypeEV3] = "EV3",
|
||||
[MfDesfireTypeUnknown] = "UNK",
|
||||
};
|
||||
|
||||
static const char* mf_desfire_size_strings[] = {
|
||||
[MfDesfireSize2k] = "2K",
|
||||
[MfDesfireSize4k] = "4K",
|
||||
[MfDesfireSize8k] = "8K",
|
||||
[MfDesfireSize16k] = "16K",
|
||||
[MfDesfireSize32k] = "32K",
|
||||
[MfDesfireSizeUnknown] = "",
|
||||
};
|
||||
|
||||
const NfcDeviceBase nfc_device_mf_desfire = {
|
||||
.protocol_name = MF_DESFIRE_PROTOCOL_NAME,
|
||||
.alloc = (NfcDeviceAlloc)mf_desfire_alloc,
|
||||
@@ -26,7 +66,7 @@ MfDesfireData* mf_desfire_alloc(void) {
|
||||
data->master_key_versions = simple_array_alloc(&mf_desfire_key_version_array_config);
|
||||
data->application_ids = simple_array_alloc(&mf_desfire_app_id_array_config);
|
||||
data->applications = simple_array_alloc(&mf_desfire_application_array_config);
|
||||
|
||||
data->device_name = furi_string_alloc();
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -38,6 +78,7 @@ void mf_desfire_free(MfDesfireData* data) {
|
||||
simple_array_free(data->application_ids);
|
||||
simple_array_free(data->master_key_versions);
|
||||
iso14443_4a_free(data->iso14443_4a_data);
|
||||
furi_string_free(data->device_name);
|
||||
free(data);
|
||||
}
|
||||
|
||||
@@ -228,10 +269,83 @@ bool mf_desfire_is_equal(const MfDesfireData* data, const MfDesfireData* other)
|
||||
simple_array_is_equal(data->applications, other->applications);
|
||||
}
|
||||
|
||||
static MfDesfireType mf_desfire_get_type_from_version(const MfDesfireVersion* const version) {
|
||||
MfDesfireType type = MfDesfireTypeUnknown;
|
||||
|
||||
switch(version->hw_major) {
|
||||
case MF_DESFIRE_HW_MAJOR_TYPE_EV1:
|
||||
type = MfDesfireTypeEV1;
|
||||
break;
|
||||
case MF_DESFIRE_HW_MAJOR_TYPE_EV2:
|
||||
type = MfDesfireTypeEV2;
|
||||
break;
|
||||
case MF_DESFIRE_HW_MAJOR_TYPE_EV2_XL:
|
||||
type = MfDesfireTypeEV2XL;
|
||||
break;
|
||||
case MF_DESFIRE_HW_MAJOR_TYPE_EV3:
|
||||
type = MfDesfireTypeEV3;
|
||||
break;
|
||||
default:
|
||||
if(MF_DESFIRE_TEST_TYPE_MF3ICD40(version->hw_major, version->hw_minor, version->hw_storage))
|
||||
type = MfDesfireTypeMF3ICD40;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static MfDesfireSize mf_desfire_get_size_from_version(const MfDesfireVersion* const version) {
|
||||
MfDesfireSize size = MfDesfireSizeUnknown;
|
||||
|
||||
switch(version->hw_storage) {
|
||||
case MF_DESFIRE_STORAGE_SIZE_2K:
|
||||
size = MfDesfireSize2k;
|
||||
break;
|
||||
case MF_DESFIRE_STORAGE_SIZE_4K:
|
||||
size = MfDesfireSize4k;
|
||||
break;
|
||||
case MF_DESFIRE_STORAGE_SIZE_8K:
|
||||
size = MfDesfireSize8k;
|
||||
break;
|
||||
case MF_DESFIRE_STORAGE_SIZE_16K:
|
||||
size = MfDesfireSize16k;
|
||||
break;
|
||||
case MF_DESFIRE_STORAGE_SIZE_32K:
|
||||
size = MfDesfireSize32k;
|
||||
break;
|
||||
default:
|
||||
if(MF_DESFIRE_TEST_TYPE_MF3ICD40(version->hw_major, version->hw_minor, version->hw_storage))
|
||||
size = MfDesfireSize4k;
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
const char* mf_desfire_get_device_name(const MfDesfireData* data, NfcDeviceNameType name_type) {
|
||||
UNUSED(data);
|
||||
UNUSED(name_type);
|
||||
return MF_DESFIRE_PROTOCOL_NAME;
|
||||
furi_check(data);
|
||||
|
||||
const MfDesfireType type = mf_desfire_get_type_from_version(&data->version);
|
||||
const MfDesfireSize size = mf_desfire_get_size_from_version(&data->version);
|
||||
|
||||
if(type == MfDesfireTypeUnknown) {
|
||||
furi_string_printf(data->device_name, "Unknown %s", MF_DESFIRE_PROTOCOL_NAME);
|
||||
} else if(name_type == NfcDeviceNameTypeFull) {
|
||||
furi_string_printf(
|
||||
data->device_name,
|
||||
"%s %s %s",
|
||||
MF_DESFIRE_PROTOCOL_NAME,
|
||||
mf_desfire_type_strings[type],
|
||||
mf_desfire_size_strings[size]);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
data->device_name,
|
||||
"%s %s",
|
||||
mf_desfire_type_strings[type],
|
||||
mf_desfire_size_strings[size]);
|
||||
}
|
||||
|
||||
return furi_string_get_cstr(data->device_name);
|
||||
}
|
||||
|
||||
const uint8_t* mf_desfire_get_uid(const MfDesfireData* data, size_t* uid_len) {
|
||||
|
||||
@@ -29,6 +29,28 @@ extern "C" {
|
||||
#define MF_DESFIRE_APP_ID_SIZE (3)
|
||||
#define MF_DESFIRE_VALUE_SIZE (4)
|
||||
|
||||
typedef enum {
|
||||
MfDesfireTypeMF3ICD40,
|
||||
MfDesfireTypeEV1,
|
||||
MfDesfireTypeEV2,
|
||||
MfDesfireTypeEV2XL,
|
||||
MfDesfireTypeEV3,
|
||||
|
||||
MfDesfireTypeUnknown,
|
||||
MfDesfireTypeNum,
|
||||
} MfDesfireType;
|
||||
|
||||
typedef enum {
|
||||
MfDesfireSize2k,
|
||||
MfDesfireSize4k,
|
||||
MfDesfireSize8k,
|
||||
MfDesfireSize16k,
|
||||
MfDesfireSize32k,
|
||||
|
||||
MfDesfireSizeUnknown,
|
||||
MfDesfireSizeNum,
|
||||
} MfDesfireSize;
|
||||
|
||||
typedef struct {
|
||||
uint8_t hw_vendor;
|
||||
uint8_t hw_type;
|
||||
@@ -131,6 +153,7 @@ typedef enum {
|
||||
MfDesfireErrorProtocol,
|
||||
MfDesfireErrorTimeout,
|
||||
MfDesfireErrorAuthentication,
|
||||
MfDesfireErrorCommandNotSupported,
|
||||
} MfDesfireError;
|
||||
|
||||
typedef struct {
|
||||
@@ -141,6 +164,7 @@ typedef struct {
|
||||
SimpleArray* master_key_versions;
|
||||
SimpleArray* application_ids;
|
||||
SimpleArray* applications;
|
||||
FuriString* device_name;
|
||||
} MfDesfireData;
|
||||
|
||||
extern const NfcDeviceBase nfc_device_mf_desfire;
|
||||
|
||||
@@ -82,9 +82,12 @@ static NfcCommand mf_desfire_poller_handler_read_free_memory(MfDesfirePoller* in
|
||||
FURI_LOG_D(TAG, "Read free memory success");
|
||||
instance->state = MfDesfirePollerStateReadMasterKeySettings;
|
||||
} else if(instance->error == MfDesfireErrorNotPresent) {
|
||||
FURI_LOG_D(TAG, "Read free memoty is unsupported");
|
||||
FURI_LOG_D(TAG, "Read free memory is not present");
|
||||
instance->state = MfDesfirePollerStateReadMasterKeySettings;
|
||||
command = NfcCommandReset;
|
||||
} else if(instance->error == MfDesfireErrorCommandNotSupported) {
|
||||
FURI_LOG_D(TAG, "Read free memory is unsupported");
|
||||
instance->state = MfDesfirePollerStateReadMasterKeySettings;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to read free memory");
|
||||
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
|
||||
|
||||
@@ -25,6 +25,8 @@ MfDesfireError mf_desfire_process_status_code(uint8_t status_code) {
|
||||
return MfDesfireErrorNone;
|
||||
case MF_DESFIRE_STATUS_AUTHENTICATION_ERROR:
|
||||
return MfDesfireErrorAuthentication;
|
||||
case MF_DESFIRE_STATUS_ILLEGAL_COMMAND_CODE:
|
||||
return MfDesfireErrorCommandNotSupported;
|
||||
default:
|
||||
return MfDesfireErrorProtocol;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef struct {
|
||||
FuriThreadId thread_id;
|
||||
MfUltralightError error;
|
||||
MfUltralightPollerContextData data;
|
||||
const MfUltralightPollerAuthContext* auth_context;
|
||||
} MfUltralightPollerContext;
|
||||
|
||||
typedef MfUltralightError (*MfUltralightPollerCmdHandler)(
|
||||
@@ -250,12 +251,17 @@ static NfcCommand mf_ultralight_poller_read_callback(NfcGenericEvent event, void
|
||||
poller_context->error = mfu_event->data->error;
|
||||
command = NfcCommandStop;
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
mfu_event->data->auth_context.skip_auth = true;
|
||||
if(mf_ultralight_support_feature(
|
||||
mfu_poller->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
mfu_event->data->auth_context.skip_auth = false;
|
||||
memset(
|
||||
mfu_poller->auth_context.tdes_key.data, 0x00, MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE);
|
||||
if(poller_context->auth_context != NULL) {
|
||||
mfu_event->data->auth_context = *poller_context->auth_context;
|
||||
} else {
|
||||
mfu_event->data->auth_context.skip_auth = true;
|
||||
if(mfu_poller->data->type == MfUltralightTypeMfulC) {
|
||||
mfu_event->data->auth_context.skip_auth = false;
|
||||
memset(
|
||||
mfu_poller->auth_context.tdes_key.data,
|
||||
0x00,
|
||||
MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,13 +272,17 @@ static NfcCommand mf_ultralight_poller_read_callback(NfcGenericEvent event, void
|
||||
return command;
|
||||
}
|
||||
|
||||
MfUltralightError mf_ultralight_poller_sync_read_card(Nfc* nfc, MfUltralightData* data) {
|
||||
MfUltralightError mf_ultralight_poller_sync_read_card(
|
||||
Nfc* nfc,
|
||||
MfUltralightData* data,
|
||||
const MfUltralightPollerAuthContext* auth_context) {
|
||||
furi_check(nfc);
|
||||
furi_check(data);
|
||||
|
||||
MfUltralightPollerContext poller_context = {};
|
||||
poller_context.thread_id = furi_thread_get_current_id();
|
||||
poller_context.data.data = mf_ultralight_alloc();
|
||||
poller_context.auth_context = auth_context;
|
||||
|
||||
NfcPoller* poller = nfc_poller_alloc(nfc, NfcProtocolMfUltralight);
|
||||
nfc_poller_start(poller, mf_ultralight_poller_read_callback, &poller_context);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "mf_ultralight.h"
|
||||
#include "mf_ultralight_poller.h"
|
||||
#include <nfc/nfc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -27,7 +28,10 @@ MfUltralightError mf_ultralight_poller_sync_read_tearing_flag(
|
||||
uint8_t flag_num,
|
||||
MfUltralightTearingFlag* data);
|
||||
|
||||
MfUltralightError mf_ultralight_poller_sync_read_card(Nfc* nfc, MfUltralightData* data);
|
||||
MfUltralightError mf_ultralight_poller_sync_read_card(
|
||||
Nfc* nfc,
|
||||
MfUltralightData* data,
|
||||
const MfUltralightPollerAuthContext* auth_context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ static NfcCommand st25tb_poller_request_mode_handler(St25tbPoller* instance) {
|
||||
St25tbPollerEventDataModeRequest* mode_request_data =
|
||||
&instance->st25tb_event_data.mode_request;
|
||||
|
||||
furi_assert(mode_request_data->mode < St25tbPollerModeNum);
|
||||
furi_check(mode_request_data->mode < St25tbPollerModeNum);
|
||||
|
||||
if(mode_request_data->mode == St25tbPollerModeRead) {
|
||||
instance->state = St25tbPollerStateRead;
|
||||
|
||||
Reference in New Issue
Block a user