mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-24 22:07:14 +03:00
[FL-3787] NFC: Slix privacy password reveal and Desfire detect fix (#3504)
* slix: fix incorrect default privacy passwords * slix poller: add check privacy password state * mf desfire: change detect algorithm * mf desfire: change detection algorithm to check master key version * mf desfire: change assert to check * Update api symbols and cleanup code Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
11d7f53854
commit
f633f476c8
@ -225,8 +225,8 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
|
|||||||
bool protocol_detected = false;
|
bool protocol_detected = false;
|
||||||
|
|
||||||
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
||||||
MfDesfireVersion version = {};
|
MfDesfireKeyVersion key_version = {0};
|
||||||
const MfDesfireError error = mf_desfire_poller_read_version(instance, &version);
|
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
|
||||||
protocol_detected = (error == MfDesfireErrorNone);
|
protocol_detected = (error == MfDesfireErrorNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,21 @@ MfDesfireError
|
|||||||
MfDesfireError
|
MfDesfireError
|
||||||
mf_desfire_poller_read_key_settings(MfDesfirePoller* instance, MfDesfireKeySettings* data);
|
mf_desfire_poller_read_key_settings(MfDesfirePoller* instance, MfDesfireKeySettings* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read key version on MfDesfire card.
|
||||||
|
*
|
||||||
|
* Must ONLY be used inside the callback function.
|
||||||
|
*
|
||||||
|
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||||
|
* @param[out] key_num key number.
|
||||||
|
* @param[in] data pointer to the MfDesfireKeyVersion structure to be filled with key version data.
|
||||||
|
* @return MfDesfireErrorNone on success, an error code on failure.
|
||||||
|
*/
|
||||||
|
MfDesfireError mf_desfire_poller_read_key_version(
|
||||||
|
MfDesfirePoller* instance,
|
||||||
|
uint8_t key_num,
|
||||||
|
MfDesfireKeyVersion* data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read key versions on MfDesfire card.
|
* @brief Read key versions on MfDesfire card.
|
||||||
*
|
*
|
||||||
|
@ -139,6 +139,28 @@ MfDesfireError
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MfDesfireError mf_desfire_poller_read_key_version(
|
||||||
|
MfDesfirePoller* instance,
|
||||||
|
uint8_t key_num,
|
||||||
|
MfDesfireKeyVersion* data) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(data);
|
||||||
|
|
||||||
|
bit_buffer_set_size_bytes(instance->input_buffer, sizeof(uint8_t) * 2);
|
||||||
|
bit_buffer_set_byte(instance->input_buffer, 0, MF_DESFIRE_CMD_GET_KEY_VERSION);
|
||||||
|
bit_buffer_set_byte(instance->input_buffer, 1, key_num);
|
||||||
|
|
||||||
|
MfDesfireError error =
|
||||||
|
mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
||||||
|
if(error == MfDesfireErrorNone) {
|
||||||
|
if(!mf_desfire_key_version_parse(data, instance->result_buffer)) {
|
||||||
|
error = MfDesfireErrorProtocol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
MfDesfireError mf_desfire_poller_read_key_versions(
|
MfDesfireError mf_desfire_poller_read_key_versions(
|
||||||
MfDesfirePoller* instance,
|
MfDesfirePoller* instance,
|
||||||
SimpleArray* data,
|
SimpleArray* data,
|
||||||
@ -148,22 +170,11 @@ MfDesfireError mf_desfire_poller_read_key_versions(
|
|||||||
|
|
||||||
simple_array_init(data, count);
|
simple_array_init(data, count);
|
||||||
|
|
||||||
bit_buffer_set_size_bytes(instance->input_buffer, sizeof(uint8_t) * 2);
|
|
||||||
bit_buffer_set_byte(instance->input_buffer, 0, MF_DESFIRE_CMD_GET_KEY_VERSION);
|
|
||||||
|
|
||||||
MfDesfireError error = MfDesfireErrorNone;
|
MfDesfireError error = MfDesfireErrorNone;
|
||||||
|
|
||||||
for(uint32_t i = 0; i < count; ++i) {
|
for(uint32_t i = 0; i < count; ++i) {
|
||||||
bit_buffer_set_byte(instance->input_buffer, 1, i);
|
error = mf_desfire_poller_read_key_version(instance, i, simple_array_get(data, i));
|
||||||
|
|
||||||
error = mf_desfire_send_chunks(instance, instance->input_buffer, instance->result_buffer);
|
|
||||||
|
|
||||||
if(error != MfDesfireErrorNone) break;
|
if(error != MfDesfireErrorNone) break;
|
||||||
|
|
||||||
if(!mf_desfire_key_version_parse(simple_array_get(data, i), instance->result_buffer)) {
|
|
||||||
error = MfDesfireErrorProtocol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -78,8 +78,8 @@ typedef struct {
|
|||||||
static const SlixPasswordConfig slix_password_configs[] = {
|
static const SlixPasswordConfig slix_password_configs[] = {
|
||||||
[SlixPasswordTypeRead] = {SLIX_PASSWORD_READ_KEY, SLIX_TYPE_FEATURE_READ, 0x00000000U},
|
[SlixPasswordTypeRead] = {SLIX_PASSWORD_READ_KEY, SLIX_TYPE_FEATURE_READ, 0x00000000U},
|
||||||
[SlixPasswordTypeWrite] = {SLIX_PASSWORD_WRITE_KEY, SLIX_TYPE_FEATURE_WRITE, 0x00000000U},
|
[SlixPasswordTypeWrite] = {SLIX_PASSWORD_WRITE_KEY, SLIX_TYPE_FEATURE_WRITE, 0x00000000U},
|
||||||
[SlixPasswordTypePrivacy] = {SLIX_PASSWORD_PRIVACY_KEY, SLIX_TYPE_FEATURE_PRIVACY, 0xFFFFFFFFU},
|
[SlixPasswordTypePrivacy] = {SLIX_PASSWORD_PRIVACY_KEY, SLIX_TYPE_FEATURE_PRIVACY, 0x0F0F0F0FU},
|
||||||
[SlixPasswordTypeDestroy] = {SLIX_PASSWORD_DESTROY_KEY, SLIX_TYPE_FEATURE_DESTROY, 0xFFFFFFFFU},
|
[SlixPasswordTypeDestroy] = {SLIX_PASSWORD_DESTROY_KEY, SLIX_TYPE_FEATURE_DESTROY, 0x0F0F0F0FU},
|
||||||
[SlixPasswordTypeEasAfi] = {SLIX_PASSWORD_EAS_KEY, SLIX_TYPE_FEATURE_EAS, 0x00000000U},
|
[SlixPasswordTypeEasAfi] = {SLIX_PASSWORD_EAS_KEY, SLIX_TYPE_FEATURE_EAS, 0x00000000U},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,17 +73,62 @@ static NfcCommand slix_poller_handler_read_signature(SlixPoller* instance) {
|
|||||||
if(slix_type_has_features(instance->type, SLIX_TYPE_FEATURE_SIGNATURE)) {
|
if(slix_type_has_features(instance->type, SLIX_TYPE_FEATURE_SIGNATURE)) {
|
||||||
instance->error = slix_poller_read_signature(instance, &instance->data->signature);
|
instance->error = slix_poller_read_signature(instance, &instance->data->signature);
|
||||||
if(instance->error == SlixErrorNone) {
|
if(instance->error == SlixErrorNone) {
|
||||||
instance->poller_state = SlixPollerStateReady;
|
instance->poller_state = SlixPollerStateCheckPrivacyPassword;
|
||||||
} else {
|
} else {
|
||||||
instance->poller_state = SlixPollerStateError;
|
instance->poller_state = SlixPollerStateError;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instance->poller_state = SlixPollerStateReady;
|
instance->poller_state = SlixPollerStateCheckPrivacyPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NfcCommandContinue;
|
return NfcCommandContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NfcCommand slix_poller_handler_check_privacy_password(SlixPoller* instance) {
|
||||||
|
NfcCommand command = NfcCommandContinue;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!slix_type_has_features(instance->type, SLIX_TYPE_FEATURE_PRIVACY)) {
|
||||||
|
instance->poller_state = SlixPollerStateReady;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(instance->privacy_password_checked) {
|
||||||
|
instance->poller_state = SlixPollerStateReady;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->slix_event.type = SlixPollerEventTypePrivacyUnlockRequest;
|
||||||
|
command = instance->callback(instance->general_event, instance->context);
|
||||||
|
|
||||||
|
if(!instance->slix_event_data.privacy_password.password_set) {
|
||||||
|
instance->poller_state = SlixPollerStateReady;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlixPassword pwd = instance->slix_event_data.privacy_password.password;
|
||||||
|
FURI_LOG_I(TAG, "Trying to check privacy password: %08lX", pwd);
|
||||||
|
|
||||||
|
instance->error = slix_poller_get_random_number(instance, &instance->random_number);
|
||||||
|
if(instance->error != SlixErrorNone) {
|
||||||
|
instance->poller_state = SlixPollerStateReady;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->error = slix_poller_set_password(instance, SlixPasswordTypePrivacy, pwd);
|
||||||
|
if(instance->error != SlixErrorNone) {
|
||||||
|
command = NfcCommandReset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Found privacy password");
|
||||||
|
instance->data->passwords[SlixPasswordTypePrivacy] = pwd;
|
||||||
|
instance->privacy_password_checked = true;
|
||||||
|
instance->poller_state = SlixPollerStateReady;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) {
|
static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) {
|
||||||
NfcCommand command = NfcCommandContinue;
|
NfcCommand command = NfcCommandContinue;
|
||||||
instance->poller_state = SlixPollerStateError;
|
instance->poller_state = SlixPollerStateError;
|
||||||
@ -108,6 +153,7 @@ static NfcCommand slix_poller_handler_privacy_unlock(SlixPoller* instance) {
|
|||||||
|
|
||||||
FURI_LOG_I(TAG, "Privacy mode disabled");
|
FURI_LOG_I(TAG, "Privacy mode disabled");
|
||||||
instance->data->passwords[SlixPasswordTypePrivacy] = pwd;
|
instance->data->passwords[SlixPasswordTypePrivacy] = pwd;
|
||||||
|
instance->privacy_password_checked = true;
|
||||||
instance->poller_state = SlixPollerStateIdle;
|
instance->poller_state = SlixPollerStateIdle;
|
||||||
slix_unlocked = true;
|
slix_unlocked = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
@ -140,6 +186,7 @@ static const SlixPollerStateHandler slix_poller_state_handler[SlixPollerStateNum
|
|||||||
[SlixPollerStateError] = slix_poller_handler_error,
|
[SlixPollerStateError] = slix_poller_handler_error,
|
||||||
[SlixPollerStateGetNxpSysInfo] = slix_poller_handler_get_nfc_system_info,
|
[SlixPollerStateGetNxpSysInfo] = slix_poller_handler_get_nfc_system_info,
|
||||||
[SlixPollerStateReadSignature] = slix_poller_handler_read_signature,
|
[SlixPollerStateReadSignature] = slix_poller_handler_read_signature,
|
||||||
|
[SlixPollerStateCheckPrivacyPassword] = slix_poller_handler_check_privacy_password,
|
||||||
[SlixPollerStatePrivacyUnlock] = slix_poller_handler_privacy_unlock,
|
[SlixPollerStatePrivacyUnlock] = slix_poller_handler_privacy_unlock,
|
||||||
[SlixPollerStateReady] = slix_poller_handler_ready,
|
[SlixPollerStateReady] = slix_poller_handler_ready,
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,7 @@ typedef enum {
|
|||||||
SlixPollerStateIdle,
|
SlixPollerStateIdle,
|
||||||
SlixPollerStateGetNxpSysInfo,
|
SlixPollerStateGetNxpSysInfo,
|
||||||
SlixPollerStateReadSignature,
|
SlixPollerStateReadSignature,
|
||||||
|
SlixPollerStateCheckPrivacyPassword,
|
||||||
SlixPollerStatePrivacyUnlock,
|
SlixPollerStatePrivacyUnlock,
|
||||||
SlixPollerStateReady,
|
SlixPollerStateReady,
|
||||||
SlixPollerStateError,
|
SlixPollerStateError,
|
||||||
@ -27,6 +28,7 @@ struct SlixPoller {
|
|||||||
SlixPollerState poller_state;
|
SlixPollerState poller_state;
|
||||||
SlixError error;
|
SlixError error;
|
||||||
SlixRandomNumber random_number;
|
SlixRandomNumber random_number;
|
||||||
|
bool privacy_password_checked;
|
||||||
|
|
||||||
BitBuffer* tx_buffer;
|
BitBuffer* tx_buffer;
|
||||||
BitBuffer* rx_buffer;
|
BitBuffer* rx_buffer;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,60.0,,
|
Version,+,60.1,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,60.0,,
|
Version,+,60.1,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@ -2444,6 +2444,7 @@ Function,+,mf_desfire_poller_read_file_settings_multi,MfDesfireError,"MfDesfireP
|
|||||||
Function,+,mf_desfire_poller_read_file_value,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, MfDesfireFileData*"
|
Function,+,mf_desfire_poller_read_file_value,MfDesfireError,"MfDesfirePoller*, MfDesfireFileId, MfDesfireFileData*"
|
||||||
Function,+,mf_desfire_poller_read_free_memory,MfDesfireError,"MfDesfirePoller*, MfDesfireFreeMemory*"
|
Function,+,mf_desfire_poller_read_free_memory,MfDesfireError,"MfDesfirePoller*, MfDesfireFreeMemory*"
|
||||||
Function,+,mf_desfire_poller_read_key_settings,MfDesfireError,"MfDesfirePoller*, MfDesfireKeySettings*"
|
Function,+,mf_desfire_poller_read_key_settings,MfDesfireError,"MfDesfirePoller*, MfDesfireKeySettings*"
|
||||||
|
Function,+,mf_desfire_poller_read_key_version,MfDesfireError,"MfDesfirePoller*, uint8_t, MfDesfireKeyVersion*"
|
||||||
Function,+,mf_desfire_poller_read_key_versions,MfDesfireError,"MfDesfirePoller*, SimpleArray*, uint32_t"
|
Function,+,mf_desfire_poller_read_key_versions,MfDesfireError,"MfDesfirePoller*, SimpleArray*, uint32_t"
|
||||||
Function,+,mf_desfire_poller_read_version,MfDesfireError,"MfDesfirePoller*, MfDesfireVersion*"
|
Function,+,mf_desfire_poller_read_version,MfDesfireError,"MfDesfirePoller*, MfDesfireVersion*"
|
||||||
Function,+,mf_desfire_poller_select_application,MfDesfireError,"MfDesfirePoller*, const MfDesfireApplicationId*"
|
Function,+,mf_desfire_poller_select_application,MfDesfireError,"MfDesfirePoller*, const MfDesfireApplicationId*"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user