mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
total cleanup. finally, bitlib
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <bit_lib.h>
|
||||
#include "tools/t5577.h"
|
||||
#define TAG "Clear T5577"
|
||||
|
||||
@@ -21,8 +22,7 @@ static void lfrfid_clear_t5577_password_and_config_to_EM(LfRfid* app) {
|
||||
};
|
||||
|
||||
// Clear custom password
|
||||
uint32_t custom_pass = (app->password[0] << 24) | (app->password[1] << 16) |
|
||||
(app->password[2] << 8) | (app->password[3]);
|
||||
uint32_t custom_pass = bit_lib_bytes_to_num_be(app->password, 4);
|
||||
snprintf(curr_buf, sizeof(curr_buf), "Custom password");
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include "bit_lib.h"
|
||||
#include "gui/scene_manager.h"
|
||||
|
||||
int next_scene;
|
||||
@@ -16,7 +17,7 @@ void lfrfid_scene_enter_password_on_enter(void* context) {
|
||||
const uint32_t* password_list = lfrfid_get_t5577_default_passwords(&password_list_size);
|
||||
uint32_t pass = password_list[furi_get_tick() % password_list_size];
|
||||
|
||||
for(uint8_t i = 0; i < 4; i++) app->password[4 - (i + 1)] = (pass >> (8 * i)) & 0xFF;
|
||||
bit_lib_num_to_bytes_be(pass, 4, app->password);
|
||||
}
|
||||
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "Aime"
|
||||
|
||||
static const uint64_t aime_key = 0x574343467632;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
|
||||
#define TAG "AllInOne"
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
#include <applications/services/locale/locale.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -16,17 +16,14 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "core/string.h"
|
||||
#include "furi_hal_rtc.h"
|
||||
#include "helpers/nfc_emv_parser.h"
|
||||
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/emv/emv.h"
|
||||
#include "protocols/nfc_protocol.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include "helpers/nfc_emv_parser.h"
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "EMV"
|
||||
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
*/
|
||||
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "../../api/gallagher/gallagher_util.h"
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <bit_lib.h>
|
||||
|
||||
static bool gallagher_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
furi_assert(device);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "HI!"
|
||||
#define KEY_LENGTH 6
|
||||
#define HI_KEY_TO_GEN 5
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "HID"
|
||||
|
||||
static const uint64_t hid_key = 0x484944204953;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* itso.c - Parser for ITSO cards (United Kingdom). */
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||
|
||||
#include <applications/services/locale/locale.h>
|
||||
|
||||
@@ -17,14 +17,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Kazan"
|
||||
@@ -134,7 +131,7 @@ static bool kazan_verify(Nfc* nfc) {
|
||||
FURI_LOG_D(TAG, "Verifying sector %u", verification_sector_number);
|
||||
|
||||
MfClassicKey key_1 = {0};
|
||||
nfc_util_num2bytes(
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v1[verification_sector_number].a, COUNT_OF(key_1.data), key_1.data);
|
||||
|
||||
MfClassicAuthContext auth_context;
|
||||
@@ -145,7 +142,7 @@ static bool kazan_verify(Nfc* nfc) {
|
||||
TAG, "Failed to read block %u: %d. Keys: v1", verification_block_number, error);
|
||||
|
||||
MfClassicKey key_2 = {0};
|
||||
nfc_util_num2bytes(
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v2[verification_sector_number].a, COUNT_OF(key_2.data), key_2.data);
|
||||
|
||||
MfClassicAuthContext auth_context;
|
||||
@@ -196,17 +193,23 @@ static bool kazan_read(Nfc* nfc, NfcDevice* device) {
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
nfc_util_num2bytes(kazan_1k_keys_v1[i].a, sizeof(MfClassicKey), keys_v1.key_a[i].data);
|
||||
nfc_util_num2bytes(kazan_1k_keys_v2[i].a, sizeof(MfClassicKey), keys_v2.key_a[i].data);
|
||||
nfc_util_num2bytes(kazan_1k_keys_v3[i].a, sizeof(MfClassicKey), keys_v3.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v1[i].a, sizeof(MfClassicKey), keys_v1.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v2[i].a, sizeof(MfClassicKey), keys_v2.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v3[i].a, sizeof(MfClassicKey), keys_v3.key_a[i].data);
|
||||
|
||||
FURI_BIT_SET(keys_v1.key_a_mask, i);
|
||||
FURI_BIT_SET(keys_v2.key_a_mask, i);
|
||||
FURI_BIT_SET(keys_v3.key_a_mask, i);
|
||||
|
||||
nfc_util_num2bytes(kazan_1k_keys_v1[i].b, sizeof(MfClassicKey), keys_v1.key_b[i].data);
|
||||
nfc_util_num2bytes(kazan_1k_keys_v2[i].b, sizeof(MfClassicKey), keys_v2.key_b[i].data);
|
||||
nfc_util_num2bytes(kazan_1k_keys_v3[i].b, sizeof(MfClassicKey), keys_v3.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v1[i].b, sizeof(MfClassicKey), keys_v1.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v2[i].b, sizeof(MfClassicKey), keys_v2.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
kazan_1k_keys_v3[i].b, sizeof(MfClassicKey), keys_v3.key_b[i].data);
|
||||
|
||||
FURI_BIT_SET(keys_v1.key_b_mask, i);
|
||||
FURI_BIT_SET(keys_v2.key_b_mask, i);
|
||||
@@ -261,8 +264,8 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
const MfClassicSectorTrailer* sec_tr =
|
||||
mf_classic_get_sector_trailer_by_sector(data, ticket_sector_number);
|
||||
|
||||
keys.a = nfc_util_bytes2num(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
keys.b = nfc_util_bytes2num(sec_tr->key_b.data, COUNT_OF(sec_tr->key_b.data));
|
||||
keys.a = bit_lib_bytes_to_num_be(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
keys.b = bit_lib_bytes_to_num_be(sec_tr->key_b.data, COUNT_OF(sec_tr->key_b.data));
|
||||
|
||||
if(((keys.a != kazan_1k_keys_v1[8].a) && (keys.a != kazan_1k_keys_v2[8].a)) ||
|
||||
((keys.b != kazan_1k_keys_v1[8].b) && (keys.b != kazan_1k_keys_v2[8].b))) {
|
||||
@@ -305,11 +308,11 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
start_block_num = mf_classic_get_first_block_num_of_sector(balance_sector_number);
|
||||
block_start_ptr = &data->block[start_block_num].data[0];
|
||||
|
||||
const uint32_t trip_counter = nfc_util_bytes2num_little_endian(block_start_ptr, 4);
|
||||
const uint32_t trip_counter = bit_lib_bytes_to_num_le(block_start_ptr, 4);
|
||||
|
||||
size_t uid_len = 0;
|
||||
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
|
||||
const uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4);
|
||||
const uint32_t card_number = bit_lib_bytes_to_num_le(uid, 4);
|
||||
|
||||
furi_string_cat_printf(
|
||||
parsed_data, "\e#Kazan transport card\nCard number: %lu\n", card_number);
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "Metromoney"
|
||||
|
||||
typedef struct {
|
||||
@@ -61,7 +59,7 @@ static bool metromoney_verify(Nfc* nfc) {
|
||||
FURI_LOG_D(TAG, "Verifying sector %u", ticket_sector_number);
|
||||
|
||||
MfClassicKey key = {0};
|
||||
nfc_util_num2bytes(
|
||||
bit_lib_num_to_bytes_be(
|
||||
metromoney_1k_keys[ticket_sector_number].a, COUNT_OF(key.data), key.data);
|
||||
|
||||
MfClassicAuthContext auth_context;
|
||||
@@ -100,9 +98,11 @@ static bool metromoney_read(Nfc* nfc, NfcDevice* device) {
|
||||
.key_b_mask = 0,
|
||||
};
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
nfc_util_num2bytes(metromoney_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
metromoney_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
FURI_BIT_SET(keys.key_a_mask, i);
|
||||
nfc_util_num2bytes(metromoney_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(
|
||||
metromoney_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
FURI_BIT_SET(keys.key_b_mask, i);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ static bool metromoney_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
const MfClassicSectorTrailer* sec_tr =
|
||||
mf_classic_get_sector_trailer_by_sector(data, ticket_sector_number);
|
||||
|
||||
const uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
const uint64_t key =
|
||||
bit_lib_bytes_to_num_be(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
if(key != metromoney_1k_keys[ticket_sector_number].a) break;
|
||||
|
||||
// Parse data
|
||||
@@ -147,14 +148,14 @@ static bool metromoney_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
const uint8_t* block_start_ptr =
|
||||
&data->block[start_block_num + ticket_block_number].data[0];
|
||||
|
||||
uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4) - 100;
|
||||
uint32_t balance = bit_lib_bytes_to_num_le(block_start_ptr, 4) - 100;
|
||||
|
||||
uint32_t balance_lari = balance / 100;
|
||||
uint8_t balance_tetri = balance % 100;
|
||||
|
||||
size_t uid_len = 0;
|
||||
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
|
||||
uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4);
|
||||
uint32_t card_number = bit_lib_bytes_to_num_le(uid, 4);
|
||||
|
||||
furi_string_printf(
|
||||
parsed_data,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "Microel"
|
||||
#define KEY_LENGTH 6
|
||||
#define UID_LENGTH 4
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "MiZIP"
|
||||
#define KEY_LENGTH 6
|
||||
#define MIZIP_KEY_TO_GEN 5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <machine/endian.h>
|
||||
#include <nfc/protocols/st25tb/st25tb.h>
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* Reference: https://github.com/metrodroid/metrodroid/wiki/Myki
|
||||
*/
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||
|
||||
static const MfDesfireApplicationId myki_app_id = {.data = {0x00, 0x11, 0xf2}};
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Made by @Willy-JL
|
||||
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "NDEF"
|
||||
|
||||
static bool is_text(const uint8_t* buf, size_t len) {
|
||||
@@ -162,18 +163,18 @@ static void parse_ndef_wifi(FuriString* str, const uint8_t* payload, uint32_t pa
|
||||
|
||||
size_t i = 0;
|
||||
while(i < payload_len) {
|
||||
uint16_t field_id = nfc_util_bytes2num(payload + i, 2);
|
||||
uint16_t field_id = bit_lib_bytes_to_num_be(payload + i, 2);
|
||||
i += 2;
|
||||
uint16_t field_len = nfc_util_bytes2num(payload + i, 2);
|
||||
uint16_t field_len = bit_lib_bytes_to_num_be(payload + i, 2);
|
||||
i += 2;
|
||||
|
||||
if(field_id == CREDENTIAL_FIELD_ID) {
|
||||
furi_string_cat(str, "WiFi\n");
|
||||
size_t start_position = i;
|
||||
while(i < start_position + field_len) {
|
||||
uint16_t cfg_id = nfc_util_bytes2num(payload + i, 2);
|
||||
uint16_t cfg_id = bit_lib_bytes_to_num_be(payload + i, 2);
|
||||
i += 2;
|
||||
uint16_t cfg_len = nfc_util_bytes2num(payload + i, 2);
|
||||
uint16_t cfg_len = bit_lib_bytes_to_num_be(payload + i, 2);
|
||||
i += 2;
|
||||
|
||||
if(i + cfg_len > start_position + field_len) {
|
||||
@@ -196,7 +197,7 @@ static void parse_ndef_wifi(FuriString* str, const uint8_t* payload, uint32_t pa
|
||||
if(cfg_len != AUTH_TYPE_EXPECTED_SIZE) {
|
||||
return;
|
||||
}
|
||||
short auth_type = nfc_util_bytes2num(payload + i, 2);
|
||||
short auth_type = bit_lib_bytes_to_num_be(payload + i, 2);
|
||||
i += 2;
|
||||
const char* auth;
|
||||
switch(auth_type) {
|
||||
@@ -318,7 +319,7 @@ static const uint8_t* parse_ndef_message(
|
||||
if(short_record) {
|
||||
payload_len = *cur++;
|
||||
} else {
|
||||
payload_len = nfc_util_bytes2num(cur, 4);
|
||||
payload_len = bit_lib_bytes_to_num_be(cur, 4);
|
||||
cur += 4;
|
||||
}
|
||||
|
||||
@@ -397,7 +398,7 @@ static bool ndef_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
cur = end;
|
||||
break;
|
||||
}
|
||||
len = nfc_util_bytes2num(++cur, 2);
|
||||
len = bit_lib_bytes_to_num_be(++cur, 2);
|
||||
cur += 2;
|
||||
}
|
||||
if(cur + len >= end) {
|
||||
@@ -439,7 +440,7 @@ static bool ndef_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
cur = end;
|
||||
break;
|
||||
}
|
||||
cur += nfc_util_bytes2num(cur + 1, 2) + 3; // Shift by TLV length
|
||||
cur += bit_lib_bytes_to_num_be(cur + 1, 2) + 3; // Shift by TLV length
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
*/
|
||||
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <applications/services/locale/locale.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
|
||||
|
||||
#include <applications/services/locale/locale.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
static const MfDesfireApplicationId opal_app_id = {.data = {0x31, 0x45, 0x53}};
|
||||
|
||||
static const MfDesfireFileId opal_file_id = 0x07;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "Plantain"
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// FZ plugin by @noproto
|
||||
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "Saflok"
|
||||
#define MAGIC_TABLE_SIZE 192
|
||||
@@ -78,7 +78,7 @@ static bool saflok_verify(Nfc* nfc) {
|
||||
FURI_LOG_D(TAG, "Saflok: Verifying sector %i", CHECK_SECTOR);
|
||||
|
||||
MfClassicKey key = {0};
|
||||
nfc_util_num2bytes(saflok_1k_keys[CHECK_SECTOR].a, COUNT_OF(key.data), key.data);
|
||||
bit_lib_num_to_bytes_be(saflok_1k_keys[CHECK_SECTOR].a, COUNT_OF(key.data), key.data);
|
||||
|
||||
MfClassicAuthContext auth_context;
|
||||
MfClassicError error =
|
||||
@@ -119,7 +119,7 @@ static bool saflok_read(Nfc* nfc, NfcDevice* device) {
|
||||
|
||||
uint8_t key[KEY_LENGTH];
|
||||
generate_saflok_key(uid, key);
|
||||
uint64_t num_key = nfc_util_bytes2num(key, KEY_LENGTH);
|
||||
uint64_t num_key = bit_lib_bytes_to_num_be(key, KEY_LENGTH);
|
||||
FURI_LOG_D(TAG, "Saflok: Key generated for UID: %012llX", num_key);
|
||||
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
@@ -130,9 +130,9 @@ static bool saflok_read(Nfc* nfc, NfcDevice* device) {
|
||||
|
||||
MfClassicDeviceKeys keys = {};
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
nfc_util_num2bytes(saflok_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(saflok_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
FURI_BIT_SET(keys.key_a_mask, i);
|
||||
nfc_util_num2bytes(saflok_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(saflok_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
FURI_BIT_SET(keys.key_b_mask, i);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <core/check.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <core/string.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <core/check.h>
|
||||
|
||||
#define TAG "Social_Moscow"
|
||||
|
||||
@@ -65,447 +61,6 @@ static const MfClassicKeyPair social_moscow_4k_keys[] = {
|
||||
|
||||
#define TOPBIT(X) (1 << ((X)-1))
|
||||
|
||||
typedef enum {
|
||||
BitLibParityEven,
|
||||
BitLibParityOdd,
|
||||
BitLibParityAlways0,
|
||||
BitLibParityAlways1,
|
||||
} BitLibParity;
|
||||
|
||||
typedef struct {
|
||||
const char mark;
|
||||
const size_t start;
|
||||
const size_t length;
|
||||
} BitLibRegion;
|
||||
|
||||
void bit_lib_push_bit(uint8_t* data, size_t data_size, bool bit) {
|
||||
size_t last_index = data_size - 1;
|
||||
|
||||
for(size_t i = 0; i < last_index; ++i) {
|
||||
data[i] = (data[i] << 1) | ((data[i + 1] >> 7) & 1);
|
||||
}
|
||||
data[last_index] = (data[last_index] << 1) | bit;
|
||||
}
|
||||
|
||||
void bit_lib_set_bit(uint8_t* data, size_t position, bool bit) {
|
||||
if(bit) {
|
||||
data[position / 8] |= 1UL << (7 - (position % 8));
|
||||
} else {
|
||||
data[position / 8] &= ~(1UL << (7 - (position % 8)));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_set_bits(uint8_t* data, size_t position, uint8_t byte, uint8_t length) {
|
||||
furi_check(length <= 8);
|
||||
furi_check(length > 0);
|
||||
|
||||
for(uint8_t i = 0; i < length; ++i) {
|
||||
uint8_t shift = (length - 1) - i;
|
||||
bit_lib_set_bit(data, position + i, (byte >> shift) & 1); //-V610
|
||||
}
|
||||
}
|
||||
|
||||
bool bit_lib_get_bit(const uint8_t* data, size_t position) {
|
||||
return (data[position / 8] >> (7 - (position % 8))) & 1;
|
||||
}
|
||||
|
||||
uint8_t bit_lib_get_bits(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint8_t shift = position % 8;
|
||||
if(shift == 0) {
|
||||
return data[position / 8] >> (8 - length);
|
||||
} else {
|
||||
// TODO fix read out of bounds
|
||||
uint8_t value = (data[position / 8] << (shift));
|
||||
value |= data[position / 8 + 1] >> (8 - shift);
|
||||
value = value >> (8 - length);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t bit_lib_get_bits_16(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint16_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint32_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else if(length <= 16) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
} else if(length <= 24) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= bit_lib_get_bits(data, position + 16, length - 16);
|
||||
} else {
|
||||
value = (uint32_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint32_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint32_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= bit_lib_get_bits(data, position + 24, length - 24);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t bit_lib_get_bits_64(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint64_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else if(length <= 16) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
} else if(length <= 24) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= bit_lib_get_bits(data, position + 16, length - 16);
|
||||
} else if(length <= 32) {
|
||||
value = (uint64_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= bit_lib_get_bits(data, position + 24, length - 24);
|
||||
} else {
|
||||
value = (uint64_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 24, 8) << (length - 32);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 32, 8) << (length - 40);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 40, 8) << (length - 48);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 48, 8) << (length - 56);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 56, 8) << (length - 64);
|
||||
value |= bit_lib_get_bits(data, position + 64, length - 64);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool bit_lib_test_parity_32(uint32_t bits, BitLibParity parity) {
|
||||
#if !defined __GNUC__
|
||||
#error Please, implement parity test for non-GCC compilers
|
||||
#else
|
||||
switch(parity) {
|
||||
case BitLibParityEven:
|
||||
return __builtin_parity(bits);
|
||||
case BitLibParityOdd:
|
||||
return !__builtin_parity(bits);
|
||||
default:
|
||||
furi_crash("Unknown parity");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bit_lib_test_parity(
|
||||
const uint8_t* bits,
|
||||
size_t position,
|
||||
uint8_t length,
|
||||
BitLibParity parity,
|
||||
uint8_t parity_length) {
|
||||
uint32_t parity_block;
|
||||
bool result = true;
|
||||
const size_t parity_blocks_count = length / parity_length;
|
||||
|
||||
for(size_t i = 0; i < parity_blocks_count; ++i) {
|
||||
switch(parity) {
|
||||
case BitLibParityEven:
|
||||
case BitLibParityOdd:
|
||||
parity_block = bit_lib_get_bits_32(bits, position + i * parity_length, parity_length);
|
||||
if(!bit_lib_test_parity_32(parity_block, parity)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
case BitLibParityAlways0:
|
||||
if(bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
case BitLibParityAlways1:
|
||||
if(!bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!result) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t bit_lib_add_parity(
|
||||
const uint8_t* data,
|
||||
size_t position,
|
||||
uint8_t* dest,
|
||||
size_t dest_position,
|
||||
uint8_t source_length,
|
||||
uint8_t parity_length,
|
||||
BitLibParity parity) {
|
||||
uint32_t parity_word = 0;
|
||||
size_t j = 0, bit_count = 0;
|
||||
for(int word = 0; word < source_length; word += parity_length - 1) {
|
||||
for(int bit = 0; bit < parity_length - 1; bit++) {
|
||||
parity_word = (parity_word << 1) | bit_lib_get_bit(data, position + word + bit);
|
||||
bit_lib_set_bit(
|
||||
dest, dest_position + j++, bit_lib_get_bit(data, position + word + bit));
|
||||
}
|
||||
// if parity fails then return 0
|
||||
switch(parity) {
|
||||
case BitLibParityAlways0:
|
||||
bit_lib_set_bit(dest, dest_position + j++, 0);
|
||||
break; // marker bit which should be a 0
|
||||
case BitLibParityAlways1:
|
||||
bit_lib_set_bit(dest, dest_position + j++, 1);
|
||||
break; // marker bit which should be a 1
|
||||
default:
|
||||
bit_lib_set_bit(
|
||||
dest,
|
||||
dest_position + j++,
|
||||
(bit_lib_test_parity_32(parity_word, BitLibParityOdd) ^ parity) ^ 1);
|
||||
break;
|
||||
}
|
||||
bit_count += parity_length;
|
||||
parity_word = 0;
|
||||
}
|
||||
// if we got here then all the parities passed
|
||||
// return bit count
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
size_t bit_lib_remove_bit_every_nth(uint8_t* data, size_t position, uint8_t length, uint8_t n) {
|
||||
size_t counter = 0;
|
||||
size_t result_counter = 0;
|
||||
uint8_t bit_buffer = 0;
|
||||
uint8_t bit_counter = 0;
|
||||
|
||||
while(counter < length) {
|
||||
if((counter + 1) % n != 0) {
|
||||
bit_buffer = (bit_buffer << 1) | bit_lib_get_bit(data, position + counter);
|
||||
bit_counter++;
|
||||
}
|
||||
|
||||
if(bit_counter == 8) {
|
||||
bit_lib_set_bits(data, position + result_counter, bit_buffer, 8);
|
||||
bit_counter = 0;
|
||||
bit_buffer = 0;
|
||||
result_counter += 8;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
if(bit_counter != 0) {
|
||||
bit_lib_set_bits(data, position + result_counter, bit_buffer, bit_counter);
|
||||
result_counter += bit_counter;
|
||||
}
|
||||
return result_counter;
|
||||
}
|
||||
|
||||
void bit_lib_copy_bits(
|
||||
uint8_t* data,
|
||||
size_t position,
|
||||
size_t length,
|
||||
const uint8_t* source,
|
||||
size_t source_position) {
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
bit_lib_set_bit(data, position + i, bit_lib_get_bit(source, source_position + i));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_reverse_bits(uint8_t* data, size_t position, uint8_t length) {
|
||||
size_t i = 0;
|
||||
size_t j = length - 1;
|
||||
|
||||
while(i < j) {
|
||||
bool tmp = bit_lib_get_bit(data, position + i);
|
||||
bit_lib_set_bit(data, position + i, bit_lib_get_bit(data, position + j));
|
||||
bit_lib_set_bit(data, position + j, tmp);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t bit_lib_get_bit_count(uint32_t data) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_popcountl(data);
|
||||
#else
|
||||
#error Please, implement popcount for non-GCC compilers
|
||||
#endif
|
||||
}
|
||||
|
||||
void bit_lib_print_bits(const uint8_t* data, size_t length) {
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
printf("%u", bit_lib_get_bit(data, i));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_print_regions(
|
||||
const BitLibRegion* regions,
|
||||
size_t region_count,
|
||||
const uint8_t* data,
|
||||
size_t length) {
|
||||
// print data
|
||||
bit_lib_print_bits(data, length);
|
||||
printf("\r\n");
|
||||
|
||||
// print regions
|
||||
for(size_t c = 0; c < length; ++c) {
|
||||
bool print = false;
|
||||
|
||||
for(size_t i = 0; i < region_count; i++) {
|
||||
if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
|
||||
print = true;
|
||||
printf("%c", regions[i].mark);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!print) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
// print regions data
|
||||
for(size_t c = 0; c < length; ++c) {
|
||||
bool print = false;
|
||||
|
||||
for(size_t i = 0; i < region_count; i++) {
|
||||
if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
|
||||
print = true;
|
||||
printf("%u", bit_lib_get_bit(data, c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!print) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
uint16_t bit_lib_reverse_16_fast(uint16_t data) {
|
||||
uint16_t result = 0;
|
||||
result |= (data & 0x8000) >> 15;
|
||||
result |= (data & 0x4000) >> 13;
|
||||
result |= (data & 0x2000) >> 11;
|
||||
result |= (data & 0x1000) >> 9;
|
||||
result |= (data & 0x0800) >> 7;
|
||||
result |= (data & 0x0400) >> 5;
|
||||
result |= (data & 0x0200) >> 3;
|
||||
result |= (data & 0x0100) >> 1;
|
||||
result |= (data & 0x0080) << 1;
|
||||
result |= (data & 0x0040) << 3;
|
||||
result |= (data & 0x0020) << 5;
|
||||
result |= (data & 0x0010) << 7;
|
||||
result |= (data & 0x0008) << 9;
|
||||
result |= (data & 0x0004) << 11;
|
||||
result |= (data & 0x0002) << 13;
|
||||
result |= (data & 0x0001) << 15;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t bit_lib_reverse_8_fast(uint8_t byte) {
|
||||
byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4;
|
||||
byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2;
|
||||
byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1;
|
||||
return byte;
|
||||
}
|
||||
|
||||
uint16_t bit_lib_crc8(
|
||||
uint8_t const* data,
|
||||
size_t data_size,
|
||||
uint8_t polynom,
|
||||
uint8_t init,
|
||||
bool ref_in,
|
||||
bool ref_out,
|
||||
uint8_t xor_out) {
|
||||
uint8_t crc = init;
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
uint8_t byte = data[i];
|
||||
if(ref_in) bit_lib_reverse_bits(&byte, 0, 8);
|
||||
crc ^= byte;
|
||||
|
||||
for(size_t j = 8; j > 0; --j) {
|
||||
if(crc & TOPBIT(8)) {
|
||||
crc = (crc << 1) ^ polynom;
|
||||
} else {
|
||||
crc = (crc << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ref_out) bit_lib_reverse_bits(&crc, 0, 8);
|
||||
crc ^= xor_out;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t bit_lib_crc16(
|
||||
uint8_t const* data,
|
||||
size_t data_size,
|
||||
uint16_t polynom,
|
||||
uint16_t init,
|
||||
bool ref_in,
|
||||
bool ref_out,
|
||||
uint16_t xor_out) {
|
||||
uint16_t crc = init;
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
uint8_t byte = data[i];
|
||||
if(ref_in) byte = bit_lib_reverse_16_fast(byte) >> 8;
|
||||
|
||||
for(size_t j = 0; j < 8; ++j) {
|
||||
bool c15 = (crc >> 15 & 1);
|
||||
bool bit = (byte >> (7 - j) & 1);
|
||||
crc <<= 1;
|
||||
if(c15 ^ bit) crc ^= polynom;
|
||||
}
|
||||
}
|
||||
|
||||
if(ref_out) crc = bit_lib_reverse_16_fast(crc);
|
||||
crc ^= xor_out;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
|
||||
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
|
||||
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
|
||||
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
|
||||
#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \
|
||||
((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
|
||||
|
||||
void timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) {
|
||||
uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
|
||||
datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR;
|
||||
|
||||
while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) {
|
||||
days -= furi_hal_rtc_get_days_per_year(datetime->year);
|
||||
(datetime->year)++;
|
||||
}
|
||||
|
||||
datetime->month = 1;
|
||||
while(days >= furi_hal_rtc_get_days_per_month(
|
||||
FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year), datetime->month)) {
|
||||
days -= furi_hal_rtc_get_days_per_month(
|
||||
FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year), datetime->month);
|
||||
(datetime->month)++;
|
||||
}
|
||||
|
||||
datetime->day = days + 1;
|
||||
datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR;
|
||||
datetime->minute =
|
||||
(seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
||||
uint32_t timestamp = days * 24 * 60 * 60;
|
||||
FuriHalRtcDateTime start_datetime = {0};
|
||||
@@ -513,7 +68,7 @@ void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t
|
||||
start_datetime.month = 12;
|
||||
start_datetime.day = 31;
|
||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
||||
timestamp_to_datetime(timestamp, datetime);
|
||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
||||
}
|
||||
|
||||
void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
||||
@@ -523,7 +78,7 @@ void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, ui
|
||||
start_datetime.month = 12;
|
||||
start_datetime.day = 31;
|
||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
||||
timestamp_to_datetime(timestamp, datetime);
|
||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
||||
}
|
||||
|
||||
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
@@ -671,7 +226,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_start_trip_date) * 24 * 60 + card_start_trip_time,
|
||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||
&card_start_trip_minutes_s,
|
||||
1992);
|
||||
furi_string_printf(
|
||||
@@ -1486,7 +1041,7 @@ static bool social_moscow_verify_type(Nfc* nfc, MfClassicType type) {
|
||||
FURI_LOG_D(TAG, "Verifying sector %lu", cfg.data_sector);
|
||||
|
||||
MfClassicKey key = {0};
|
||||
nfc_util_num2bytes(cfg.keys[cfg.data_sector].a, COUNT_OF(key.data), key.data);
|
||||
bit_lib_num_to_bytes_be(cfg.keys[cfg.data_sector].a, COUNT_OF(key.data), key.data);
|
||||
|
||||
MfClassicAuthContext auth_context;
|
||||
MfClassicError error =
|
||||
@@ -1527,9 +1082,9 @@ static bool social_moscow_read(Nfc* nfc, NfcDevice* device) {
|
||||
|
||||
MfClassicDeviceKeys keys = {};
|
||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||
nfc_util_num2bytes(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
bit_lib_num_to_bytes_be(cfg.keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||
FURI_BIT_SET(keys.key_a_mask, i);
|
||||
nfc_util_num2bytes(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
bit_lib_num_to_bytes_be(cfg.keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
|
||||
FURI_BIT_SET(keys.key_b_mask, i);
|
||||
}
|
||||
|
||||
@@ -1566,9 +1121,9 @@ static bool social_moscow_parse(const NfcDevice* device, FuriString* parsed_data
|
||||
mf_classic_get_sector_trailer_by_sector(data, cfg.data_sector);
|
||||
|
||||
const uint64_t key_a =
|
||||
nfc_util_bytes2num(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
bit_lib_bytes_to_num_be(sec_tr->key_a.data, COUNT_OF(sec_tr->key_a.data));
|
||||
const uint64_t key_b =
|
||||
nfc_util_bytes2num(sec_tr->key_b.data, COUNT_OF(sec_tr->key_b.data));
|
||||
bit_lib_bytes_to_num_be(sec_tr->key_b.data, COUNT_OF(sec_tr->key_b.data));
|
||||
if((key_a != cfg.keys[cfg.data_sector].a) || (key_b != cfg.keys[cfg.data_sector].b)) break;
|
||||
|
||||
uint32_t card_code = bit_lib_get_bits_32(data->block[60].data, 8, 24);
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <core/check.h>
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <core/string.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <core/check.h>
|
||||
|
||||
#define TAG "Troika"
|
||||
|
||||
@@ -66,447 +62,6 @@ static const MfClassicKeyPair troika_4k_keys[] = {
|
||||
|
||||
#define TOPBIT(X) (1 << ((X)-1))
|
||||
|
||||
typedef enum {
|
||||
BitLibParityEven,
|
||||
BitLibParityOdd,
|
||||
BitLibParityAlways0,
|
||||
BitLibParityAlways1,
|
||||
} BitLibParity;
|
||||
|
||||
typedef struct {
|
||||
const char mark;
|
||||
const size_t start;
|
||||
const size_t length;
|
||||
} BitLibRegion;
|
||||
|
||||
void bit_lib_push_bit(uint8_t* data, size_t data_size, bool bit) {
|
||||
size_t last_index = data_size - 1;
|
||||
|
||||
for(size_t i = 0; i < last_index; ++i) {
|
||||
data[i] = (data[i] << 1) | ((data[i + 1] >> 7) & 1);
|
||||
}
|
||||
data[last_index] = (data[last_index] << 1) | bit;
|
||||
}
|
||||
|
||||
void bit_lib_set_bit(uint8_t* data, size_t position, bool bit) {
|
||||
if(bit) {
|
||||
data[position / 8] |= 1UL << (7 - (position % 8));
|
||||
} else {
|
||||
data[position / 8] &= ~(1UL << (7 - (position % 8)));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_set_bits(uint8_t* data, size_t position, uint8_t byte, uint8_t length) {
|
||||
furi_check(length <= 8);
|
||||
furi_check(length > 0);
|
||||
|
||||
for(uint8_t i = 0; i < length; ++i) {
|
||||
uint8_t shift = (length - 1) - i;
|
||||
bit_lib_set_bit(data, position + i, (byte >> shift) & 1); //-V610
|
||||
}
|
||||
}
|
||||
|
||||
bool bit_lib_get_bit(const uint8_t* data, size_t position) {
|
||||
return (data[position / 8] >> (7 - (position % 8))) & 1;
|
||||
}
|
||||
|
||||
uint8_t bit_lib_get_bits(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint8_t shift = position % 8;
|
||||
if(shift == 0) {
|
||||
return data[position / 8] >> (8 - length);
|
||||
} else {
|
||||
// TODO fix read out of bounds
|
||||
uint8_t value = (data[position / 8] << (shift));
|
||||
value |= data[position / 8 + 1] >> (8 - shift);
|
||||
value = value >> (8 - length);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t bit_lib_get_bits_16(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint16_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint32_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else if(length <= 16) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
} else if(length <= 24) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= bit_lib_get_bits(data, position + 16, length - 16);
|
||||
} else {
|
||||
value = (uint32_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint32_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint32_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= bit_lib_get_bits(data, position + 24, length - 24);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t bit_lib_get_bits_64(const uint8_t* data, size_t position, uint8_t length) {
|
||||
uint64_t value = 0;
|
||||
if(length <= 8) {
|
||||
value = bit_lib_get_bits(data, position, length);
|
||||
} else if(length <= 16) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, length - 8);
|
||||
} else if(length <= 24) {
|
||||
value = bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= bit_lib_get_bits(data, position + 16, length - 16);
|
||||
} else if(length <= 32) {
|
||||
value = (uint64_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= bit_lib_get_bits(data, position + 24, length - 24);
|
||||
} else {
|
||||
value = (uint64_t)bit_lib_get_bits(data, position, 8) << (length - 8);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 24, 8) << (length - 32);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 32, 8) << (length - 40);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 40, 8) << (length - 48);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 48, 8) << (length - 56);
|
||||
value |= (uint64_t)bit_lib_get_bits(data, position + 56, 8) << (length - 64);
|
||||
value |= bit_lib_get_bits(data, position + 64, length - 64);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool bit_lib_test_parity_32(uint32_t bits, BitLibParity parity) {
|
||||
#if !defined __GNUC__
|
||||
#error Please, implement parity test for non-GCC compilers
|
||||
#else
|
||||
switch(parity) {
|
||||
case BitLibParityEven:
|
||||
return __builtin_parity(bits);
|
||||
case BitLibParityOdd:
|
||||
return !__builtin_parity(bits);
|
||||
default:
|
||||
furi_crash("Unknown parity");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bit_lib_test_parity(
|
||||
const uint8_t* bits,
|
||||
size_t position,
|
||||
uint8_t length,
|
||||
BitLibParity parity,
|
||||
uint8_t parity_length) {
|
||||
uint32_t parity_block;
|
||||
bool result = true;
|
||||
const size_t parity_blocks_count = length / parity_length;
|
||||
|
||||
for(size_t i = 0; i < parity_blocks_count; ++i) {
|
||||
switch(parity) {
|
||||
case BitLibParityEven:
|
||||
case BitLibParityOdd:
|
||||
parity_block = bit_lib_get_bits_32(bits, position + i * parity_length, parity_length);
|
||||
if(!bit_lib_test_parity_32(parity_block, parity)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
case BitLibParityAlways0:
|
||||
if(bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
case BitLibParityAlways1:
|
||||
if(!bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
|
||||
result = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!result) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t bit_lib_add_parity(
|
||||
const uint8_t* data,
|
||||
size_t position,
|
||||
uint8_t* dest,
|
||||
size_t dest_position,
|
||||
uint8_t source_length,
|
||||
uint8_t parity_length,
|
||||
BitLibParity parity) {
|
||||
uint32_t parity_word = 0;
|
||||
size_t j = 0, bit_count = 0;
|
||||
for(int word = 0; word < source_length; word += parity_length - 1) {
|
||||
for(int bit = 0; bit < parity_length - 1; bit++) {
|
||||
parity_word = (parity_word << 1) | bit_lib_get_bit(data, position + word + bit);
|
||||
bit_lib_set_bit(
|
||||
dest, dest_position + j++, bit_lib_get_bit(data, position + word + bit));
|
||||
}
|
||||
// if parity fails then return 0
|
||||
switch(parity) {
|
||||
case BitLibParityAlways0:
|
||||
bit_lib_set_bit(dest, dest_position + j++, 0);
|
||||
break; // marker bit which should be a 0
|
||||
case BitLibParityAlways1:
|
||||
bit_lib_set_bit(dest, dest_position + j++, 1);
|
||||
break; // marker bit which should be a 1
|
||||
default:
|
||||
bit_lib_set_bit(
|
||||
dest,
|
||||
dest_position + j++,
|
||||
(bit_lib_test_parity_32(parity_word, BitLibParityOdd) ^ parity) ^ 1);
|
||||
break;
|
||||
}
|
||||
bit_count += parity_length;
|
||||
parity_word = 0;
|
||||
}
|
||||
// if we got here then all the parities passed
|
||||
// return bit count
|
||||
return bit_count;
|
||||
}
|
||||
|
||||
size_t bit_lib_remove_bit_every_nth(uint8_t* data, size_t position, uint8_t length, uint8_t n) {
|
||||
size_t counter = 0;
|
||||
size_t result_counter = 0;
|
||||
uint8_t bit_buffer = 0;
|
||||
uint8_t bit_counter = 0;
|
||||
|
||||
while(counter < length) {
|
||||
if((counter + 1) % n != 0) {
|
||||
bit_buffer = (bit_buffer << 1) | bit_lib_get_bit(data, position + counter);
|
||||
bit_counter++;
|
||||
}
|
||||
|
||||
if(bit_counter == 8) {
|
||||
bit_lib_set_bits(data, position + result_counter, bit_buffer, 8);
|
||||
bit_counter = 0;
|
||||
bit_buffer = 0;
|
||||
result_counter += 8;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
if(bit_counter != 0) {
|
||||
bit_lib_set_bits(data, position + result_counter, bit_buffer, bit_counter);
|
||||
result_counter += bit_counter;
|
||||
}
|
||||
return result_counter;
|
||||
}
|
||||
|
||||
void bit_lib_copy_bits(
|
||||
uint8_t* data,
|
||||
size_t position,
|
||||
size_t length,
|
||||
const uint8_t* source,
|
||||
size_t source_position) {
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
bit_lib_set_bit(data, position + i, bit_lib_get_bit(source, source_position + i));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_reverse_bits(uint8_t* data, size_t position, uint8_t length) {
|
||||
size_t i = 0;
|
||||
size_t j = length - 1;
|
||||
|
||||
while(i < j) {
|
||||
bool tmp = bit_lib_get_bit(data, position + i);
|
||||
bit_lib_set_bit(data, position + i, bit_lib_get_bit(data, position + j));
|
||||
bit_lib_set_bit(data, position + j, tmp);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t bit_lib_get_bit_count(uint32_t data) {
|
||||
#if defined __GNUC__
|
||||
return __builtin_popcountl(data);
|
||||
#else
|
||||
#error Please, implement popcount for non-GCC compilers
|
||||
#endif
|
||||
}
|
||||
|
||||
void bit_lib_print_bits(const uint8_t* data, size_t length) {
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
printf("%u", bit_lib_get_bit(data, i));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_lib_print_regions(
|
||||
const BitLibRegion* regions,
|
||||
size_t region_count,
|
||||
const uint8_t* data,
|
||||
size_t length) {
|
||||
// print data
|
||||
bit_lib_print_bits(data, length);
|
||||
printf("\r\n");
|
||||
|
||||
// print regions
|
||||
for(size_t c = 0; c < length; ++c) {
|
||||
bool print = false;
|
||||
|
||||
for(size_t i = 0; i < region_count; i++) {
|
||||
if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
|
||||
print = true;
|
||||
printf("%c", regions[i].mark);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!print) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
// print regions data
|
||||
for(size_t c = 0; c < length; ++c) {
|
||||
bool print = false;
|
||||
|
||||
for(size_t i = 0; i < region_count; i++) {
|
||||
if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
|
||||
print = true;
|
||||
printf("%u", bit_lib_get_bit(data, c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!print) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
uint16_t bit_lib_reverse_16_fast(uint16_t data) {
|
||||
uint16_t result = 0;
|
||||
result |= (data & 0x8000) >> 15;
|
||||
result |= (data & 0x4000) >> 13;
|
||||
result |= (data & 0x2000) >> 11;
|
||||
result |= (data & 0x1000) >> 9;
|
||||
result |= (data & 0x0800) >> 7;
|
||||
result |= (data & 0x0400) >> 5;
|
||||
result |= (data & 0x0200) >> 3;
|
||||
result |= (data & 0x0100) >> 1;
|
||||
result |= (data & 0x0080) << 1;
|
||||
result |= (data & 0x0040) << 3;
|
||||
result |= (data & 0x0020) << 5;
|
||||
result |= (data & 0x0010) << 7;
|
||||
result |= (data & 0x0008) << 9;
|
||||
result |= (data & 0x0004) << 11;
|
||||
result |= (data & 0x0002) << 13;
|
||||
result |= (data & 0x0001) << 15;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t bit_lib_reverse_8_fast(uint8_t byte) {
|
||||
byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4;
|
||||
byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2;
|
||||
byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1;
|
||||
return byte;
|
||||
}
|
||||
|
||||
uint16_t bit_lib_crc8(
|
||||
uint8_t const* data,
|
||||
size_t data_size,
|
||||
uint8_t polynom,
|
||||
uint8_t init,
|
||||
bool ref_in,
|
||||
bool ref_out,
|
||||
uint8_t xor_out) {
|
||||
uint8_t crc = init;
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
uint8_t byte = data[i];
|
||||
if(ref_in) bit_lib_reverse_bits(&byte, 0, 8);
|
||||
crc ^= byte;
|
||||
|
||||
for(size_t j = 8; j > 0; --j) {
|
||||
if(crc & TOPBIT(8)) {
|
||||
crc = (crc << 1) ^ polynom;
|
||||
} else {
|
||||
crc = (crc << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ref_out) bit_lib_reverse_bits(&crc, 0, 8);
|
||||
crc ^= xor_out;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t bit_lib_crc16(
|
||||
uint8_t const* data,
|
||||
size_t data_size,
|
||||
uint16_t polynom,
|
||||
uint16_t init,
|
||||
bool ref_in,
|
||||
bool ref_out,
|
||||
uint16_t xor_out) {
|
||||
uint16_t crc = init;
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
uint8_t byte = data[i];
|
||||
if(ref_in) byte = bit_lib_reverse_16_fast(byte) >> 8;
|
||||
|
||||
for(size_t j = 0; j < 8; ++j) {
|
||||
bool c15 = (crc >> 15 & 1);
|
||||
bool bit = (byte >> (7 - j) & 1);
|
||||
crc <<= 1;
|
||||
if(c15 ^ bit) crc ^= polynom;
|
||||
}
|
||||
}
|
||||
|
||||
if(ref_out) crc = bit_lib_reverse_16_fast(crc);
|
||||
crc ^= xor_out;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
|
||||
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
|
||||
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
|
||||
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
|
||||
#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \
|
||||
((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
|
||||
|
||||
void timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) {
|
||||
uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
|
||||
datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR;
|
||||
|
||||
while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) {
|
||||
days -= furi_hal_rtc_get_days_per_year(datetime->year);
|
||||
(datetime->year)++;
|
||||
}
|
||||
|
||||
datetime->month = 1;
|
||||
while(days >= furi_hal_rtc_get_days_per_month(
|
||||
FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year), datetime->month)) {
|
||||
days -= furi_hal_rtc_get_days_per_month(
|
||||
FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year), datetime->month);
|
||||
(datetime->month)++;
|
||||
}
|
||||
|
||||
datetime->day = days + 1;
|
||||
datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR;
|
||||
datetime->minute =
|
||||
(seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
||||
uint32_t timestamp = days * 24 * 60 * 60;
|
||||
FuriHalRtcDateTime start_datetime = {0};
|
||||
@@ -514,7 +69,7 @@ void from_days_to_datetime(uint16_t days, FuriHalRtcDateTime* datetime, uint16_t
|
||||
start_datetime.month = 12;
|
||||
start_datetime.day = 31;
|
||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
||||
timestamp_to_datetime(timestamp, datetime);
|
||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
||||
}
|
||||
|
||||
void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, uint16_t start_year) {
|
||||
@@ -524,7 +79,7 @@ void from_minutes_to_datetime(uint32_t minutes, FuriHalRtcDateTime* datetime, ui
|
||||
start_datetime.month = 12;
|
||||
start_datetime.day = 31;
|
||||
timestamp += furi_hal_rtc_datetime_to_timestamp(&start_datetime);
|
||||
timestamp_to_datetime(timestamp, datetime);
|
||||
furi_hal_rtc_timestamp_to_datetime(timestamp, datetime);
|
||||
}
|
||||
|
||||
bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
@@ -620,7 +175,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_start_trip_date) * 24 * 60 + card_start_trip_time,
|
||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||
&card_start_trip_minutes_s,
|
||||
1992);
|
||||
furi_string_printf(
|
||||
@@ -697,7 +252,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_start_trip_date) * 24 * 60 + card_start_trip_time,
|
||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||
&card_start_trip_minutes_s,
|
||||
1992);
|
||||
furi_string_printf(
|
||||
@@ -871,7 +426,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_start_trip_date) * 24 * 60 + card_start_trip_time,
|
||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||
&card_start_trip_minutes_s,
|
||||
1992);
|
||||
furi_string_printf(
|
||||
@@ -952,7 +507,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
from_days_to_datetime(card_use_before_date, &card_use_before_date_s, 1992);
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_start_trip_date) * 24 * 60 + card_start_trip_time,
|
||||
(card_start_trip_date)*24 * 60 + card_start_trip_time,
|
||||
&card_start_trip_minutes_s,
|
||||
1992);
|
||||
furi_string_printf(
|
||||
@@ -1092,7 +647,7 @@ bool parse_transport_block(const MfClassicBlock* block, FuriString* result) {
|
||||
|
||||
FuriHalRtcDateTime card_start_trip_minutes_s = {0};
|
||||
from_minutes_to_datetime(
|
||||
(card_valid_to_date) * 24 * 60 + card_valid_for_minutes - card_start_trip_neg_minutes,
|
||||
(card_valid_to_date)*24 * 60 + card_valid_for_minutes - card_start_trip_neg_minutes,
|
||||
&card_start_trip_minutes_s,
|
||||
2016); //-time
|
||||
furi_string_printf(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#define TAG "TwoCities"
|
||||
|
||||
@@ -23,16 +23,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/core_defines.h"
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Umarsh"
|
||||
|
||||
@@ -19,14 +19,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <bit_lib/bit_lib.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <bit_lib.h>
|
||||
|
||||
#define TAG "WashCity"
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -18,15 +18,13 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "furi_hal_rtc.h"
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Zolotaya Korona"
|
||||
|
||||
@@ -40,26 +38,6 @@ static const uint8_t info_sector_signature[] = {0xE2, 0x87, 0x80, 0x8E, 0x20, 0x
|
||||
0xAE, 0xE0, 0xAE, 0xAD, 0xA0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint64_t bytes2num_bcd(const uint8_t* src, uint8_t len_bytes, bool* is_bcd) {
|
||||
furi_assert(src);
|
||||
furi_assert(len_bytes <= 9);
|
||||
|
||||
uint64_t result = 0;
|
||||
*is_bcd = true;
|
||||
|
||||
for(uint8_t i = 0; i < len_bytes; i++) {
|
||||
if(((src[i] / 16) > 9) || ((src[i] % 16) > 9)) *is_bcd = false;
|
||||
|
||||
result *= 10;
|
||||
result += src[i] / 16;
|
||||
|
||||
result *= 10;
|
||||
result += src[i] % 16;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_data) {
|
||||
furi_assert(device);
|
||||
|
||||
@@ -90,12 +68,14 @@ static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_da
|
||||
|
||||
// INFO SECTOR
|
||||
// block 1
|
||||
const uint8_t region_number = bytes2num_bcd(block_start_ptr + 10, 1, &verified);
|
||||
const uint8_t region_number = bit_lib_bytes_to_num_bcd(block_start_ptr + 10, 1, &verified);
|
||||
|
||||
// block 2
|
||||
block_start_ptr = &data->block[start_info_block_number + 2].data[4];
|
||||
const uint16_t card_number_prefix = bytes2num_bcd(block_start_ptr, 2, &verified);
|
||||
const uint64_t card_number_postfix = bytes2num_bcd(block_start_ptr + 2, 8, &verified) / 10;
|
||||
const uint16_t card_number_prefix =
|
||||
bit_lib_bytes_to_num_bcd(block_start_ptr, 2, &verified);
|
||||
const uint64_t card_number_postfix =
|
||||
bit_lib_bytes_to_num_bcd(block_start_ptr + 2, 8, &verified) / 10;
|
||||
|
||||
// TRIP SECTOR
|
||||
const uint8_t start_trip_block_number =
|
||||
@@ -104,33 +84,29 @@ static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_da
|
||||
block_start_ptr = &data->block[start_trip_block_number].data[7];
|
||||
|
||||
const uint8_t status = block_start_ptr[0] % 16;
|
||||
const uint16_t sequence_number = nfc_util_bytes2num(block_start_ptr + 1, 2);
|
||||
const uint8_t discount_code = nfc_util_bytes2num(block_start_ptr + 3, 1);
|
||||
const uint16_t sequence_number = bit_lib_bytes_to_num_be(block_start_ptr + 1, 2);
|
||||
const uint8_t discount_code = bit_lib_bytes_to_num_be(block_start_ptr + 3, 1);
|
||||
|
||||
// block 1: refill block
|
||||
block_start_ptr = &data->block[start_trip_block_number + 1].data[1];
|
||||
|
||||
const uint16_t refill_machine_id = nfc_util_bytes2num_little_endian(block_start_ptr, 2);
|
||||
const uint32_t last_refill_timestamp =
|
||||
nfc_util_bytes2num_little_endian(block_start_ptr + 2, 4);
|
||||
const uint32_t last_refill_amount =
|
||||
nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4);
|
||||
const uint16_t refill_machine_id = bit_lib_bytes_to_num_le(block_start_ptr, 2);
|
||||
const uint32_t last_refill_timestamp = bit_lib_bytes_to_num_le(block_start_ptr + 2, 4);
|
||||
const uint32_t last_refill_amount = bit_lib_bytes_to_num_le(block_start_ptr + 6, 4);
|
||||
const uint32_t last_refill_amount_rub = last_refill_amount / 100;
|
||||
const uint8_t last_refill_amount_kop = last_refill_amount % 100;
|
||||
const uint16_t refill_counter = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 2);
|
||||
const uint16_t refill_counter = bit_lib_bytes_to_num_le(block_start_ptr + 10, 2);
|
||||
|
||||
FuriHalRtcDateTime last_refill_datetime = {0};
|
||||
furi_hal_rtc_timestamp_to_datetime(last_refill_timestamp, &last_refill_datetime);
|
||||
|
||||
// block 2: trip block
|
||||
block_start_ptr = &data->block[start_trip_block_number + 2].data[0];
|
||||
const char validator_first_letter =
|
||||
nfc_util_bytes2num_little_endian(block_start_ptr + 1, 1);
|
||||
const uint32_t validator_id = bytes2num_bcd(block_start_ptr + 2, 3, &verified);
|
||||
const uint32_t last_trip_timestamp =
|
||||
nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4);
|
||||
const uint8_t track_number = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 1);
|
||||
const uint32_t prev_balance = nfc_util_bytes2num_little_endian(block_start_ptr + 11, 4);
|
||||
const char validator_first_letter = bit_lib_bytes_to_num_le(block_start_ptr + 1, 1);
|
||||
const uint32_t validator_id = bit_lib_bytes_to_num_bcd(block_start_ptr + 2, 3, &verified);
|
||||
const uint32_t last_trip_timestamp = bit_lib_bytes_to_num_le(block_start_ptr + 6, 4);
|
||||
const uint8_t track_number = bit_lib_bytes_to_num_le(block_start_ptr + 10, 1);
|
||||
const uint32_t prev_balance = bit_lib_bytes_to_num_le(block_start_ptr + 11, 4);
|
||||
const uint32_t prev_balance_rub = prev_balance / 100;
|
||||
const uint8_t prev_balance_kop = prev_balance % 100;
|
||||
|
||||
@@ -143,7 +119,7 @@ static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_da
|
||||
block_start_ptr = &data->block[start_purse_block_number].data[0];
|
||||
|
||||
// block 0
|
||||
const uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4);
|
||||
const uint32_t balance = bit_lib_bytes_to_num_le(block_start_ptr, 4);
|
||||
|
||||
uint32_t balance_rub = balance / 100;
|
||||
uint8_t balance_kop = balance % 100;
|
||||
|
||||
@@ -17,41 +17,19 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "furi_hal_rtc.h"
|
||||
#include "nfc_supported_card_plugin.h"
|
||||
#include <flipper_application.h>
|
||||
|
||||
#include "protocols/mf_classic/mf_classic.h"
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <bit_lib.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "Zolotaya Korona Online"
|
||||
|
||||
#define TRIP_SECTOR_NUM (4)
|
||||
#define INFO_SECTOR_NUM (15)
|
||||
|
||||
uint64_t bytes2num_bcd(const uint8_t* src, uint8_t len_bytes, bool* is_bcd) {
|
||||
furi_assert(src);
|
||||
furi_assert(len_bytes <= 9);
|
||||
|
||||
uint64_t result = 0;
|
||||
*is_bcd = true;
|
||||
|
||||
for(uint8_t i = 0; i < len_bytes; i++) {
|
||||
if(((src[i] / 16) > 9) || ((src[i] % 16) > 9)) *is_bcd = false;
|
||||
|
||||
result *= 10;
|
||||
result += src[i] / 16;
|
||||
|
||||
result *= 10;
|
||||
result += src[i] % 16;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool parse_online_card_tariff(uint16_t tariff_num, FuriString* tariff_name) {
|
||||
bool tariff_parsed = false;
|
||||
|
||||
@@ -111,21 +89,22 @@ static bool zolotaya_korona_online_parse(const NfcDevice* device, FuriString* pa
|
||||
|
||||
// Validate card number
|
||||
bool is_bcd;
|
||||
const uint16_t card_number_prefix = bytes2num_bcd(block_start_ptr, 2, &is_bcd);
|
||||
const uint16_t card_number_prefix = bit_lib_bytes_to_num_bcd(block_start_ptr, 2, &is_bcd);
|
||||
if(!is_bcd) break;
|
||||
if(card_number_prefix != 9643) break;
|
||||
const uint64_t card_number_postfix = bytes2num_bcd(block_start_ptr + 2, 8, &is_bcd) / 10;
|
||||
const uint64_t card_number_postfix =
|
||||
bit_lib_bytes_to_num_bcd(block_start_ptr + 2, 8, &is_bcd) / 10;
|
||||
if(!is_bcd) break;
|
||||
|
||||
// Parse data
|
||||
FuriString* tariff_name = furi_string_alloc();
|
||||
|
||||
block_start_ptr = &data->block[start_info_block_number].data[1];
|
||||
const uint16_t tariff = nfc_util_bytes2num(block_start_ptr, 2);
|
||||
const uint16_t tariff = bit_lib_bytes_to_num_be(block_start_ptr, 2);
|
||||
parse_online_card_tariff(tariff, tariff_name);
|
||||
|
||||
block_start_ptr = &data->block[start_trip_block_number].data[0];
|
||||
const uint8_t region_number = nfc_util_bytes2num(block_start_ptr, 1);
|
||||
const uint8_t region_number = bit_lib_bytes_to_num_be(block_start_ptr, 1);
|
||||
|
||||
furi_string_cat_printf(
|
||||
parsed_data,
|
||||
|
||||
@@ -605,8 +605,7 @@ static void lfrfid_worker_mode_write_and_set_pass_process(LFRFIDWorker* worker)
|
||||
FURI_LOG_D(TAG, "Data write with pass");
|
||||
|
||||
LfRfid* app = worker->cb_ctx;
|
||||
uint32_t pass = (app->password[0] << 24) | (app->password[1] << 16) |
|
||||
(app->password[2] << 8) | (app->password[3]);
|
||||
uint32_t pass = bit_lib_bytes_to_num_be(app->password, 4);
|
||||
|
||||
request->t5577.mask = 0b10000001;
|
||||
for(uint8_t i = 0; i < request->t5577.blocks_to_write; i++)
|
||||
|
||||
Reference in New Issue
Block a user