| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- #include "reader_analyzer.h"
- #include <lib/nfc/protocols/nfc_util.h>
- #include <lib/nfc/protocols/mifare_classic.h>
- #include <m-array.h>
- #include "mfkey32.h"
- #include "nfc_debug_pcap.h"
- #include "nfc_debug_log.h"
- #define TAG "ReaderAnalyzer"
- #define READER_ANALYZER_MAX_BUFF_SIZE (1024)
- typedef struct {
- bool reader_to_tag;
- bool crc_dropped;
- uint16_t len;
- } ReaderAnalyzerHeader;
- typedef enum {
- ReaderAnalyzerNfcDataMfClassic,
- } ReaderAnalyzerNfcData;
- struct ReaderAnalyzer {
- FuriHalNfcDevData nfc_data;
- bool alive;
- FuriStreamBuffer* stream;
- FuriThread* thread;
- ReaderAnalyzerParseDataCallback callback;
- void* context;
- ReaderAnalyzerMode mode;
- Mfkey32* mfkey32;
- NfcDebugLog* debug_log;
- NfcDebugPcap* pcap;
- };
- const FuriHalNfcDevData reader_analyzer_nfc_data[] = {
- [ReaderAnalyzerNfcDataMfClassic] =
- {.sak = 0x08,
- .atqa = {0x44, 0x00},
- .interface = FuriHalNfcInterfaceRf,
- .type = FuriHalNfcTypeA,
- .uid_len = 7,
- .uid = {0x04, 0x77, 0x70, 0x2A, 0x23, 0x4F, 0x80},
- .cuid = 0x2A234F80},
- };
- void reader_analyzer_parse(ReaderAnalyzer* instance, uint8_t* buffer, size_t size) {
- if(size < sizeof(ReaderAnalyzerHeader)) return;
- size_t bytes_i = 0;
- while(bytes_i < size) {
- ReaderAnalyzerHeader* header = (ReaderAnalyzerHeader*)&buffer[bytes_i];
- uint16_t len = header->len;
- if(bytes_i + len > size) break;
- bytes_i += sizeof(ReaderAnalyzerHeader);
- if(instance->mfkey32) {
- mfkey32_process_data(
- instance->mfkey32,
- &buffer[bytes_i],
- len,
- header->reader_to_tag,
- header->crc_dropped);
- }
- if(instance->pcap) {
- nfc_debug_pcap_process_data(
- instance->pcap, &buffer[bytes_i], len, header->reader_to_tag, header->crc_dropped);
- }
- if(instance->debug_log) {
- nfc_debug_log_process_data(
- instance->debug_log,
- &buffer[bytes_i],
- len,
- header->reader_to_tag,
- header->crc_dropped);
- }
- bytes_i += len;
- }
- }
- int32_t reader_analyzer_thread(void* context) {
- ReaderAnalyzer* reader_analyzer = context;
- uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {};
- while(reader_analyzer->alive || !furi_stream_buffer_is_empty(reader_analyzer->stream)) {
- size_t ret = furi_stream_buffer_receive(
- reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50);
- if(ret) {
- reader_analyzer_parse(reader_analyzer, buffer, ret);
- }
- }
- return 0;
- }
- ReaderAnalyzer* reader_analyzer_alloc() {
- ReaderAnalyzer* instance = malloc(sizeof(ReaderAnalyzer));
- instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
- instance->alive = false;
- instance->stream =
- furi_stream_buffer_alloc(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader));
- instance->thread = furi_thread_alloc();
- furi_thread_set_name(instance->thread, "ReaderAnalyzerWorker");
- furi_thread_set_stack_size(instance->thread, 2048);
- furi_thread_set_callback(instance->thread, reader_analyzer_thread);
- furi_thread_set_context(instance->thread, instance);
- furi_thread_set_priority(instance->thread, FuriThreadPriorityLow);
- return instance;
- }
- static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) {
- furi_assert(context);
- ReaderAnalyzer* instance = context;
- if(event == Mfkey32EventParamCollected) {
- if(instance->callback) {
- instance->callback(ReaderAnalyzerEventMfkeyCollected, instance->context);
- }
- }
- }
- void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
- furi_assert(instance);
- furi_stream_buffer_reset(instance->stream);
- if(mode & ReaderAnalyzerModeDebugLog) {
- instance->debug_log = nfc_debug_log_alloc();
- }
- if(mode & ReaderAnalyzerModeMfkey) {
- instance->mfkey32 = mfkey32_alloc(instance->nfc_data.cuid);
- if(instance->mfkey32) {
- mfkey32_set_callback(instance->mfkey32, reader_analyzer_mfkey_callback, instance);
- }
- }
- if(mode & ReaderAnalyzerModeDebugPcap) {
- instance->pcap = nfc_debug_pcap_alloc();
- }
- instance->alive = true;
- furi_thread_start(instance->thread);
- }
- void reader_analyzer_stop(ReaderAnalyzer* instance) {
- furi_assert(instance);
- instance->alive = false;
- furi_thread_join(instance->thread);
- if(instance->debug_log) {
- nfc_debug_log_free(instance->debug_log);
- instance->debug_log = NULL;
- }
- if(instance->mfkey32) {
- mfkey32_free(instance->mfkey32);
- instance->mfkey32 = NULL;
- }
- if(instance->pcap) {
- nfc_debug_pcap_free(instance->pcap);
- }
- }
- void reader_analyzer_free(ReaderAnalyzer* instance) {
- furi_assert(instance);
- reader_analyzer_stop(instance);
- furi_thread_free(instance->thread);
- furi_stream_buffer_free(instance->stream);
- free(instance);
- }
- void reader_analyzer_set_callback(
- ReaderAnalyzer* instance,
- ReaderAnalyzerParseDataCallback callback,
- void* context) {
- furi_assert(instance);
- furi_assert(callback);
- instance->callback = callback;
- instance->context = context;
- }
- NfcProtocol
- reader_analyzer_guess_protocol(ReaderAnalyzer* instance, uint8_t* buff_rx, uint16_t len) {
- furi_assert(instance);
- furi_assert(buff_rx);
- UNUSED(len);
- NfcProtocol protocol = NfcDeviceProtocolUnknown;
- if((buff_rx[0] == 0x60) || (buff_rx[0] == 0x61)) {
- protocol = NfcDeviceProtocolMifareClassic;
- }
- return protocol;
- }
- FuriHalNfcDevData* reader_analyzer_get_nfc_data(ReaderAnalyzer* instance) {
- furi_assert(instance);
- return &instance->nfc_data;
- }
- static void reader_analyzer_write(
- ReaderAnalyzer* instance,
- uint8_t* data,
- uint16_t len,
- bool reader_to_tag,
- bool crc_dropped) {
- ReaderAnalyzerHeader header = {
- .reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len};
- size_t data_sent = 0;
- data_sent = furi_stream_buffer_send(
- instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever);
- if(data_sent != sizeof(ReaderAnalyzerHeader)) {
- FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader));
- }
- data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever);
- if(data_sent != len) {
- FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len);
- }
- }
- static void
- reader_analyzer_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
- UNUSED(crc_dropped);
- ReaderAnalyzer* reader_analyzer = context;
- uint16_t bytes = bits < 8 ? 1 : bits / 8;
- reader_analyzer_write(reader_analyzer, data, bytes, false, crc_dropped);
- }
- static void
- reader_analyzer_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
- UNUSED(crc_dropped);
- ReaderAnalyzer* reader_analyzer = context;
- uint16_t bytes = bits < 8 ? 1 : bits / 8;
- reader_analyzer_write(reader_analyzer, data, bytes, true, crc_dropped);
- }
- void reader_analyzer_prepare_tx_rx(
- ReaderAnalyzer* instance,
- FuriHalNfcTxRxContext* tx_rx,
- bool is_picc) {
- furi_assert(instance);
- furi_assert(tx_rx);
- if(is_picc) {
- tx_rx->sniff_tx = reader_analyzer_write_rx;
- tx_rx->sniff_rx = reader_analyzer_write_tx;
- } else {
- tx_rx->sniff_rx = reader_analyzer_write_rx;
- tx_rx->sniff_tx = reader_analyzer_write_tx;
- }
- tx_rx->sniff_context = instance;
- }
|