NFC: add Slix capabilities (#3652)

* iso15693 listener: fix inventory cmd and buffer overflow
* iso15 listener: fix read multiple blocks command
* slix: print password
* slix: add capabilities field
* slix listener: skip password validation for special capability
* slix: fix capability name
* slix: add capabilities handler to verify and reset
* nfc test: introduce slix tests
* fbt: change toolchain back to 33 version
* slix: fix saving capablities comment
* unit tests: add slix files to resources
* slix: fix set passwrd signature
* nfc tests: add set correct password test
* nfc test: complete slix password tests
* nfc test: add slix file test
* nfc test: handle errors in worker callback
* iso15693_3: code clean up
* iso15693_listener: fix incorrect afi handling
* slix: chage capabilities format to one word camel case
* unit tests: update nfc files with new slix format

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich
2024-05-17 12:58:32 +01:00
committed by GitHub
parent 603a86dbe6
commit 217bfac2fc
13 changed files with 375 additions and 24 deletions

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"))