nfc_worker.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. #include "nfc_worker_i.h"
  2. #include <api-hal.h>
  3. #include "nfc_protocols/emv_decoder.h"
  4. #include "nfc_protocols/mifare_ultralight.h"
  5. #define NFC_WORKER_TAG "nfc worker"
  6. /***************************** NFC Worker API *******************************/
  7. NfcWorker* nfc_worker_alloc() {
  8. NfcWorker* nfc_worker = furi_alloc(sizeof(NfcWorker));
  9. // Worker thread attributes
  10. nfc_worker->thread_attr.name = "nfc_worker";
  11. nfc_worker->thread_attr.stack_size = 8192;
  12. nfc_worker->callback = NULL;
  13. nfc_worker->context = NULL;
  14. // Initialize rfal
  15. nfc_worker->error = api_hal_nfc_init();
  16. if(nfc_worker->error == ERR_NONE) {
  17. api_hal_nfc_start_sleep();
  18. nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
  19. } else {
  20. nfc_worker_change_state(nfc_worker, NfcWorkerStateBroken);
  21. }
  22. return nfc_worker;
  23. }
  24. void nfc_worker_free(NfcWorker* nfc_worker) {
  25. furi_assert(nfc_worker);
  26. free(nfc_worker);
  27. }
  28. NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) {
  29. return nfc_worker->state;
  30. }
  31. ReturnCode nfc_worker_get_error(NfcWorker* nfc_worker) {
  32. return nfc_worker->error;
  33. }
  34. void nfc_worker_set_emulation_params(NfcWorker* nfc_worker, NfcDeviceData* data) {
  35. furi_assert(nfc_worker);
  36. furi_assert(data);
  37. nfc_worker->emulate_params = *data;
  38. }
  39. void nfc_worker_start(
  40. NfcWorker* nfc_worker,
  41. NfcWorkerState state,
  42. NfcWorkerResult* result_dest,
  43. NfcWorkerCallback callback,
  44. void* context) {
  45. furi_assert(nfc_worker);
  46. furi_assert(nfc_worker->state == NfcWorkerStateReady);
  47. furi_assert(result_dest);
  48. nfc_worker->callback = callback;
  49. nfc_worker->context = context;
  50. nfc_worker->last_result = result_dest;
  51. nfc_worker_change_state(nfc_worker, state);
  52. nfc_worker->thread = osThreadNew(nfc_worker_task, nfc_worker, &nfc_worker->thread_attr);
  53. }
  54. void nfc_worker_stop(NfcWorker* nfc_worker) {
  55. furi_assert(nfc_worker);
  56. if(nfc_worker->state == NfcWorkerStateBroken || nfc_worker->state == NfcWorkerStateReady) {
  57. return;
  58. }
  59. nfc_worker_change_state(nfc_worker, NfcWorkerStateStop);
  60. }
  61. void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
  62. nfc_worker->state = state;
  63. }
  64. /***************************** NFC Worker Thread *******************************/
  65. void nfc_worker_task(void* context) {
  66. NfcWorker* nfc_worker = context;
  67. api_hal_power_insomnia_enter();
  68. api_hal_nfc_exit_sleep();
  69. if(nfc_worker->state == NfcWorkerStateDetect) {
  70. nfc_worker_detect(nfc_worker);
  71. } else if(nfc_worker->state == NfcWorkerStateEmulate) {
  72. nfc_worker_emulate(nfc_worker);
  73. } else if(nfc_worker->state == NfcWorkerStateReadEMV) {
  74. nfc_worker_read_emv(nfc_worker);
  75. } else if(nfc_worker->state == NfcWorkerStateEmulateEMV) {
  76. nfc_worker_emulate_emv(nfc_worker);
  77. } else if(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
  78. nfc_worker_read_mf_ultralight(nfc_worker);
  79. } else if(nfc_worker->state == NfcWorkerStateField) {
  80. nfc_worker_field(nfc_worker);
  81. }
  82. api_hal_nfc_deactivate();
  83. nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
  84. api_hal_power_insomnia_exit();
  85. osThreadExit();
  86. }
  87. void nfc_worker_detect(NfcWorker* nfc_worker) {
  88. rfalNfcDevice* dev_list;
  89. rfalNfcDevice* dev;
  90. uint8_t dev_cnt;
  91. NfcDeviceData* result = &nfc_worker->last_result->nfc_detect_data;
  92. while(nfc_worker->state == NfcWorkerStateDetect) {
  93. if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true)) {
  94. // Process first found device
  95. dev = &dev_list[0];
  96. result->uid_len = dev->nfcidLen;
  97. memcpy(result->uid, dev->nfcid, dev->nfcidLen);
  98. if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCA) {
  99. result->device = NfcDeviceNfca;
  100. result->atqa[0] = dev->dev.nfca.sensRes.anticollisionInfo;
  101. result->atqa[1] = dev->dev.nfca.sensRes.platformInfo;
  102. result->sak = dev->dev.nfca.selRes.sak;
  103. if(mf_ul_check_card_type(
  104. dev->dev.nfca.sensRes.anticollisionInfo,
  105. dev->dev.nfca.sensRes.platformInfo,
  106. dev->dev.nfca.selRes.sak)) {
  107. result->protocol = NfcDeviceProtocolMfUltralight;
  108. } else {
  109. result->protocol = NfcDeviceProtocolUnknown;
  110. }
  111. } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCB) {
  112. result->device = NfcDeviceNfcb;
  113. } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCF) {
  114. result->device = NfcDeviceNfcf;
  115. } else if(dev->type == RFAL_NFC_LISTEN_TYPE_NFCV) {
  116. result->device = NfcDeviceNfcv;
  117. }
  118. // Notify caller and exit
  119. if(nfc_worker->callback) {
  120. nfc_worker->callback(nfc_worker->context);
  121. }
  122. break;
  123. }
  124. osDelay(100);
  125. }
  126. }
  127. void nfc_worker_emulate(NfcWorker* nfc_worker) {
  128. NfcDeviceData* param = &nfc_worker->emulate_params;
  129. while(nfc_worker->state == NfcWorkerStateEmulate) {
  130. if(api_hal_nfc_listen(param->uid, param->uid_len, param->atqa, param->sak, 100)) {
  131. FURI_LOG_I(NFC_WORKER_TAG, "Reader detected");
  132. }
  133. osDelay(10);
  134. }
  135. }
  136. void nfc_worker_read_emv(NfcWorker* nfc_worker) {
  137. ReturnCode err;
  138. rfalNfcDevice* dev_list;
  139. EmvApplication emv_app = {};
  140. uint8_t dev_cnt = 0;
  141. uint8_t tx_buff[255] = {};
  142. uint16_t tx_len = 0;
  143. uint8_t* rx_buff;
  144. uint16_t* rx_len;
  145. NfcEmvData* result = &nfc_worker->last_result->nfc_emv_data;
  146. while(nfc_worker->state == NfcWorkerStateReadEMV) {
  147. memset(&emv_app, 0, sizeof(emv_app));
  148. if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
  149. // Card was found. Check that it supports EMV
  150. if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) {
  151. FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command");
  152. tx_len = emv_prepare_select_ppse(tx_buff);
  153. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  154. if(err != ERR_NONE) {
  155. FURI_LOG_E(NFC_WORKER_TAG, "Error during selection PPSE request: %d", err);
  156. api_hal_nfc_deactivate();
  157. continue;
  158. }
  159. FURI_LOG_I(
  160. NFC_WORKER_TAG, "Select PPSE response received. Start parsing response");
  161. if(emv_decode_ppse_response(rx_buff, *rx_len, &emv_app)) {
  162. FURI_LOG_I(NFC_WORKER_TAG, "Select PPSE responce parced");
  163. } else {
  164. FURI_LOG_E(NFC_WORKER_TAG, "Can't find pay application");
  165. api_hal_nfc_deactivate();
  166. continue;
  167. }
  168. FURI_LOG_I(NFC_WORKER_TAG, "Starting application ...");
  169. tx_len = emv_prepare_select_app(tx_buff, &emv_app);
  170. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  171. if(err != ERR_NONE) {
  172. FURI_LOG_E(
  173. NFC_WORKER_TAG, "Error during application selection request: %d", err);
  174. api_hal_nfc_deactivate();
  175. continue;
  176. }
  177. FURI_LOG_I(
  178. NFC_WORKER_TAG,
  179. "Select application response received. Start parsing response");
  180. if(emv_decode_select_app_response(rx_buff, *rx_len, &emv_app)) {
  181. FURI_LOG_I(NFC_WORKER_TAG, "Card name: %s", emv_app.name);
  182. memcpy(result->name, emv_app.name, sizeof(emv_app.name));
  183. } else {
  184. FURI_LOG_E(NFC_WORKER_TAG, "Can't read card name");
  185. api_hal_nfc_deactivate();
  186. continue;
  187. }
  188. FURI_LOG_I(NFC_WORKER_TAG, "Starting Get Processing Options command ...");
  189. tx_len = emv_prepare_get_proc_opt(tx_buff, &emv_app);
  190. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  191. if(err != ERR_NONE) {
  192. FURI_LOG_E(
  193. NFC_WORKER_TAG, "Error during Get Processing Options command: %d", err);
  194. api_hal_nfc_deactivate();
  195. continue;
  196. }
  197. if(emv_decode_get_proc_opt(rx_buff, *rx_len, &emv_app)) {
  198. FURI_LOG_I(NFC_WORKER_TAG, "Card number parsed");
  199. memcpy(result->number, emv_app.card_number, sizeof(emv_app.card_number));
  200. // Notify caller and exit
  201. if(nfc_worker->callback) {
  202. nfc_worker->callback(nfc_worker->context);
  203. }
  204. break;
  205. } else {
  206. // Mastercard doesn't give PAN / card number as GPO response
  207. // Iterate over all files found in application
  208. bool pan_found = false;
  209. for(uint8_t i = 0; (i < emv_app.afl.size) && !pan_found; i += 4) {
  210. uint8_t sfi = emv_app.afl.data[i] >> 3;
  211. uint8_t record_start = emv_app.afl.data[i + 1];
  212. uint8_t record_end = emv_app.afl.data[i + 2];
  213. // Iterate over all records in file
  214. for(uint8_t record = record_start; record <= record_end; ++record) {
  215. tx_len = emv_prepare_read_sfi_record(tx_buff, sfi, record);
  216. err = api_hal_nfc_data_exchange(
  217. tx_buff, tx_len, &rx_buff, &rx_len, false);
  218. if(err != ERR_NONE) {
  219. FURI_LOG_E(
  220. NFC_WORKER_TAG,
  221. "Error reading application sfi %d, record %d",
  222. sfi,
  223. record);
  224. }
  225. if(emv_decode_read_sfi_record(rx_buff, *rx_len, &emv_app)) {
  226. pan_found = true;
  227. break;
  228. }
  229. }
  230. }
  231. if(pan_found) {
  232. FURI_LOG_I(NFC_WORKER_TAG, "Card PAN found");
  233. memcpy(result->number, emv_app.card_number, sizeof(emv_app.card_number));
  234. // Notify caller and exit
  235. if(nfc_worker->callback) {
  236. nfc_worker->callback(nfc_worker->context);
  237. }
  238. break;
  239. } else {
  240. FURI_LOG_E(NFC_WORKER_TAG, "Can't read card number");
  241. }
  242. api_hal_nfc_deactivate();
  243. }
  244. } else {
  245. // Can't find EMV card
  246. FURI_LOG_W(NFC_WORKER_TAG, "Card doesn't support EMV");
  247. api_hal_nfc_deactivate();
  248. }
  249. } else {
  250. // Can't find EMV card
  251. FURI_LOG_W(NFC_WORKER_TAG, "Can't find any cards");
  252. api_hal_nfc_deactivate();
  253. }
  254. osDelay(20);
  255. }
  256. }
  257. void nfc_worker_emulate_emv(NfcWorker* nfc_worker) {
  258. ReturnCode err;
  259. uint8_t tx_buff[255] = {};
  260. uint16_t tx_len = 0;
  261. uint8_t* rx_buff;
  262. uint16_t* rx_len;
  263. NfcDeviceData params = {
  264. .uid = {0xCF, 0x72, 0xd4, 0x40},
  265. .uid_len = 4,
  266. .atqa = {0x00, 0x04},
  267. .sak = 0x20,
  268. .device = NfcDeviceNfca,
  269. .protocol = NfcDeviceProtocolEMV,
  270. };
  271. while(nfc_worker->state == NfcWorkerStateEmulateEMV) {
  272. if(api_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, 100)) {
  273. FURI_LOG_I(NFC_WORKER_TAG, "POS terminal detected");
  274. // Read data from POS terminal
  275. err = api_hal_nfc_data_exchange(NULL, 0, &rx_buff, &rx_len, false);
  276. if(err == ERR_NONE) {
  277. FURI_LOG_I(NFC_WORKER_TAG, "Received Select PPSE");
  278. } else {
  279. FURI_LOG_E(NFC_WORKER_TAG, "Error in 1st data exchange: select PPSE");
  280. api_hal_nfc_deactivate();
  281. continue;
  282. }
  283. FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT PPSE ANS");
  284. tx_len = emv_select_ppse_ans(tx_buff);
  285. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  286. if(err == ERR_NONE) {
  287. FURI_LOG_I(NFC_WORKER_TAG, "Received Select APP");
  288. } else {
  289. FURI_LOG_E(NFC_WORKER_TAG, "Error in 2nd data exchange: select APP");
  290. api_hal_nfc_deactivate();
  291. continue;
  292. }
  293. FURI_LOG_I(NFC_WORKER_TAG, "Transive SELECT APP ANS");
  294. tx_len = emv_select_app_ans(tx_buff);
  295. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  296. if(err == ERR_NONE) {
  297. FURI_LOG_I(NFC_WORKER_TAG, "Received PDOL");
  298. } else {
  299. FURI_LOG_E(NFC_WORKER_TAG, "Error in 3rd data exchange: receive PDOL");
  300. api_hal_nfc_deactivate();
  301. continue;
  302. }
  303. FURI_LOG_I(NFC_WORKER_TAG, "Transive PDOL ANS");
  304. tx_len = emv_get_proc_opt_ans(tx_buff);
  305. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  306. if(err == ERR_NONE) {
  307. FURI_LOG_I(NFC_WORKER_TAG, "Received PDOL");
  308. }
  309. api_hal_nfc_deactivate();
  310. } else {
  311. FURI_LOG_W(NFC_WORKER_TAG, "Can't find reader");
  312. }
  313. osDelay(20);
  314. }
  315. }
  316. void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) {
  317. ReturnCode err;
  318. rfalNfcDevice* dev_list;
  319. uint8_t dev_cnt = 0;
  320. uint8_t tx_buff[255] = {};
  321. uint16_t tx_len = 0;
  322. uint8_t* rx_buff;
  323. uint16_t* rx_len;
  324. MfUltralightRead mf_ul_read;
  325. NfcMifareUlData* result = &nfc_worker->last_result->nfc_mifare_ul_data;
  326. while(nfc_worker->state == NfcWorkerStateReadMfUltralight) {
  327. api_hal_nfc_deactivate();
  328. memset(&mf_ul_read, 0, sizeof(mf_ul_read));
  329. if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) {
  330. if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA &&
  331. mf_ul_check_card_type(
  332. dev_list[0].dev.nfca.sensRes.anticollisionInfo,
  333. dev_list[0].dev.nfca.sensRes.platformInfo,
  334. dev_list[0].dev.nfca.selRes.sak)) {
  335. // Get Mifare Ultralight version
  336. FURI_LOG_I(
  337. NFC_WORKER_TAG, "Found Mifare Ultralight tag. Trying to get tag version");
  338. tx_len = mf_ul_prepare_get_version(tx_buff);
  339. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  340. if(err == ERR_NONE) {
  341. mf_ul_parse_get_version_response(rx_buff, &mf_ul_read);
  342. FURI_LOG_I(
  343. NFC_WORKER_TAG,
  344. "Mifare Ultralight Type: %d, Pages: %d",
  345. mf_ul_read.type,
  346. mf_ul_read.pages_to_read);
  347. } else if(err == ERR_TIMEOUT) {
  348. FURI_LOG_W(
  349. NFC_WORKER_TAG,
  350. "Card doesn't respond to GET VERSION command. Reinit card and set default read parameters");
  351. err = ERR_NONE;
  352. mf_ul_set_default_version(&mf_ul_read);
  353. // Reinit device
  354. api_hal_nfc_deactivate();
  355. if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 300, false)) {
  356. FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search");
  357. continue;
  358. }
  359. } else {
  360. FURI_LOG_E(
  361. NFC_WORKER_TAG,
  362. "Error getting Mifare Ultralight version. Error code: %d",
  363. err);
  364. continue;
  365. }
  366. // Dump Mifare Ultralight card
  367. FURI_LOG_I(NFC_WORKER_TAG, "Trying to read pages");
  368. if(mf_ul_read.support_fast_read) {
  369. // Read card with FAST_READ command
  370. tx_len = mf_ul_prepare_fast_read(tx_buff, 0x00, mf_ul_read.pages_to_read - 1);
  371. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  372. if(err == ERR_NONE) {
  373. FURI_LOG_I(
  374. NFC_WORKER_TAG,
  375. "Fast read pages %d - %d succeed",
  376. 0,
  377. mf_ul_read.pages_to_read - 1);
  378. memcpy(mf_ul_read.dump, rx_buff, mf_ul_read.pages_to_read * 4);
  379. mf_ul_read.pages_readed = mf_ul_read.pages_to_read;
  380. } else {
  381. FURI_LOG_E(NFC_WORKER_TAG, "Fast read failed");
  382. continue;
  383. }
  384. } else {
  385. // READ card with READ command (4 pages at a time)
  386. for(uint8_t page = 0; page < mf_ul_read.pages_to_read; page += 4) {
  387. tx_len = mf_ul_prepare_read(tx_buff, page);
  388. err = api_hal_nfc_data_exchange(tx_buff, tx_len, &rx_buff, &rx_len, false);
  389. if(err == ERR_NONE) {
  390. FURI_LOG_I(
  391. NFC_WORKER_TAG, "Read pages %d - %d succeed", page, page + 3);
  392. memcpy(&mf_ul_read.dump[page * 4], rx_buff, 4 * 4);
  393. mf_ul_read.pages_readed += 4;
  394. } else {
  395. FURI_LOG_W(
  396. NFC_WORKER_TAG, "Read pages %d - %d failed", page, page + 3);
  397. }
  398. }
  399. }
  400. // Fill result data
  401. result->nfc_data.uid_len = dev_list[0].dev.nfca.nfcId1Len;
  402. result->nfc_data.atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo;
  403. result->nfc_data.atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo;
  404. result->nfc_data.sak = dev_list[0].dev.nfca.selRes.sak;
  405. memcpy(
  406. result->nfc_data.uid, dev_list[0].dev.nfca.nfcId1, result->nfc_data.uid_len);
  407. memcpy(result->man_block, mf_ul_read.dump, 4 * 3);
  408. memcpy(result->otp, &mf_ul_read.dump[4 * 3], 4);
  409. result->dump_size = mf_ul_read.pages_readed * 4;
  410. memcpy(result->full_dump, mf_ul_read.dump, result->dump_size);
  411. for(uint8_t i = 0; i < mf_ul_read.pages_readed * 4; i += 4) {
  412. printf("Page %2d: ", i / 4);
  413. for(uint8_t j = 0; j < 4; j++) {
  414. printf("%02X ", mf_ul_read.dump[i + j]);
  415. }
  416. printf("\r\n");
  417. }
  418. // Notify caller and exit
  419. if(nfc_worker->callback) {
  420. nfc_worker->callback(nfc_worker->context);
  421. }
  422. break;
  423. } else {
  424. FURI_LOG_W(NFC_WORKER_TAG, "Tag does not support Mifare Ultralight");
  425. }
  426. } else {
  427. FURI_LOG_W(NFC_WORKER_TAG, "Can't find any tags");
  428. }
  429. osDelay(100);
  430. }
  431. }
  432. void nfc_worker_field(NfcWorker* nfc_worker) {
  433. api_hal_nfc_field_on();
  434. while(nfc_worker->state == NfcWorkerStateField) {
  435. osDelay(50);
  436. }
  437. api_hal_nfc_field_off();
  438. }