reader_analyzer.c 7.5 KB

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