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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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] = {};
|
||||
|
||||
Reference in New Issue
Block a user