Skip to content

Commit

Permalink
Merge branch 'ofw_dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
xMasterX committed Dec 29, 2023
2 parents 40cc784 + a7b60bf commit e5ceef3
Show file tree
Hide file tree
Showing 14 changed files with 294 additions and 15 deletions.
76 changes: 76 additions & 0 deletions applications/main/infrared/resources/infrared/assets/ac.ir

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions applications/main/nfc/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ App(
sources=["plugins/supported_cards/zolotaya_korona.c"],
)

App(
appid="hid_parser",
apptype=FlipperAppType.PLUGIN,
entry_point="hid_plugin_ep",
targets=["f7"],
requires=["nfc"],
sources=["plugins/supported_cards/hid.c"],
)

App(
appid="nfc_start",
targets=["f7"],
Expand Down
153 changes: 153 additions & 0 deletions applications/main/nfc/plugins/supported_cards/hid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include "nfc_supported_card_plugin.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>

#define TAG "HID"

static const uint64_t hid_key = 0x484944204953;

bool hid_verify(Nfc* nfc) {
bool verified = false;

do {
const uint8_t verify_sector = 1;
uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector);
FURI_LOG_D(TAG, "Verifying sector %u", verify_sector);

MfClassicKey key = {};
nfc_util_num2bytes(hid_key, COUNT_OF(key.data), key.data);

MfClassicAuthContext auth_ctx = {};
MfClassicError error =
mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);

if(error != MfClassicErrorNone) {
FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
break;
}

verified = true;
} while(false);

return verified;
}

static bool hid_read(Nfc* nfc, NfcDevice* device) {
furi_assert(nfc);
furi_assert(device);

bool is_read = false;

MfClassicData* data = mf_classic_alloc();
nfc_device_copy_data(device, NfcProtocolMfClassic, data);

do {
MfClassicType type = MfClassicType1k;
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
if(error != MfClassicErrorNone) break;

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);
FURI_BIT_SET(keys.key_a_mask, i);
nfc_util_num2bytes(hid_key, sizeof(MfClassicKey), keys.key_b[i].data);
FURI_BIT_SET(keys.key_b_mask, i);
}

error = mf_classic_poller_sync_read(nfc, &keys, data);
if(error != MfClassicErrorNone) {
FURI_LOG_W(TAG, "Failed to read data");
break;
}

nfc_device_set_data(device, NfcProtocolMfClassic, data);

is_read = true;
} while(false);

mf_classic_free(data);

return is_read;
}

static uint8_t get_bit_length(const uint8_t* half_block) {
uint8_t bitLength = 0;
uint32_t* halves = (uint32_t*)half_block;
if(halves[0] == 0) {
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
bitLength = 31 - leading0s;
} else {
uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[0]));
bitLength = 63 - leading0s;
}

return bitLength;
}

static uint64_t get_pacs_bits(const uint8_t* block, uint8_t bitLength) {
// Remove sentinel bit from credential. Byteswapping to handle array of bytes vs 64bit value
uint64_t sentinel = __builtin_bswap64(1ULL << bitLength);
uint64_t swapped = 0;
memcpy(&swapped, block, sizeof(uint64_t));
swapped = __builtin_bswap64(swapped ^ sentinel);
FURI_LOG_D(TAG, "PACS: (%d) %016llx", bitLength, swapped);
return swapped;
}

static bool hid_parse(const NfcDevice* device, FuriString* parsed_data) {
furi_assert(device);

const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);

bool parsed = false;

do {
// verify key
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);
if(key != hid_key) break;

// Currently doesn't support bit length > 63
const uint8_t* credential_block = data->block[5].data + 8;

uint8_t bitLength = get_bit_length(credential_block);
if(bitLength == 0) break;

uint64_t credential = get_pacs_bits(credential_block, bitLength);
if(credential == 0) break;

furi_string_printf(parsed_data, "\e#HID Card\n%dbit\n%llx", bitLength, credential);

parsed = true;

} while(false);

return parsed;
}

/* Actual implementation of app<>plugin interface */
static const NfcSupportedCardsPlugin hid_plugin = {
.protocol = NfcProtocolMfClassic,
.verify = hid_verify,
.read = hid_read,
.parse = hid_parse,
};

