reader_analyzer.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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 = furi_thread_alloc();
  90. furi_thread_set_name(instance->thread, "ReaderAnalyzerWorker");
  91. furi_thread_set_stack_size(instance->thread, 2048);
  92. furi_thread_set_callback(instance->thread, reader_analyzer_thread);
  93. furi_thread_set_context(instance->thread, instance);
  94. furi_thread_set_priority(instance->thread, FuriThreadPriorityLow);
  95. return instance;
  96. }
  97. static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) {
  98. furi_assert(context);
  99. ReaderAnalyzer* instance = context;
  100. if(event == Mfkey32EventParamCollected) {
  101. if(instance->callback) {
  102. instance->callback(ReaderAnalyzerEventMfkeyCollected, instance->context);
  103. }
  104. }
  105. }
  106. void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
  107. furi_assert(instance);
  108. furi_stream_buffer_reset(instance->stream);
  109. if(mode & ReaderAnalyzerModeDebugLog) {
  110. instance->debug_log = nfc_debug_log_alloc();
  111. }
  112. if(mode & ReaderAnalyzerModeMfkey) {
  113. instance->mfkey32 = mfkey32_alloc(instance->nfc_data.cuid);
  114. if(instance->mfkey32) {
  115. mfkey32_set_callback(instance->mfkey32, reader_analyzer_mfkey_callback, instance);
  116. }
  117. }
  118. if(mode & ReaderAnalyzerModeDebugPcap) {
  119. instance->pcap = nfc_debug_pcap_alloc();
  120. }
  121. instance->alive = true;
  122. furi_thread_start(instance->thread);
  123. }
  124. void reader_analyzer_stop(ReaderAnalyzer* instance) {
  125. furi_assert(instance);
  126. instance->alive = false;
  127. furi_thread_join(instance->thread);
  128. if(instance->debug_log) {
  129. nfc_debug_log_free(instance->debug_log);
  130. instance->debug_log = NULL;
  131. }
  132. if(instance->mfkey32) {
  133. mfkey32_free(instance->mfkey32);
  134. instance->mfkey32 = NULL;
  135. }
  136. if(instance->pcap) {
  137. nfc_debug_pcap_free(instance->pcap);
  138. }
  139. }
  140. void reader_analyzer_free(ReaderAnalyzer* instance) {
  141. furi_assert(instance);
  142. reader_analyzer_stop(instance);
  143. furi_thread_free(instance->thread);
  144. furi_stream_buffer_free(instance->stream);
  145. free(instance);
  146. }
  147. void reader_analyzer_set_callback(
  148. ReaderAnalyzer* instance,
  149. ReaderAnalyzerParseDataCallback callback,
  150. void* context) {
  151. furi_assert(instance);
  152. furi_assert(callback);
  153. instance->callback = callback;
  154. instance->context = context;
  155. }
  156. NfcProtocol
  157. reader_analyzer_guess_protocol(ReaderAnalyzer* instance, uint8_t* buff_rx, uint16_t len) {
  158. furi_assert(instance);
  159. furi_assert(buff_rx);
  160. UNUSED(len);
  161. NfcProtocol protocol = NfcDeviceProtocolUnknown;
  162. if((buff_rx[0] == 0x60) || (buff_rx[0] == 0x61)) {
  163. protocol = NfcDeviceProtocolMifareClassic;
  164. }
  165. return protocol;
  166. }
  167. FuriHalNfcDevData* reader_analyzer_get_nfc_data(ReaderAnalyzer* instance) {
  168. furi_assert(instance);
  169. instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
  170. return &instance->nfc_data;
  171. }
  172. void reader_analyzer_set_nfc_data(ReaderAnalyzer* instance, FuriHalNfcDevData* nfc_data) {
  173. furi_assert(instance);
  174. furi_assert(nfc_data);
  175. memcpy(&instance->nfc_data, nfc_data, sizeof(FuriHalNfcDevData));
  176. }
  177. static void reader_analyzer_write(
  178. ReaderAnalyzer* instance,
  179. uint8_t* data,
  180. uint16_t len,
  181. bool reader_to_tag,
  182. bool crc_dropped) {
  183. ReaderAnalyzerHeader header = {
  184. .reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len};
  185. size_t data_sent = 0;
  186. data_sent = furi_stream_buffer_send(
  187. instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever);
  188. if(data_sent != sizeof(ReaderAnalyzerHeader)) {
  189. FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader));
  190. }
  191. data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever);
  192. if(data_sent != len) {
  193. FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len);
  194. }
  195. }
  196. static void
  197. reader_analyzer_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  198. UNUSED(crc_dropped);
  199. ReaderAnalyzer* reader_analyzer = context;
  200. uint16_t bytes = bits < 8 ? 1 : bits / 8;
  201. reader_analyzer_write(reader_analyzer, data, bytes, false, crc_dropped);
  202. }
  203. static void
  204. reader_analyzer_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  205. UNUSED(crc_dropped);
  206. ReaderAnalyzer* reader_analyzer = context;
  207. uint16_t bytes = bits < 8 ? 1 : bits / 8;
  208. reader_analyzer_write(reader_analyzer, data, bytes, true, crc_dropped);
  209. }
  210. void reader_analyzer_prepare_tx_rx(
  211. ReaderAnalyzer* instance,
  212. FuriHalNfcTxRxContext* tx_rx,
  213. bool is_picc) {
  214. furi_assert(instance);
  215. furi_assert(tx_rx);
  216. if(is_picc) {
  217. tx_rx->sniff_tx = reader_analyzer_write_rx;
  218. tx_rx->sniff_rx = reader_analyzer_write_tx;
  219. } else {
  220. tx_rx->sniff_rx = reader_analyzer_write_rx;
  221. tx_rx->sniff_tx = reader_analyzer_write_tx;
  222. }
  223. tx_rx->sniff_context = instance;
  224. }