1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-13 13:09:49 +04:00

Merge branch 'astra/3746-mfp-detect' of https://github.com/flipperdevices/flipperzero-firmware into astra/3746-mfp-detect

This commit is contained in:
Astra
2024-05-20 19:19:22 +09:00
71 changed files with 2907 additions and 612 deletions

View File

@@ -8,7 +8,7 @@
#define TAG "Iso15693_3Listener"
#define ISO15693_3_LISTENER_BUFFER_SIZE (64U)
#define ISO15693_3_LISTENER_BUFFER_SIZE (256U)
Iso15693_3Listener* iso15693_3_listener_alloc(Nfc* nfc, Iso15693_3Data* data) {
furi_assert(nfc);
@@ -67,6 +67,7 @@ NfcCommand iso15693_3_listener_run(NfcGenericEvent event, void* context) {
if(nfc_event->type == NfcEventTypeRxEnd) {
BitBuffer* rx_buffer = nfc_event->data.buffer;
bit_buffer_reset(instance->tx_buffer);
if(iso13239_crc_check(Iso13239CrcTypeDefault, rx_buffer)) {
iso13239_crc_trim(rx_buffer);

View File

@@ -64,7 +64,9 @@ static Iso15693_3Error iso15693_3_listener_inventory_handler(
if(afi_flag) {
const uint8_t afi = *data++;
// When AFI flag is set, ignore non-matching requests
if(afi != instance->data->system_info.afi) break;
if(afi != 0) {
if(afi != instance->data->system_info.afi) break;
}
}
const uint8_t mask_len = *data++;
@@ -260,16 +262,9 @@ static Iso15693_3Error iso15693_3_listener_read_multi_blocks_handler(
}
const uint32_t block_index_start = request->first_block_num;
const uint32_t block_index_end = block_index_start + request->block_count;
const uint32_t block_count = request->block_count + 1;
const uint32_t block_count_max = instance->data->system_info.block_count;
const uint32_t block_count_available = block_count_max - block_index_start;
if(block_count > block_count_available) {
error = Iso15693_3ErrorInternal;
break;
}
const uint32_t block_index_end =
MIN((block_index_start + request->block_count + 1),
((uint32_t)instance->data->system_info.block_count - 1));
error = iso15693_3_listener_extension_handler(
instance,

View File

@@ -14,6 +14,7 @@
#define SLIX_TYPE_INDICATOR_SLIX (0x02U)
#define SLIX_TYPE_INDICATOR_SLIX2 (0x01U)
#define SLIX_CAPABILITIES_KEY "Capabilities"
#define SLIX_PASSWORD_READ_KEY "Password Read"
#define SLIX_PASSWORD_WRITE_KEY "Password Write"
#define SLIX_PASSWORD_PRIVACY_KEY "Password Privacy"
@@ -69,6 +70,11 @@ static const SlixTypeFeatures slix_type_features[] = {
[SlixTypeSlix2] = SLIX_TYPE_FEATURES_SLIX2,
};
static const char* slix_capabilities_names[SlixCapabilitiesCount] = {
[SlixCapabilitiesDefault] = "Default",
[SlixCapabilitiesAcceptAllPasswords] = "AcceptAllPasswords",
};
typedef struct {
const char* key;
SlixTypeFeatures feature_flag;
@@ -110,6 +116,7 @@ void slix_reset(SlixData* data) {
furi_check(data);
iso15693_3_reset(data->iso15693_3_data);
data->capabilities = SlixCapabilitiesDefault;
slix_password_set_defaults(data->passwords);
memset(&data->system_info, 0, sizeof(SlixSystemInfo));
@@ -123,6 +130,7 @@ void slix_copy(SlixData* data, const SlixData* other) {
furi_check(other);
iso15693_3_copy(data->iso15693_3_data, other->iso15693_3_data);
data->capabilities = other->capabilities;
memcpy(data->passwords, other->passwords, sizeof(SlixPassword) * SlixPasswordTypeCount);
memcpy(data->signature, other->signature, sizeof(SlixSignature));
@@ -138,6 +146,30 @@ bool slix_verify(SlixData* data, const FuriString* device_type) {
return false;
}
static bool slix_load_capabilities(SlixData* data, FlipperFormat* ff) {
bool capabilities_loaded = false;
FuriString* capabilities_str = furi_string_alloc();
if(!flipper_format_read_string(ff, SLIX_CAPABILITIES_KEY, capabilities_str)) {
if(flipper_format_rewind(ff)) {
data->capabilities = SlixCapabilitiesDefault;
capabilities_loaded = true;
}
} else {
for(size_t i = 0; i < COUNT_OF(slix_capabilities_names); i++) {
if(furi_string_cmp_str(capabilities_str, slix_capabilities_names[i]) == 0) {
data->capabilities = i;
capabilities_loaded = true;
break;
}
}
}
furi_string_free(capabilities_str);
return capabilities_loaded;
}
static bool slix_load_passwords(SlixPassword* passwords, SlixType slix_type, FlipperFormat* ff) {
bool ret = true;
@@ -164,13 +196,14 @@ bool slix_load(SlixData* data, FlipperFormat* ff, uint32_t version) {
furi_check(ff);
bool loaded = false;
do {
if(!iso15693_3_load(data->iso15693_3_data, ff, version)) break;
const SlixType slix_type = slix_get_type(data);
if(slix_type >= SlixTypeCount) break;
if(!slix_load_capabilities(data, ff)) break;
if(!slix_load_passwords(data->passwords, slix_type, ff)) break;
if(slix_type_has_features(slix_type, SLIX_TYPE_FEATURE_SIGNATURE)) {
@@ -220,6 +253,33 @@ bool slix_load(SlixData* data, FlipperFormat* ff, uint32_t version) {
return loaded;
}
static bool slix_save_capabilities(const SlixData* data, FlipperFormat* ff) {
bool save_success = false;
FuriString* tmp_str = furi_string_alloc();
do {
furi_string_set_str(
tmp_str, "SLIX capabilities field affects emulation modes. Possible options: ");
for(size_t i = 0; i < SlixCapabilitiesCount; i++) {
furi_string_cat_str(tmp_str, slix_capabilities_names[i]);
if(i < SlixCapabilitiesCount - 1) {
furi_string_cat(tmp_str, ", ");
}
}
if(!flipper_format_write_comment_cstr(ff, furi_string_get_cstr(tmp_str))) break;
if(!flipper_format_write_string_cstr(
ff, SLIX_CAPABILITIES_KEY, slix_capabilities_names[data->capabilities]))
break;
save_success = true;
} while(false);
furi_string_free(tmp_str);
return save_success;
}
static bool
slix_save_passwords(const SlixPassword* passwords, SlixType slix_type, FlipperFormat* ff) {
bool ret = true;
@@ -251,6 +311,8 @@ bool slix_save(const SlixData* data, FlipperFormat* ff) {
if(!iso15693_3_save(data->iso15693_3_data, ff)) break;
if(!flipper_format_write_comment_cstr(ff, SLIX_PROTOCOL_NAME " specific data")) break;
if(!slix_save_capabilities(data, ff)) break;
if(!flipper_format_write_comment_cstr(
ff,
"Passwords are optional. If a password is omitted, a default value will be used"))

View File

@@ -91,12 +91,20 @@ typedef struct {
SlixLockBits lock_bits;
} SlixSystemInfo;
typedef enum {
SlixCapabilitiesDefault,
SlixCapabilitiesAcceptAllPasswords,
SlixCapabilitiesCount,
} SlixCapabilities;
typedef struct {
Iso15693_3Data* iso15693_3_data;
SlixSystemInfo system_info;
SlixSignature signature;
SlixPassword passwords[SlixPasswordTypeCount];
SlixPrivacy privacy;
SlixCapabilities capabilities;
} SlixData;
SlixData* slix_alloc(void);

View File

@@ -54,6 +54,13 @@ static SlixError slix_listener_set_password(
}
SlixListenerSessionState* session_state = &instance->session_state;
// With AcceptAllPassword capability set skip password validation
if(instance->data->capabilities == SlixCapabilitiesAcceptAllPasswords) {
session_state->password_match[password_type] = true;
break;
}
session_state->password_match[password_type] =
(password == slix_get_password(slix_data, password_type));

View File

@@ -114,7 +114,8 @@ static NfcCommand slix_poller_handler_check_privacy_password(SlixPoller* instanc
break;
}
instance->error = slix_poller_set_password(instance, SlixPasswordTypePrivacy, pwd);
instance->error = slix_poller_set_password(
instance, SlixPasswordTypePrivacy, pwd, instance->random_number);
if(instance->error != SlixErrorNone) {
command = NfcCommandReset;
break;
@@ -145,7 +146,8 @@ static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) {
instance->error = slix_poller_get_random_number(instance, &instance->random_number);
if(instance->error != SlixErrorNone) break;
instance->error = slix_poller_set_password(instance, SlixPasswordTypePrivacy, pwd);
instance->error = slix_poller_set_password(
instance, SlixPasswordTypePrivacy, pwd, instance->random_number);
if(instance->error != SlixErrorNone) {
command = NfcCommandReset;
break;

View File

@@ -107,12 +107,16 @@ SlixError slix_poller_get_random_number(SlixPoller* instance, SlixRandomNumber*
* Must ONLY be used inside the callback function.
*
* @param[in, out] instance pointer to the instance to be used in the transaction.
* @param[out] type SlixPasswordType instance.
* @param[out] password SlixPassword instance.
* @param[in] type SlixPasswordType instance.
* @param[in] password SlixPassword instance.
* @param[in] random_number SlixRandomNumber instance.
* @return SlixErrorNone on success, an error code on failure.
*/
SlixError
slix_poller_set_password(SlixPoller* instance, SlixPasswordType type, SlixPassword password);
SlixError slix_poller_set_password(
SlixPoller* instance,
SlixPasswordType type,
SlixPassword password,
SlixRandomNumber random_number);
#ifdef __cplusplus
}

View File

@@ -92,8 +92,11 @@ SlixError slix_poller_get_random_number(SlixPoller* instance, SlixRandomNumber*
return error;
}
SlixError
slix_poller_set_password(SlixPoller* instance, SlixPasswordType type, SlixPassword password) {
SlixError slix_poller_set_password(
SlixPoller* instance,
SlixPasswordType type,
SlixPassword password,
SlixRandomNumber random_number) {
furi_assert(instance);
bool skip_uid = (type == SlixPasswordTypePrivacy);
@@ -102,8 +105,8 @@ SlixError
uint8_t password_type = (0x01 << type);
bit_buffer_append_byte(instance->tx_buffer, password_type);
uint8_t rn_l = instance->random_number >> 8;
uint8_t rn_h = instance->random_number;
uint8_t rn_l = random_number >> 8;
uint8_t rn_h = random_number;
uint32_t double_rand_num = (rn_h << 24) | (rn_l << 16) | (rn_h << 8) | rn_l;
uint32_t xored_password = double_rand_num ^ password;
uint8_t xored_password_arr[4] = {};