Merge remote-tracking branch 'upstream/dev' into emv-fixes

This commit is contained in:
Methodius 2024-02-15 00:37:24 +09:00
commit 8dd59a5d9e
No known key found for this signature in database
GPG key ID: 122FA99A00B41679
76 changed files with 823 additions and 1274 deletions

View file

@ -6,15 +6,9 @@
"cortex-debug.enableTelemetry": false,
"cortex-debug.variableUseNaturalFormat": true,
"cortex-debug.showRTOS": true,
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin",
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/openocd/bin/openocd.exe",
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
"editor.formatOnSave": true,
"files.associations": {
"*.scons": "python",

View file

@ -1,6 +1,6 @@
#include <furi.h>
#include "../minunit.h"
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
MU_TEST(test_bit_lib_increment_index) {
uint32_t index = 0;
@ -218,6 +218,178 @@ MU_TEST(test_bit_lib_get_bits_32) {
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_32(value, 0, 32));
}
MU_TEST(test_bit_lib_get_bits_64) {
uint8_t value[8] = {
0b00001001,
0b10110001,
0b10001100,
0b01100010,
0b00001001,
0b10110001,
0b10001100,
0b01100010};
mu_assert_int_eq(0b0, bit_lib_get_bits_64(value, 0, 1));
mu_assert_int_eq(0b00, bit_lib_get_bits_64(value, 0, 2));
mu_assert_int_eq(0b000, bit_lib_get_bits_64(value, 0, 3));
mu_assert_int_eq(0b0000, bit_lib_get_bits_64(value, 0, 4));
mu_assert_int_eq(0b00001, bit_lib_get_bits_64(value, 0, 5));
mu_assert_int_eq(0b000010, bit_lib_get_bits_64(value, 0, 6));
mu_assert_int_eq(0b0000100, bit_lib_get_bits_64(value, 0, 7));
mu_assert_int_eq(0b00001001, bit_lib_get_bits_64(value, 0, 8));
mu_assert_int_eq(0b000010011, bit_lib_get_bits_64(value, 0, 9));
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_64(value, 0, 10));
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_64(value, 0, 11));
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_64(value, 0, 12));
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_64(value, 0, 13));
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_64(value, 0, 14));
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_64(value, 0, 15));
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_64(value, 0, 16));
mu_assert_int_eq(0b00001001101100011, bit_lib_get_bits_64(value, 0, 17));
mu_assert_int_eq(0b000010011011000110, bit_lib_get_bits_64(value, 0, 18));
mu_assert_int_eq(0b0000100110110001100, bit_lib_get_bits_64(value, 0, 19));
mu_assert_int_eq(0b00001001101100011000, bit_lib_get_bits_64(value, 0, 20));
mu_assert_int_eq(0b000010011011000110001, bit_lib_get_bits_64(value, 0, 21));
mu_assert_int_eq(0b0000100110110001100011, bit_lib_get_bits_64(value, 0, 22));
mu_assert_int_eq(0b00001001101100011000110, bit_lib_get_bits_64(value, 0, 23));
mu_assert_int_eq(0b000010011011000110001100, bit_lib_get_bits_64(value, 0, 24));
mu_assert_int_eq(0b0000100110110001100011000, bit_lib_get_bits_64(value, 0, 25));
mu_assert_int_eq(0b00001001101100011000110001, bit_lib_get_bits_64(value, 0, 26));
mu_assert_int_eq(0b000010011011000110001100011, bit_lib_get_bits_64(value, 0, 27));
mu_assert_int_eq(0b0000100110110001100011000110, bit_lib_get_bits_64(value, 0, 28));
mu_assert_int_eq(0b00001001101100011000110001100, bit_lib_get_bits_64(value, 0, 29));
mu_assert_int_eq(0b000010011011000110001100011000, bit_lib_get_bits_64(value, 0, 30));
mu_assert_int_eq(0b0000100110110001100011000110001, bit_lib_get_bits_64(value, 0, 31));
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_64(value, 0, 32));
uint64_t res = bit_lib_get_bits_64(value, 0, 33);
uint64_t expected = 0b000010011011000110001100011000100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 34);
expected = 0b0000100110110001100011000110001000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 35);
expected = 0b00001001101100011000110001100010000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 36);
expected = 0b000010011011000110001100011000100000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 37);
expected = 0b0000100110110001100011000110001000001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 38);
expected = 0b00001001101100011000110001100010000010;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 39);
expected = 0b000010011011000110001100011000100000100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 40);
expected = 0b0000100110110001100011000110001000001001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 41);
expected = 0b00001001101100011000110001100010000010011;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 42);
expected = 0b000010011011000110001100011000100000100110;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 43);
expected = 0b0000100110110001100011000110001000001001101;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 44);
expected = 0b00001001101100011000110001100010000010011011;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 45);
expected = 0b000010011011000110001100011000100000100110110;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 46);
expected = 0b0000100110110001100011000110001000001001101100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 47);
expected = 0b00001001101100011000110001100010000010011011000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 48);
expected = 0b000010011011000110001100011000100000100110110001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 49);
expected = 0b0000100110110001100011000110001000001001101100011;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 50);
expected = 0b00001001101100011000110001100010000010011011000110;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 51);
expected = 0b000010011011000110001100011000100000100110110001100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 52);
expected = 0b0000100110110001100011000110001000001001101100011000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 53);
expected = 0b00001001101100011000110001100010000010011011000110001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 54);
expected = 0b000010011011000110001100011000100000100110110001100011;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 55);
expected = 0b0000100110110001100011000110001000001001101100011000110;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 56);
expected = 0b00001001101100011000110001100010000010011011000110001100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 57);
expected = 0b000010011011000110001100011000100000100110110001100011000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 58);
expected = 0b0000100110110001100011000110001000001001101100011000110001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 59);
expected = 0b00001001101100011000110001100010000010011011000110001100011;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 60);
expected = 0b000010011011000110001100011000100000100110110001100011000110;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 61);
expected = 0b0000100110110001100011000110001000001001101100011000110001100;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 62);
expected = 0b00001001101100011000110001100010000010011011000110001100011000;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 63);
expected = 0b000010011011000110001100011000100000100110110001100011000110001;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
res = bit_lib_get_bits_64(value, 0, 64);
expected = 0b0000100110110001100011000110001000001001101100011000110001100010;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
}
MU_TEST(test_bit_lib_test_parity_u32) {
// test even parity
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityEven), 0);
@ -447,6 +619,95 @@ MU_TEST(test_bit_lib_crc16) {
mu_assert_int_eq(0x31C3, bit_lib_crc16(data, data_size, 0x1021, 0x0000, false, false, 0x0000));
}
MU_TEST(test_bit_lib_num_to_bytes_be) {
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
uint8_t dest[8];
bit_lib_num_to_bytes_be(0x01, 1, dest);
mu_assert_mem_eq(src, dest, sizeof(src[0]));
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 4, dest);
mu_assert_mem_eq(src + 4, dest, 4 * sizeof(src[0]));
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 8, dest);
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
bit_lib_num_to_bytes_be(bit_lib_bytes_to_num_be(src, 8), 8, dest);
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
}
MU_TEST(test_bit_lib_num_to_bytes_le) {
uint8_t dest[8];
uint8_t n2b_le_expected_1[] = {0x01};
bit_lib_num_to_bytes_le(0x01, 1, dest);
mu_assert_mem_eq(n2b_le_expected_1, dest, sizeof(n2b_le_expected_1[0]));
uint8_t n2b_le_expected_2[] = {0xEF, 0xCD, 0xAB, 0x89};
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 4, dest);
mu_assert_mem_eq(n2b_le_expected_2, dest, 4 * sizeof(n2b_le_expected_2[0]));
uint8_t n2b_le_expected_3[] = {0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01};
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 8, dest);
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
bit_lib_num_to_bytes_le(bit_lib_bytes_to_num_le(n2b_le_expected_3, 8), 8, dest);
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
}
MU_TEST(test_bit_lib_bytes_to_num_be) {
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
uint64_t res;
res = bit_lib_bytes_to_num_be(src, 1);
mu_assert_int_eq(0x01, res);
res = bit_lib_bytes_to_num_be(src, 4);
mu_assert_int_eq(0x01234567, res);
res = bit_lib_bytes_to_num_be(src, 8);
uint64_t expected = 0x0123456789ABCDEF;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
}
MU_TEST(test_bit_lib_bytes_to_num_le) {
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
uint64_t res;
res = bit_lib_bytes_to_num_le(src, 1);
mu_assert_int_eq(0x01, res);
res = bit_lib_bytes_to_num_le(src, 4);
mu_assert_int_eq(0x67452301, res);
res = bit_lib_bytes_to_num_le(src, 8);
uint64_t expected = 0xEFCDAB8967452301;
mu_assert_mem_eq(&expected, &res, sizeof(expected));
}
MU_TEST(test_bit_lib_bytes_to_num_bcd) {
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
uint64_t res;
bool is_bcd_res;
res = bit_lib_bytes_to_num_bcd(src, 1, &is_bcd_res);
mu_assert_int_eq(01, res);
mu_assert_int_eq(true, is_bcd_res);
res = bit_lib_bytes_to_num_bcd(src, 4, &is_bcd_res);
mu_assert_int_eq(1234567, res);
mu_assert_int_eq(true, is_bcd_res);
uint8_t digits[5] = {0x98, 0x76, 0x54, 0x32, 0x10};
uint64_t expected = 9876543210;
res = bit_lib_bytes_to_num_bcd(digits, 5, &is_bcd_res);
mu_assert_mem_eq(&expected, &res, sizeof(expected));
mu_assert_int_eq(true, is_bcd_res);
res = bit_lib_bytes_to_num_bcd(src, 8, &is_bcd_res);
mu_assert_int_eq(false, is_bcd_res);
}
MU_TEST_SUITE(test_bit_lib) {
MU_RUN_TEST(test_bit_lib_increment_index);
MU_RUN_TEST(test_bit_lib_is_set);
@ -457,6 +718,7 @@ MU_TEST_SUITE(test_bit_lib) {
MU_RUN_TEST(test_bit_lib_get_bits);
MU_RUN_TEST(test_bit_lib_get_bits_16);
MU_RUN_TEST(test_bit_lib_get_bits_32);
MU_RUN_TEST(test_bit_lib_get_bits_64);
MU_RUN_TEST(test_bit_lib_test_parity_u32);
MU_RUN_TEST(test_bit_lib_test_parity);
MU_RUN_TEST(test_bit_lib_remove_bit_every_nth);
@ -465,6 +727,11 @@ MU_TEST_SUITE(test_bit_lib) {
MU_RUN_TEST(test_bit_lib_get_bit_count);
MU_RUN_TEST(test_bit_lib_reverse_16_fast);
MU_RUN_TEST(test_bit_lib_crc16);
MU_RUN_TEST(test_bit_lib_num_to_bytes_be);
MU_RUN_TEST(test_bit_lib_num_to_bytes_le);
MU_RUN_TEST(test_bit_lib_bytes_to_num_be);
MU_RUN_TEST(test_bit_lib_bytes_to_num_le);
MU_RUN_TEST(test_bit_lib_bytes_to_num_bcd);
}
int run_minunit_test_bit_lib() {

View file

@ -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);

View file

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

View file

@ -2,7 +2,7 @@
#include <m-array.h>
#include <nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
#include <stream/stream.h>
#include <stream/buffered_file_stream.h>
@ -63,9 +63,9 @@ static bool mfkey32_logger_add_nonce_to_existing_params(
if(params->sector_num != sector_num) continue;
if(params->key_type != auth_context->key_type) continue;
params->nt1 = nfc_util_bytes2num(auth_context->nt.data, sizeof(MfClassicNt));
params->nr1 = nfc_util_bytes2num(auth_context->nr.data, sizeof(MfClassicNr));
params->ar1 = nfc_util_bytes2num(auth_context->ar.data, sizeof(MfClassicAr));
params->nt1 = bit_lib_bytes_to_num_be(auth_context->nt.data, sizeof(MfClassicNt));
params->nr1 = bit_lib_bytes_to_num_be(auth_context->nr.data, sizeof(MfClassicNr));
params->ar1 = bit_lib_bytes_to_num_be(auth_context->ar.data, sizeof(MfClassicAr));
params->is_filled = true;
instance->params_collected++;
@ -90,9 +90,9 @@ void mfkey32_logger_add_nonce(Mfkey32Logger* instance, MfClassicAuthContext* aut
.cuid = instance->cuid,
.sector_num = sector_num,
.key_type = auth_context->key_type,
.nt0 = nfc_util_bytes2num(auth_context->nt.data, sizeof(MfClassicNt)),
.nr0 = nfc_util_bytes2num(auth_context->nr.data, sizeof(MfClassicNr)),
.ar0 = nfc_util_bytes2num(auth_context->ar.data, sizeof(MfClassicAr)),
.nt0 = bit_lib_bytes_to_num_be(auth_context->nt.data, sizeof(MfClassicNt)),
.nr0 = bit_lib_bytes_to_num_be(auth_context->nr.data, sizeof(MfClassicNr)),
.ar0 = bit_lib_bytes_to_num_be(auth_context->ar.data, sizeof(MfClassicAr)),
};
Mfkey32LoggerParams_push_back(instance->params_arr, params);
instance->nonces_saves++;

View file

@ -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 <nfc/helpers/nfc_util.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;
@ -19,7 +18,7 @@ bool aime_verify(Nfc* nfc) {
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);
MfClassicKey key = {};
nfc_util_num2bytes(aime_key, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(aime_key, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_ctx = {};
MfClassicError error =
@ -53,9 +52,9 @@ static bool aime_read(Nfc* nfc, NfcDevice* device) {
data->type = type;
MfClassicDeviceKeys keys = {};
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
nfc_util_num2bytes(aime_key, sizeof(MfClassicKey), keys.key_a[i].data);
bit_lib_num_to_bytes_be(aime_key, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(aime_key, sizeof(MfClassicKey), keys.key_b[i].data);
bit_lib_num_to_bytes_be(aime_key, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
@ -85,7 +84,7 @@ static bool aime_parse(const NfcDevice* device, FuriString* parsed_data) {
do {
// verify key
MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 0);
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
if(key != aime_key) break;
// Aime Magic is stored at block 1, starts from byte 0, len 4 bytes

View file

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

View file

@ -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 <lib/nfc/helpers/nfc_util.h>
#include <bit_lib.h>
#include <applications/services/locale/locale.h>
#include <furi_hal_rtc.h>
#include <inttypes.h>
@ -194,12 +195,12 @@ static bool dump_ride_event(const uint8_t* record, FuriString* parsed_data);
// Unmarshal a 32-bit integer, big endian, unsigned
static inline uint32_t get_u32be(const uint8_t* field) {
return nfc_util_bytes2num(field, 4);
return bit_lib_bytes_to_num_be(field, 4);
}
// Unmarshal a 16-bit integer, big endian, unsigned
static uint16_t get_u16be(const uint8_t* field) {
return nfc_util_bytes2num(field, 2);
return bit_lib_bytes_to_num_be(field, 2);
}
// Unmarshal a 16-bit integer, big endian, signed, two's-complement
@ -330,7 +331,7 @@ static bool decode_id_file(const uint8_t* ef8_data, ClipperCardInfo* info) {
// uk ?8?? Unknown, 8-bit byte
// card_id U32BE Card identifier
//
info->serial_number = nfc_util_bytes2num(&ef8_data[1], 4);
info->serial_number = bit_lib_bytes_to_num_be(&ef8_data[1], 4);
return true;
}

View file

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

View file

@ -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 <nfc/helpers/nfc_util.h>
#include <bit_lib.h>
static bool gallagher_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device);
@ -30,8 +29,9 @@ static bool gallagher_parse(const NfcDevice* device, FuriString* parsed_data) {
// Test 1: The first 8 bytes and the second 8 bytes should be bitwise inverses.
const uint8_t* credential_block_start_ptr =
&data->block[credential_sector_start_block_number].data[0];
uint64_t cardholder_credential = nfc_util_bytes2num(credential_block_start_ptr, 8);
uint64_t cardholder_credential_inverse = nfc_util_bytes2num(credential_block_start_ptr + 8, 8);
uint64_t cardholder_credential = bit_lib_bytes_to_num_be(credential_block_start_ptr, 8);
uint64_t cardholder_credential_inverse =
bit_lib_bytes_to_num_be(credential_block_start_ptr + 8, 8);
// Due to endianness, this is testing the bytes in the wrong order,
// but the result still should be correct.
if(cardholder_credential != ~cardholder_credential_inverse) {

View file

@ -1,9 +1,9 @@
#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 "HI!"
#define KEY_LENGTH 6
@ -91,7 +91,7 @@ static bool hi_verify_type(Nfc* nfc, MfClassicType type) {
FURI_LOG_D(TAG, "Verifying sector %lu", cfg.verify_sector);
MfClassicKey key = {0};
nfc_util_num2bytes(cfg.keys[cfg.verify_sector].b, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(cfg.keys[cfg.verify_sector].b, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_context;
MfClassicError error =
@ -139,16 +139,16 @@ static bool hi_read(Nfc* nfc, NfcDevice* device) {
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
if(cfg.keys[i].a == 0x000000000000 && cfg.keys[i].b == 0x000000000000) {
cfg.keys[i].a = nfc_util_bytes2num(keyA[i], KEY_LENGTH);
cfg.keys[i].b = nfc_util_bytes2num(keyB[i], KEY_LENGTH);
cfg.keys[i].a = bit_lib_bytes_to_num_be(keyA[i], KEY_LENGTH);
cfg.keys[i].b = bit_lib_bytes_to_num_be(keyB[i], KEY_LENGTH);
}
}
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);
}
@ -184,7 +184,7 @@ static bool hi_parse(const NfcDevice* device, FuriString* parsed_data) {
// Verify key
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, cfg.verify_sector);
uint64_t key = nfc_util_bytes2num(sec_tr->key_b.data, 6);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_b.data, 6);
if(key != cfg.keys[cfg.verify_sector].b) return false;
//Get UID

View file

@ -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 <nfc/helpers/nfc_util.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;
@ -19,7 +18,7 @@ bool hid_verify(Nfc* nfc) {
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);
MfClassicKey key = {};
nfc_util_num2bytes(hid_key, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(hid_key, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_ctx = {};
MfClassicError error =
@ -53,9 +52,9 @@ static bool hid_read(Nfc* nfc, NfcDevice* device) {
data->type = type;
MfClassicDeviceKeys keys = {};
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_a[i].data);
bit_lib_num_to_bytes_be(hid_key, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_b[i].data);
bit_lib_num_to_bytes_be(hid_key, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
@ -111,7 +110,7 @@ static bool hid_parse(const NfcDevice* device, FuriString* parsed_data) {
const uint8_t verify_sector = 1;
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, verify_sector);
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
if(key != hid_key) break;
// Currently doesn't support bit length > 63

View file

@ -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>

View file

@ -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);

View file

@ -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,

View file

@ -1,9 +1,9 @@
#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 "Microel"
#define KEY_LENGTH 6
@ -116,7 +116,8 @@ static bool microel_read(Nfc* nfc, NfcDevice* device) {
// Check key 0a to verify if it is a microel card
MfClassicKey key = {0};
nfc_util_num2bytes(nfc_util_bytes2num(keyA, KEY_LENGTH), COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(
bit_lib_bytes_to_num_be(keyA, KEY_LENGTH), COUNT_OF(key.data), key.data);
const uint8_t block_num = mf_classic_get_first_block_num_of_sector(0); // This is 0
MfClassicAuthContext auth_context;
error =
@ -128,17 +129,19 @@ static bool microel_read(Nfc* nfc, NfcDevice* device) {
// Save keys generated to stucture
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
if(microel_1k_keys[i].a == 0x000000000000) {
microel_1k_keys[i].a = nfc_util_bytes2num(keyA, KEY_LENGTH);
microel_1k_keys[i].a = bit_lib_bytes_to_num_be(keyA, KEY_LENGTH);
}
if(microel_1k_keys[i].b == 0x000000000000) {
microel_1k_keys[i].b = nfc_util_bytes2num(keyB, KEY_LENGTH);
microel_1k_keys[i].b = bit_lib_bytes_to_num_be(keyB, KEY_LENGTH);
}
}
MfClassicDeviceKeys keys = {};
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
nfc_util_num2bytes(microel_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
bit_lib_num_to_bytes_be(
microel_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(microel_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
bit_lib_num_to_bytes_be(
microel_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
@ -179,8 +182,8 @@ static bool microel_parse(const NfcDevice* device, FuriString* parsed_data) {
// Verify key
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, verify_sector);
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
uint64_t key_for_check_from_array = nfc_util_bytes2num(keyA, KEY_LENGTH);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
uint64_t key_for_check_from_array = bit_lib_bytes_to_num_be(keyA, KEY_LENGTH);
if(key != key_for_check_from_array) break;
//Get credit in block number 8

View file

@ -1,9 +1,9 @@
#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 "MiZIP"
#define KEY_LENGTH 6
@ -102,7 +102,7 @@ static bool mizip_verify_type(Nfc* nfc, MfClassicType type) {
FURI_LOG_D(TAG, "Verifying sector %lu", cfg.verify_sector);
MfClassicKey key = {0};
nfc_util_num2bytes(cfg.keys[cfg.verify_sector].b, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(cfg.keys[cfg.verify_sector].b, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_context;
MfClassicError error =
@ -152,16 +152,16 @@ static bool mizip_read(Nfc* nfc, NfcDevice* device) {
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
if(cfg.keys[i].a == 0x000000000000 && cfg.keys[i].b == 0x000000000000) {
cfg.keys[i].a = nfc_util_bytes2num(keyA[i], KEY_LENGTH);
cfg.keys[i].b = nfc_util_bytes2num(keyB[i], KEY_LENGTH);
cfg.keys[i].a = bit_lib_bytes_to_num_be(keyA[i], KEY_LENGTH);
cfg.keys[i].b = bit_lib_bytes_to_num_be(keyB[i], KEY_LENGTH);
}
}
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);
}
@ -197,7 +197,7 @@ static bool mizip_parse(const NfcDevice* device, FuriString* parsed_data) {
// Verify key
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, cfg.verify_sector);
uint64_t key = nfc_util_bytes2num(sec_tr->key_b.data, 6);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_b.data, 6);
if(key != cfg.keys[cfg.verify_sector].b) return false;
//Get UID

View file

@ -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>

View file

@ -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}};

View file

@ -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;

View file

@ -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;

View file

@ -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 <nfc/helpers/nfc_util.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
#include <bit_lib.h>
#define TAG "Plantain"
typedef struct {
@ -87,7 +86,7 @@ static bool plantain_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 =
@ -128,9 +127,9 @@ static bool plantain_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);
}
@ -166,7 +165,8 @@ static bool plantain_parse(const NfcDevice* device, FuriString* parsed_data) {
const MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, cfg.data_sector);
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 != cfg.keys[cfg.data_sector].a) break;
// Point to block 0 of sector 4, value 0

View file

@ -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);
}

View file

@ -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);

View file

@ -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 "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(
@ -1509,7 +1064,7 @@ static bool troika_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 =
@ -1552,9 +1107,9 @@ static bool troika_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(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);
}
@ -1590,7 +1145,8 @@ static bool troika_parse(const NfcDevice* device, FuriString* parsed_data) {
const MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(data, cfg.data_sector);
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 != cfg.keys[cfg.data_sector].a) break;
FuriString* metro_result = furi_string_alloc();

View file

@ -3,7 +3,7 @@
#include <flipper_application/flipper_application.h>
#include <nfc/nfc_device.h>
#include <nfc/helpers/nfc_util.h>
#include <bit_lib.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
#define TAG "TwoCities"
@ -45,7 +45,7 @@ bool two_cities_verify(Nfc* nfc) {
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);
MfClassicKey key = {};
nfc_util_num2bytes(two_cities_4k_keys[verify_sector].a, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(two_cities_4k_keys[verify_sector].a, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_ctx = {};
MfClassicError error =
@ -78,9 +78,11 @@ static bool two_cities_read(Nfc* nfc, NfcDevice* device) {
data->type = type;
MfClassicDeviceKeys keys = {};
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
nfc_util_num2bytes(two_cities_4k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
bit_lib_num_to_bytes_be(
two_cities_4k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(two_cities_4k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
bit_lib_num_to_bytes_be(
two_cities_4k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
@ -110,7 +112,7 @@ static bool two_cities_parse(const NfcDevice* device, FuriString* parsed_data) {
do {
// Verify key
MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 4);
uint64_t key = nfc_util_bytes2num(sec_tr->key_a.data, 6);
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
if(key != two_cities_4k_keys[4].a) return false;
// =====

View file

@ -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 <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 "Umarsh"
@ -63,27 +59,27 @@ static bool umarsh_parse(const NfcDevice* device, FuriString* parsed_data) {
// Validate specific for Umarsh ticket sector header
const uint8_t* block_start_ptr = &data->block[ticket_sector_start_block_number].data[0];
const uint32_t header_part_0 = nfc_util_bytes2num(block_start_ptr, 4);
const uint32_t header_part_1 = nfc_util_bytes2num(block_start_ptr + 4, 4);
const uint32_t header_part_0 = bit_lib_bytes_to_num_be(block_start_ptr, 4);
const uint32_t header_part_1 = bit_lib_bytes_to_num_be(block_start_ptr + 4, 4);
if((header_part_0 + header_part_1) != 0xFFFFFFFF) break;
// Data parsing from block 1
block_start_ptr = &data->block[ticket_sector_start_block_number + 1].data[0];
const uint16_t expiry_date = nfc_util_bytes2num(block_start_ptr + 1, 2);
const uint16_t expiry_date = bit_lib_bytes_to_num_be(block_start_ptr + 1, 2);
const uint8_t region_number = (((block_start_ptr[8] >> 5) & 0x07) << 4) |
(block_start_ptr[12] & 0x0F);
const uint8_t refill_counter = nfc_util_bytes2num(block_start_ptr + 7, 1);
const uint32_t card_number = nfc_util_bytes2num(block_start_ptr + 8, 4) & 0x3FFFFFFF;
const uint8_t refill_counter = bit_lib_bytes_to_num_be(block_start_ptr + 7, 1);
const uint32_t card_number = bit_lib_bytes_to_num_be(block_start_ptr + 8, 4) & 0x3FFFFFFF;
if(card_number == 0) break;
// Data parsing from block 2
block_start_ptr = &data->block[ticket_sector_start_block_number + 2].data[0];
const uint16_t valid_to = nfc_util_bytes2num(block_start_ptr, 2);
const uint32_t terminal_number = nfc_util_bytes2num(block_start_ptr + 3, 3);
const uint16_t last_refill_date = nfc_util_bytes2num(block_start_ptr + 6, 2);
const uint16_t balance_rub = (nfc_util_bytes2num(block_start_ptr + 8, 2)) & 0x7FFF;
const uint8_t balance_kop = nfc_util_bytes2num(block_start_ptr + 10, 1) & 0x7F;
const uint16_t valid_to = bit_lib_bytes_to_num_be(block_start_ptr, 2);
const uint32_t terminal_number = bit_lib_bytes_to_num_be(block_start_ptr + 3, 3);
const uint16_t last_refill_date = bit_lib_bytes_to_num_be(block_start_ptr + 6, 2);
const uint16_t balance_rub = (bit_lib_bytes_to_num_be(block_start_ptr + 8, 2)) & 0x7FFF;
const uint8_t balance_kop = bit_lib_bytes_to_num_be(block_start_ptr + 10, 1) & 0x7F;
FuriHalRtcDateTime expiry_datetime;
bool is_expiry_datetime_valid = parse_datetime(expiry_date, &expiry_datetime);

View file

@ -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 <nfc/helpers/nfc_util.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
#include <bit_lib.h>
#define TAG "WashCity"
typedef struct {
@ -63,7 +61,8 @@ static bool washcity_verify(Nfc* nfc) {
FURI_LOG_D(TAG, "Verifying sector %u", ticket_sector_number);
MfClassicKey key = {0};
nfc_util_num2bytes(washcity_1k_keys[ticket_sector_number].a, COUNT_OF(key.data), key.data);
bit_lib_num_to_bytes_be(
washcity_1k_keys[ticket_sector_number].a, COUNT_OF(key.data), key.data);
MfClassicAuthContext auth_context;
MfClassicError error = mf_classic_poller_sync_auth(
@ -101,9 +100,11 @@ static bool washcity_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(washcity_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
bit_lib_num_to_bytes_be(
washcity_1k_keys[i].a, sizeof(MfClassicKey), keys.key_a[i].data);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(washcity_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
bit_lib_num_to_bytes_be(
washcity_1k_keys[i].b, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}
@ -138,7 +139,8 @@ static bool washcity_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 != washcity_1k_keys[ticket_sector_number].a) break;
// Parse data
@ -148,7 +150,7 @@ static bool washcity_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(block_start_ptr + 2, 2);
uint32_t balance = bit_lib_bytes_to_num_be(block_start_ptr + 2, 2);
uint32_t balance_usd = balance / 100;
uint8_t balance_cents = balance % 100;
@ -157,7 +159,7 @@ static bool washcity_parse(const NfcDevice* device, FuriString* parsed_data) {
const uint8_t* uid = mf_classic_get_uid(data, &uid_len);
// Card Number is printed in HEX (equal to UID)
uint64_t card_number = nfc_util_bytes2num(uid, uid_len);
uint64_t card_number = bit_lib_bytes_to_num_be(uid, uid_len);
furi_string_printf(
parsed_data,

View file

@ -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;

View file

@ -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,

View file

@ -1,11 +1,12 @@
#include "../nfc_app_i.h"
#include <nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
void nfc_scene_slix_key_input_byte_input_callback(void* context) {
NfcApp* instance = context;
SlixPassword password = nfc_util_bytes2num(instance->byte_input_store, sizeof(SlixPassword));
SlixPassword password =
bit_lib_bytes_to_num_be(instance->byte_input_store, sizeof(SlixPassword));
slix_unlock_set_password(instance->slix_unlock, password);
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventByteInputDone);
}

View file

@ -117,6 +117,10 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
static void text_box_view_draw_callback(Canvas* canvas, void* _model) {
TextBoxModel* model = _model;
if(!model->text) {
return;
}
canvas_clear(canvas);
if(model->font == TextBoxFontText) {
canvas_set_font(canvas, FontSecondary);

View file

@ -71,7 +71,8 @@ void furi_string_reserve(FuriString* s, size_t alloc) {
}
void furi_string_reset(FuriString* s) {
string_reset(s->string);
string_clear(s->string);
string_init(s->string);
}
void furi_string_swap(FuriString* v1, FuriString* v2) {

View file

@ -3,6 +3,7 @@
- `FreeRTOS-Kernel` - FreeRTOS kernel source code
- `FreeRTOS-glue` - Extra glue to hold together FreeRTOS kernel and flipper firmware
- `app-scened-template` - C++ app library
- `bit_lib` - library for working with bits/bytes directly
- `callback-connector` - Callback connector library
- `cmsis_core` - CMSIS Core package, contain cortex-m core headers
- `cxxheaderparser` - C++ headers parser, used by SDK bundler

View file

@ -42,6 +42,7 @@ libs = env.BuildModules(
"nanopb",
"update_util",
"heatshrink",
"bit_lib",
],
)

22
lib/bit_lib/SConscript Normal file
View file

@ -0,0 +1,22 @@
Import("env")
env.Append(
LINT_SOURCES=[
Dir("."),
],
CPPPATH=[
"#/lib/bit_lib",
],
SDK_HEADERS=[
File("bit_lib.h"),
],
)
libenv = env.Clone(FW_LIB_NAME="bit_lib")
libenv.ApplyLibFlags()
sources = libenv.GlobRecursive("*.c*")
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Return("lib")

View file

@ -78,6 +78,57 @@ uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t lengt
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 if(length <= 40) {
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 |= bit_lib_get_bits(data, position + 32, length - 32);
} else if(length <= 48) {
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 |= bit_lib_get_bits(data, position + 40, length - 40);
} else if(length <= 56) {
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 |= bit_lib_get_bits(data, position + 48, length - 48);
} 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 |= bit_lib_get_bits(data, position + 56, length - 56);
}
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
@ -365,3 +416,70 @@ uint16_t bit_lib_crc16(
return crc;
}
void bit_lib_num_to_bytes_be(uint64_t src, uint8_t len, uint8_t* dest) {
furi_assert(dest);
furi_assert(len <= 8);
while(len--) {
dest[len] = (uint8_t)src;
src >>= 8;
}
}
void bit_lib_num_to_bytes_le(uint64_t src, uint8_t len, uint8_t* dest) {
furi_assert(dest);
furi_assert(len <= 8);
for(int i = 0; i < len; i++) {
dest[i] = (uint8_t)(src >> (8 * i));
}
}
uint64_t bit_lib_bytes_to_num_be(const uint8_t* src, uint8_t len) {
furi_assert(src);
furi_assert(len <= 8);
uint64_t res = 0;
while(len--) {
res = (res << 8) | (*src);
src++;
}
return res;
}
uint64_t bit_lib_bytes_to_num_le(const uint8_t* src, uint8_t len) {
furi_assert(src);
furi_assert(len <= 8);
uint64_t res = 0;
uint8_t shift = 0;
while(len--) {
res |= ((uint64_t)*src) << (8 * shift++);
src++;
}
return res;
}
uint64_t bit_lib_bytes_to_num_bcd(const uint8_t* src, uint8_t len, bool* is_bcd) {
furi_assert(src);
furi_assert(len <= 9);
uint64_t res = 0;
uint8_t nibble_1, nibble_2;
*is_bcd = true;
for(uint8_t i = 0; i < len; i++) {
nibble_1 = src[i] / 16;
nibble_2 = src[i] % 16;
if((nibble_1 > 9) || (nibble_2 > 9)) *is_bcd = false;
res *= 10;
res += nibble_1;
res *= 10;
res += nibble_2;
}
return res;
}

View file

@ -90,6 +90,15 @@ uint16_t bit_lib_get_bits_16(const uint8_t* data, size_t position, uint8_t lengt
*/
uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t length);
/**
* @brief Get the bits of a data, as uint64_t.
* @param data The data to get the bits from.
* @param position The position of the first bit.
* @param length The length of the bits.
* @return The bits.
*/
uint64_t bit_lib_get_bits_64(const uint8_t* data, size_t position, uint8_t length);
/**
* @brief Test parity of given bits
* @param bits Bits to test parity of
@ -267,6 +276,54 @@ uint16_t bit_lib_crc16(
bool ref_out,
uint16_t xor_out);
/**
* @brief Convert number to bytes in big endian order
*
* @param src number to convert
* @param len max used bytes count
* @param dest destination
* @return void
*/
void bit_lib_num_to_bytes_be(uint64_t src, uint8_t len, uint8_t* dest);
/**
* @brief Convert number to bytes in little endian order
*
* @param src number to convert
* @param len max used bytes count
* @param dest destination
* @return void
*/
void bit_lib_num_to_bytes_le(uint64_t src, uint8_t len, uint8_t* dest);
/**
* @brief Convert bytes to number in big endian order
*
* @param src byte array
* @param len max used bytes count
* @return uint64_t
*/
uint64_t bit_lib_bytes_to_num_be(const uint8_t* src, uint8_t len);
/**
* @brief Convert bytes to number in little endian order
*
* @param src byte array
* @param len max used bytes count
* @return uint64_t
*/
uint64_t bit_lib_bytes_to_num_le(const uint8_t* src, uint8_t len);
/**
* @brief Convert bytes in binary-coded decimal encoding to number
*
* @param src byte array
* @param len max used bytes count
* @param is_bcd will be true if all processed bytes is BCD encoded (no A-F nibbles)
* @return uint64_t
*/
uint64_t bit_lib_bytes_to_num_bcd(const uint8_t* src, uint8_t len, bool* is_bcd);
#ifdef __cplusplus
}
#endif

View file

@ -12,7 +12,6 @@ env.Append(
File("lfrfid_raw_worker.h"),
File("lfrfid_raw_file.h"),
File("lfrfid_dict_file.h"),
File("tools/bit_lib.h"),
File("protocols/lfrfid_protocols.h"),
],
)

View file

@ -1,7 +1,7 @@
#include "lfrfid_dict_file.h"
#include <storage/storage.h>
#include <flipper_format/flipper_format.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#define LFRFID_DICT_FILETYPE "Flipper RFID key"

View file

@ -6,7 +6,7 @@
#include <toolbox/pulse_protocols/pulse_glue.h>
#include <toolbox/buffer_stream.h>
#include "tools/varint_pair.h"
#include "tools/bit_lib.h"
#include <lib/bit_lib/bit_lib.h>
#define TAG "LfRfidWorker"
@ -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++)

View file

@ -2,7 +2,7 @@
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define JITTER_TIME (20)

View file

@ -3,7 +3,7 @@
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include "lfrfid_protocols.h"
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)

View file

@ -2,7 +2,7 @@
#include "toolbox/level_duration.h"
#include "protocol_fdx_b.h"
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#include <furi_hal_rtc.h>

View file

@ -1,7 +1,7 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define GALLAGHER_CLOCK_PER_BIT (32)

View file

@ -3,7 +3,7 @@
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include "lfrfid_protocols.h"
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)

View file

@ -3,7 +3,7 @@
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include "lfrfid_protocols.h"
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)

View file

@ -1,6 +1,6 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
// Example: 4944544B 351FBE4B

View file

@ -1,6 +1,6 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define INDALA26_PREAMBLE_BIT_SIZE (33)

View file

@ -2,7 +2,7 @@
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define JITTER_TIME (20)

View file

@ -2,7 +2,7 @@
#include "toolbox/level_duration.h"
#include "protocol_jablotron.h"
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define JABLOTRON_ENCODED_BIT_SIZE (64)

View file

@ -1,6 +1,6 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define KERI_PREAMBLE_BIT_SIZE (33)

View file

@ -1,6 +1,6 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define NEXWATCH_PREAMBLE_BIT_SIZE (8)

View file

@ -2,7 +2,7 @@
#include <math.h>
#include <toolbox/protocols/protocol.h>
#include <toolbox/hex.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define PAC_STANLEY_ENCODED_BIT_SIZE (128)

View file

@ -2,7 +2,7 @@
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define JITTER_TIME (20)

View file

@ -3,7 +3,7 @@
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include "lfrfid_protocols.h"
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)

View file

@ -1,7 +1,7 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include <bit_lib/bit_lib.h>
#include "lfrfid_protocols.h"
#define VIKING_CLOCK_PER_BIT (32)

View file

@ -13,41 +13,6 @@ static const uint8_t nfc_util_odd_byte_parity[256] = {
0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1};
void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest) {
furi_assert(dest);
furi_assert(len <= 8);
while(len--) {
dest[len] = (uint8_t)src;
src >>= 8;
}
}
uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len) {
furi_assert(src);
furi_assert(len <= 8);
uint64_t res = 0;
while(len--) {
res = (res << 8) | (*src);
src++;
}
return res;
}
uint64_t nfc_util_bytes2num_little_endian(const uint8_t* src, uint8_t len) {
furi_assert(src);
furi_assert(len <= 8);
uint64_t res = 0;
uint8_t shift = 0;
while(len--) {
res |= ((uint64_t)*src) << (8 * shift++);
src++;
}
return res;
}
uint8_t nfc_util_even_parity32(uint32_t data) {
// data ^= data >> 16;
// data ^= data >> 8;

View file

@ -6,12 +6,6 @@
extern "C" {
#endif
void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest);
uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len);
uint64_t nfc_util_bytes2num_little_endian(const uint8_t* src, uint8_t len);
uint8_t nfc_util_even_parity32(uint32_t data);
uint8_t nfc_util_odd_parity8(uint8_t data);

View file

@ -1,6 +1,7 @@
#include "crypto1.h"
#include <lib/nfc/helpers/nfc_util.h>
#include <lib/bit_lib/bit_lib.h>
#include <furi.h>
// Algorithm from https://github.com/RfidResearchGroup/proxmark3.git
@ -151,7 +152,7 @@ void crypto1_encrypt_reader_nonce(
furi_assert(out);
bit_buffer_set_size_bytes(out, 8);
uint32_t nt_num = nfc_util_bytes2num(nt, sizeof(uint32_t));
uint32_t nt_num = bit_lib_bytes_to_num_be(nt, sizeof(uint32_t));
crypto1_init(crypto, key);
if(is_nested) {

View file

@ -3,7 +3,7 @@
#include <furi/furi.h>
#include <toolbox/hex.h>
#include <lib/nfc/helpers/nfc_util.h>
#include <lib/bit_lib/bit_lib.h>
#define MF_CLASSIC_PROTOCOL_NAME "Mifare Classic"
@ -121,7 +121,8 @@ static void mf_classic_parse_block(FuriString* block_str, MfClassicData* data, u
// Load Key A
// Key A mask 0b0000000000111111 = 0x003f
if((block_unknown_bytes_mask & 0x003f) == 0) {
uint64_t key = nfc_util_bytes2num(sec_tr_tmp->key_a.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(sec_tr_tmp->key_a.data, sizeof(MfClassicKey));
mf_classic_set_key_found(data, sector_num, MfClassicKeyTypeA, key);
}
// Load Access Bits
@ -132,7 +133,8 @@ static void mf_classic_parse_block(FuriString* block_str, MfClassicData* data, u
// Load Key B
// Key B mask 0b1111110000000000 = 0xfc00
if((block_unknown_bytes_mask & 0xfc00) == 0) {
uint64_t key = nfc_util_bytes2num(sec_tr_tmp->key_b.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(sec_tr_tmp->key_b.data, sizeof(MfClassicKey));
mf_classic_set_key_found(data, sector_num, MfClassicKeyTypeB, key);
}
} else {
@ -493,7 +495,7 @@ void mf_classic_set_key_found(
uint8_t key_arr[6] = {};
MfClassicSectorTrailer* sec_trailer =
mf_classic_get_sector_trailer_by_sector(data, sector_num);
nfc_util_num2bytes(key, 6, key_arr);
bit_lib_num_to_bytes_be(key, 6, key_arr);
if(key_type == MfClassicKeyTypeA) {
memcpy(sec_trailer->key_a.data, key_arr, sizeof(MfClassicKey));
FURI_BIT_SET(data->key_a_mask, sector_num);

View file

@ -3,7 +3,7 @@
#include <nfc/protocols/nfc_listener_base.h>
#include <nfc/helpers/iso14443_crc.h>
#include <nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
#include <furi.h>
#include <furi_hal_random.h>
@ -68,14 +68,15 @@ static MfClassicListenerCommand mf_classic_listener_auth_first_part_handler(
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(instance->data, sector_num);
MfClassicKey* key = (key_type == MfClassicKeyTypeA) ? &sec_tr->key_a : &sec_tr->key_b;
uint64_t key_num = nfc_util_bytes2num(key->data, sizeof(MfClassicKey));
uint64_t key_num = bit_lib_bytes_to_num_be(key->data, sizeof(MfClassicKey));
uint32_t cuid = iso14443_3a_get_cuid(instance->data->iso14443_3a_data);
instance->auth_context.key_type = key_type;
instance->auth_context.block_num = block_num;
furi_hal_random_fill_buf(instance->auth_context.nt.data, sizeof(MfClassicNt));
uint32_t nt_num = nfc_util_bytes2num(instance->auth_context.nt.data, sizeof(MfClassicNt));
uint32_t nt_num =
bit_lib_bytes_to_num_be(instance->auth_context.nt.data, sizeof(MfClassicNt));
crypto1_init(instance->crypto, key_num);
if(instance->comm_state == MfClassicListenerCommStatePlain) {
@ -88,7 +89,7 @@ static MfClassicListenerCommand mf_classic_listener_auth_first_part_handler(
command = MfClassicListenerCommandProcessed;
} else {
uint8_t key_stream[4] = {};
nfc_util_num2bytes(nt_num ^ cuid, sizeof(uint32_t), key_stream);
bit_lib_num_to_bytes_be(nt_num ^ cuid, sizeof(uint32_t), key_stream);
bit_buffer_copy_bytes(
instance->tx_plain_buffer, instance->auth_context.nt.data, sizeof(MfClassicNt));
crypto1_encrypt(
@ -147,11 +148,14 @@ static MfClassicListenerCommand
instance->callback(instance->generic_event, instance->context);
}
uint32_t nr_num = nfc_util_bytes2num(instance->auth_context.nr.data, sizeof(MfClassicNr));
uint32_t ar_num = nfc_util_bytes2num(instance->auth_context.ar.data, sizeof(MfClassicAr));
uint32_t nr_num =
bit_lib_bytes_to_num_be(instance->auth_context.nr.data, sizeof(MfClassicNr));
uint32_t ar_num =
bit_lib_bytes_to_num_be(instance->auth_context.ar.data, sizeof(MfClassicAr));
crypto1_word(instance->crypto, nr_num, 1);
uint32_t nt_num = nfc_util_bytes2num(instance->auth_context.nt.data, sizeof(MfClassicNt));
uint32_t nt_num =
bit_lib_bytes_to_num_be(instance->auth_context.nt.data, sizeof(MfClassicNt));
uint32_t secret_poller = ar_num ^ crypto1_word(instance->crypto, 0, 0);
if(secret_poller != prng_successor(nt_num, 64)) {
FURI_LOG_T(
@ -161,7 +165,7 @@ static MfClassicListenerCommand
}
uint32_t at_num = prng_successor(nt_num, 96);
nfc_util_num2bytes(at_num, sizeof(uint32_t), instance->auth_context.at.data);
bit_lib_num_to_bytes_be(at_num, sizeof(uint32_t), instance->auth_context.at.data);
bit_buffer_copy_bytes(
instance->tx_plain_buffer, instance->auth_context.at.data, sizeof(MfClassicAr));
crypto1_encrypt(

View file

@ -73,7 +73,7 @@ static void mf_classic_poller_check_key_b_is_readable(
break;
MfClassicSectorTrailer* sec_tr = (MfClassicSectorTrailer*)data;
uint64_t key_b = nfc_util_bytes2num(sec_tr->key_b.data, sizeof(MfClassicKey));
uint64_t key_b = bit_lib_bytes_to_num_be(sec_tr->key_b.data, sizeof(MfClassicKey));
uint8_t sector_num = mf_classic_get_sector_by_block(block_num);
mf_classic_set_key_found(instance->data, sector_num, MfClassicKeyTypeB, key_b);
} while(false);
@ -456,7 +456,7 @@ NfcCommand mf_classic_poller_handler_request_read_sector_blocks(MfClassicPoller*
MfClassicError error = MfClassicErrorNone;
if(!sec_read_ctx->auth_passed) {
uint64_t key = nfc_util_bytes2num(sec_read_ctx->key.data, sizeof(MfClassicKey));
uint64_t key = bit_lib_bytes_to_num_be(sec_read_ctx->key.data, sizeof(MfClassicKey));
FURI_LOG_D(
TAG,
"Auth to block %d with key %c: %06llx",
@ -530,7 +530,8 @@ NfcCommand mf_classic_poller_handler_auth_a(MfClassicPoller* instance) {
instance->state = MfClassicPollerStateAuthKeyB;
} else {
uint8_t block = mf_classic_get_first_block_num_of_sector(dict_attack_ctx->current_sector);
uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
FURI_LOG_D(TAG, "Auth to block %d with key A: %06llx", block, key);
MfClassicError error = mf_classic_poller_auth(
@ -568,7 +569,8 @@ NfcCommand mf_classic_poller_handler_auth_b(MfClassicPoller* instance) {
}
} else {
uint8_t block = mf_classic_get_first_block_num_of_sector(dict_attack_ctx->current_sector);
uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
FURI_LOG_D(TAG, "Auth to block %d with key B: %06llx", block, key);
MfClassicError error = mf_classic_poller_auth(
@ -711,7 +713,8 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_a(MfClassicPoller* insta
} else {
uint8_t block =
mf_classic_get_first_block_num_of_sector(dict_attack_ctx->reuse_key_sector);
uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
FURI_LOG_D(TAG, "Key attack auth to block %d with key A: %06llx", block, key);
MfClassicError error = mf_classic_poller_auth(
@ -746,7 +749,8 @@ NfcCommand mf_classic_poller_handler_key_reuse_auth_key_b(MfClassicPoller* insta
} else {
uint8_t block =
mf_classic_get_first_block_num_of_sector(dict_attack_ctx->reuse_key_sector);
uint64_t key = nfc_util_bytes2num(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
uint64_t key =
bit_lib_bytes_to_num_be(dict_attack_ctx->current_key.data, sizeof(MfClassicKey));
FURI_LOG_D(TAG, "Key attack auth to block %d with key B: %06llx", block, key);
MfClassicError error = mf_classic_poller_auth(

View file

@ -128,7 +128,7 @@ static MfClassicError mf_classic_poller_auth_common(
}
uint32_t cuid = iso14443_3a_get_cuid(instance->data->iso14443_3a_data);
uint64_t key_num = nfc_util_bytes2num(key->data, sizeof(MfClassicKey));
uint64_t key_num = bit_lib_bytes_to_num_be(key->data, sizeof(MfClassicKey));
MfClassicNr nr = {};
furi_hal_random_fill_buf(nr.data, sizeof(MfClassicNr));

View file

@ -2,7 +2,7 @@
#include "mf_classic_poller.h"
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h>
#include <lib/nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
#include "crypto1.h"
#ifdef __cplusplus

View file

@ -1,6 +1,6 @@
#include "mf_ultralight.h"
#include <nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
#include <furi.h>
#define MF_ULTRALIGHT_PROTOCOL_NAME "NTAG/Ultralight"
@ -603,10 +603,10 @@ bool mf_ultralight_is_all_data_read(const MfUltralightData* data) {
} else {
MfUltralightConfigPages* config = NULL;
if(mf_ultralight_get_config_page(data, &config)) {
uint32_t pass =
nfc_util_bytes2num(config->password.data, sizeof(MfUltralightAuthPassword));
uint32_t pass = bit_lib_bytes_to_num_be(
config->password.data, sizeof(MfUltralightAuthPassword));
uint16_t pack =
nfc_util_bytes2num(config->pack.data, sizeof(MfUltralightAuthPack));
bit_lib_bytes_to_num_be(config->pack.data, sizeof(MfUltralightAuthPack));
all_read = ((pass != 0) || (pack != 0));
}
}

View file

@ -417,7 +417,7 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance
command = instance->callback(instance->general_event, instance->context);
if(!instance->mfu_event.data->auth_context.skip_auth) {
instance->auth_context.password = instance->mfu_event.data->auth_context.password;
uint32_t pass = nfc_util_bytes2num(
uint32_t pass = bit_lib_bytes_to_num_be(
instance->auth_context.password.data, sizeof(MfUltralightAuthPassword));
FURI_LOG_D(TAG, "Trying to authenticate with password %08lX", pass);
instance->error = mf_ultralight_poller_auth_pwd(instance, &instance->auth_context);
@ -497,14 +497,14 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll
config->pack = instance->auth_context.pack;
} else if(config->access.authlim == 0) {
FURI_LOG_D(TAG, "No limits in authentication. Trying default password");
nfc_util_num2bytes(
bit_lib_num_to_bytes_be(
MF_ULTRALIGHT_DEFAULT_PASSWORD,
sizeof(MfUltralightAuthPassword),
instance->auth_context.password.data);
instance->error = mf_ultralight_poller_auth_pwd(instance, &instance->auth_context);
if(instance->error == MfUltralightErrorNone) {
FURI_LOG_D(TAG, "Default password detected");
nfc_util_num2bytes(
bit_lib_num_to_bytes_be(
MF_ULTRALIGHT_DEFAULT_PASSWORD,
sizeof(MfUltralightAuthPassword),
config->password.data);

View file

@ -2,7 +2,7 @@
#include "mf_ultralight_poller.h"
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h>
#include <lib/nfc/helpers/nfc_util.h>
#include <lib/bit_lib/bit_lib.h>
#ifdef __cplusplus
extern "C" {

View file

@ -1,5 +1,5 @@
#include "slix_poller_i.h"
#include <nfc/helpers/nfc_util.h>
#include <bit_lib/bit_lib.h>
#include <furi.h>
@ -107,7 +107,7 @@ SlixError
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] = {};
nfc_util_num2bytes(xored_password, 4, xored_password_arr);
bit_lib_num_to_bytes_be(xored_password, 4, xored_password_arr);
bit_buffer_append_bytes(instance->tx_buffer, xored_password_arr, 4);
SlixError error = SlixErrorNone;

View file

@ -24,17 +24,17 @@ set "FBT_TOOLCHAIN_ROOT=%FBT_TOOLCHAIN_PATH%\toolchain\x86_64-windows"
set "FBT_TOOLCHAIN_VERSION_FILE=%FBT_TOOLCHAIN_ROOT%\VERSION"
if not exist "%FBT_TOOLCHAIN_ROOT%" (
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%"
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%" || exit /b
)
if not exist "%FBT_TOOLCHAIN_VERSION_FILE%" (
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%"
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%" || exit /b
)
set /p REAL_TOOLCHAIN_VERSION=<"%FBT_TOOLCHAIN_VERSION_FILE%"
if not "%REAL_TOOLCHAIN_VERSION%" == "%FLIPPER_TOOLCHAIN_VERSION%" (
echo FBT: starting toolchain upgrade process..
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%"
powershell -ExecutionPolicy Bypass -File "%FBT_ROOT%\scripts\toolchain\windows-toolchain-download.ps1" %flipper_toolchain_version% "%FBT_TOOLCHAIN_ROOT%" || exit /b
set /p REAL_TOOLCHAIN_VERSION=<"%FBT_TOOLCHAIN_VERSION_FILE%"
)

View file

@ -208,9 +208,12 @@ fbtenv_show_unpack_percentage()
fbtenv_unpack_toolchain()
{
echo "Unpacking toolchain to '$FBT_TOOLCHAIN_PATH/toolchain':";
rm $FBT_TOOLCHAIN_PATH/toolchain/current || true;
tar -xvf "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_TAR" -C "$FBT_TOOLCHAIN_PATH/toolchain" 2>&1 | fbtenv_show_unpack_percentage;
mkdir -p "$FBT_TOOLCHAIN_PATH/toolchain" || return 1;
mv "$FBT_TOOLCHAIN_PATH/toolchain/$TOOLCHAIN_DIR" "$TOOLCHAIN_ARCH_DIR" || return 1;
printf "linking toolchain to 'current'..";
ln -s "$TOOLCHAIN_ARCH_DIR" "$FBT_TOOLCHAIN_PATH/toolchain/current" || return 1;
echo "done";
return 0;
}

View file

@ -18,6 +18,13 @@ if (Test-Path -LiteralPath "$toolchain_target_path") {
Remove-Item -LiteralPath "$toolchain_target_path" -Force -Recurse
Write-Host "done!"
}
if (Test-path -Path "$toolchain_target_path\..\current") {
Write-Host -NoNewline "Unlinking 'current'.."
Remove-Item -LiteralPath "$toolchain_target_path\..\current" -Force
Write-Host "done!"
}
if (!(Test-Path -Path "$toolchain_zip_temp_path" -PathType Leaf)) {
Write-Host -NoNewline "Downloading Windows toolchain.."
$wc = New-Object net.webclient
@ -42,6 +49,8 @@ Add-Type -Assembly "System.IO.Compression.Filesystem"
Write-Host -NoNewline "moving.."
Move-Item -LiteralPath "$toolchain_dist_temp_path" -Destination "$toolchain_target_path" -Force
Write-Host -NoNewline "linking to 'current'.."
cmd /c mklink /J "$toolchain_target_path\..\current" "$toolchain_target_path"
Write-Host "done!"
Write-Host -NoNewline "Cleaning up temporary files.."

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,55.2,,
Version,+,56.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -37,6 +37,7 @@ Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,,
Header,+,applications/services/rpc/rpc_app.h,,
Header,+,applications/services/storage/storage.h,,
Header,+,lib/bit_lib/bit_lib.h,,
Header,+,lib/digital_signal/digital_sequence.h,,
Header,+,lib/digital_signal/digital_signal.h,,
Header,+,lib/drivers/cc1101_regs.h,,
@ -574,6 +575,32 @@ Function,+,bit_buffer_starts_with_byte,_Bool,"const BitBuffer*, uint8_t"
Function,+,bit_buffer_write_bytes,void,"const BitBuffer*, void*, size_t"
Function,+,bit_buffer_write_bytes_mid,void,"const BitBuffer*, void*, size_t, size_t"
Function,+,bit_buffer_write_bytes_with_parity,void,"const BitBuffer*, void*, size_t, size_t*"
Function,+,bit_lib_add_parity,size_t,"const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity"
Function,+,bit_lib_bytes_to_num_bcd,uint64_t,"const uint8_t*, uint8_t, _Bool*"
Function,+,bit_lib_bytes_to_num_be,uint64_t,"const uint8_t*, uint8_t"
Function,+,bit_lib_bytes_to_num_le,uint64_t,"const uint8_t*, uint8_t"
Function,+,bit_lib_copy_bits,void,"uint8_t*, size_t, size_t, const uint8_t*, size_t"
Function,+,bit_lib_crc16,uint16_t,"const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t"
Function,+,bit_lib_crc8,uint16_t,"const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t"
Function,+,bit_lib_get_bit,_Bool,"const uint8_t*, size_t"
Function,+,bit_lib_get_bit_count,uint8_t,uint32_t
Function,+,bit_lib_get_bits,uint8_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_16,uint16_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_32,uint32_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_64,uint64_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_num_to_bytes_be,void,"uint64_t, uint8_t, uint8_t*"
Function,+,bit_lib_num_to_bytes_le,void,"uint64_t, uint8_t, uint8_t*"
Function,+,bit_lib_print_bits,void,"const uint8_t*, size_t"
Function,+,bit_lib_print_regions,void,"const BitLibRegion*, size_t, const uint8_t*, size_t"
Function,+,bit_lib_push_bit,void,"uint8_t*, size_t, _Bool"
Function,+,bit_lib_remove_bit_every_nth,size_t,"uint8_t*, size_t, uint8_t, uint8_t"
Function,+,bit_lib_reverse_16_fast,uint16_t,uint16_t
Function,+,bit_lib_reverse_8_fast,uint8_t,uint8_t
Function,+,bit_lib_reverse_bits,void,"uint8_t*, size_t, uint8_t"
Function,+,bit_lib_set_bit,void,"uint8_t*, size_t, _Bool"
Function,+,bit_lib_set_bits,void,"uint8_t*, size_t, uint8_t, uint8_t"
Function,+,bit_lib_test_parity,_Bool,"const uint8_t*, size_t, uint8_t, BitLibParity, uint8_t"
Function,+,bit_lib_test_parity_32,_Bool,"uint32_t, BitLibParity"
Function,+,ble_app_get_key_storage_buff,void,"uint8_t**, uint16_t*"
Function,+,ble_app_init,_Bool,
Function,+,ble_app_thread_stop,void,

1 entry status name type params
2 Version + 55.2 56.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
37 Header + applications/services/power/power_service/power.h
38 Header + applications/services/rpc/rpc_app.h
39 Header + applications/services/storage/storage.h
40 Header + lib/bit_lib/bit_lib.h
41 Header + lib/digital_signal/digital_sequence.h
42 Header + lib/digital_signal/digital_signal.h
43 Header + lib/drivers/cc1101_regs.h
575 Function + bit_buffer_write_bytes void const BitBuffer*, void*, size_t
576 Function + bit_buffer_write_bytes_mid void const BitBuffer*, void*, size_t, size_t
577 Function + bit_buffer_write_bytes_with_parity void const BitBuffer*, void*, size_t, size_t*
578 Function + bit_lib_add_parity size_t const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity
579 Function + bit_lib_bytes_to_num_bcd uint64_t const uint8_t*, uint8_t, _Bool*
580 Function + bit_lib_bytes_to_num_be uint64_t const uint8_t*, uint8_t
581 Function + bit_lib_bytes_to_num_le uint64_t const uint8_t*, uint8_t
582 Function + bit_lib_copy_bits void uint8_t*, size_t, size_t, const uint8_t*, size_t
583 Function + bit_lib_crc16 uint16_t const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t
584 Function + bit_lib_crc8 uint16_t const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t
585 Function + bit_lib_get_bit _Bool const uint8_t*, size_t
586 Function + bit_lib_get_bit_count uint8_t uint32_t
587 Function + bit_lib_get_bits uint8_t const uint8_t*, size_t, uint8_t
588 Function + bit_lib_get_bits_16 uint16_t const uint8_t*, size_t, uint8_t
589 Function + bit_lib_get_bits_32 uint32_t const uint8_t*, size_t, uint8_t
590 Function + bit_lib_get_bits_64 uint64_t const uint8_t*, size_t, uint8_t
591 Function + bit_lib_num_to_bytes_be void uint64_t, uint8_t, uint8_t*
592 Function + bit_lib_num_to_bytes_le void uint64_t, uint8_t, uint8_t*
593 Function + bit_lib_print_bits void const uint8_t*, size_t
594 Function + bit_lib_print_regions void const BitLibRegion*, size_t, const uint8_t*, size_t
595 Function + bit_lib_push_bit void uint8_t*, size_t, _Bool
596 Function + bit_lib_remove_bit_every_nth size_t uint8_t*, size_t, uint8_t, uint8_t
597 Function + bit_lib_reverse_16_fast uint16_t uint16_t
598 Function + bit_lib_reverse_8_fast uint8_t uint8_t
599 Function + bit_lib_reverse_bits void uint8_t*, size_t, uint8_t
600 Function + bit_lib_set_bit void uint8_t*, size_t, _Bool
601 Function + bit_lib_set_bits void uint8_t*, size_t, uint8_t, uint8_t
602 Function + bit_lib_test_parity _Bool const uint8_t*, size_t, uint8_t, BitLibParity, uint8_t
603 Function + bit_lib_test_parity_32 _Bool uint32_t, BitLibParity
604 Function + ble_app_get_key_storage_buff void uint8_t**, uint16_t*
605 Function + ble_app_init _Bool
606 Function + ble_app_thread_stop void

View file

@ -36,7 +36,8 @@
"update_util",
"heatshrink",
"flipperformat",
"flipper18"
"flipper18",
"bit_lib"
],
"excluded_sources": [
"furi_hal_infrared.c",

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,55.2,,
Version,+,56.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
@ -38,6 +38,7 @@ Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,,
Header,+,applications/services/rpc/rpc_app.h,,
Header,+,applications/services/storage/storage.h,,
Header,+,lib/bit_lib/bit_lib.h,,
Header,+,lib/digital_signal/digital_sequence.h,,
Header,+,lib/digital_signal/digital_signal.h,,
Header,+,lib/drivers/cc1101_regs.h,,
@ -62,7 +63,6 @@ Header,+,lib/lfrfid/lfrfid_raw_file.h,,
Header,+,lib/lfrfid/lfrfid_raw_worker.h,,
Header,+,lib/lfrfid/lfrfid_worker.h,,
Header,+,lib/lfrfid/protocols/lfrfid_protocols.h,,
Header,+,lib/lfrfid/tools/bit_lib.h,,
Header,+,lib/libusb_stm32/inc/hid_usage_button.h,,
Header,+,lib/libusb_stm32/inc/hid_usage_consumer.h,,
Header,+,lib/libusb_stm32/inc/hid_usage_desktop.h,,
@ -648,6 +648,9 @@ Function,+,bit_buffer_write_bytes,void,"const BitBuffer*, void*, size_t"
Function,+,bit_buffer_write_bytes_mid,void,"const BitBuffer*, void*, size_t, size_t"
Function,+,bit_buffer_write_bytes_with_parity,void,"const BitBuffer*, void*, size_t, size_t*"
Function,+,bit_lib_add_parity,size_t,"const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity"
Function,+,bit_lib_bytes_to_num_bcd,uint64_t,"const uint8_t*, uint8_t, _Bool*"
Function,+,bit_lib_bytes_to_num_be,uint64_t,"const uint8_t*, uint8_t"
Function,+,bit_lib_bytes_to_num_le,uint64_t,"const uint8_t*, uint8_t"
Function,+,bit_lib_copy_bits,void,"uint8_t*, size_t, size_t, const uint8_t*, size_t"
Function,+,bit_lib_crc16,uint16_t,"const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t"
Function,+,bit_lib_crc8,uint16_t,"const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t"
@ -656,6 +659,9 @@ Function,+,bit_lib_get_bit_count,uint8_t,uint32_t
Function,+,bit_lib_get_bits,uint8_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_16,uint16_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_32,uint32_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_get_bits_64,uint64_t,"const uint8_t*, size_t, uint8_t"
Function,+,bit_lib_num_to_bytes_be,void,"uint64_t, uint8_t, uint8_t*"
Function,+,bit_lib_num_to_bytes_le,void,"uint64_t, uint8_t, uint8_t*"
Function,+,bit_lib_print_bits,void,"const uint8_t*, size_t"
Function,+,bit_lib_print_regions,void,"const BitLibRegion*, size_t, const uint8_t*, size_t"
Function,+,bit_lib_push_bit,void,"uint8_t*, size_t, _Bool"
@ -2672,10 +2678,7 @@ Function,+,nfc_set_guard_time_us,void,"Nfc*, uint32_t"
Function,+,nfc_set_mask_receive_time_fc,void,"Nfc*, uint32_t"
Function,+,nfc_start,void,"Nfc*, NfcEventCallback, void*"
Function,+,nfc_stop,void,Nfc*
Function,+,nfc_util_bytes2num,uint64_t,"const uint8_t*, uint8_t"
Function,+,nfc_util_bytes2num_little_endian,uint64_t,"const uint8_t*, uint8_t"
Function,+,nfc_util_even_parity32,uint8_t,uint32_t
Function,+,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*"
Function,+,nfc_util_odd_parity,void,"const uint8_t*, uint8_t*, uint8_t"
Function,+,nfc_util_odd_parity8,uint8_t,uint8_t
Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*"

1 entry status name type params
2 Version + 55.2 56.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
38 Header + applications/services/power/power_service/power.h
39 Header + applications/services/rpc/rpc_app.h
40 Header + applications/services/storage/storage.h
41 Header + lib/bit_lib/bit_lib.h
42 Header + lib/digital_signal/digital_sequence.h
43 Header + lib/digital_signal/digital_signal.h
44 Header + lib/drivers/cc1101_regs.h
63 Header + lib/lfrfid/lfrfid_raw_worker.h
64 Header + lib/lfrfid/lfrfid_worker.h
65 Header + lib/lfrfid/protocols/lfrfid_protocols.h
Header + lib/lfrfid/tools/bit_lib.h
66 Header + lib/libusb_stm32/inc/hid_usage_button.h
67 Header + lib/libusb_stm32/inc/hid_usage_consumer.h
68 Header + lib/libusb_stm32/inc/hid_usage_desktop.h
648 Function + bit_buffer_write_bytes_mid void const BitBuffer*, void*, size_t, size_t
649 Function + bit_buffer_write_bytes_with_parity void const BitBuffer*, void*, size_t, size_t*
650 Function + bit_lib_add_parity size_t const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity
651 Function + bit_lib_bytes_to_num_bcd uint64_t const uint8_t*, uint8_t, _Bool*
652 Function + bit_lib_bytes_to_num_be uint64_t const uint8_t*, uint8_t
653 Function + bit_lib_bytes_to_num_le uint64_t const uint8_t*, uint8_t
654 Function + bit_lib_copy_bits void uint8_t*, size_t, size_t, const uint8_t*, size_t
655 Function + bit_lib_crc16 uint16_t const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t
656 Function + bit_lib_crc8 uint16_t const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t
659 Function + bit_lib_get_bits uint8_t const uint8_t*, size_t, uint8_t
660 Function + bit_lib_get_bits_16 uint16_t const uint8_t*, size_t, uint8_t
661 Function + bit_lib_get_bits_32 uint32_t const uint8_t*, size_t, uint8_t
662 Function + bit_lib_get_bits_64 uint64_t const uint8_t*, size_t, uint8_t
663 Function + bit_lib_num_to_bytes_be void uint64_t, uint8_t, uint8_t*
664 Function + bit_lib_num_to_bytes_le void uint64_t, uint8_t, uint8_t*
665 Function + bit_lib_print_bits void const uint8_t*, size_t
666 Function + bit_lib_print_regions void const BitLibRegion*, size_t, const uint8_t*, size_t
667 Function + bit_lib_push_bit void uint8_t*, size_t, _Bool
2678 Function + nfc_set_mask_receive_time_fc void Nfc*, uint32_t
2679 Function + nfc_start void Nfc*, NfcEventCallback, void*
2680 Function + nfc_stop void Nfc*
Function + nfc_util_bytes2num uint64_t const uint8_t*, uint8_t
Function + nfc_util_bytes2num_little_endian uint64_t const uint8_t*, uint8_t
2681 Function + nfc_util_even_parity32 uint8_t uint32_t
Function + nfc_util_num2bytes void uint64_t, uint8_t, uint8_t*
2682 Function + nfc_util_odd_parity void const uint8_t*, uint8_t*, uint8_t
2683 Function + nfc_util_odd_parity8 uint8_t uint8_t
2684 Function + notification_internal_message void NotificationApp*, const NotificationSequence*

View file

@ -48,6 +48,7 @@
"update_util",
"heatshrink",
"flipperformat",
"flipper7"
"flipper7",
"bit_lib"
]
}