mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-18 00:33:09 +00:00
f6eb79e1e5
* Merge remote-tracking branch 'origin/dev' into dev * Add basic API interface (inspired by advanced plugins example), modify NfcSupportedCardsLoadContext to contain a pointer to a resolver * WIP: API resolver implemented / passed to plugin via context, still having resolution issues * Attempt to add constants to the nfc_app_api_table list * WIP: We're defining the constants directly in nfc_app_api.c to see if this fixes our woes, which it does not. * WIP: Remove furi_assert(false) (lmao) * Working implementation of Gallagher decoding via exposed plugin API * lib: api_hashtable: change log level for symbol not found message * nfc app: alloc composite resolver along with supported cards * nfc app: rework nfc api structure * nfc app: fix memory leakage in supported cards Co-authored-by: gornekich <n.gorbadey@gmail.com>
87 lines
No EOL
3.2 KiB
C
87 lines
No EOL
3.2 KiB
C
/* gallagher.c - NFC supported cards plugin for Gallagher access control cards (New Zealand).
|
|
* Author: Nick Mooney (nick@mooney.nz)
|
|
*
|
|
* Reference: https://github.com/megabug/gallagher-research
|
|
*/
|
|
|
|
#include "nfc_supported_card_plugin.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>
|
|
|
|
static bool gallagher_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|
furi_assert(device);
|
|
furi_assert(parsed_data);
|
|
|
|
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
|
|
|
if(!(data->type == MfClassicType1k || data->type == MfClassicType4k)) {
|
|
return false;
|
|
}
|
|
|
|
// It's possible for a single tag to contain multiple credentials,
|
|
// but this is currently unimplementecd.
|
|
const uint8_t credential_sector_start_block_number =
|
|
mf_classic_get_first_block_num_of_sector(GALLAGHER_CREDENTIAL_SECTOR);
|
|
|
|
// 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);
|
|
// 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) {
|
|
return false;
|
|
}
|
|
|
|
// Test 2: The contents of the second block should be equal to the GALLAGHER_CARDAX_ASCII constant.
|
|
const uint8_t* cardax_block_start_ptr =
|
|
&data->block[credential_sector_start_block_number + 1].data[0];
|
|
if(memcmp(cardax_block_start_ptr, GALLAGHER_CARDAX_ASCII, MF_CLASSIC_BLOCK_SIZE) != 0) {
|
|
return false;
|
|
}
|
|
|
|
// Deobfuscate the credential data
|
|
GallagherCredential credential;
|
|
gallagher_deobfuscate_and_parse_credential(&credential, credential_block_start_ptr);
|
|
|
|
char display_region = 'A';
|
|
// Per https://github.com/megabug/gallagher-research/blob/master/formats/cardholder/cardholder.md,
|
|
// regions are generally A-P.
|
|
if(credential.region < 16) {
|
|
display_region = display_region + (char)credential.region;
|
|
} else {
|
|
display_region = '?';
|
|
}
|
|
|
|
furi_string_cat_printf(
|
|
parsed_data,
|
|
"\e#Gallagher NZ\nFacility %c%u\nCard %lu (IL %u)",
|
|
display_region,
|
|
credential.facility,
|
|
credential.card,
|
|
credential.issue);
|
|
return true;
|
|
}
|
|
|
|
static const NfcSupportedCardsPlugin gallagher_plugin = {
|
|
.protocol = NfcProtocolMfClassic,
|
|
.verify = NULL,
|
|
.read = NULL,
|
|
.parse = gallagher_parse,
|
|
};
|
|
|
|
static const FlipperAppPluginDescriptor gallagher_plugin_descriptor = {
|
|
.appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID,
|
|
.ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION,
|
|
.entry_point = &gallagher_plugin,
|
|
};
|
|
|
|
/* Plugin entry point */
|
|
const FlipperAppPluginDescriptor* gallagher_plugin_ep() {
|
|
return &gallagher_plugin_descriptor;
|
|
} |