reader_analyzer.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #include "reader_analyzer.h"
  2. #include <lib/nfc/protocols/nfc_util.h>
  3. #include <lib/nfc/protocols/mifare_classic.h>
  4. #include <m-array.h>
  5. #include "mfkey32.h"
  6. #include "nfc_debug_pcap.h"
  7. #include "nfc_debug_log.h"
  8. #define TAG "ReaderAnalyzer"
  9. #define READER_ANALYZER_MAX_BUFF_SIZE (1024)
  10. typedef struct {
  11. bool reader_to_tag;
  12. bool crc_dropped;
  13. uint16_t len;
  14. } ReaderAnalyzerHeader;
  15. typedef enum {
  16. ReaderAnalyzerNfcDataMfClassic,
  17. } ReaderAnalyzerNfcData;
  18. struct ReaderAnalyzer {
  19. FuriHalNfcDevData nfc_data;
  20. bool alive;
  21. FuriStreamBuffer* stream;
  22. FuriThread* thread;
  23. ReaderAnalyzerParseDataCallback callback;
  24. void* context;
  25. ReaderAnalyzerMode mode;
  26. Mfkey32* mfkey32;
  27. NfcDebugLog* debug_log;
  28. NfcDebugPcap* pcap;
  29. };
  30. const FuriHalNfcDevData reader_analyzer_nfc_data[] = {
  31. [ReaderAnalyzerNfcDataMfClassic] =
  32. {.sak = 0x08,
  33. .atqa = {0x44, 0x00},
  34. .interface = FuriHalNfcInterfaceRf,
  35. .type = FuriHalNfcTypeA,
  36. .uid_len = 7,
  37. .uid = {0x04, 0x77, 0x70, 0x2A, 0x23, 0x4F, 0x80},
  38. .cuid = 0x2A234F80},
  39. };
  40. void reader_analyzer_parse(ReaderAnalyzer* instance, uint8_t* buffer, size_t size) {
  41. if(size < sizeof(ReaderAnalyzerHeader)) return;
  42. size_t bytes_i = 0;
  43. while(bytes_i < size) {
  44. ReaderAnalyzerHeader* header = (ReaderAnalyzerHeader*)&buffer[bytes_i];
  45. uint16_t len = header->len;
  46. if(bytes_i + len > size) break;
  47. bytes_i += sizeof(ReaderAnalyzerHeader);
  48. if(instance->mfkey32) {
  49. mfkey32_process_data(
  50. instance->mfkey32,
  51. &buffer[bytes_i],
  52. len,
  53. header->reader_to_tag,
  54. header->crc_dropped);
  55. }
  56. if(instance->pcap) {
  57. nfc_debug_pcap_process_data(
  58. instance->pcap, &buffer[bytes_i], len, header->reader_to_tag, header->crc_dropped);
  59. }
  60. if(instance->debug_log) {
  61. nfc_debug_log_process_data(
  62. instance->debug_log,
  63. &buffer[bytes_i],
  64. len,
  65. header->reader_to_tag,
  66. header->crc_dropped);
  67. }
  68. bytes_i += len;
  69. }
  70. }
  71. int32_t reader_analyzer_thread(void* context) {
  72. ReaderAnalyzer* reader_analyzer = context;
  73. uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {};
  74. while(reader_analyzer->alive || !furi_stream_buffer_is_empty(reader_analyzer->stream)) {
  75. size_t ret = furi_stream_buffer_receive(
  76. reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50);
  77. if(ret) {
  78. reader_analyzer_parse(reader_analyzer, buffer, ret);
  79. }
  80. }
  81. return 0;
  82. }
  83. ReaderAnalyzer* reader_analyzer_alloc() {
  84. ReaderAnalyzer* instance = malloc(sizeof(ReaderAnalyzer));
  85. instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
  86. instance->alive = false;
  87. instance->stream =
  88. furi_stream_buffer_alloc(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader));
  89. instance->thread =
  90. furi_thread_alloc_ex("ReaderAnalyzerWorker", 2048, reader_analyzer_thread, instance);
  91. furi_thread_set_priority(instance->thread, FuriThreadPriorityLow);
  92. return instance;
  93. }
  94. static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) {
  95. furi_assert(context);
  96. ReaderAnalyzer* instance = context;
  97. if(event == Mfkey32EventParamCollected) {
  98. if(instance->callback) {
  99. instance->callback(ReaderAnalyzerEventMfkeyCollected, instance->context);
  100. }
  101. }
  102. }
  103. void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
  104. furi_assert(instance);
  105. furi_stream_buffer_reset(instance->stream);
  106. if(mode & ReaderAnalyzerModeDebugLog) {
  107. instance->debug_log = nfc_debug_log_alloc();
  108. }
  109. if(mode & ReaderAnalyzerModeMfkey) {
  110. instance->mfkey32 = mfkey32_alloc(instance->nfc_data.cuid);
  111. if(instance->mfkey32) {
  112. mfkey32_set_callback(instance->mfkey32, reader_analyzer_mfkey_callback, instance);
  113. }
  114. }
  115. if(mode & ReaderAnalyzerModeDebugPcap) {
  116. instance->pcap = nfc_debug_pcap_alloc();
  117. }
  118. instance->alive = true;
  119. furi_thread_start(instance->thread);
  120. }
  121. void reader_analyzer_stop(ReaderAnalyzer* instance) {
  122. furi_assert(instance);
  123. instance->alive = false;
  124. furi_thread_join(instance->thread);
  125. if(instance->debug_log) {
  126. nfc_debug_log_free(instance->debug_log);
  127. instance->debug_log = NULL;
  128. }
  129. if(instance->mfkey32) {
  130. mfkey32_free(instance->mfkey32);
  131. instance->mfkey32 = NULL;
  132. }
  133. if(instance->pcap) {
  134. nfc_debug_pcap_free(instance->pcap);
  135. instance->pcap = NULL;
  136. }
  137. }
  138. void reader_analyzer_free(ReaderAnalyzer* instance) {
  139. furi_assert(instance);
  140. reader_analyzer_stop(instance);
  141. furi_thread_free(instance->thread);
  142. furi_stream_buffer_free(instance->stream);
  143. free(instance);
  144. }
  145. void reader_analyzer_set_callback(
  146. ReaderAnalyzer* instance,
  147. ReaderAnalyzerParseDataCallback callback,
  148. void* context) {
  149. furi_assert(instance);
  150. furi_assert(callback);
  151. instance->callback = callback;
  152. instance->context = context;
  153. }
  154. NfcProtocol
  155. reader_analyzer_guess_protocol(ReaderAnalyzer* instance, uint8_t* buff_rx, uint16_t len) {
  156. furi_assert(instance);
  157. furi_assert(buff_rx);
  158. UNUSED(len);
  159. NfcProtocol protocol = NfcDeviceProtocolUnknown;
  160. if((buff_rx[0] == 0x60) || (buff_rx[0] == 0x61)) {
  161. protocol = NfcDeviceProtocolMifareClassic;
  162. }
  163. return protocol;
  164. }
  165. FuriHalNfcDevData* reader_analyzer_get_nfc_data(ReaderAnalyzer* instance) {
  166. furi_assert(instance);
  167. instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
  168. return &instance->nfc_data;
  169. }
  170. void reader_analyzer_set_nfc_data(ReaderAnalyzer* instance, FuriHalNfcDevData* nfc_data) {
  171. furi_assert(instance);
  172. furi_assert(nfc_data);
  173. memcpy(&instance->nfc_data, nfc_data, sizeof(FuriHalNfcDevData));
  174. }
  175. static void reader_analyzer_write(
  176. ReaderAnalyzer* instance,
  177. uint8_t* data,
  178. uint16_t len,
  179. bool reader_to_tag,
  180. bool crc_dropped) {
  181. ReaderAnalyzerHeader header = {
  182. .reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len};
  183. size_t data_sent = 0;
  184. data_sent = furi_stream_buffer_send(
  185. instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever);
  186. if(data_sent != sizeof(ReaderAnalyzerHeader)) {
  187. FURI_LOG_W(TAG, "Sent %zu out of %zu bytes", data_sent, sizeof(ReaderAnalyzerHeader));
  188. }
  189. data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever);
  190. if(data_sent != len) {
  191. FURI_LOG_W(TAG, "Sent %zu out of %u bytes", data_sent, len);
  192. }
  193. }
  194. static void
  195. reader_analyzer_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  196. UNUSED(crc_dropped);
  197. ReaderAnalyzer* reader_analyzer = context;
  198. uint16_t bytes = bits < 8 ? 1 : bits / 8;
  199. reader_analyzer_write(reader_analyzer, data, bytes, false, crc_dropped);
  200. }
  201. static void
  202. reader_analyzer_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  203. UNUSED(crc_dropped);
  204. ReaderAnalyzer* reader_analyzer = context;
  205. uint16_t bytes = bits < 8 ? 1 : bits / 8;
  206. reader_analyzer_write(reader_analyzer, data, bytes, true, crc_dropped);
  207. }
  208. void reader_analyzer_prepare_tx_rx(
  209. ReaderAnalyzer* instance,
  210. FuriHalNfcTxRxContext* tx_rx,
  211. bool is_picc) {
  212. furi_assert(instance);
  213. furi_assert(tx_rx);
  214. if(is_picc) {
  215. tx_rx->sniff_tx = reader_analyzer_write_rx;
  216. tx_rx->sniff_rx = reader_analyzer_write_tx;
  217. } else {
  218. tx_rx->sniff_rx = reader_analyzer_write_rx;
  219. tx_rx->sniff_tx = reader_analyzer_write_tx;
  220. }
  221. tx_rx->sniff_context = instance;
  222. }