mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-28 01:58:11 -07:00
Merge remote-tracking branch 'ofw/dev' into feat/nfc-type-4
This commit is contained in:
@@ -173,33 +173,35 @@ bool iso15693_3_load(Iso15693_3Data* data, FlipperFormat* ff, uint32_t version)
|
||||
|
||||
if(flipper_format_key_exist(ff, ISO15693_3_BLOCK_COUNT_KEY) &&
|
||||
flipper_format_key_exist(ff, ISO15693_3_BLOCK_SIZE_KEY)) {
|
||||
data->system_info.flags |= ISO15693_3_SYSINFO_FLAG_MEMORY;
|
||||
|
||||
uint32_t block_count;
|
||||
if(!flipper_format_read_uint32(ff, ISO15693_3_BLOCK_COUNT_KEY, &block_count, 1)) break;
|
||||
|
||||
data->system_info.block_count = block_count;
|
||||
data->system_info.flags |= ISO15693_3_SYSINFO_FLAG_MEMORY;
|
||||
|
||||
if(!flipper_format_read_hex(
|
||||
ff, ISO15693_3_BLOCK_SIZE_KEY, &(data->system_info.block_size), 1))
|
||||
break;
|
||||
|
||||
simple_array_init(
|
||||
data->block_data, data->system_info.block_size * data->system_info.block_count);
|
||||
|
||||
if(!flipper_format_read_hex(
|
||||
ff,
|
||||
ISO15693_3_DATA_CONTENT_KEY,
|
||||
simple_array_get_data(data->block_data),
|
||||
simple_array_get_count(data->block_data)))
|
||||
break;
|
||||
|
||||
if(flipper_format_key_exist(ff, ISO15693_3_SECURITY_STATUS_KEY)) {
|
||||
if(data->system_info.block_count > 0 && data->system_info.block_size > 0) {
|
||||
simple_array_init(
|
||||
data->block_data,
|
||||
data->system_info.block_size * data->system_info.block_count);
|
||||
simple_array_init(data->block_security, data->system_info.block_count);
|
||||
|
||||
const bool security_loaded = has_lock_bits ?
|
||||
iso15693_3_load_security(data, ff) :
|
||||
iso15693_3_load_security_legacy(data, ff);
|
||||
if(!security_loaded) break;
|
||||
if(!flipper_format_read_hex(
|
||||
ff,
|
||||
ISO15693_3_DATA_CONTENT_KEY,
|
||||
simple_array_get_data(data->block_data),
|
||||
simple_array_get_count(data->block_data)))
|
||||
break;
|
||||
|
||||
if(flipper_format_key_exist(ff, ISO15693_3_SECURITY_STATUS_KEY)) {
|
||||
const bool security_loaded = has_lock_bits ?
|
||||
iso15693_3_load_security(data, ff) :
|
||||
iso15693_3_load_security_legacy(data, ff);
|
||||
if(!security_loaded) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,22 +262,24 @@ bool iso15693_3_save(const Iso15693_3Data* data, FlipperFormat* ff) {
|
||||
ff, ISO15693_3_BLOCK_SIZE_KEY, &data->system_info.block_size, 1))
|
||||
break;
|
||||
|
||||
if(!flipper_format_write_hex(
|
||||
ff,
|
||||
ISO15693_3_DATA_CONTENT_KEY,
|
||||
simple_array_cget_data(data->block_data),
|
||||
simple_array_get_count(data->block_data)))
|
||||
break;
|
||||
if(data->system_info.block_count > 0 && data->system_info.block_size > 0) {
|
||||
if(!flipper_format_write_hex(
|
||||
ff,
|
||||
ISO15693_3_DATA_CONTENT_KEY,
|
||||
simple_array_cget_data(data->block_data),
|
||||
simple_array_get_count(data->block_data)))
|
||||
break;
|
||||
|
||||
if(!flipper_format_write_comment_cstr(
|
||||
ff, "Block Security Status: 01 = locked, 00 = not locked"))
|
||||
break;
|
||||
if(!flipper_format_write_hex(
|
||||
ff,
|
||||
ISO15693_3_SECURITY_STATUS_KEY,
|
||||
simple_array_cget_data(data->block_security),
|
||||
simple_array_get_count(data->block_security)))
|
||||
break;
|
||||
if(!flipper_format_write_comment_cstr(
|
||||
ff, "Block Security Status: 01 = locked, 00 = not locked"))
|
||||
break;
|
||||
if(!flipper_format_write_hex(
|
||||
ff,
|
||||
ISO15693_3_SECURITY_STATUS_KEY,
|
||||
simple_array_cget_data(data->block_security),
|
||||
simple_array_get_count(data->block_security)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
saved = true;
|
||||
} while(false);
|
||||
|
||||
@@ -100,10 +100,12 @@ Iso15693_3Error iso15693_3_poller_activate(Iso15693_3Poller* instance, Iso15693_
|
||||
break;
|
||||
}
|
||||
|
||||
if(system_info->block_count > 0) {
|
||||
// Read blocks: Optional command
|
||||
if(system_info->block_count > 0 && system_info->block_size > 0) {
|
||||
simple_array_init(
|
||||
data->block_data, system_info->block_count * system_info->block_size);
|
||||
simple_array_init(data->block_security, system_info->block_count);
|
||||
|
||||
// Read blocks: Optional command
|
||||
ret = iso15693_3_poller_read_blocks(
|
||||
instance,
|
||||
simple_array_get_data(data->block_data),
|
||||
@@ -115,8 +117,6 @@ Iso15693_3Error iso15693_3_poller_activate(Iso15693_3Poller* instance, Iso15693_
|
||||
}
|
||||
|
||||
// Get block security status: Optional command
|
||||
simple_array_init(data->block_security, system_info->block_count);
|
||||
|
||||
ret = iso15693_3_poller_get_blocks_security(
|
||||
instance, simple_array_get_data(data->block_security), system_info->block_count);
|
||||
if(ret != Iso15693_3ErrorNone) {
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct {
|
||||
uint8_t cmd_start_byte;
|
||||
size_t cmd_len_bits;
|
||||
size_t command_num;
|
||||
MfClassicListenerCommandHandler* handler;
|
||||
const MfClassicListenerCommandHandler* handler;
|
||||
} MfClassicListenerCmd;
|
||||
|
||||
static void mf_classic_listener_prepare_emulation(MfClassicListener* instance) {
|
||||
@@ -441,42 +441,42 @@ static MfClassicListenerCommand
|
||||
return command;
|
||||
}
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_halt_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_halt_handlers[] = {
|
||||
mf_classic_listener_halt_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_auth_key_a_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_auth_key_a_handlers[] = {
|
||||
mf_classic_listener_auth_key_a_handler,
|
||||
mf_classic_listener_auth_second_part_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_auth_key_b_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_auth_key_b_handlers[] = {
|
||||
mf_classic_listener_auth_key_b_handler,
|
||||
mf_classic_listener_auth_second_part_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_read_block_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_read_block_handlers[] = {
|
||||
mf_classic_listener_read_block_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_write_block_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_write_block_handlers[] = {
|
||||
mf_classic_listener_write_block_first_part_handler,
|
||||
mf_classic_listener_write_block_second_part_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_value_dec_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_value_dec_handlers[] = {
|
||||
mf_classic_listener_value_dec_handler,
|
||||
mf_classic_listener_value_data_receive_handler,
|
||||
mf_classic_listener_value_transfer_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_value_inc_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_value_inc_handlers[] = {
|
||||
mf_classic_listener_value_inc_handler,
|
||||
mf_classic_listener_value_data_receive_handler,
|
||||
mf_classic_listener_value_transfer_handler,
|
||||
};
|
||||
|
||||
static MfClassicListenerCommandHandler mf_classic_listener_value_restore_handlers[] = {
|
||||
static const MfClassicListenerCommandHandler mf_classic_listener_value_restore_handlers[] = {
|
||||
mf_classic_listener_value_restore_handler,
|
||||
mf_classic_listener_value_data_receive_handler,
|
||||
mf_classic_listener_value_transfer_handler,
|
||||
|
||||
@@ -104,6 +104,7 @@ typedef enum {
|
||||
MfDesfireFileTypeValue = 2,
|
||||
MfDesfireFileTypeLinearRecord = 3,
|
||||
MfDesfireFileTypeCyclicRecord = 4,
|
||||
MfDesfireFileTypeTransactionMac = 5,
|
||||
} MfDesfireFileType;
|
||||
|
||||
typedef enum {
|
||||
@@ -135,6 +136,11 @@ typedef struct {
|
||||
uint32_t max;
|
||||
uint32_t cur;
|
||||
} record;
|
||||
struct {
|
||||
uint8_t key_option;
|
||||
uint8_t key_version;
|
||||
uint32_t counter_limit;
|
||||
} transaction_mac;
|
||||
};
|
||||
} MfDesfireFileSettings;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "mf_desfire_i.h"
|
||||
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
#define TAG "MfDesfire"
|
||||
|
||||
#define BITS_IN_BYTE (8U)
|
||||
@@ -47,6 +49,10 @@
|
||||
#define MF_DESFIRE_FFF_FILE_MAX_KEY "Max"
|
||||
#define MF_DESFIRE_FFF_FILE_CUR_KEY "Cur"
|
||||
|
||||
#define MF_DESFIRE_FFF_FILE_KEY_OPTION_KEY "Key Option"
|
||||
#define MF_DESFIRE_FFF_FILE_KEY_VERSION_KEY "Key Version"
|
||||
#define MF_DESFIRE_FFF_FILE_COUNTER_LIMIT_KEY "Counter Limit"
|
||||
|
||||
bool mf_desfire_version_parse(MfDesfireVersion* data, const BitBuffer* buf) {
|
||||
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfDesfireVersion);
|
||||
|
||||
@@ -183,12 +189,19 @@ bool mf_desfire_file_settings_parse(MfDesfireFileSettings* data, const BitBuffer
|
||||
uint32_t cur : 3 * BITS_IN_BYTE;
|
||||
} MfDesfireFileSettingsRecord;
|
||||
|
||||
typedef struct FURI_PACKED {
|
||||
uint8_t key_option;
|
||||
uint8_t key_version;
|
||||
uint8_t counter_limit[];
|
||||
} MfDesfireFileSettingsTransactionMac;
|
||||
|
||||
typedef struct FURI_PACKED {
|
||||
MfDesfireFileSettingsHeader header;
|
||||
union {
|
||||
MfDesfireFileSettingsData data;
|
||||
MfDesfireFileSettingsValue value;
|
||||
MfDesfireFileSettingsRecord record;
|
||||
MfDesfireFileSettingsTransactionMac transaction_mac;
|
||||
};
|
||||
} MfDesfireFileSettingsLayout;
|
||||
|
||||
@@ -197,7 +210,7 @@ bool mf_desfire_file_settings_parse(MfDesfireFileSettings* data, const BitBuffer
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
const uint8_t* data_ptr = bit_buffer_get_data(buf);
|
||||
const size_t min_data_size =
|
||||
sizeof(MfDesfireFileSettingsHeader) + sizeof(MfDesfireFileSettingsData);
|
||||
sizeof(MfDesfireFileSettingsHeader) + sizeof(MfDesfireFileSettingsTransactionMac);
|
||||
|
||||
if(data_size < min_data_size) {
|
||||
FURI_LOG_E(
|
||||
@@ -217,17 +230,11 @@ bool mf_desfire_file_settings_parse(MfDesfireFileSettings* data, const BitBuffer
|
||||
|
||||
if(file_settings_temp.type == MfDesfireFileTypeStandard ||
|
||||
file_settings_temp.type == MfDesfireFileTypeBackup) {
|
||||
memcpy(
|
||||
&layout.data,
|
||||
&data_ptr[sizeof(MfDesfireFileSettingsHeader)],
|
||||
sizeof(MfDesfireFileSettingsData));
|
||||
memcpy(&layout.data, &data_ptr[bytes_processed], sizeof(MfDesfireFileSettingsData));
|
||||
file_settings_temp.data.size = layout.data.size;
|
||||
bytes_processed += sizeof(MfDesfireFileSettingsData);
|
||||
} else if(file_settings_temp.type == MfDesfireFileTypeValue) {
|
||||
memcpy(
|
||||
&layout.value,
|
||||
&data_ptr[sizeof(MfDesfireFileSettingsHeader)],
|
||||
sizeof(MfDesfireFileSettingsValue));
|
||||
memcpy(&layout.value, &data_ptr[bytes_processed], sizeof(MfDesfireFileSettingsValue));
|
||||
file_settings_temp.value.lo_limit = layout.value.lo_limit;
|
||||
file_settings_temp.value.hi_limit = layout.value.hi_limit;
|
||||
file_settings_temp.value.limited_credit_value = layout.value.limited_credit_value;
|
||||
@@ -237,13 +244,34 @@ bool mf_desfire_file_settings_parse(MfDesfireFileSettings* data, const BitBuffer
|
||||
file_settings_temp.type == MfDesfireFileTypeLinearRecord ||
|
||||
file_settings_temp.type == MfDesfireFileTypeCyclicRecord) {
|
||||
memcpy(
|
||||
&layout.record,
|
||||
&data_ptr[sizeof(MfDesfireFileSettingsHeader)],
|
||||
sizeof(MfDesfireFileSettingsRecord));
|
||||
&layout.record, &data_ptr[bytes_processed], sizeof(MfDesfireFileSettingsRecord));
|
||||
file_settings_temp.record.size = layout.record.size;
|
||||
file_settings_temp.record.max = layout.record.max;
|
||||
file_settings_temp.record.cur = layout.record.cur;
|
||||
bytes_processed += sizeof(MfDesfireFileSettingsRecord);
|
||||
} else if(file_settings_temp.type == MfDesfireFileTypeTransactionMac) {
|
||||
const bool has_counter_limit = (layout.header.comm & 0x20) != 0;
|
||||
memcpy(
|
||||
&layout.transaction_mac,
|
||||
&data_ptr[bytes_processed],
|
||||
sizeof(MfDesfireFileSettingsTransactionMac));
|
||||
file_settings_temp.transaction_mac.key_option = layout.transaction_mac.key_option;
|
||||
file_settings_temp.transaction_mac.key_version = layout.transaction_mac.key_version;
|
||||
if(!has_counter_limit) {
|
||||
file_settings_temp.transaction_mac.counter_limit = 0;
|
||||
} else {
|
||||
// AES (4b) or LRP (2b)
|
||||
const size_t counter_limit_size = (layout.transaction_mac.key_option & 0x02) ? 4 :
|
||||
2;
|
||||
memcpy(
|
||||
&layout.transaction_mac,
|
||||
&data_ptr[bytes_processed],
|
||||
sizeof(MfDesfireFileSettingsTransactionMac) + counter_limit_size);
|
||||
file_settings_temp.transaction_mac.counter_limit = bit_lib_bytes_to_num_be(
|
||||
layout.transaction_mac.counter_limit, counter_limit_size);
|
||||
bytes_processed += counter_limit_size;
|
||||
}
|
||||
bytes_processed += sizeof(MfDesfireFileSettingsTransactionMac);
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Unknown file type: %02x", file_settings_temp.type);
|
||||
break;
|
||||
@@ -483,6 +511,21 @@ bool mf_desfire_file_settings_load(
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_CUR_KEY);
|
||||
if(!flipper_format_read_uint32(ff, furi_string_get_cstr(key), &data->record.cur, 1))
|
||||
break;
|
||||
} else if(data->type == MfDesfireFileTypeTransactionMac) {
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_KEY_OPTION_KEY);
|
||||
if(!flipper_format_read_hex(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.key_option, 1))
|
||||
break;
|
||||
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_KEY_VERSION_KEY);
|
||||
if(!flipper_format_read_hex(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.key_version, 1))
|
||||
break;
|
||||
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_COUNTER_LIMIT_KEY);
|
||||
if(!flipper_format_read_uint32(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.counter_limit, 1))
|
||||
break;
|
||||
}
|
||||
|
||||
success = true;
|
||||
@@ -731,6 +774,21 @@ bool mf_desfire_file_settings_save(
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_CUR_KEY);
|
||||
if(!flipper_format_write_uint32(ff, furi_string_get_cstr(key), &data->record.cur, 1))
|
||||
break;
|
||||
} else if(data->type == MfDesfireFileTypeTransactionMac) {
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_KEY_OPTION_KEY);
|
||||
if(!flipper_format_write_hex(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.key_option, 1))
|
||||
break;
|
||||
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_KEY_VERSION_KEY);
|
||||
if(!flipper_format_write_hex(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.key_version, 1))
|
||||
break;
|
||||
|
||||
furi_string_printf(key, "%s %s", prefix, MF_DESFIRE_FFF_FILE_COUNTER_LIMIT_KEY);
|
||||
if(!flipper_format_write_uint32(
|
||||
ff, furi_string_get_cstr(key), &data->transaction_mac.counter_limit, 1))
|
||||
break;
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
@@ -551,7 +551,7 @@ MfDesfireError mf_desfire_poller_read_file_data_multi(
|
||||
file_type == MfDesfireFileTypeLinearRecord ||
|
||||
file_type == MfDesfireFileTypeCyclicRecord) {
|
||||
error = mf_desfire_poller_read_file_records(
|
||||
instance, file_id, 0, file_settings_cur->data.size, file_data);
|
||||
instance, file_id, 0, file_settings_cur->record.size, file_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
* When implementing a new protocol, add its implementation
|
||||
* here under its own index defined in nfc_protocol.h.
|
||||
*/
|
||||
const NfcDeviceBase* nfc_devices[NfcProtocolNum] = {
|
||||
const NfcDeviceBase* const nfc_devices[NfcProtocolNum] = {
|
||||
[NfcProtocolIso14443_3a] = &nfc_device_iso14443_3a,
|
||||
[NfcProtocolIso14443_3b] = &nfc_device_iso14443_3b,
|
||||
[NfcProtocolIso14443_4a] = &nfc_device_iso14443_4a,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const NfcDeviceBase* nfc_devices[];
|
||||
extern const NfcDeviceBase* const nfc_devices[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <nfc/protocols/slix/slix_listener_defs.h>
|
||||
#include <nfc/protocols/type_4_tag/type_4_tag_listener_defs.h>
|
||||
|
||||
const NfcListenerBase* nfc_listeners_api[NfcProtocolNum] = {
|
||||
const NfcListenerBase* const nfc_listeners_api[NfcProtocolNum] = {
|
||||
[NfcProtocolIso14443_3a] = &nfc_listener_iso14443_3a,
|
||||
[NfcProtocolIso14443_3b] = NULL,
|
||||
[NfcProtocolIso14443_4a] = &nfc_listener_iso14443_4a,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const NfcListenerBase* nfc_listeners_api[NfcProtocolNum];
|
||||
extern const NfcListenerBase* const nfc_listeners_api[NfcProtocolNum];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <nfc/protocols/ntag4xx/ntag4xx_poller_defs.h>
|
||||
#include <nfc/protocols/type_4_tag/type_4_tag_poller_defs.h>
|
||||
|
||||
const NfcPollerBase* nfc_pollers_api[NfcProtocolNum] = {
|
||||
const NfcPollerBase* const nfc_pollers_api[NfcProtocolNum] = {
|
||||
[NfcProtocolIso14443_3a] = &nfc_poller_iso14443_3a,
|
||||
[NfcProtocolIso14443_3b] = &nfc_poller_iso14443_3b,
|
||||
[NfcProtocolIso14443_4a] = &nfc_poller_iso14443_4a,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const NfcPollerBase* nfc_pollers_api[NfcProtocolNum];
|
||||
extern const NfcPollerBase* const nfc_pollers_api[NfcProtocolNum];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user