nfc_worker.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "nfc_worker_i.h"
  2. #include <furi_hal_rtc.h>
  3. #include "ST25RFAL002/platform.h"
  4. #define TAG "NfcWorker"
  5. /***************************** NFC Worker API *******************************/
  6. NfcWorker* nfc_worker_alloc() {
  7. NfcWorker* nfc_worker = malloc(sizeof(NfcWorker));
  8. // Worker thread attributes
  9. nfc_worker->thread = furi_thread_alloc_ex("NfcWorker", 8192, nfc_worker_task, nfc_worker);
  10. nfc_worker->callback = NULL;
  11. nfc_worker->context = NULL;
  12. nfc_worker->storage = furi_record_open(RECORD_STORAGE);
  13. // Initialize rfal
  14. while(furry_hal_nfc_is_busy()) {
  15. furi_delay_ms(10);
  16. }
  17. nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
  18. return nfc_worker;
  19. }
  20. void nfc_worker_free(NfcWorker* nfc_worker) {
  21. furi_assert(nfc_worker);
  22. furi_thread_free(nfc_worker->thread);
  23. furi_record_close(RECORD_STORAGE);
  24. free(nfc_worker);
  25. }
  26. NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) {
  27. return nfc_worker->state;
  28. }
  29. void nfc_worker_start(
  30. NfcWorker* nfc_worker,
  31. NfcWorkerState state,
  32. NfcDeviceData* dev_data,
  33. NfcWorkerCallback callback,
  34. void* context) {
  35. furi_check(nfc_worker);
  36. //furi_check(dev_data);
  37. while(furry_hal_nfc_is_busy()) {
  38. furi_delay_ms(10);
  39. }
  40. furry_hal_nfc_deinit();
  41. furry_hal_nfc_init();
  42. nfc_worker->callback = callback;
  43. nfc_worker->context = context;
  44. nfc_worker->dev_data = dev_data;
  45. nfc_worker_change_state(nfc_worker, state);
  46. furi_thread_start(nfc_worker->thread);
  47. }
  48. void nfc_worker_stop(NfcWorker* nfc_worker) {
  49. furi_assert(nfc_worker);
  50. furi_assert(nfc_worker->thread);
  51. if(furi_thread_get_state(nfc_worker->thread) != FuriThreadStateStopped) {
  52. furry_hal_nfc_stop();
  53. nfc_worker_change_state(nfc_worker, NfcWorkerStateStop);
  54. furi_thread_join(nfc_worker->thread);
  55. }
  56. }
  57. void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
  58. nfc_worker->state = state;
  59. }
  60. /***************************** NFC Worker Thread *******************************/
  61. int32_t nfc_worker_task(void* context) {
  62. NfcWorker* nfc_worker = context;
  63. furry_hal_nfc_exit_sleep();
  64. if(nfc_worker->state == NfcWorkerStateRead) {
  65. if(nfc_worker->dev_data->read_mode == NfcReadModeAuto) {
  66. nfc_worker_read(nfc_worker);
  67. } else {
  68. nfc_worker_read_type(nfc_worker);
  69. }
  70. } else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
  71. nfc_worker_emulate_uid(nfc_worker);
  72. } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
  73. nfc_worker_emulate_mf_ultralight(nfc_worker);
  74. } else if(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
  75. nfc_worker_mf_ultralight_read_auth(nfc_worker);
  76. }
  77. furry_hal_nfc_sleep();
  78. nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
  79. return 0;
  80. }
  81. static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) {
  82. bool read_success = false;
  83. MfUltralightReader reader = {};
  84. MfUltralightData data = {};
  85. do {
  86. furry_hal_nfc_sleep();
  87. // Otherwise, try to read as usual
  88. if(!furry_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break;
  89. if(!mf_ul_read_card(tx_rx, &reader, &data)) break;
  90. // Copy data
  91. nfc_worker->dev_data->mf_ul_data = data;
  92. read_success = true;
  93. } while(false);
  94. return read_success;
  95. }
  96. static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) {
  97. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  98. bool card_read = false;
  99. furry_hal_nfc_sleep();
  100. if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
  101. FURI_LOG_I(TAG, "Mifare Ultralight / NTAG detected");
  102. nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl;
  103. card_read = nfc_worker_read_mf_ultralight(nfc_worker, tx_rx);
  104. } else if(nfc_data->interface == FurryHalNfcInterfaceIsoDep) {
  105. FURI_LOG_I(TAG, "ISO14443-4 card detected");
  106. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  107. card_read = true;
  108. } else {
  109. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  110. card_read = true;
  111. }
  112. return card_read;
  113. }
  114. void nfc_worker_read(NfcWorker* nfc_worker) {
  115. furi_assert(nfc_worker);
  116. furi_assert(nfc_worker->callback);
  117. nfc_device_data_clear(nfc_worker->dev_data);
  118. NfcDeviceData* dev_data = nfc_worker->dev_data;
  119. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  120. FurryHalNfcTxRxContext tx_rx = {};
  121. NfcWorkerEvent event = 0;
  122. bool card_not_detected_notified = false;
  123. while(nfc_worker->state == NfcWorkerStateRead) {
  124. if(furry_hal_nfc_detect(nfc_data, 300)) {
  125. // Process first found device
  126. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  127. card_not_detected_notified = false;
  128. if(nfc_data->type == FurryHalNfcTypeA) {
  129. if(nfc_worker_read_nfca(nfc_worker, &tx_rx)) {
  130. if(dev_data->protocol == NfcDeviceProtocolMifareUl) {
  131. event = NfcWorkerEventReadMfUltralight;
  132. break;
  133. } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
  134. event = NfcWorkerEventReadMfClassicDone;
  135. break;
  136. } else if(dev_data->protocol == NfcDeviceProtocolMifareDesfire) {
  137. event = NfcWorkerEventReadMfDesfire;
  138. break;
  139. } else if(dev_data->protocol == NfcDeviceProtocolEMV) {
  140. event = NfcWorkerEventReadBankCard;
  141. break;
  142. } else if(dev_data->protocol == NfcDeviceProtocolUnknown) {
  143. event = NfcWorkerEventReadUidNfcA;
  144. break;
  145. }
  146. } else {
  147. if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
  148. event = NfcWorkerEventReadMfClassicDictAttackRequired;
  149. break;
  150. }
  151. }
  152. } else if(nfc_data->type == FurryHalNfcTypeB) {
  153. event = NfcWorkerEventReadUidNfcB;
  154. break;
  155. } else if(nfc_data->type == FurryHalNfcTypeF) {
  156. event = NfcWorkerEventReadUidNfcF;
  157. break;
  158. }
  159. } else {
  160. if(!card_not_detected_notified) {
  161. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  162. card_not_detected_notified = true;
  163. }
  164. }
  165. furry_hal_nfc_sleep();
  166. furi_delay_ms(100);
  167. }
  168. // Notify caller and exit
  169. if(event > NfcWorkerEventReserved) {
  170. nfc_worker->callback(event, nfc_worker->context);
  171. }
  172. }
  173. void nfc_worker_read_type(NfcWorker* nfc_worker) {
  174. furi_assert(nfc_worker);
  175. furi_assert(nfc_worker->callback);
  176. NfcReadMode read_mode = nfc_worker->dev_data->read_mode;
  177. nfc_device_data_clear(nfc_worker->dev_data);
  178. //NfcDeviceData* dev_data = nfc_worker->dev_data;
  179. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  180. FurryHalNfcTxRxContext tx_rx = {};
  181. NfcWorkerEvent event = 0;
  182. bool card_not_detected_notified = false;
  183. while(nfc_worker->state == NfcWorkerStateRead) {
  184. if(furry_hal_nfc_detect(nfc_data, 300)) {
  185. FURI_LOG_D(TAG, "Card detected");
  186. furry_hal_nfc_sleep();
  187. // Process first found device
  188. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  189. card_not_detected_notified = false;
  190. if(nfc_data->type == FurryHalNfcTypeA) {
  191. if(read_mode == NfcReadModeMfClassic) {
  192. // none
  193. } else if(read_mode == NfcReadModeMfUltralight) {
  194. FURI_LOG_I(TAG, "Mifare Ultralight / NTAG");
  195. nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl;
  196. if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) {
  197. event = NfcWorkerEventReadMfUltralight;
  198. break;
  199. }
  200. } else if(read_mode == NfcReadModeNFCA) {
  201. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  202. event = NfcWorkerEventReadUidNfcA;
  203. break;
  204. }
  205. }
  206. } else {
  207. if(!card_not_detected_notified) {
  208. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  209. card_not_detected_notified = true;
  210. }
  211. }
  212. furry_hal_nfc_sleep();
  213. furi_delay_ms(100);
  214. }
  215. // Notify caller and exit
  216. if(event > NfcWorkerEventReserved) {
  217. nfc_worker->callback(event, nfc_worker->context);
  218. }
  219. }
  220. void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
  221. FurryHalNfcTxRxContext tx_rx = {};
  222. FurryHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;
  223. NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data;
  224. // TODO add support for RATS
  225. // Need to save ATS to support ISO-14443A-4 emulation
  226. while(nfc_worker->state == NfcWorkerStateUidEmulate) {
  227. if(furry_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) {
  228. if(furry_hal_nfc_tx_rx(&tx_rx, 100)) {
  229. reader_data->size = tx_rx.rx_bits / 8;
  230. if(reader_data->size > 0) {
  231. memcpy(reader_data->data, tx_rx.rx_data, reader_data->size);
  232. if(nfc_worker->callback) {
  233. nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
  234. }
  235. }
  236. } else {
  237. FURI_LOG_E(TAG, "Failed to get reader commands");
  238. }
  239. }
  240. }
  241. }
  242. void nfc_worker_mf_ultralight_auth_received_callback(MfUltralightAuth auth, void* context) {
  243. furi_assert(context);
  244. NfcWorker* nfc_worker = context;
  245. nfc_worker->dev_data->mf_ul_auth = auth;
  246. if(nfc_worker->callback) {
  247. nfc_worker->callback(NfcWorkerEventMfUltralightPwdAuth, nfc_worker->context);
  248. }
  249. }
  250. void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) {
  251. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  252. MfUltralightEmulator emulator = {};
  253. mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data);
  254. // TODO rework with reader analyzer
  255. emulator.auth_received_callback = nfc_worker_mf_ultralight_auth_received_callback;
  256. emulator.context = nfc_worker;
  257. rfal_platform_spi_acquire();
  258. while(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
  259. mf_ul_reset_emulation(&emulator, true);
  260. furry_hal_nfc_emulate_nfca(
  261. nfc_data->uid,
  262. nfc_data->uid_len,
  263. nfc_data->atqa,
  264. nfc_data->sak,
  265. mf_ul_prepare_emulation_response,
  266. &emulator,
  267. 5000);
  268. // Check if data was modified
  269. if(emulator.data_changed) {
  270. nfc_worker->dev_data->mf_ul_data = emulator.data;
  271. if(nfc_worker->callback) {
  272. nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
  273. }
  274. emulator.data_changed = false;
  275. }
  276. }
  277. rfal_platform_spi_release();
  278. }
  279. void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) {
  280. furi_assert(nfc_worker);
  281. furi_assert(nfc_worker->callback);
  282. MfUltralightData* data = &nfc_worker->dev_data->mf_ul_data;
  283. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  284. FurryHalNfcTxRxContext tx_rx = {};
  285. MfUltralightReader reader = {};
  286. mf_ul_reset(data);
  287. uint32_t key = 0;
  288. uint16_t pack = 0;
  289. while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
  290. furry_hal_nfc_sleep();
  291. if(furry_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FurryHalNfcTypeA) {
  292. if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
  293. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  294. if(data->auth_method == MfUltralightAuthMethodManual ||
  295. data->auth_method == MfUltralightAuthMethodAuto) {
  296. nfc_worker->callback(NfcWorkerEventMfUltralightPassKey, nfc_worker->context);
  297. key = nfc_util_bytes2num(data->auth_key, 4);
  298. } else if(data->auth_method == MfUltralightAuthMethodAmeebo) {
  299. key = mf_ul_pwdgen_amiibo(nfc_data);
  300. } else if(data->auth_method == MfUltralightAuthMethodXiaomi) {
  301. key = mf_ul_pwdgen_xiaomi(nfc_data);
  302. } else {
  303. FURI_LOG_E(TAG, "Incorrect auth method");
  304. break;
  305. }
  306. data->auth_success = mf_ultralight_authenticate(&tx_rx, key, &pack);
  307. if(!data->auth_success) {
  308. // Reset card
  309. furry_hal_nfc_sleep();
  310. if(!furry_hal_nfc_activate_nfca(300, NULL)) {
  311. nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context);
  312. break;
  313. }
  314. }
  315. mf_ul_read_card(&tx_rx, &reader, data);
  316. if(data->auth_success) {
  317. MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(data);
  318. if(config_pages != NULL) {
  319. config_pages->auth_data.pwd.value = REVERSE_BYTES_U32(key);
  320. config_pages->auth_data.pack.value = pack;
  321. }
  322. nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
  323. break;
  324. } else {
  325. nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context);
  326. break;
  327. }
  328. } else {
  329. nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context);
  330. furi_delay_ms(10);
  331. }
  332. } else {
  333. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  334. furi_delay_ms(10);
  335. }
  336. }
  337. }