/* Plugin descriptor to comply with basic plugin specification */
static const FlipperAppPluginDescriptor hid_plugin_descriptor = {
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
.entry_point = &hid_plugin,
};

/* Plugin entry point - must return a pointer to const descriptor */
const FlipperAppPluginDescriptor* hid_plugin_ep() {
return &hid_plugin_descriptor;
}
34 changes: 34 additions & 0 deletions applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc
Original file line number Diff line number Diff line change
Expand Up @@ -3831,3 +3831,37 @@ ADC169F922CB
# Volgograd (Russia) Volna transport cards keys
2B787A063D5D
D37C8F1793F7
# Bandai Namco Passport [fka Banapassport] / Sega Aime Card
6090D00632F5
019761AA8082
574343467632
A99164400748
62742819AD7C
CC5075E42BA1
B9DF35A0814C
8AF9C718F23D
58CD5C3673CB
FC80E88EB88C
7A3CDAD7C023
30424C029001
024E4E44001F
ECBBFA57C6AD
4757698143BD
1D30972E6485
F8526D1A8D6D
1300EC8C7E80
F80A65A87FFA
DEB06ED4AF8E
4AD96BF28190
000390014D41
0800F9917CB0
730050555253
4146D4A956C4
131157FBB126
E69DD9015A43
337237F254D5
9A8389F32FBF
7B8FB4A7100B
C8382A233993
7B304F2A12A6
FC9418BF788B
2 changes: 1 addition & 1 deletion lib/nfc/nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static int32_t nfc_worker_listener(void* context) {
} else if(command == NfcCommandReset) {
furi_hal_nfc_listener_enable_rx();
} else if(command == NfcCommandSleep) {
furi_hal_nfc_listener_sleep();
furi_hal_nfc_listener_idle();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/felica/felica_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ typedef struct FelicaPoller FelicaPoller;
* @brief Enumeration of possible Felica poller event types.
*/
typedef enum {
FelicaPollerEventTypeError, /**< The card was activated by the poller. */
FelicaPollerEventTypeReady, /**< An error occured during activation procedure. */
FelicaPollerEventTypeError, /**< An error occured during activation procedure. */
FelicaPollerEventTypeReady, /**< The card was activated by the poller. */
} FelicaPollerEventType;

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/iso14443_3a/iso14443_3a_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ typedef struct Iso14443_3aPoller Iso14443_3aPoller;
* @brief Enumeration of possible Iso14443_3a poller event types.
*/
typedef enum {
Iso14443_3aPollerEventTypeError, /**< The card was activated by the poller. */
Iso14443_3aPollerEventTypeReady, /**< An error occured during activation procedure. */
Iso14443_3aPollerEventTypeError, /**< An error occured during activation procedure. */
Iso14443_3aPollerEventTypeReady, /**< The card was activated by the poller. */
} Iso14443_3aPollerEventType;

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/iso14443_3b/iso14443_3b_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ typedef struct Iso14443_3bPoller Iso14443_3bPoller;
* @brief Enumeration of possible Iso14443_3b poller event types.
*/
typedef enum {
Iso14443_3bPollerEventTypeError, /**< The card was activated by the poller. */
Iso14443_3bPollerEventTypeReady, /**< An error occured during activation procedure. */
Iso14443_3bPollerEventTypeError, /**< An error occured during activation procedure. */
Iso14443_3bPollerEventTypeReady, /**< The card was activated by the poller. */
} Iso14443_3bPollerEventType;

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ typedef struct Iso14443_4aPoller Iso14443_4aPoller;
* @brief Enumeration of possible Iso14443_4a poller event types.
*/
typedef enum {
Iso14443_4aPollerEventTypeError, /**< The card was activated by the poller. */
Iso14443_4aPollerEventTypeReady, /**< An error occured during activation procedure. */
Iso14443_4aPollerEventTypeError, /**< An error occured during activation procedure. */
Iso14443_4aPollerEventTypeReady, /**< The card was activated by the poller. */
} Iso14443_4aPollerEventType;

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/iso14443_4b/iso14443_4b_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ typedef struct Iso14443_4bPoller Iso14443_4bPoller;
* @brief Enumeration of possible Iso14443_4b poller event types.
*/
typedef enum {
Iso14443_4bPollerEventTypeError, /**< The card was activated by the poller. */
Iso14443_4bPollerEventTypeReady, /**< An error occured during activation procedure. */
Iso14443_4bPollerEventTypeError, /**< An error occured during activation procedure. */
Iso14443_4bPollerEventTypeReady, /**< The card was activated by the poller. */
} Iso14443_4bPollerEventType;

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/nfc/protocols/iso15693_3/iso15693_3_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ typedef struct Iso15693_3Poller Iso15693_3Poller;
* @brief Enumeration of possible Iso15693_3 poller event types.
*/
typedef enum {
Iso15693_3PollerEventTypeError, /**< The card was activated by the poller. */
Iso15693_3PollerEventTypeReady, /**< An error occured during activation procedure. */
Iso15693_3PollerEventTypeError, /**< An error occured during activation procedure. */
Iso15693_3PollerEventTypeReady, /**< The card was activated by the poller. */
} Iso15693_3PollerEventType;

/**
Expand Down
6 changes: 5 additions & 1 deletion lib/nfc/protocols/mf_classic/mf_classic_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static void mf_classic_listener_reset_state(MfClassicListener* instance) {
instance->state = MfClassicListenerStateIdle;
instance->cmd_in_progress = false;
instance->current_cmd_handler_idx = 0;
instance->write_block = 0;
instance->transfer_value = 0;
instance->transfer_valid = false;
instance->value_cmd = MfClassicValueCommandInvalid;
Expand Down Expand Up @@ -240,11 +241,13 @@ static MfClassicListenerCommand mf_classic_listener_write_block_first_part_handl

uint8_t block_num = bit_buffer_get_byte(buff, 1);
if(block_num >= instance->total_block_num) break;
if(block_num == 0) break;

uint8_t sector_num = mf_classic_get_sector_by_block(block_num);
uint8_t auth_sector_num = mf_classic_get_sector_by_block(auth_ctx->block_num);
if(sector_num != auth_sector_num) break;

instance->write_block = block_num;
instance->cmd_in_progress = true;
instance->current_cmd_handler_idx++;
command = MfClassicListenerCommandAck;
Expand All @@ -265,7 +268,7 @@ static MfClassicListenerCommand mf_classic_listener_write_block_second_part_hand
size_t buff_size = bit_buffer_get_size_bytes(buff);
if(buff_size != sizeof(MfClassicBlock)) break;

uint8_t block_num = auth_ctx->block_num;
uint8_t block_num = instance->write_block;
MfClassicKeyType key_type = auth_ctx->key_type;
MfClassicBlock block = instance->data->block[block_num];

Expand Down Expand Up @@ -609,6 +612,7 @@ NfcCommand mf_classic_listener_run(NfcGenericEvent event, void* context) {

mf_classic_listener_send_short_frame(instance, nack);
mf_classic_listener_reset_state(instance);
command = NfcCommandSleep;
} else if(mfc_command == MfClassicListenerCommandSilent) {
command = NfcCommandReset;
} else if(mfc_command == MfClassicListenerCommandSleep) {
Expand Down
3 changes: 3 additions & 0 deletions lib/nfc/protocols/mf_classic/mf_classic_listener_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ struct MfClassicListener {
Crypto1* crypto;
MfClassicAuthContext auth_context;

// Write block context
uint8_t write_block;

// Value operation data
int32_t transfer_value;
bool transfer_valid;
Expand Down
2 changes: 1 addition & 1 deletion scripts/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def init(self):
self.parser_list.set_defaults(func=self.list)

self.parser_stress = self.subparsers.add_parser("stress", help="Stress test")
self.parser.add_argument(
self.parser_stress.add_argument(
"-c", "--count", type=int, default=10, help="Iteration count"
)
self.parser_stress.add_argument("flipper_path", help="Flipper path")
Expand Down

0 comments on commit e5ceef3

Please sign in to comment.