nfc_worker.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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 == NfcWorkerStateMfClassicEmulate) {
  73. nfc_worker_emulate_mf_classic(nfc_worker);
  74. } else if(nfc_worker->state == NfcWorkerStateMfClassicWrite) {
  75. nfc_worker_write_mf_classic(nfc_worker);
  76. } else if(nfc_worker->state == NfcWorkerStateMfClassicUpdate) {
  77. nfc_worker_update_mf_classic(nfc_worker);
  78. } else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
  79. nfc_worker_mf_classic_dict_attack(nfc_worker);
  80. }
  81. furry_hal_nfc_sleep();
  82. nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
  83. return 0;
  84. }
  85. static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) {
  86. furi_assert(nfc_worker->callback);
  87. bool read_success = false;
  88. do {
  89. // Try to read card with key cache
  90. FURI_LOG_I(TAG, "Search for key cache ...");
  91. if(nfc_worker->callback(NfcWorkerEventReadMfClassicLoadKeyCache, nfc_worker->context)) {
  92. FURI_LOG_I(TAG, "Load keys cache success. Start reading");
  93. uint8_t sectors_read =
  94. mf_classic_update_card(tx_rx, &nfc_worker->dev_data->mf_classic_data);
  95. uint8_t sectors_total =
  96. mf_classic_get_total_sectors_num(nfc_worker->dev_data->mf_classic_data.type);
  97. FURI_LOG_I(TAG, "Read %d sectors out of %d total", sectors_read, sectors_total);
  98. read_success = mf_classic_is_card_read(&nfc_worker->dev_data->mf_classic_data);
  99. }
  100. } while(false);
  101. return read_success;
  102. }
  103. static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) {
  104. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  105. bool card_read = false;
  106. furry_hal_nfc_sleep();
  107. if(mf_classic_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) {
  108. FURI_LOG_I(TAG, "Mifare Classic detected");
  109. nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
  110. nfc_worker->dev_data->mf_classic_data.type =
  111. mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
  112. card_read = nfc_worker_read_mf_classic(nfc_worker, tx_rx);
  113. } else if(nfc_data->interface == FurryHalNfcInterfaceIsoDep) {
  114. FURI_LOG_I(TAG, "ISO14443-4 card detected");
  115. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  116. card_read = true;
  117. } else {
  118. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  119. card_read = true;
  120. }
  121. return card_read;
  122. }
  123. void nfc_worker_read(NfcWorker* nfc_worker) {
  124. furi_assert(nfc_worker);
  125. furi_assert(nfc_worker->callback);
  126. nfc_device_data_clear(nfc_worker->dev_data);
  127. NfcDeviceData* dev_data = nfc_worker->dev_data;
  128. FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
  129. FurryHalNfcTxRxContext tx_rx = {};
  130. NfcWorkerEvent event = 0;
  131. bool card_not_detected_notified = false;
  132. while(nfc_worker->state == NfcWorkerStateRead) {
  133. if(furry_hal_nfc_detect(nfc_data, 300)) {
  134. // Process first found device
  135. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  136. card_not_detected_notified = false;
  137. if(nfc_data->type == FurryHalNfcTypeA) {
  138. if(nfc_worker_read_nfca(nfc_worker, &tx_rx)) {
  139. if(dev_data->protocol == NfcDeviceProtocolMifareClassic) {
  140. event = NfcWorkerEventReadMfClassicDone;
  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. nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
  193. nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type(
  194. nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
  195. if(nfc_worker_read_mf_classic(nfc_worker, &tx_rx)) {
  196. FURI_LOG_D(TAG, "Card read");
  197. dev_data->protocol = NfcDeviceProtocolMifareClassic;
  198. event = NfcWorkerEventReadMfClassicDone;
  199. break;
  200. } else {
  201. FURI_LOG_D(TAG, "Card read failed");
  202. dev_data->protocol = NfcDeviceProtocolMifareClassic;
  203. event = NfcWorkerEventReadMfClassicDictAttackRequired;
  204. break;
  205. }
  206. } else if(read_mode == NfcReadModeNFCA) {
  207. nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
  208. event = NfcWorkerEventReadUidNfcA;
  209. break;
  210. }
  211. }
  212. } else {
  213. if(!card_not_detected_notified) {
  214. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  215. card_not_detected_notified = true;
  216. }
  217. }
  218. furry_hal_nfc_sleep();
  219. furi_delay_ms(100);
  220. }
  221. // Notify caller and exit
  222. if(event > NfcWorkerEventReserved) {
  223. nfc_worker->callback(event, nfc_worker->context);
  224. }
  225. }
  226. void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
  227. FurryHalNfcTxRxContext tx_rx = {};
  228. FurryHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;
  229. NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data;
  230. // TODO add support for RATS
  231. // Need to save ATS to support ISO-14443A-4 emulation
  232. while(nfc_worker->state == NfcWorkerStateUidEmulate) {
  233. if(furry_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) {
  234. if(furry_hal_nfc_tx_rx(&tx_rx, 100)) {
  235. reader_data->size = tx_rx.rx_bits / 8;
  236. if(reader_data->size > 0) {
  237. memcpy(reader_data->data, tx_rx.rx_data, reader_data->size);
  238. if(nfc_worker->callback) {
  239. nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
  240. }
  241. }
  242. } else {
  243. FURI_LOG_E(TAG, "Failed to get reader commands");
  244. }
  245. }
  246. }
  247. }
  248. static bool nfc_worker_mf_get_b_key_from_sector_trailer(
  249. FurryHalNfcTxRxContext* tx_rx,
  250. uint16_t sector,
  251. uint64_t key,
  252. uint64_t* found_key) {
  253. // Some access conditions allow reading B key via A key
  254. uint8_t block = mf_classic_get_sector_trailer_block_num_by_sector(sector);
  255. Crypto1 crypto = {};
  256. MfClassicBlock block_tmp = {};
  257. MfClassicAuthContext auth_context = {.sector = sector, .key_a = MF_CLASSIC_NO_KEY, .key_b = 0};
  258. furry_hal_nfc_sleep();
  259. if(mf_classic_auth_attempt(tx_rx, &crypto, &auth_context, key)) {
  260. if(mf_classic_read_block(tx_rx, &crypto, block, &block_tmp)) {
  261. *found_key = nfc_util_bytes2num(&block_tmp.value[10], sizeof(uint8_t) * 6);
  262. return *found_key;
  263. }
  264. }
  265. return false;
  266. }
  267. static void nfc_worker_mf_classic_key_attack(
  268. NfcWorker* nfc_worker,
  269. uint64_t key,
  270. FurryHalNfcTxRxContext* tx_rx,
  271. uint16_t start_sector) {
  272. furi_assert(nfc_worker);
  273. furi_assert(nfc_worker->callback);
  274. bool card_found_notified = true;
  275. bool card_removed_notified = false;
  276. MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
  277. NfcMfClassicDictAttackData* dict_attack_data =
  278. &nfc_worker->dev_data->mf_classic_dict_attack_data;
  279. uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
  280. furi_assert(start_sector < total_sectors);
  281. nfc_worker->callback(NfcWorkerEventKeyAttackStart, nfc_worker->context);
  282. // Check every sector's A and B keys with the given key
  283. for(size_t i = start_sector; i < total_sectors; i++) {
  284. nfc_worker->callback(NfcWorkerEventKeyAttackNextSector, nfc_worker->context);
  285. dict_attack_data->current_sector = i;
  286. furry_hal_nfc_sleep();
  287. if(furry_hal_nfc_activate_nfca(200, NULL)) {
  288. furry_hal_nfc_sleep();
  289. if(!card_found_notified) {
  290. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  291. card_found_notified = true;
  292. card_removed_notified = false;
  293. }
  294. uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
  295. if(mf_classic_is_sector_read(data, i)) continue;
  296. if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
  297. FURI_LOG_D(TAG, "Trying A key for sector %d, key: %012llX", i, key);
  298. if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) {
  299. mf_classic_set_key_found(data, i, MfClassicKeyA, key);
  300. FURI_LOG_D(TAG, "Key A found: %012llX", key);
  301. nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
  302. uint64_t found_key;
  303. if(nfc_worker_mf_get_b_key_from_sector_trailer(tx_rx, i, key, &found_key)) {
  304. FURI_LOG_D(TAG, "Found B key via reading sector %d", i);
  305. mf_classic_set_key_found(data, i, MfClassicKeyB, found_key);
  306. if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
  307. nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
  308. }
  309. }
  310. }
  311. furry_hal_nfc_sleep();
  312. }
  313. if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
  314. FURI_LOG_D(TAG, "Trying B key for sector %d, key: %012llX", i, key);
  315. if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) {
  316. mf_classic_set_key_found(data, i, MfClassicKeyB, key);
  317. FURI_LOG_D(TAG, "Key B found: %012llX", key);
  318. nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
  319. }
  320. }
  321. if(mf_classic_is_sector_read(data, i)) continue;
  322. mf_classic_read_sector(tx_rx, data, i);
  323. } else {
  324. if(!card_removed_notified) {
  325. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  326. card_removed_notified = true;
  327. card_found_notified = false;
  328. }
  329. }
  330. if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
  331. }
  332. nfc_worker->callback(NfcWorkerEventKeyAttackStop, nfc_worker->context);
  333. }
  334. void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
  335. furi_assert(nfc_worker);
  336. furi_assert(nfc_worker->callback);
  337. MfClassicData* data = &nfc_worker->dev_data->mf_classic_data;
  338. NfcMfClassicDictAttackData* dict_attack_data =
  339. &nfc_worker->dev_data->mf_classic_dict_attack_data;
  340. uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type);
  341. uint64_t key = 0;
  342. uint64_t prev_key = 0;
  343. FurryHalNfcTxRxContext tx_rx = {};
  344. bool card_found_notified = true;
  345. bool card_removed_notified = false;
  346. // Load dictionary
  347. MfClassicDict* dict = dict_attack_data->dict;
  348. if(!dict) {
  349. FURI_LOG_E(TAG, "Dictionary not found");
  350. nfc_worker->callback(NfcWorkerEventNoDictFound, nfc_worker->context);
  351. return;
  352. }
  353. FURI_LOG_D(
  354. TAG, "Start Dictionary attack, Key Count %lu", mf_classic_dict_get_total_keys(dict));
  355. for(size_t i = 0; i < total_sectors; i++) {
  356. FURI_LOG_I(TAG, "Sector %d", i);
  357. nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context);
  358. uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
  359. if(mf_classic_is_sector_read(data, i)) continue;
  360. if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
  361. mf_classic_is_key_found(data, i, MfClassicKeyB))
  362. continue;
  363. uint16_t key_index = 0;
  364. while(mf_classic_dict_get_next_key(dict, &key)) {
  365. FURI_LOG_T(TAG, "Key %d", key_index);
  366. if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) {
  367. nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context);
  368. }
  369. furry_hal_nfc_sleep();
  370. uint32_t cuid;
  371. if(furry_hal_nfc_activate_nfca(200, &cuid)) {
  372. bool deactivated = false;
  373. if(!card_found_notified) {
  374. nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
  375. card_found_notified = true;
  376. card_removed_notified = false;
  377. nfc_worker_mf_classic_key_attack(nfc_worker, prev_key, &tx_rx, i);
  378. deactivated = true;
  379. }
  380. FURI_LOG_D(TAG, "Try to auth to sector %d with key %012llX", i, key);
  381. if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
  382. if(mf_classic_authenticate_skip_activate(
  383. &tx_rx, block_num, key, MfClassicKeyA, !deactivated, cuid)) {
  384. mf_classic_set_key_found(data, i, MfClassicKeyA, key);
  385. FURI_LOG_D(TAG, "Key A found: %012llX", key);
  386. nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
  387. uint64_t found_key;
  388. if(nfc_worker_mf_get_b_key_from_sector_trailer(
  389. &tx_rx, i, key, &found_key)) {
  390. FURI_LOG_D(TAG, "Found B key via reading sector %d", i);
  391. mf_classic_set_key_found(data, i, MfClassicKeyB, found_key);
  392. if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
  393. nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
  394. }
  395. nfc_worker_mf_classic_key_attack(nfc_worker, found_key, &tx_rx, i + 1);
  396. break;
  397. }
  398. nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
  399. }
  400. furry_hal_nfc_sleep();
  401. deactivated = true;
  402. } else {
  403. // If the key A is marked as found and matches the searching key, invalidate it
  404. MfClassicSectorTrailer* sec_trailer =
  405. mf_classic_get_sector_trailer_by_sector(data, i);
  406. uint8_t current_key[6];
  407. nfc_util_num2bytes(key, 6, current_key);
  408. if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
  409. memcmp(sec_trailer->key_a, current_key, 6) == 0) {
  410. if(!mf_classic_authenticate_skip_activate(
  411. &tx_rx, block_num, key, MfClassicKeyA, !deactivated, cuid)) {
  412. mf_classic_set_key_not_found(data, i, MfClassicKeyA);
  413. FURI_LOG_D(TAG, "Key %dA not found in attack", i);
  414. }
  415. }
  416. furry_hal_nfc_sleep();
  417. deactivated = true;
  418. }
  419. if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
  420. if(mf_classic_authenticate_skip_activate(
  421. &tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) { //-V547
  422. FURI_LOG_D(TAG, "Key B found: %012llX", key);
  423. mf_classic_set_key_found(data, i, MfClassicKeyB, key);
  424. nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
  425. nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
  426. }
  427. deactivated = true; //-V1048
  428. } else {
  429. // If the key B is marked as found and matches the searching key, invalidate it
  430. MfClassicSectorTrailer* sec_trailer =
  431. mf_classic_get_sector_trailer_by_sector(data, i);
  432. uint8_t current_key[6];
  433. nfc_util_num2bytes(key, 6, current_key);
  434. if(mf_classic_is_key_found(data, i, MfClassicKeyB) &&
  435. memcmp(sec_trailer->key_b, current_key, 6) == 0) {
  436. if(!mf_classic_authenticate_skip_activate(
  437. &tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) { //-V547
  438. mf_classic_set_key_not_found(data, i, MfClassicKeyB);
  439. FURI_LOG_D(TAG, "Key %dB not found in attack", i);
  440. }
  441. furry_hal_nfc_sleep();
  442. deactivated = true; //-V1048
  443. }
  444. }
  445. if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
  446. mf_classic_is_key_found(data, i, MfClassicKeyB))
  447. break;
  448. if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
  449. } else {
  450. if(!card_removed_notified) {
  451. nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
  452. card_removed_notified = true;
  453. card_found_notified = false;
  454. }
  455. if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
  456. }
  457. prev_key = key;
  458. }
  459. if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
  460. mf_classic_read_sector(&tx_rx, data, i);
  461. mf_classic_dict_rewind(dict);
  462. }
  463. if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
  464. nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
  465. } else {
  466. nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context);
  467. }
  468. }